diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index f50ee3821cc..3602de769e1 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -15189,6 +15189,7 @@ cycle_id = "sci-entrance" }, /obj/structure/disposalpipe/segment, +/obj/machinery/scanner_gate/preset_guns, /turf/open/floor/iron/textured_half, /area/station/security/brig/entrance) "fKx" = ( @@ -30896,6 +30897,7 @@ cycle_id = "sci-entrance" }, /obj/structure/disposalpipe/segment, +/obj/machinery/scanner_gate/preset_guns, /turf/open/floor/iron/textured_half, /area/station/security/brig/entrance) "kKD" = ( diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 8a25706a1f7..18116748bcc 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -50664,6 +50664,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/scanner_gate/preset_guns, /turf/open/floor/iron/dark, /area/station/security/brig) "mEH" = ( @@ -80365,6 +80366,7 @@ dir = 4 }, /obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/scanner_gate/preset_guns, /turf/open/floor/iron/dark, /area/station/security/brig) "ucA" = ( diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index e29c029d8d9..ef84443ce31 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -15783,6 +15783,7 @@ cycle_id = "brigoutpost" }, /obj/effect/mapping_helpers/airlock/access/all/security/entrance, +/obj/machinery/scanner_gate/preset_guns, /turf/open/floor/iron/dark/textured_edge{ dir = 8 }, @@ -18827,6 +18828,7 @@ cycle_id = "brigoutpost" }, /obj/effect/mapping_helpers/airlock/access/all/security/entrance, +/obj/machinery/scanner_gate/preset_guns, /turf/open/floor/iron/dark/textured_edge{ dir = 4 }, diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 9fd7c6aac01..b0f6d7f0690 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -15270,6 +15270,7 @@ cycle_id = "brig-entrance" }, /obj/effect/mapping_helpers/airlock/access/all/security/entrance, +/obj/machinery/scanner_gate/preset_guns, /turf/open/floor/iron, /area/station/security/brig) "frZ" = ( @@ -16178,6 +16179,7 @@ cycle_id = "brig-entrance" }, /obj/effect/mapping_helpers/airlock/access/all/security/entrance, +/obj/machinery/scanner_gate/preset_guns, /turf/open/floor/iron, /area/station/security/brig) "fMf" = ( diff --git a/_maps/map_files/NorthStar/north_star.dmm b/_maps/map_files/NorthStar/north_star.dmm index 081edcaf677..8d7a99da8e7 100644 --- a/_maps/map_files/NorthStar/north_star.dmm +++ b/_maps/map_files/NorthStar/north_star.dmm @@ -10210,6 +10210,7 @@ /obj/structure/disposalpipe/segment, /obj/effect/turf_decal/tile/red/fourcorners, /obj/effect/mapping_helpers/airlock/access/all/security/general, +/obj/machinery/scanner_gate/preset_guns, /turf/open/floor/iron/dark, /area/station/security/checkpoint) "cBq" = ( @@ -29793,6 +29794,7 @@ }, /obj/structure/disposalpipe/segment, /obj/effect/mapping_helpers/airlock/access/all/security/entrance, +/obj/machinery/scanner_gate/preset_guns, /turf/open/floor/iron/dark, /area/station/security/brig) "hLP" = ( @@ -35063,6 +35065,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/cable, /obj/effect/mapping_helpers/airlock/access/all/security/entrance, +/obj/machinery/scanner_gate/preset_guns, /turf/open/floor/iron/dark, /area/station/security/brig) "jfs" = ( @@ -55322,6 +55325,7 @@ /obj/effect/turf_decal/tile/red/fourcorners, /obj/effect/mapping_helpers/airlock/access/all/security/general, /obj/structure/disposalpipe/segment, +/obj/machinery/scanner_gate/preset_guns, /turf/open/floor/iron/dark, /area/station/security/checkpoint) "ojM" = ( diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index efc6e69075a..4be002dfd2d 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -32278,6 +32278,7 @@ }, /obj/machinery/door/firedoor, /obj/effect/mapping_helpers/airlock/access/all/security/entrance, +/obj/machinery/scanner_gate/preset_guns, /turf/open/floor/iron, /area/station/security/brig) "kul" = ( @@ -47384,6 +47385,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/landmark/navigate_destination/sec, +/obj/machinery/scanner_gate/preset_guns, /turf/open/floor/iron, /area/station/security/brig) "pLs" = ( @@ -53602,6 +53604,7 @@ }, /obj/machinery/door/firedoor, /obj/effect/mapping_helpers/airlock/access/all/security/entrance, +/obj/machinery/scanner_gate/preset_guns, /turf/open/floor/iron, /area/station/security/brig) "rUe" = ( @@ -66155,6 +66158,7 @@ /obj/machinery/door/firedoor, /obj/effect/mapping_helpers/airlock/access/all/security/entrance, /obj/structure/disposalpipe/segment, +/obj/machinery/scanner_gate/preset_guns, /turf/open/floor/iron, /area/station/security/brig) "wiU" = ( diff --git a/_maps/map_files/wawastation/wawastation.dmm b/_maps/map_files/wawastation/wawastation.dmm index 17a558b4f5e..fbeea130c8b 100644 --- a/_maps/map_files/wawastation/wawastation.dmm +++ b/_maps/map_files/wawastation/wawastation.dmm @@ -2419,6 +2419,7 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/scanner_gate/preset_guns, /turf/open/floor/iron, /area/station/security/brig/entrance) "aNR" = ( @@ -39733,6 +39734,7 @@ /obj/machinery/door/firedoor, /obj/effect/mapping_helpers/airlock/access/all/security/entrance, /obj/structure/disposalpipe/segment, +/obj/machinery/scanner_gate/preset_guns, /turf/open/floor/iron, /area/station/security/brig/entrance) "odG" = ( diff --git a/code/game/machinery/scanner_gate.dm b/code/game/machinery/scanner_gate.dm index 860a5b1bc05..04fcbe55dbd 100644 --- a/code/game/machinery/scanner_gate.dm +++ b/code/game/machinery/scanner_gate.dm @@ -23,11 +23,11 @@ desc = "A gate able to perform mid-depth scans on any organisms who pass under it." icon = 'icons/obj/machines/scangate.dmi' icon_state = "scangate" + layer = ABOVE_MOB_LAYER circuit = /obj/item/circuitboard/machine/scanner_gate + COOLDOWN_DECLARE(next_beep) var/scanline_timer - ///Internal timer to prevent audio spam. - var/next_beep = 0 ///Bool to check if the scanner's controls are locked by an ID. var/locked = FALSE ///Which setting is the scanner checking for? See defines in scanner_gate.dm for the list. @@ -46,6 +46,10 @@ var/light_fail = FALSE ///Does the scanner ignore light_pass and light_fail for sending signals? var/ignore_signals = FALSE + ///Modifier to the chance of scanner being false positive/negative + var/minus_false_beep = 0 + ///Base false positive/negative chance + var/base_false_beep = 5 ///Is an n-spect scanner attached to the gate? Enables contraband scanning. var/obj/item/inspector/n_spect = null @@ -60,6 +64,11 @@ AddElement(/datum/element/connect_loc, loc_connections) register_context() +/obj/machinery/scanner_gate/RefreshParts() + . = ..() + for(var/datum/stock_part/scanning_module/scanning_module in component_parts) + minus_false_beep = scanning_module.tier //The better are scanninning modules - the lower is chance of False Positives + /obj/machinery/scanner_gate/Destroy() qdel(wires) set_wires(null) @@ -73,6 +82,8 @@ /obj/machinery/scanner_gate/examine(mob/user) . = ..() + + . += span_notice("It's set to scan for [span_boldnotice(scangate_mode)].") if(locked) . += span_notice("The control panel is ID-locked. Swipe a valid ID to unlock it.") else @@ -143,6 +154,10 @@ /obj/machinery/scanner_gate/crowbar_act(mob/living/user, obj/item/tool) . = ..() if(n_spect) + if(locked) + balloon_alert(user, "locked!") + return ITEM_INTERACT_BLOCKING + to_chat(user, span_notice("You uninstall [n_spect] from [src].")) n_spect.forceMove(drop_location()) return ITEM_INTERACT_SUCCESS @@ -166,20 +181,24 @@ /obj/machinery/scanner_gate/proc/perform_scan(mob/living/M) var/beep = FALSE var/color = null + var/detected_thing = null switch(scangate_mode) if(SCANGATE_NONE) return if(SCANGATE_WANTED) if(ishuman(M)) + detected_thing = "Warrant" var/mob/living/carbon/human/H = M var/perpname = H.get_face_name(H.get_id_name()) var/datum/record/crew/target = find_record(perpname) if(!target || (target.wanted_status == WANTED_ARREST)) beep = TRUE if(SCANGATE_MINDSHIELD) + detected_thing = "Mindshield" if(HAS_TRAIT(M, TRAIT_MINDSHIELD)) beep = TRUE if(SCANGATE_DISEASE) + detected_thing = "[disease_threshold] infection" if(iscarbon(M)) var/mob/living/carbon/C = M if(get_disease_severity_value(C.check_virus()) >= get_disease_severity_value(disease_threshold)) @@ -190,30 +209,41 @@ var/datum/species/scan_species = /datum/species/human switch(detect_species) if(SCANGATE_LIZARD) + detected_thing = "Lizardperson" scan_species = /datum/species/lizard if(SCANGATE_FLY) + detected_thing = "Flyperson" scan_species = /datum/species/fly if(SCANGATE_FELINID) + detected_thing = "Felinid" scan_species = /datum/species/human/felinid if(SCANGATE_PLASMAMAN) + detected_thing = "Plasmaman" scan_species = /datum/species/plasmaman if(SCANGATE_MOTH) + detected_thing = "Mothperson" scan_species = /datum/species/moth if(SCANGATE_JELLY) + detected_thing = "Jellyperson" scan_species = /datum/species/jelly if(SCANGATE_POD) + detected_thing = "Podperson" scan_species = /datum/species/pod if(SCANGATE_GOLEM) + detected_thing = "Golem" scan_species = /datum/species/golem if(SCANGATE_ZOMBIE) + detected_thing = "Zombie" scan_species = /datum/species/zombie if(is_species(H, scan_species)) beep = TRUE if(detect_species == SCANGATE_ZOMBIE) //Can detect dormant zombies + detected_thing = "Romerol infection" if(H.get_organ_slot(ORGAN_SLOT_ZOMBIE)) beep = TRUE if(SCANGATE_GUNS) for(var/I in M.get_contents()) + detected_thing = "Weapons" if(isgun(I)) beep = TRUE break @@ -222,10 +252,13 @@ var/mob/living/carbon/human/H = M if(H.nutrition <= detect_nutrition && detect_nutrition == NUTRITION_LEVEL_STARVING) beep = TRUE + detected_thing = "Starvation" if(H.nutrition >= detect_nutrition && detect_nutrition == NUTRITION_LEVEL_FAT) beep = TRUE + detected_thing = "Obesity" if(SCANGATE_CONTRABAND) for(var/obj/item/content in M.get_all_contents_skipping_traits(TRAIT_CONTRABAND_BLOCKER)) + detected_thing = "Contraband" if(content.is_contraband()) beep = TRUE break @@ -234,8 +267,12 @@ if(reverse) beep = !beep + + if(prob(base_false_beep - minus_false_beep)) //False positive/negative + beep = prob(50) + if(beep) - alarm_beep() + alarm_beep(detected_thing) SEND_SIGNAL(src, COMSIG_SCANGATE_PASS_TRIGGER, M) if(!ignore_signals) color = wires.get_color_of_wire(WIRE_ACCEPT) @@ -251,12 +288,15 @@ use_energy(active_power_usage) -/obj/machinery/scanner_gate/proc/alarm_beep() - if(next_beep <= world.time) - next_beep = world.time + (2 SECONDS) - playsound(src, 'sound/machines/scanbuzz.ogg', 100, FALSE) - var/mutable_appearance/alarm_display = mutable_appearance(icon, "alarm_light") - flick_overlay_view(alarm_display, 2 SECONDS) +/obj/machinery/scanner_gate/proc/alarm_beep(detected_thing) + if(!COOLDOWN_FINISHED(src, next_beep)) + return + + if(detected_thing) + say("[detected_thing][reverse ? " not " : " "]detected!!") + + COOLDOWN_START(src, next_beep, 2 SECONDS) + playsound(src, 'sound/machines/scanbuzz.ogg', 100, FALSE) set_scanline("alarm", 2 SECONDS) /obj/machinery/scanner_gate/can_interact(mob/user) @@ -321,6 +361,11 @@ detect_nutrition = NUTRITION_LEVEL_FAT . = TRUE +/obj/machinery/scanner_gate/preset_guns + locked = TRUE + req_access = ACCESS_SECURITY + scangate_mode = SCANGATE_GUNS + #undef SCANGATE_NONE #undef SCANGATE_MINDSHIELD #undef SCANGATE_DISEASE diff --git a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm index f4168b7b377..96206b800e3 100644 --- a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm @@ -329,7 +329,7 @@ /obj/item/circuitboard/machine/scanner_gate name = "Scanner Gate" - greyscale_colors = CIRCUIT_COLOR_ENGINEERING + greyscale_colors = CIRCUIT_COLOR_SECURITY build_path = /obj/machinery/scanner_gate req_components = list( /datum/stock_part/scanning_module = 3) diff --git a/code/game/objects/items/inspector.dm b/code/game/objects/items/inspector.dm index b73917bfba8..e7546d4c1d9 100644 --- a/code/game/objects/items/inspector.dm +++ b/code/game/objects/items/inspector.dm @@ -8,7 +8,7 @@ */ /obj/item/inspector name = "\improper N-spect scanner" - desc = "Central Command standard issue inspection device. Can perform either wide area scans that central command can use to verify the security of the station, or detailed scans to determine if an item is contraband." + desc = "Central Command standard issue inspection device. Can perform either wide area scans that central command can use to verify the security of the station, or detailed scan. Can scan people for contraband on their person or items being contraband." icon = 'icons/obj/devices/scanner.dmi' icon_state = "inspector" worn_icon_state = "salestagger" @@ -20,6 +20,7 @@ interaction_flags_click = NEED_DEXTERITY throw_range = 1 throw_speed = 1 + COOLDOWN_DECLARE(scanning_person) //Cooldown for scanning a carbon ///How long it takes to print on time each mode, ordered NORMAL, FAST, HONK var/list/time_list = list(5 SECONDS, 1 SECONDS, 0.1 SECONDS) ///Which print time mode we're on. @@ -106,18 +107,28 @@ if(!cell || !cell.use(INSPECTOR_ENERGY_USAGE_LOW)) balloon_alert(user, "check cell!") return ITEM_INTERACT_BLOCKING - if(!isitem(interacting_with)) - return ITEM_INTERACT_BLOCKING - var/obj/item/contraband_item = interacting_with - var/contraband_status = contraband_item.is_contraband() - if((!contraband_status && scans_correctly) || (contraband_status && !scans_correctly)) + + if(iscarbon(interacting_with)) //Prevents insta scanning people + if(!COOLDOWN_FINISHED(src, scanning_person)) + return ITEM_INTERACT_BLOCKING + + visible_message(span_warning("[user] starts scanning [interacting_with] with [src]")) + to_chat(interacting_with, span_userdanger("[user] is trying to scan you for contraband!")) + balloon_alert_to_viewers("scanning...") + playsound(src, 'sound/effects/genetics.ogg', 40, FALSE) + COOLDOWN_START(src, scanning_person, 4 SECONDS) + if(!do_after(user, 4 SECONDS, interacting_with)) + return ITEM_INTERACT_BLOCKING + + if(contraband_scan(interacting_with, user)) + playsound(src, 'sound/machines/uplinkerror.ogg', 40) + balloon_alert(user, "contraband detected!") + return ITEM_INTERACT_SUCCESS + else playsound(src, 'sound/machines/ping.ogg', 20) balloon_alert(user, "clear") return ITEM_INTERACT_SUCCESS - playsound(src, 'sound/machines/uplinkerror.ogg', 40) - balloon_alert(user, "contraband detected!") - return ITEM_INTERACT_SUCCESS /obj/item/inspector/add_context(atom/source, list/context, obj/item/held_item, mob/user) var/update_context = FALSE @@ -145,6 +156,29 @@ return CONTEXTUAL_SCREENTIP_SET return NONE +/** + * Scans the carbon or item for contraband. + * + * Arguments: + * - scanned - what or who is scanned? + * - user - who is performing the scanning? + */ +/obj/item/inspector/proc/contraband_scan(scanned, user) + if(iscarbon(scanned)) + var/mob/living/carbon/scanned_carbon = scanned + for(var/obj/item/content in scanned_carbon.get_all_contents_skipping_traits(TRAIT_CONTRABAND_BLOCKER)) + var/contraband_content = content.is_contraband() + if((contraband_content && scans_correctly) || (!contraband_content && !scans_correctly)) + return TRUE + + if(isitem(scanned)) + var/obj/item/contraband_item = scanned + var/contraband_status = contraband_item.is_contraband() + if((contraband_status && scans_correctly) || (!contraband_status && !scans_correctly)) + return TRUE + + return FALSE + /** * Create our report * diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index 77ca77e8ba0..a88da6537b6 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -377,7 +377,7 @@ /obj/item/storage/backpack/satchel/flat name = "smuggler's satchel" - desc = "A very slim satchel that can easily fit into tight spaces." + desc = "A very slim satchel that can easily fit into tight spaces. Its contents cannot be detected by contraband scanners." icon_state = "satchel-flat" inhand_icon_state = "satchel-flat" w_class = WEIGHT_CLASS_NORMAL //Can fit in backpacks itself. diff --git a/code/modules/cargo/markets/market_items/misc.dm b/code/modules/cargo/markets/market_items/misc.dm index 6e61bf87f0c..b0ea8948580 100644 --- a/code/modules/cargo/markets/market_items/misc.dm +++ b/code/modules/cargo/markets/market_items/misc.dm @@ -90,7 +90,7 @@ /datum/market_item/misc/smugglers_satchel name = "Smuggler's Satchel" - desc = "This easily hidden satchel can become a versatile tool to anybody with the desire to keep certain items out of sight and out of mind." + desc = "This easily hidden satchel can become a versatile tool to anybody with the desire to keep certain items out of sight and out of mind. Its contents cannot be detected by contraband scanners." item = /obj/item/storage/backpack/satchel/flat/empty price_min = CARGO_CRATE_VALUE * 3.75 diff --git a/code/modules/uplink/uplink_items/stealthy_tools.dm b/code/modules/uplink/uplink_items/stealthy_tools.dm index 48c25e638de..40e5df8febd 100644 --- a/code/modules/uplink/uplink_items/stealthy_tools.dm +++ b/code/modules/uplink/uplink_items/stealthy_tools.dm @@ -87,7 +87,7 @@ /datum/uplink_item/stealthy_tools/smugglersatchel name = "Smuggler's Satchel" desc = "This satchel is thin enough to be hidden in the gap between plating and tiling; great for stashing \ - your stolen goods. Comes with a crowbar, a floor tile and some contraband inside." + your stolen goods. Comes with a crowbar, a floor tile and some contraband inside. Its contents cannot be detected by contraband scanners." item = /obj/item/storage/backpack/satchel/flat/with_tools cost = 1 surplus = 30 diff --git a/icons/obj/machines/scangate.dmi b/icons/obj/machines/scangate.dmi index 6af8750414a..9dacefab353 100644 Binary files a/icons/obj/machines/scangate.dmi and b/icons/obj/machines/scangate.dmi differ