From 55731d405e793b57c6ef01c6a909d84f37487901 Mon Sep 17 00:00:00 2001 From: Alan Date: Fri, 17 Jul 2026 02:31:24 -0400 Subject: [PATCH] Tweak flashlight messages and migrate to the new attack chain. (#32193) * Tweak flashlight messages and migrate to the new attack chain. * Call parent proc in activate_self() procs. * Return ITEM_INTERACT_COMPLETE after eye check, add mob check to eye check. * Apply some suggestions from CRUNCH review Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com> Signed-off-by: Alan * Apply other suggestions from CRUNCH review. Add CRUNCH flair. * Apply additional suggestion from CRUNCH review. Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com> Signed-off-by: Alan * Apply suggestions from code review Co-authored-by: 1080pCat <96908085+1080pCat@users.noreply.github.com> Signed-off-by: Alan * Update other aperture message. * Add fingerprints. --------- Signed-off-by: Alan Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com> Co-authored-by: 1080pCat <96908085+1080pCat@users.noreply.github.com> Co-authored-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com> --- code/game/objects/items/devices/flashlight.dm | 195 ++++++++++++------ 1 file changed, 129 insertions(+), 66 deletions(-) diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 3af6b44fac7..3a0363af03f 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -11,8 +11,10 @@ actions_types = list(/datum/action/item_action/toggle_light) light_color = "#ffffd0" var/on = FALSE - var/brightness_on = 4 //luminosity when on + /// Luminosity when turned on. + var/brightness_on = 4 var/togglesound = 'sound/weapons/empty.ogg' + new_attack_chain = TRUE /obj/item/flashlight/Initialize(mapload) . = ..() @@ -31,56 +33,111 @@ set_light(0) update_icon() -/obj/item/flashlight/attack_self__legacy__attackchain(mob/user) +/obj/item/flashlight/activate_self(mob/user) + if(..()) + return ITEM_INTERACT_COMPLETE if(!isturf(user.loc)) - to_chat(user, "You cannot turn the light on while in this [user.loc].")//To prevent some lighting anomalities. - return FALSE + to_chat(user, "You cannot toggle [src] while obscured by [user.loc].") // To prevent some lighting anomalities. + return ITEM_INTERACT_COMPLETE on = !on playsound(user, togglesound, 100, 1) update_brightness() update_action_buttons() - return TRUE - -/obj/item/flashlight/attack__legacy__attackchain(mob/living/M as mob, mob/living/user as mob) add_fingerprint(user) - if(on && user.zone_selected == "eyes") + return ITEM_INTERACT_COMPLETE - if((HAS_TRAIT(user, TRAIT_CLUMSY) || user.getBrainLoss() >= 60) && prob(50)) //too dumb to use flashlight properly - return ..() //just hit them in the head +/obj/item/flashlight/interact_with_atom(atom/target, mob/living/user, list/modifiers) + add_fingerprint(user) + if(istype(target, /obj/structure/ai_core/deactivated)) + to_chat(user, SPAN_NOTICE("You can already tell there's no AI in this core, but you shine [src] at it anyway. It doesn't respond.")) + add_fingerprint(user) + return ITEM_INTERACT_COMPLETE - if(!(ishuman(user) || SSticker) && SSticker.mode.name != "monkey") //don't have dexterity - to_chat(user, SPAN_NOTICE("You don't have the dexterity to do this!")) - return - - var/mob/living/carbon/human/H = M //mob has protective eyewear - if(istype(H) && ((H.head && H.head.flags_cover & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) || (H.glasses && H.glasses.flags_cover & GLASSESCOVERSEYES))) - to_chat(user, SPAN_NOTICE("You're going to need to remove that [(H.head && H.head.flags_cover & HEADCOVERSEYES) ? "helmet" : (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) ? "mask" : "glasses"] first.")) - return - - if(M == user) //they're using it on themselves - if(M.flash_eyes(visual = 1)) - M.visible_message(SPAN_NOTICE("[M] directs [src] to [M.p_their()] eyes."), \ - SPAN_NOTICE("You wave the light in front of your eyes! Trippy!")) - else - M.visible_message(SPAN_NOTICE("[M] directs [src] to [M.p_their()] eyes."), \ - SPAN_NOTICE("You wave the light in front of your eyes.")) - else - - user.visible_message(SPAN_NOTICE("[user] directs [src] to [M]'s eyes."), \ - SPAN_NOTICE("You direct [src] to [M]'s eyes.")) - - if(istype(H)) //robots and aliens are unaffected - var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes) - if(M.stat == DEAD || !eyes || HAS_TRAIT(M, TRAIT_BLIND)) //mob is dead or fully blind - to_chat(user, SPAN_NOTICE("[M]'s pupils are unresponsive to the light!")) - else if(HAS_TRAIT(M, TRAIT_XRAY_VISION) || eyes.see_in_dark >= 8) //The mob's either got the X-RAY vision or has a tapetum lucidum (extreme nightvision, i.e. Vulp/Tajara with COLOURBLIND & their monkey forms). - to_chat(user, SPAN_NOTICE("[M]'s pupils glow eerily!")) - else //they're okay! - if(M.flash_eyes(visual = 1)) - to_chat(user, SPAN_NOTICE("[M]'s pupils narrow.")) - else + if(!ismob(target)) return ..() + if(!(on && user.zone_selected == "eyes")) + return ..() + + if((HAS_TRAIT(user, TRAIT_CLUMSY) || user.getBrainLoss() >= 60) && prob(50)) // Too dumb to use flashlight properly. + return ..() // Just hit them in the head. + + if(!(ishuman(user) || SSticker) && SSticker.mode.name != "monkey") // Don't have necessary dexterity. + to_chat(user, SPAN_NOTICE("You don't have the dexterity to do this!")) + return ITEM_INTERACT_COMPLETE + + var/mob/living/carbon/human/human_target = target + if(istype(human_target) && \ + ((human_target.head && human_target.head.flags_cover & HEADCOVERSEYES) || \ + (human_target.wear_mask && human_target.wear_mask.flags_cover & MASKCOVERSEYES) || \ + (human_target.glasses && human_target.glasses.flags_cover & GLASSESCOVERSEYES))) + // Mob has protective eyewear. + var/blocking_target = "glasses" + if(human_target.wear_mask && human_target.wear_mask.flags_cover & MASKCOVERSEYES) + blocking_target = "mask" + if(human_target.head && human_target.head.flags_cover & HEADCOVERSEYES) + blocking_target = "helmet" + to_chat(user, SPAN_NOTICE("You're going to need to remove the [blocking_target] first.")) + return ITEM_INTERACT_COMPLETE + + if(target == user) // They're using it on themselves. + if(human_target.flash_eyes(visual = TRUE)) + target.visible_message(SPAN_NOTICE("[target] directs [src] to [target.p_their()] eyes."), + SPAN_NOTICE("You wave the light in front of your eyes! Trippy!")) + else + target.visible_message(SPAN_NOTICE("[target] directs [src] to [target.p_their()] eyes."), + SPAN_NOTICE("You wave the light in front of your eyes.")) + add_fingerprint(user) + return ITEM_INTERACT_COMPLETE + + user.visible_message(SPAN_NOTICE("[user] directs [src] to [target]'s eyes."), + SPAN_NOTICE("You direct [src] to [target]'s eyes.")) + + if(issilicon(target)) + var/mob/living/silicon/robot/silicon_target = target + var/datum/robot_component/camera/camera + add_fingerprint(user) + if(isrobot(target)) + camera = silicon_target.get_component("camera") + if(!camera) + to_chat(user, SPAN_WARNING("[target]'s camera is missing!")) + return ITEM_INTERACT_COMPLETE + if(silicon_target.stat == DEAD || (camera && camera.component_disabled)) + to_chat(user, SPAN_WARNING("[target]'s camera doesn't respond to the light!")) + return ITEM_INTERACT_COMPLETE + to_chat(user, SPAN_NOTICE("[target]'s camera aperture makes a series of clicks as it adjusts to the light.")) + return ITEM_INTERACT_COMPLETE + + if(!istype(human_target)) // Aliens are unaffected. + return ITEM_INTERACT_COMPLETE + + if(!human_target.bodyparts_by_name["head"]) + to_chat(user, SPAN_WARNING("You can't find [target]'s [ismachineperson(target) ? "camera" : "eyes"] because they have no head!")) + return ITEM_INTERACT_COMPLETE + + add_fingerprint(user) + var/obj/item/organ/internal/eyes/eyes = human_target.get_int_organ(/obj/item/organ/internal/eyes) + if(!eyes) + to_chat(user, SPAN_WARNING("[target] has no [ismachineperson(target) ? "camera" : "eyes"]!")) + return ITEM_INTERACT_COMPLETE + + if(human_target.stat == DEAD || HAS_TRAIT(human_target, TRAIT_BLIND)) // Target is dead or fully blind. + to_chat(user, SPAN_NOTICE("[target]'s [ismachineperson(target) ? "camera doesn't" : "pupils don't"] respond to the light!")) + return ITEM_INTERACT_COMPLETE + + if(HAS_TRAIT(target, TRAIT_XRAY_VISION) || eyes.see_in_dark >= 3) + // Target has X-RAY vision or has a tapetum lucidum. + // (extreme nightvision, i.e. Vulp/Tajara with COLOURBLIND & their monkey forms) + if(ismachineperson(target)) + to_chat(user, SPAN_NOTICE("[target]'s camera lens reflects the light eerily!")) + else + to_chat(user, SPAN_NOTICE("[target]'s pupils glow eerily!")) + return ITEM_INTERACT_COMPLETE + + if(human_target.flash_eyes(visual = TRUE)) + to_chat(user, SPAN_NOTICE("[target]'s [ismachineperson(target) ? "camera aperture narrows" : "pupils narrow"].")) + return ITEM_INTERACT_COMPLETE + /obj/item/flashlight/extinguish_light(force = FALSE) if(on) on = FALSE @@ -143,7 +200,7 @@ if(user.stat || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED) || !Adjacent(user)) return - attack_self__legacy__attackchain(user) + activate_self(user) //Bananalamp /obj/item/flashlight/lamp/bananalamp @@ -205,18 +262,17 @@ attack_verb = list() update_brightness() -/obj/item/flashlight/flare/attack_self__legacy__attackchain(mob/user) +/obj/item/flashlight/flare/activate_self(mob/user) // Usual checks if(!fuel) - to_chat(user, SPAN_NOTICE("[src] is out of fuel.")) - return + to_chat(user, SPAN_WARNING("[src] is already burnt out!")) + return ITEM_INTERACT_COMPLETE if(on) - to_chat(user, SPAN_NOTICE("[src] is already on.")) - return + to_chat(user, SPAN_WARNING("[src] is already lit!")) + return ITEM_INTERACT_COMPLETE - . = ..() // All good, turn it on. - if(.) + if(..()) user.visible_message(SPAN_NOTICE("[user] activates [src]."), SPAN_NOTICE("You activate [src].")) if(produce_heat) force = on_damage @@ -224,6 +280,7 @@ hitsound = 'sound/items/welder.ogg' attack_verb = list("burnt", "singed") START_PROCESSING(SSobj, src) + return ITEM_INTERACT_COMPLETE /obj/item/flashlight/flare/used fuel = 0 @@ -335,7 +392,9 @@ update_brightness() icon_state = initial(icon_state) -/obj/item/flashlight/slime/attack_self__legacy__attackchain(mob/user) +/obj/item/flashlight/slime/activate_self(mob/user) + if(!user) + return ..() return //Bio-luminescence does not toggle. /obj/item/flashlight/slime/extinguish_light(force = FALSE) @@ -368,25 +427,29 @@ emp_cur_charges = min(emp_cur_charges+1, emp_max_charges) return TRUE -/obj/item/flashlight/emp/attack__legacy__attackchain(mob/living/M as mob, mob/living/user as mob) +/obj/item/flashlight/emp/interact_with_atom(atom/target, mob/living/user, list/modifiers) if(on && user.zone_selected == "eyes") // call original attack proc only if aiming at the eyes - ..() - return + return ..() -/obj/item/flashlight/emp/afterattack__legacy__attackchain(atom/A as mob|obj, mob/user, proximity) - if(!proximity) return - if(emp_cur_charges > 0) - emp_cur_charges -= 1 - A.visible_message("[user] blinks \the [src] at \the [A].", \ - "[user] blinks \the [src] at \the [A].") - if(ismob(A)) - var/mob/M = A - add_attack_logs(user, M, "Hit with EMP-light") - to_chat(user, "[src] now has [emp_cur_charges] charge\s.") - A.emp_act(EMP_HEAVY) - else +/obj/item/flashlight/emp/pre_attack(atom/target, mob/living/user, params) + if(..()) + return FINISH_ATTACK + if(emp_cur_charges <= 0) to_chat(user, SPAN_WARNING("\The [src] needs time to recharge!")) - return + return FINISH_ATTACK + +/obj/item/flashlight/emp/attack(mob/living/target, mob/living/carbon/human/user) + if(..()) + return FINISH_ATTACK + emp_cur_charges -= 1 + target.visible_message( + SPAN_DANGER("[user] blinks [src] at [target]!"), + SPAN_USERDANGER("[user] blinks [src] at you!") + ) + if(ismob(target)) + add_attack_logs(user, target, "Hit with EMP-light") + to_chat(user, SPAN_NOTICE("[src] now has [emp_cur_charges] charge\s.")) + target.emp_act(EMP_HEAVY) /// invisible lighting source /obj/item/flashlight/spotlight