diff --git a/code/__DEFINES/jamming_defines.dm b/code/__DEFINES/jamming_defines.dm index d3644e74d67f8..51fb5fb1c752e 100644 --- a/code/__DEFINES/jamming_defines.dm +++ b/code/__DEFINES/jamming_defines.dm @@ -1,8 +1,10 @@ //Radio jammer levels //They will jam any signals that have the same or lower protection value +#define JAMMER_LEVEL_NONE -1 //Jams nothing #define RADIO_JAMMER_ABDUCTOR_LEVEL 1 //Power of the abductor radio jammer #define RADIO_JAMMER_TRAITOR_LEVEL 3 //Power of the traitor radio jammer +#define RADIO_JAMMER_MAINTENANCE_LEVEL 0 // Maintenance jams some signals with minor jamming //Radio jammer protection level #define JAMMER_PROTECTION_RADIO_BASIC 0 //Basic comms channels @@ -12,3 +14,12 @@ #define JAMMER_PROTECTION_WIRELESS 1 //Wireless networking #define JAMMER_PROTECTION_AI_SHELL 2 //AI shell protection #define JAMMER_PROTECTION_SILICON_COMMS 1 //Silicon comms +#define JAMMER_PROTECTION_PDA_MESSAGE 0 //PDA messages + +// Signal jamming +/// Not jammed +#define JAM_NONE 0 +/// Some jamming effects, but not completely disabling the device +#define JAM_MINOR 1 +/// Fully jammed, cannot function +#define JAM_FULL 2 diff --git a/code/datums/components/jam_receiver.dm b/code/datums/components/jam_receiver.dm index 857f32eef59e5..97a37c4f227e4 100644 --- a/code/datums/components/jam_receiver.dm +++ b/code/datums/components/jam_receiver.dm @@ -63,7 +63,7 @@ /datum/component/jam_receiver/proc/check_jammed() var/atom/atom_parent = parent - var/new_state = atom_parent.is_jammed(intensity_resist) + var/new_state = atom_parent.is_jammed(intensity_resist) == JAM_FULL set_jammed(new_state) /datum/component/jam_receiver/proc/set_jammed(new_state) diff --git a/code/game/area/Space_Station_13_areas.dm b/code/game/area/Space_Station_13_areas.dm index 39db3eb4bdb85..d31eee7ff7f3e 100644 --- a/code/game/area/Space_Station_13_areas.dm +++ b/code/game/area/Space_Station_13_areas.dm @@ -165,7 +165,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station min_ambience_cooldown = 20 SECONDS max_ambience_cooldown = 35 SECONDS sound_environment = SOUND_AREA_TUNNEL_ENCLOSED - area_flags = BLOBS_ALLOWED | UNIQUE_AREA mood_bonus = -1 mood_message = "It's kind of cramped in here!\n" // assistants are associated with maints, jani closet is in maints, engis have to go into maints often @@ -177,6 +176,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station lights_always_start_on = TRUE color_correction = /datum/client_colour/area_color/cold_ish camera_networks = list(CAMERA_NETWORK_STATION) + area_jamming_level = RADIO_JAMMER_MAINTENANCE_LEVEL /area/maintenance/get_area_textures() return GLOB.turf_texture_maint diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 8afb44fbd6704..3fac44659aaa1 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -140,6 +140,8 @@ /// What networks should cameras in this area belong to? var/list/camera_networks = list() + var/area_jamming_level = JAMMER_LEVEL_NONE + /** * A list of teleport locations * diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 67f098cb93210..d4f9be5b1fd72 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -497,7 +497,7 @@ CREATION_TEST_IGNORE_SUBTYPES(/obj/machinery/camera) return FALSE if(machine_stat & EMPED) return FALSE - if(is_jammed(JAMMER_PROTECTION_CAMERAS)) + if(is_jammed(JAMMER_PROTECTION_CAMERAS) == JAM_FULL) return FALSE return TRUE diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index 838c200652cba..ce470ceea0032 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -99,7 +99,7 @@ track_time -= 1 SECONDS // Check for sensor beacon var/nanite_sensors = HAS_TRAIT(human_target, TRAIT_SUIT_SENSORS) - if(!human_target.is_jammed(JAMMER_PROTECTION_SENSOR_NETWORK) && (nanite_sensors || HAS_TRAIT(human_target, TRAIT_NANITE_SENSORS))) + if(target.is_jammed(JAMMER_PROTECTION_SENSOR_NETWORK) == JAM_NONE && (nanite_sensors || HAS_TRAIT(human_target, TRAIT_NANITE_SENSORS))) // Check for a uniform if not using nanites // If the GPS is on, track instantly var/obj/item/clothing/under/uniform = human_target.w_uniform diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm index c44799a9d85ae..3647f7f28369a 100644 --- a/code/game/machinery/computer/crew.dm +++ b/code/game/machinery/computer/crew.dm @@ -252,7 +252,8 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) continue // Radio transmitters are jammed - if(tracked_human.is_jammed(JAMMER_PROTECTION_SENSOR_NETWORK)) + var/jam_state = tracked_human.is_jammed(JAMMER_PROTECTION_SENSOR_NETWORK) + if(jam_state == JAM_FULL) continue // The entry for this human @@ -271,19 +272,19 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) entry["ijob"] = jobs[I.hud_state] // Binary living/dead status - if (nanite_sensors || uniform.sensor_mode >= SENSOR_LIVING) + if ((nanite_sensors || uniform.sensor_mode >= SENSOR_LIVING)) entry["life_status"] = !tracked_human.stat // Damage - if (nanite_sensors || uniform.sensor_mode >= SENSOR_VITALS) - entry["oxydam"] = round(tracked_human.getOxyLoss(), 1) - entry["toxdam"] = round(tracked_human.getToxLoss(), 1) - entry["burndam"] = round(tracked_human.getFireLoss(), 1) - entry["brutedam"] = round(tracked_human.getBruteLoss(), 1) + if ((nanite_sensors || uniform.sensor_mode >= SENSOR_VITALS)) + entry["oxydam"] = round(tracked_human.getOxyLoss(), 1) + (jam_state != JAM_NONE && rand(-5, 5)) + entry["toxdam"] = round(tracked_human.getToxLoss(), 1) + (jam_state != JAM_NONE && rand(-5, 5)) + entry["burndam"] = round(tracked_human.getFireLoss(), 1) + (jam_state != JAM_NONE && rand(-5, 5)) + entry["brutedam"] = round(tracked_human.getBruteLoss(), 1) + (jam_state != JAM_NONE && rand(-5, 5)) // Area if (pos && (nanite_sensors || uniform.sensor_mode >= SENSOR_COORDS)) - entry["area"] = get_area_name(tracked_human, TRUE) + entry["area"] = jam_state == JAM_NONE ? get_area_name(tracked_human, TRUE) : scramble_message_replace_chars(get_area_name(tracked_human, TRUE), 80) // Trackability entry["can_track"] = tracked_human.can_track() diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 3aeb15a6cc0da..8a26d17142908 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -246,7 +246,7 @@ return //Check radio signal jamming - if(is_jammed(JAMMER_PROTECTION_WIRELESS)) + if(is_jammed(JAMMER_PROTECTION_WIRELESS) == JAM_FULL) return @@ -455,14 +455,14 @@ /obj/machinery/door/airlock/proc/canAIControl(mob/user) if(protected_door) return FALSE - if(is_jammed(JAMMER_PROTECTION_WIRELESS)) + if(is_jammed(JAMMER_PROTECTION_WIRELESS) == JAM_FULL) return FALSE return ((aiControlDisabled != 1) && !isAllPowerCut()) /obj/machinery/door/airlock/proc/canAIHack() if(protected_door) return FALSE - if(is_jammed(JAMMER_PROTECTION_WIRELESS)) + if(is_jammed(JAMMER_PROTECTION_WIRELESS) == JAM_FULL) return FALSE return ((aiControlDisabled==1) && (!hackProof) && (!isAllPowerCut())); @@ -779,7 +779,7 @@ if(detonated) to_chat(user, "Unable to interface. Airlock control panel damaged.") return - if(is_jammed(JAMMER_PROTECTION_WIRELESS)) + if(is_jammed(JAMMER_PROTECTION_WIRELESS) == JAM_FULL) to_chat(user, "Unable to interface. Remote communications not responding.") return diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index a4fe805c76b50..108b64fe066af 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -385,7 +385,7 @@ CREATION_TEST_IGNORE_SUBTYPES(/obj/machinery/door/window) return //Check radio signal jamming - if(is_jammed(JAMMER_PROTECTION_WIRELESS)) + if(is_jammed(JAMMER_PROTECTION_WIRELESS) == JAM_FULL) return // Check packet access level. diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index 14f3005bc80b3..0db80db698403 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -177,7 +177,7 @@ GLOBAL_LIST_EMPTY(telecomms_list) /obj/machinery/telecomms/proc/ntnet_receive(datum/source, datum/netdata/data) //Check radio signal jamming - if(is_jammed(JAMMER_PROTECTION_WIRELESS) || machine_stat & (BROKEN|NOPOWER|MAINT|EMPED)) + if(is_jammed(JAMMER_PROTECTION_WIRELESS) == JAM_FULL || machine_stat & (BROKEN|NOPOWER|MAINT|EMPED)) return switch(data.data["type"]) diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 7728983671528..b4f87139824ac 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -299,8 +299,11 @@ channel = null // Nearby active jammers prevent the message from transmitting - if(is_jammed(freq == FREQ_CENTCOM || freq == FREQ_SYNDICATE ? JAMMER_PROTECTION_RADIO_ADVANCED : JAMMER_PROTECTION_RADIO_BASIC)) + var/jam_level = is_jammed(freq == FREQ_CENTCOM || freq == FREQ_SYNDICATE ? JAMMER_PROTECTION_RADIO_ADVANCED : JAMMER_PROTECTION_RADIO_BASIC) + if(jam_level == JAM_FULL) return + if (jam_level == JAM_MINOR) + message = Gibberish(message, TRUE) // Determine the identity information which will be attached to the signal. var/atom/movable/virtualspeaker/speaker = new(null, talking_movable, src) @@ -369,7 +372,7 @@ if (input_frequency == FREQ_SYNDICATE && !syndie) return FALSE - + // allow checks: are we listening on that frequency? if (input_frequency == frequency) return TRUE diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm index d43ae7b6a2829..18093453e3d84 100644 --- a/code/game/objects/items/devices/traitordevices.dm +++ b/code/game/objects/items/devices/traitordevices.dm @@ -290,12 +290,15 @@ effective or pretty fucking useless. ///Parameters: /// - Protection level: The amount of protection that the atom has. See jamming_defines.dm /atom/proc/is_jammed(protection_level) + . = JAM_NONE var/turf/position = get_turf(src) + var/area/location = position.loc + if (protection_level <= location.area_jamming_level) + . = JAM_MINOR for(var/datum/component/radio_jamming/jammer as anything in GLOB.active_jammers) //Check to see if the jammer is strong enough to block this signal if (protection_level > jammer.intensity) continue var/turf/jammer_turf = get_turf(jammer.parent) if(position?.get_virtual_z_level() == jammer_turf.get_virtual_z_level() && (get_dist(position, jammer_turf) <= jammer.range)) - return TRUE - return FALSE + return JAM_FULL diff --git a/code/game/objects/items/pinpointer.dm b/code/game/objects/items/pinpointer.dm index a2e9704c772d4..4832c3da6466c 100644 --- a/code/game/objects/items/pinpointer.dm +++ b/code/game/objects/items/pinpointer.dm @@ -80,7 +80,7 @@ . = ..() if(!active) return - if(!target || (!isnull(jamming_resistance) && src.is_jammed(jamming_resistance))) + if(!target || (!isnull(jamming_resistance) && src.is_jammed(jamming_resistance) != JAM_NONE)) . += "pinon[alert ? "alert" : ""]null[icon_suffix]" return var/turf/here = get_turf(src) @@ -118,7 +118,7 @@ z_level_direction = "" // getting xy result - if(get_dist_euclidian(here,there) <= minimum_range) + if(get_dist_euclidian(here,there) <= minimum_range || (target.is_jammed(jamming_resistance) != JAM_NONE) && get_dist_euclidian(here,there) < minimum_range + 25) pin_xy_result = "direct" else setDir(get_dir(here, there)) @@ -163,7 +163,7 @@ if(!here || !there) return FALSE - if(there.is_jammed(jam_level)) + if(there.is_jammed(jam_level) == JAM_FULL) return FALSE if(!powerful_z_check) // z-check will be only limited within the same area (i.e. multi-floor'ed station) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index d5ac9e90095f7..ff82790861189 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -330,7 +330,7 @@ CREATION_TEST_IGNORE_SUBTYPES(/mob/living/silicon/ai) if ((ai.get_virtual_z_level() != target.get_virtual_z_level()) && !is_station_level(ai.z)) return FALSE - if(A.is_jammed(JAMMER_PROTECTION_WIRELESS)) + if(A.is_jammed(JAMMER_PROTECTION_WIRELESS) == JAM_FULL) return FALSE if (istype(loc, /obj/item/aicard)) @@ -994,7 +994,7 @@ CREATION_TEST_IGNORE_SUBTYPES(/mob/living/silicon/ai) if (!target || target.stat || target.deployed || !(!target.connected_ai ||(target.connected_ai == src)) || (target.ratvar && !is_servant_of_ratvar(src))) return - if(target.is_jammed(JAMMER_PROTECTION_AI_SHELL)) + if(target.is_jammed(JAMMER_PROTECTION_AI_SHELL) == JAM_FULL) to_chat(src, "Unable to establish communication link with target.") return diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index 193438412356a..6c06ee77d1212 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -8,7 +8,7 @@ handle_robot_cell() /mob/living/silicon/robot/proc/handle_jamming() - if(deployed && is_jammed(JAMMER_PROTECTION_AI_SHELL)) + if(deployed && is_jammed(JAMMER_PROTECTION_AI_SHELL) == JAM_FULL) to_chat(src, "Remote connection with target lost.") undeploy() diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 659ad5d21bac9..5fb9fd6181dac 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -375,7 +375,7 @@ var/turf/T1 = get_turf(A) if (!T0 || ! T1) return FALSE - if(A.is_jammed(JAMMER_PROTECTION_WIRELESS)) + if(A.is_jammed(JAMMER_PROTECTION_WIRELESS) == JAM_FULL) return FALSE return ISINRANGE(T1.x, T0.x - interaction_range, T0.x + interaction_range) && ISINRANGE(T1.y, T0.y - interaction_range, T0.y + interaction_range) diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm index 1a0797243f43c..ad7e7749e3885 100644 --- a/code/modules/mob/living/silicon/say.dm +++ b/code/modules/mob/living/silicon/say.dm @@ -1,6 +1,6 @@ /mob/living/proc/robot_talk(message) //Cannot transmit wireless messages while jammed - if(is_jammed(JAMMER_PROTECTION_SILICON_COMMS)) + if(is_jammed(JAMMER_PROTECTION_SILICON_COMMS) == JAM_FULL) return if(CHAT_FILTER_CHECK(message)) to_chat(usr, "Your message contains forbidden words.") diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 57c63fa117ab6..3f0d2259964a3 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -1080,7 +1080,7 @@ Pass a positive integer as an argument to override a bot's default speed. /mob/living/simple_animal/bot/proc/topic_denied(mob/user) //Access check proc for bot topics! Remember to place in a bot's individual Topic if desired. //Silicons cannot remotely interfact with robots while the robot is jammed - if(issilicon(user) && is_jammed(JAMMER_PROTECTION_WIRELESS)) + if(issilicon(user) && is_jammed(JAMMER_PROTECTION_WIRELESS) == JAM_FULL) return TRUE if(!user.canUseTopic(src, !issilicon(user))) return TRUE diff --git a/code/modules/modular_computers/file_system/programs/ntmessenger.dm b/code/modules/modular_computers/file_system/programs/ntmessenger.dm index f24fc7ffbf08e..1c19cd1262b14 100644 --- a/code/modules/modular_computers/file_system/programs/ntmessenger.dm +++ b/code/modules/modular_computers/file_system/programs/ntmessenger.dm @@ -292,11 +292,17 @@ return // Check for jammers - var/turf/position = get_turf(computer) - for(var/datum/component/radio_jamming/jammer as anything in GLOB.active_jammers) - var/turf/jammer_turf = get_turf(jammer.parent) - if(position?.get_virtual_z_level() == jammer_turf.get_virtual_z_level() && (get_dist(position, jammer_turf) <= jammer.range)) - return FALSE + var/jam_level = computer.is_jammed(JAMMER_PROTECTION_PDA_MESSAGE) + + if (jam_level == JAM_FULL) + to_chat(user, "ERROR: Server isn't responding.") + if(ringer_status) + playsound(computer, 'sound/machines/terminal_error.ogg', 15, TRUE) + return + + if (jam_level == JAM_MINOR) + // Slightly more robust than comms, not quite as gibberish + message = Gibberish(message, TRUE, 30) // Send the signal var/list/string_targets = list()