From e45f17efae33cc7c492e90f0eb96a85f36355fd7 Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Tue, 12 Sep 2023 22:57:44 +0200 Subject: [PATCH] [MIRROR] John Splintercell: a gun that is only good for shooting out lights [MDB IGNORE] (#23650) * John Splintercell: a gun that is only good for shooting out lights * Removes this flashlight nonsense, we don't need copy pasted procs for something this simple --------- Co-authored-by: Hatterhat <31829017+Hatterhat@users.noreply.github.com> Co-authored-by: Pinta <68373373+softcerv@users.noreply.github.com> Co-authored-by: Giz <13398309+vinylspiders@users.noreply.github.com> --- .../__DEFINES/dcs/signals/signals_saboteur.dm | 4 ++ code/datums/components/seclight_attachable.dm | 17 ++++--- code/game/machinery/camera/camera.dm | 14 ++++-- code/game/objects/items/devices/flashlight.dm | 44 +++++++++++------- .../structures/crates_lockers/closets.dm | 2 +- .../cargo/markets/market_items/weapons.dm | 10 ++++ .../mining/equipment/kinetic_crusher.dm | 5 ++ .../carbon/human/species_types/ethereal.dm | 11 +++++ .../modules/mob/living/silicon/robot/robot.dm | 8 ++++ code/modules/power/floodlight.dm | 9 +++- code/modules/power/lighting/light.dm | 6 +++ .../projectiles/ammunition/energy/special.dm | 6 +++ code/modules/projectiles/gun.dm | 3 +- .../projectiles/guns/energy/recharge.dm | 33 +++++++++++++ .../projectile/special/lightbreaker.dm | 34 ++++++++++++++ icons/obj/weapons/guns/energy.dmi | Bin 45742 -> 46351 bytes .../modules/cell_component/code/flashlight.dm | 40 ++++++---------- tgstation.dme | 2 + 18 files changed, 191 insertions(+), 57 deletions(-) create mode 100644 code/__DEFINES/dcs/signals/signals_saboteur.dm create mode 100644 code/modules/projectiles/projectile/special/lightbreaker.dm diff --git a/code/__DEFINES/dcs/signals/signals_saboteur.dm b/code/__DEFINES/dcs/signals/signals_saboteur.dm new file mode 100644 index 00000000000..5ef536683fe --- /dev/null +++ b/code/__DEFINES/dcs/signals/signals_saboteur.dm @@ -0,0 +1,4 @@ +// Light disruptor. Not to be confused with the light eater, which permanently disables lights. + +/// from /obj/projectile/energy/fisher/on_hit() or /obj/item/gun/energy/recharge/fisher when striking a target +#define COMSIG_HIT_BY_SABOTEUR "hit_by_saboteur" diff --git a/code/datums/components/seclight_attachable.dm b/code/datums/components/seclight_attachable.dm index 56761cfd1bf..b3f36fe041a 100644 --- a/code/datums/components/seclight_attachable.dm +++ b/code/datums/components/seclight_attachable.dm @@ -98,6 +98,7 @@ RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attackby)) RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) RegisterSignal(parent, COMSIG_QDELETING, PROC_REF(on_parent_deleted)) + RegisterSignal(parent, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) /datum/component/seclite_attachable/UnregisterFromParent() UnregisterSignal(parent, list( @@ -156,12 +157,10 @@ if(!light) return FALSE - light.on = !light.on - light.update_brightness() - if(user) - user.balloon_alert(user, "[light.name] toggled [light.on ? "on":"off"]") - - playsound(light, 'sound/weapons/empty.ogg', 100, TRUE) + var/successful_toggle = light.toggle_light(user) + if(!successful_toggle) + return TRUE + user.balloon_alert(user, "[light.name] toggled [light.on ? "on":"off"]") update_light() return TRUE @@ -296,3 +295,9 @@ // Yes, this might mess with other icon state alterations, // but that's the downside of using icon states over overlays. source.icon_state = base_state + +/// Signal proc for [COMSIG_HIT_BY_SABOTEUR] that turns the light off for a few seconds. +/datum/component/seclite_attachable/proc/on_saboteur(datum/source, disrupt_duration) + SIGNAL_HANDLER + . = light.on_saboteur(source, disrupt_duration) + update_light() diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index a47115a9f60..575464a98af 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -30,7 +30,6 @@ var/busy = FALSE var/emped = FALSE //Number of consecutive EMP's on this camera var/in_use_lights = 0 - // Upgrades bitflag var/upgrades = 0 @@ -105,6 +104,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0) alarm_manager = new(src) + RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) + /obj/machinery/camera/connect_to_shuttle(mapload, obj/docking_port/mobile/port, obj/docking_port/stationary/dock) for(var/i in network) network -= i @@ -155,7 +156,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0) if(!status && powered()) . += span_info("It can reactivated with wirecutters.") -/obj/machinery/camera/emp_act(severity) +/obj/machinery/camera/emp_act(severity, reset_time = 90 SECONDS) . = ..() if(!status) return @@ -168,7 +169,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0) set_light(0) emped = emped+1 //Increase the number of consecutive EMP's update_appearance() - addtimer(CALLBACK(src, PROC_REF(post_emp_reset), emped, network), 90 SECONDS) + addtimer(CALLBACK(src, PROC_REF(post_emp_reset), emped, network), reset_time) for(var/i in GLOB.player_list) var/mob/M = i if (M.client?.eye == src) @@ -176,6 +177,11 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0) M.reset_perspective(null) to_chat(M, span_warning("The screen bursts into static!")) +/obj/machinery/camera/proc/on_saboteur(datum/source, disrupt_duration) + SIGNAL_HANDLER + emp_act(EMP_LIGHT, reset_time = disrupt_duration) + return TRUE + /obj/machinery/camera/proc/post_emp_reset(thisemp, previous_network) if(QDELETED(src)) return @@ -188,7 +194,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/camera/xray, 0) if(can_use()) GLOB.cameranet.addCamera(src) emped = 0 //Resets the consecutive EMP count - addtimer(CALLBACK(src, PROC_REF(cancelCameraAlarm)), 100) + addtimer(CALLBACK(src, PROC_REF(cancelCameraAlarm)), 10 SECONDS) /obj/machinery/camera/ex_act(severity, target) if(invuln) diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 14fc91ea7d0..ee7a66044fd 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -23,6 +23,8 @@ light_range = 4 light_power = 1 light_on = FALSE + /// If we've been forcibly disabled for a temporary amount of time. + COOLDOWN_DECLARE(disabled_time) /// Can we toggle this light on and off (used for contexual screentips only) var/toggle_context = TRUE /// The sound the light makes when it's turned on @@ -32,16 +34,15 @@ /// Is the light turned on or off currently var/on = FALSE -// SKYRAT EDIT REMOVAL BEGIN - MOVED TO MODUALR FLASHLIGHT.DM -/* /obj/item/flashlight/Initialize(mapload) . = ..() if(icon_state == "[initial(icon_state)]-on") on = TRUE update_brightness() register_context() -*/ -// SKYRAT EDIT REMOVAL END + + if(toggle_context) + RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) /obj/item/flashlight/add_context(atom/source, list/context, obj/item/held_item, mob/living/user) // single use lights can be toggled on once @@ -68,19 +69,21 @@ if(light_system == STATIC_LIGHT) update_light() -// SKYRAT EDIT REMOVAL BEGIN - MOVED TO MODUALR FLASHLIGHT.DM -/* -/obj/item/flashlight/proc/toggle_light() +/obj/item/flashlight/proc/toggle_light(mob/user) + var/disrupted = FALSE + //playsound(src, on ? sound_on : sound_off, 40, TRUE) SKYRAT EDIT REMOVAL - SOUND HANDLED IN MODULAR FLASHLIGHT.DM on = !on - playsound(src, on ? sound_on : sound_off, 40, TRUE) + if(!COOLDOWN_FINISHED(src, disabled_time)) + if(user) + balloon_alert(user, "disrupted!") + on = FALSE + disrupted = TRUE update_brightness() update_item_action_buttons() - return TRUE + return !disrupted /obj/item/flashlight/attack_self(mob/user) - toggle_light() -*/ -// SKYRAT EDIT REMOVAL END + toggle_light(user) /obj/item/flashlight/attack_hand_secondary(mob/user, list/modifiers) attack_self(user) @@ -262,6 +265,14 @@ if(istype(user) && dir != user.dir) setDir(user.dir) +/// when hit by a light disruptor - turns the light off, forces the light to be disabled for a few seconds +/obj/item/flashlight/proc/on_saboteur(datum/source, disrupt_duration) + SIGNAL_HANDLER + if(on) + toggle_light() + COOLDOWN_START(src, disabled_time, disrupt_duration) + return TRUE + /obj/item/flashlight/pen name = "penlight" desc = "A pen-sized light, used by medical staff. It can also be used to create a hologram to alert people of incoming medical assistance." @@ -420,16 +431,15 @@ damtype = BURN . = ..() -/obj/item/flashlight/flare/turn_off() //SKYRAT EDIT CHANGE - //on = FALSE SKYRAT EDIT REMOVAL +/obj/item/flashlight/flare/proc/turn_off() + on = FALSE name = initial(name) attack_verb_continuous = initial(attack_verb_continuous) attack_verb_simple = initial(attack_verb_simple) hitsound = initial(hitsound) force = initial(force) damtype = initial(damtype) - //update_brightness() - SKYRAT EDIT MOVED TO PARENT - . = ..() //SKYRAT EDIT - MODULAR PARENT PROC + update_brightness() /obj/item/flashlight/flare/extinguish() . = ..() @@ -749,11 +759,9 @@ turn_off() STOP_PROCESSING(SSobj, src) -/* SKYRAT EDIT REMOVAL /obj/item/flashlight/glowstick/proc/turn_off() on = FALSE update_appearance(UPDATE_ICON) -*/ /obj/item/flashlight/glowstick/update_appearance(updates=ALL) . = ..() diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 1e05bae6298..de19ce19058 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -15,7 +15,7 @@ contents_pressure_protection = 0 /// How insulated the thing is, for the purposes of calculating body temperature. Must be between 0 and 1! contents_thermal_insulation = 0 - pass_flags_self = LETPASSCLICKS + pass_flags_self = PASSSTRUCTURE | LETPASSCLICKS /// The overlay for the closet's door var/obj/effect/overlay/closet_door/door_obj diff --git a/code/modules/cargo/markets/market_items/weapons.dm b/code/modules/cargo/markets/market_items/weapons.dm index f40e4fa1447..6115b1e1557 100644 --- a/code/modules/cargo/markets/market_items/weapons.dm +++ b/code/modules/cargo/markets/market_items/weapons.dm @@ -63,3 +63,13 @@ price_max = CARGO_CRATE_VALUE * 2 stock_max = 2 availability_prob = 50 + +/datum/market_item/weapon/fisher + name = "SC/FISHER Saboteur Handgun" + desc = "A self-recharging, compact pistol that disrupts flashlights and security cameras, if only temporarily. Also usable in melee." + item = /obj/item/gun/energy/recharge/fisher + + price_min = CARGO_CRATE_VALUE * 2 + price_max = CARGO_CRATE_VALUE * 4 + stock_max = 1 + availability_prob = 50 diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index a1edd69ba3e..8ae842807a8 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -38,6 +38,7 @@ ) //technically it's huge and bulky, but this provides an incentive to use it AddComponent(/datum/component/two_handed, force_unwielded=0, force_wielded=20) + RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) /obj/item/kinetic_crusher/Destroy() QDEL_LIST(trophies) @@ -165,6 +166,10 @@ playsound(user, 'sound/weapons/empty.ogg', 100, TRUE) update_appearance() +/obj/item/kinetic_crusher/proc/on_saboteur(datum/source, disrupt_duration) + set_light_on(FALSE) + playsound(src, 'sound/weapons/empty.ogg', 100, TRUE) + return TRUE /obj/item/kinetic_crusher/update_icon_state() inhand_icon_state = "crusher[HAS_TRAIT(src, TRAIT_WIELDED)]" // this is not icon_state and not supported by 2hcomponent 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 9546a659e41..f087eb6b92c 100644 --- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm +++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm @@ -68,6 +68,7 @@ RegisterSignal(ethereal, COMSIG_ATOM_EMAG_ACT, PROC_REF(on_emag_act)) RegisterSignal(ethereal, COMSIG_ATOM_EMP_ACT, PROC_REF(on_emp_act)) RegisterSignal(ethereal, COMSIG_LIGHT_EATER_ACT, PROC_REF(on_light_eater)) + RegisterSignal(ethereal, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) ethereal_light = ethereal.mob_light(light_type = /obj/effect/dummy/lighting_obj/moblight/species) spec_updatehealth(ethereal) new_ethereal.set_safe_hunger_level() @@ -84,6 +85,7 @@ UnregisterSignal(former_ethereal, COMSIG_ATOM_EMAG_ACT) UnregisterSignal(former_ethereal, COMSIG_ATOM_EMP_ACT) UnregisterSignal(former_ethereal, COMSIG_LIGHT_EATER_ACT) + UnregisterSignal(former_ethereal, COMSIG_HIT_BY_SABOTEUR) QDEL_NULL(ethereal_light) return ..() @@ -147,6 +149,15 @@ if(EMP_HEAVY) addtimer(CALLBACK(src, PROC_REF(stop_emp), H), 20 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE) //We're out for 20 seconds +/datum/species/ethereal/proc/on_saboteur(datum/source, disrupt_duration) + SIGNAL_HANDLER + var/mob/living/carbon/human/our_target = source + EMPeffect = TRUE + spec_updatehealth(our_target) + to_chat(our_target, span_warning("Something inside of you crackles in a bad way.")) + our_target.take_bodypart_damage(burn = 3, wound_bonus = CANT_WOUND) + addtimer(CALLBACK(src, PROC_REF(stop_emp), our_target), disrupt_duration, TIMER_UNIQUE|TIMER_OVERRIDE) + /datum/species/ethereal/proc/on_emag_act(mob/living/carbon/human/H, mob/user) SIGNAL_HANDLER if(emageffect) diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 9732222f0cf..17e59660eb4 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -19,6 +19,7 @@ AddElement(/datum/element/ridable, /datum/component/riding/creature/cyborg) RegisterSignal(src, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, PROC_REF(charge)) RegisterSignal(src, COMSIG_LIGHT_EATER_ACT, PROC_REF(on_light_eater)) + RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) robot_modules_background = new() robot_modules_background.icon_state = "block" @@ -470,6 +471,13 @@ smash_headlamp() return COMPONENT_BLOCK_LIGHT_EATER +/// special handling for getting shot with a light disruptor/saboteur e.g. the fisher +/mob/living/silicon/robot/proc/on_saboteur(datum/source, disrupt_duration) + SIGNAL_HANDLER + if(lamp_enabled) + toggle_headlamp(TRUE) + to_chat(src, span_warning("Your headlamp was forcibly turned off. Restarting it should fix it, though.")) + return TRUE /** * Handles headlamp smashing diff --git a/code/modules/power/floodlight.dm b/code/modules/power/floodlight.dm index 3ab8ece250f..0898e31735b 100644 --- a/code/modules/power/floodlight.dm +++ b/code/modules/power/floodlight.dm @@ -144,6 +144,7 @@ /obj/machinery/power/floodlight/Initialize(mapload) . = ..() RegisterSignal(src, COMSIG_OBJ_PAINTED, TYPE_PROC_REF(/obj/machinery/power/floodlight, on_color_change)) //update light color when color changes + RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) register_context() /obj/machinery/power/floodlight/proc/on_color_change(obj/machinery/power/flood_light, mob/user, obj/item/toy/crayon/spraycan/spraycan, is_dark_color) @@ -289,6 +290,11 @@ /obj/machinery/power/floodlight/attack_ai(mob/user) return attack_hand(user) +/obj/machinery/power/floodlight/proc/on_saboteur(datum/source, disrupt_duration) + SIGNAL_HANDLER + atom_break(ENERGY) // technically, + return TRUE + /obj/machinery/power/floodlight/atom_break(damage_flag) . = ..() if(!.) @@ -297,7 +303,8 @@ var/obj/structure/floodlight_frame/floodlight_frame = new(loc) floodlight_frame.state = FLOODLIGHT_NEEDS_LIGHTS - new /obj/item/light/tube(loc) + var/obj/item/light/tube/our_light = new(loc) + our_light.shatter() qdel(src) diff --git a/code/modules/power/lighting/light.dm b/code/modules/power/lighting/light.dm index 2486a6500c1..ea6a28a8fe4 100644 --- a/code/modules/power/lighting/light.dm +++ b/code/modules/power/lighting/light.dm @@ -114,6 +114,7 @@ // Light projects out backwards from the dir of the light set_light(l_dir = REVERSE_DIR(dir)) RegisterSignal(src, COMSIG_LIGHT_EATER_ACT, PROC_REF(on_light_eater)) + RegisterSignal(src, COMSIG_HIT_BY_SABOTEUR, PROC_REF(on_saboteur)) AddElement(/datum/element/atmos_sensitive, mapload) return INITIALIZE_HINT_LATELOAD @@ -706,6 +707,11 @@ tube?.burn() return +/obj/machinery/light/proc/on_saboteur(datum/source, disrupt_duration) + SIGNAL_HANDLER + break_light_tube() + return TRUE + /obj/machinery/light/proc/grey_tide(datum/source, list/grey_tide_areas) SIGNAL_HANDLER diff --git a/code/modules/projectiles/ammunition/energy/special.dm b/code/modules/projectiles/ammunition/energy/special.dm index bedfab7b235..24fba4b9ba4 100644 --- a/code/modules/projectiles/ammunition/energy/special.dm +++ b/code/modules/projectiles/ammunition/energy/special.dm @@ -74,3 +74,9 @@ select_name = "marksman nanoshot" e_cost = 0 fire_sound = 'sound/weapons/gun/revolver/shot_alt.ogg' + +/obj/item/ammo_casing/energy/fisher + projectile_type = /obj/projectile/energy/fisher + select_name = "light-buster" + e_cost = 250 + fire_sound = 'sound/weapons/gun/general/heavy_shot_suppressed.ogg' // fwip fwip fwip fwip diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index ddacb419bbe..e76af741a18 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -26,6 +26,7 @@ var/vary_fire_sound = TRUE var/fire_sound_volume = 50 var/dry_fire_sound = 'sound/weapons/gun/general/dry_fire.ogg' + var/dry_fire_sound_volume = 30 var/suppressed = null //whether or not a message is displayed when fired var/can_suppress = FALSE var/suppressed_sound = 'sound/weapons/gun/general/heavy_shot_suppressed.ogg' @@ -169,7 +170,7 @@ /obj/item/gun/proc/shoot_with_empty_chamber(mob/living/user as mob|obj) balloon_alert_to_viewers("*click*") - playsound(src, dry_fire_sound, 30, TRUE) + playsound(src, dry_fire_sound, dry_fire_sound_volume, TRUE) /obj/item/gun/proc/fire_sounds() if(suppressed) diff --git a/code/modules/projectiles/guns/energy/recharge.dm b/code/modules/projectiles/guns/energy/recharge.dm index 6644accd8a5..eed27478755 100644 --- a/code/modules/projectiles/guns/energy/recharge.dm +++ b/code/modules/projectiles/guns/energy/recharge.dm @@ -135,3 +135,36 @@ custom_materials = list(/datum/material/iron=SHEET_MATERIAL_AMOUNT*2) suppressed = null ammo_type = list(/obj/item/ammo_casing/energy/bolt/large) + +/// A silly gun that does literally zero damage, but disrupts electrical sources of light, like flashlights. +/obj/item/gun/energy/recharge/fisher + name = "\improper SC/FISHER disruptor" + desc = "A self-recharging, permanently suppressed, and very haphazardly modified accelerator handgun that does literally nothing to anything except light fixtures and cameras. \ + Can fire twice before requiring a recharge, with bolts passing through machinery, but demands precision." + icon_state = "fisher" + base_icon_state = "fisher" + dry_fire_sound_volume = 10 + w_class = WEIGHT_CLASS_SMALL + holds_charge = TRUE + suppressed = TRUE + recharge_time = 1.2 SECONDS + ammo_type = list(/obj/item/ammo_casing/energy/fisher) + +/obj/item/gun/energy/recharge/fisher/examine_more(mob/user) + . = ..() + . += span_notice("The SC/FISHER is an illegally-modified kinetic accelerator cut down and refit into a disassembled miniature energy gun chassis, with its pressure chamber \ + attenuated to launch kinetic bolts that disrupt flashlights and cameras, if only temporarily. This effect also works on cyborg headlamps, and works longer in melee.

\ + While some would argue that this is a really terrible design choice, others argue that it is very funny to be able to shoot at light sources. Caveat emptor.") + +/obj/item/gun/energy/recharge/fisher/afterattack(atom/target, mob/living/user, flag, params) + // you should just shoot them, but in case you can't/wont + . = ..() + if(user.Adjacent(target)) + var/obj/projectile/energy/fisher/melee/simulated_hit = new + simulated_hit.on_hit(target) + +/obj/item/gun/energy/recharge/fisher/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) + // ...you reeeeeally just shoot them, but in case you can't/won't + . = ..() + var/obj/projectile/energy/fisher/melee/simulated_hit = new + simulated_hit.on_hit(hit_atom) diff --git a/code/modules/projectiles/projectile/special/lightbreaker.dm b/code/modules/projectiles/projectile/special/lightbreaker.dm new file mode 100644 index 00000000000..cf273a1d3b2 --- /dev/null +++ b/code/modules/projectiles/projectile/special/lightbreaker.dm @@ -0,0 +1,34 @@ +/obj/projectile/energy/fisher + name = "attenuated kinetic force" + alpha = 0 + damage = 0 + damage_type = BRUTE + armor_flag = BOMB + range = 14 + projectile_phasing = PASSTABLE | PASSMOB | PASSMACHINE | PASSSTRUCTURE + hitscan = TRUE + var/disrupt_duration = 10 SECONDS + +/obj/projectile/energy/fisher/on_hit(atom/target, blocked, pierce_hit) + . = ..() + SEND_SIGNAL(target, COMSIG_HIT_BY_SABOTEUR, disrupt_duration) + if(!isliving(target)) + return + var/list/things_to_disrupt = list() + var/lights_flickered = 0 + if(ishuman(target)) + var/mob/living/carbon/human/human_target = target + things_to_disrupt = human_target.get_all_gear() + else + var/mob/living/living_target = target // i guess this covers borgs too? + things_to_disrupt = living_target.get_equipped_items(include_pockets = TRUE, include_accessories = TRUE) + for(var/obj/item/thingy as anything in things_to_disrupt) + if(SEND_SIGNAL(thingy, COMSIG_HIT_BY_SABOTEUR, disrupt_duration)) + lights_flickered++ + if(lights_flickered) + to_chat(target, span_warning("Your light [lights_flickered > 1 ? "sources flick" : "source flicks"] off.")) + +/obj/projectile/energy/fisher/melee + range = 1 + suppressed = SUPPRESSED_VERY + disrupt_duration = 20 SECONDS diff --git a/icons/obj/weapons/guns/energy.dmi b/icons/obj/weapons/guns/energy.dmi index 07ac342a36d76c6099fe9871c5bd0d231a5da553..97b75335b91a0e1a8cdc5b1d6302999111abba7d 100644 GIT binary patch delta 8484 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 diff --git a/modular_skyrat/modules/cell_component/code/flashlight.dm b/modular_skyrat/modules/cell_component/code/flashlight.dm index 01de50266e3..6e585781a83 100644 --- a/modular_skyrat/modules/cell_component/code/flashlight.dm +++ b/modular_skyrat/modules/cell_component/code/flashlight.dm @@ -18,13 +18,10 @@ /obj/item/flashlight/Initialize(mapload) . = ..() - if(icon_state == "[initial(icon_state)]-on") - turn_on(FALSE) - update_brightness() - register_context() + update_item_action_buttons() if(uses_battery) - AddComponent(/datum/component/cell, cell_override, CALLBACK(src, PROC_REF(turn_off)), _has_cell_overlays = FALSE) + AddComponent(/datum/component/cell, cell_override, CALLBACK(src, PROC_REF(quietly_turn_off)), _has_cell_overlays = FALSE) /obj/item/flashlight/examine(mob/user) . = ..() @@ -55,46 +52,37 @@ set_light_power(initial(light_power)) to_chat(user, span_notice("You set [src] to low.")) -/obj/item/flashlight/proc/toggle_light() +/obj/item/flashlight/toggle_light(noisy = TRUE) + . = ..() if(on) - turn_off() - else + after_turn_on() if(uses_battery && !(item_use_power(power_use_amount, TRUE) & COMPONENT_POWER_SUCCESS)) return - turn_on(makes_noise_when_lit) - playsound(src, on ? sound_on : sound_off, 40, TRUE) - return TRUE - -/obj/item/flashlight/attack_self(mob/user) - . = ..() - toggle_light() + if(noisy) + playsound(src, on ? sound_on : sound_off, 40, TRUE) /** * Handles turning on the flashlight. * Parameters: * * noisy - Boolean on whether the flashlight should make an additional noise from being turned on or not. Defaults to TRUE. */ -/obj/item/flashlight/proc/turn_on(noisy = TRUE) - on = TRUE - if (uses_battery) +/obj/item/flashlight/proc/after_turn_on(noisy = TRUE) + if(uses_battery) START_PROCESSING(SSobj, src) - update_brightness() if(noisy) playsound(src, 'modular_skyrat/master_files/sound/effects/flashlight.ogg', 40, TRUE) //Credits to ERIS for the sound - update_item_action_buttons() -/// Handles turning off the flashlight. -/obj/item/flashlight/proc/turn_off() - on = FALSE - update_brightness() - update_item_action_buttons() +/// Quietly turns the flashlight off if it was on (called by the battery running out of charge). +/obj/item/flashlight/proc/quietly_turn_off() + if(on) + toggle_light(noisy = FALSE) /obj/item/flashlight/process(seconds_per_tick) if(!on) STOP_PROCESSING(SSobj, src) return if(uses_battery && !(item_use_power(power_use_amount) & COMPONENT_POWER_SUCCESS)) - turn_off() + quietly_turn_off() /obj/item/flashlight/update_icon_state() . = ..() diff --git a/tgstation.dme b/tgstation.dme index 194d81879f0..d1c22afce1e 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -319,6 +319,7 @@ #include "code\__DEFINES\dcs\signals\signals_radiation.dm" #include "code\__DEFINES\dcs\signals\signals_reagent.dm" #include "code\__DEFINES\dcs\signals\signals_restaurant.dm" +#include "code\__DEFINES\dcs\signals\signals_saboteur.dm" #include "code\__DEFINES\dcs\signals\signals_scangate.dm" #include "code\__DEFINES\dcs\signals\signals_screentips.dm" #include "code\__DEFINES\dcs\signals\signals_spatial_grid.dm" @@ -4991,6 +4992,7 @@ #include "code\modules\projectiles\projectile\special\floral.dm" #include "code\modules\projectiles\projectile\special\gravity.dm" #include "code\modules\projectiles\projectile\special\ion.dm" +#include "code\modules\projectiles\projectile\special\lightbreaker.dm" #include "code\modules\projectiles\projectile\special\meteor.dm" #include "code\modules\projectiles\projectile\special\mindflayer.dm" #include "code\modules\projectiles\projectile\special\neurotoxin.dm"