diff --git a/SQL/migrate-2023/V004__suit_sensors.sql b/SQL/migrate-2023/V004__suit_sensors.sql new file mode 100644 index 00000000000..d570ff4f98e --- /dev/null +++ b/SQL/migrate-2023/V004__suit_sensors.sql @@ -0,0 +1,5 @@ +-- +-- Implemented in PR #17607. +-- Adds suit sensor prefs. +-- +ALTER TABLE `ss13_characters` ADD `sensor_setting` INT(11) DEFAULT NULL AFTER `headset_choice`; diff --git a/code/__defines/_macros.dm b/code/__defines/_macros.dm index 05509dfcb22..3fa5c90694d 100644 --- a/code/__defines/_macros.dm +++ b/code/__defines/_macros.dm @@ -144,6 +144,9 @@ #define isitem(D) istype(D, /obj/item) #define islist(D) istype(D, /list) +/// Semantic define for a 0 int intended for use as a bitfield +#define EMPTY_BITFIELD 0 + // Insert an object A into a sorted list using cmp_proc (/code/_helpers/cmp.dm) for comparison. #define ADD_SORTED(list, A, cmp_proc) if(!list.len) {list.Add(A)} else {list.Insert(FindElementIndex(A, list, cmp_proc), A)} diff --git a/code/__defines/items_clothing.dm b/code/__defines/items_clothing.dm index ce3a5323248..01ef8e810df 100644 --- a/code/__defines/items_clothing.dm +++ b/code/__defines/items_clothing.dm @@ -205,3 +205,9 @@ #define SUIT_SENSOR_BINARY 1 #define SUIT_SENSOR_VITAL 2 #define SUIT_SENSOR_TRACKING 3 + +#define SUIT_SENSOR_MODES list("Off" = SUIT_SENSOR_OFF, "Binary sensors" = SUIT_SENSOR_BINARY, "Vitals tracker" = SUIT_SENSOR_VITAL, "Tracking beacon" = SUIT_SENSOR_TRACKING) + +#define SUIT_NO_SENSORS EMPTY_BITFIELD +#define SUIT_HAS_SENSORS FLAG(0) +#define SUIT_LOCKED_SENSORS FLAG(1) diff --git a/code/controllers/subsystems/job.dm b/code/controllers/subsystems/job.dm index 92e4c6adcb6..416cc47d580 100644 --- a/code/controllers/subsystems/job.dm +++ b/code/controllers/subsystems/job.dm @@ -409,6 +409,10 @@ SUBSYSTEM_DEF(jobs) BITSET(H.hud_updateflag, IMPLOYAL_HUD) BITSET(H.hud_updateflag, SPECIALROLE_HUD) + var/obj/item/clothing/under/uniform = H.w_uniform + if(istype(uniform) && uniform.has_sensor) + uniform.sensor_mode = SUIT_SENSOR_MODES[H.client.prefs.sensor_setting] + INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(show_location_blurb), H.client, 10 SECONDS) if(spawning_at == "Arrivals Shuttle") diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm index 47fedf8157d..1a108be1370 100644 --- a/code/game/jobs/job/civilian.dm +++ b/code/game/jobs/job/civilian.dm @@ -71,7 +71,7 @@ name = "Chef" jobtype = /datum/job/chef - uniform = /obj/item/clothing/under/rank/chef/nt + uniform = /obj/item/clothing/under/rank/chef suit = /obj/item/clothing/suit/chef_jacket/nt head = /obj/item/clothing/head/chefhat/nt shoes = /obj/item/clothing/shoes/sneakers/black diff --git a/code/game/objects/structures/crates_lockers/closets/job_closets.dm b/code/game/objects/structures/crates_lockers/closets/job_closets.dm index 4b73322888a..bfcbcabfa07 100644 --- a/code/game/objects/structures/crates_lockers/closets/job_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/job_closets.dm @@ -49,7 +49,7 @@ new /obj/item/device/radio/headset/headset_service(src) new /obj/item/storage/box/gloves(src) new /obj/item/storage/box/mousetraps(src) - new /obj/item/clothing/under/rank/chef/nt(src) + new /obj/item/clothing/under/rank/chef(src) new /obj/item/clothing/under/rank/chef/idris(src) new /obj/item/clothing/head/chefhat/nt(src) new /obj/item/clothing/head/chefhat/idris(src) diff --git a/code/modules/client/preference_setup/general/04_equipment.dm b/code/modules/client/preference_setup/general/04_equipment.dm index 3cd1f67a6c8..6dc9eac9509 100644 --- a/code/modules/client/preference_setup/general/04_equipment.dm +++ b/code/modules/client/preference_setup/general/04_equipment.dm @@ -16,6 +16,7 @@ S["pda_choice"] >> pref.pda_choice S["headset_choice"] >> pref.headset_choice S["primary_radio_slot"] >> pref.primary_radio_slot + S["sensor_setting"] >> pref.sensor_setting /datum/category_item/player_setup_item/general/equipment/save_character(var/savefile/S) S["all_underwear"] << pref.all_underwear @@ -27,6 +28,7 @@ S["pda_choice"] << pref.pda_choice S["headset_choice"] << pref.headset_choice S["primary_radio_slot"] << pref.primary_radio_slot + S["sensor_setting"] << pref.sensor_setting /datum/category_item/player_setup_item/general/equipment/gather_load_query() return list( @@ -40,7 +42,8 @@ "backbag_strap", "pda_choice", "headset_choice", - "primary_radio_slot" + "primary_radio_slot", + "sensor_setting" ), "args" = list("id") ) @@ -61,6 +64,7 @@ "pda_choice", "headset_choice", "primary_radio_slot", + "sensor_setting", "id" = 1, "ckey" = 1 ) @@ -77,6 +81,7 @@ "pda_choice" = pref.pda_choice, "headset_choice" = pref.headset_choice, "primary_radio_slot" = pref.primary_radio_slot, + "sensor_setting" = pref.sensor_setting, "id" = pref.current_character, "ckey" = PREF_CLIENT_CKEY ) @@ -137,6 +142,7 @@ pref.headset_choice = sanitize_integer(pref.headset_choice, 1, headsetlist.len, initial(pref.headset_choice)) if(!(pref.primary_radio_slot in primary_radio_slot_choice)) pref.primary_radio_slot = primary_radio_slot_choice[1] + pref.sensor_setting = sanitize_inlist(pref.sensor_setting, SUIT_SENSOR_MODES, get_key_by_index(SUIT_SENSOR_MODES, 0)) /datum/category_item/player_setup_item/general/equipment/content(var/mob/user) . = list() @@ -160,6 +166,7 @@ . += "PDA Type: [pdalist[pref.pda_choice]]
" . += "Headset Type: [headsetlist[pref.headset_choice]]
" . += "Primary Radio Slot: [pref.primary_radio_slot]
" + . += "Suit Sensor Setting: [pref.sensor_setting]
" return jointext(., null) @@ -217,11 +224,17 @@ return TOPIC_REFRESH_UPDATE_PREVIEW else if(href_list["change_radio_slot"]) - var/new_slot = tgui_input_list(user, "Choose which radio will be spoken into first if multiple slots are occupied.", "Charcter Preference", primary_radio_slot_choice, pref.primary_radio_slot) + var/new_slot = tgui_input_list(user, "Choose which radio will be spoken into first if multiple slots are occupied.", "Character Preference", primary_radio_slot_choice, pref.primary_radio_slot) if(!isnull(new_slot) && CanUseTopic(user)) pref.primary_radio_slot = new_slot return TOPIC_REFRESH_UPDATE_PREVIEW + else if(href_list["change_sensor_setting"]) + var/new_sensor = tgui_input_list(user, "Select a sensor mode.", "Character Preference", SUIT_SENSOR_MODES, pref.sensor_setting) + if(!isnull(new_sensor) && CanUseTopic(user)) + pref.sensor_setting = new_sensor + return TOPIC_REFRESH_UPDATE_PREVIEW + else if(href_list["change_underwear"]) var/datum/category_group/underwear/UWC = global_underwear.categories_by_name[href_list["change_underwear"]] if(!UWC) diff --git a/code/modules/client/preference_setup/preference_setup.dm b/code/modules/client/preference_setup/preference_setup.dm index 505e8002167..d52f2d3fcef 100644 --- a/code/modules/client/preference_setup/preference_setup.dm +++ b/code/modules/client/preference_setup/preference_setup.dm @@ -196,7 +196,7 @@ /datum/category_group/player_setup_category/proc/content(var/mob/user) . = "
" var/current = 0 - var/halfway = items.len / 2 + var/halfway = items.len / 2.5 for(var/datum/category_item/player_setup_item/PI in items) if(halfway && current++ >= halfway) halfway = 0 diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 5f6f2fac6e9..a7d11c507b8 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -53,6 +53,8 @@ var/list/preferences_datums = list() var/pda_choice = OUTFIT_TAB_PDA var/headset_choice = OUTFIT_HEADSET var/primary_radio_slot = "Left Ear" + ///Suit sensors setting in the loadout. + var/sensor_setting var/h_style = "Bedhead 2" //Hair type var/tail_style = null var/hair_colour = "#000000" //Hair colour hex value, for SQL loading diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 6795813a443..cc945350c36 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -1055,26 +1055,32 @@ armor = null w_class = ITEMSIZE_NORMAL equip_sound = 'sound/items/equip/jumpsuit.ogg' - var/has_sensor = 1 //For the crew computer 2 = unable to change mode - var/sensor_mode = 0 - /* - 1 = Report living/dead - 2 = Report detailed damages - 3 = Report location - */ + + ///SUIT_NO_SENSORS = No sensors, SUIT_HAS_SENSORS = Sensors, SUIT_LOCKED_SENSORS = Locked sensors + var/has_sensor = SUIT_NO_SENSORS + + ///SUIT_SENSOR_OFF = Off, SUIT_SENSOR_BINARY = Report living/dead, SUIT_SENSOR_VITAL = Report detailed damages, SUIT_SENSOR_TRACKING = Report location + var/sensor_mode = SUIT_SENSOR_OFF + var/displays_id = 1 - var/rolled_down = -1 //0 = unrolled, 1 = rolled, -1 = cannot be toggled - var/rolled_sleeves = -1 //0 = unrolled, 1 = rolled, -1 = cannot be toggled - var/initial_icon_override //If set, rolling up sleeves/rolling down will use this icon state instead of initial(). + + ///0 = unrolled, 1 = rolled, -1 = cannot be toggled + var/rolled_down = -1 + + ///0 = unrolled, 1 = rolled, -1 = cannot be toggled + var/rolled_sleeves = -1 + + ///If set, rolling up sleeves/rolling down will use this icon state instead of initial(). + var/initial_icon_override + species_restricted = list("exclude",BODYTYPE_VAURCA_BREEDER,BODYTYPE_VAURCA_WARFORM,BODYTYPE_GOLEM, BODYTYPE_TESLA_BODY) - //convenience var for defining the icon state for the overlay used when the clothing is worn. - //Also used by rolling/unrolling. + ///Convenience var for defining the icon state for the overlay used when the clothing is worn. Also used by rolling/unrolling. var/worn_state = null + valid_accessory_slots = list(ACCESSORY_SLOT_UTILITY, ACCESSORY_SLOT_UTILITY_MINOR, ACCESSORY_SLOT_ARMBAND, ACCESSORY_SLOT_GENERIC, ACCESSORY_SLOT_CAPE) restricted_accessory_slots = list(ACCESSORY_SLOT_UTILITY) - /obj/item/clothing/under/attack_hand(var/mob/user) if(LAZYLEN(accessories)) ..() @@ -1084,6 +1090,8 @@ /obj/item/clothing/under/Initialize() . = ..() + if(has_sensor) + src.verbs += /obj/item/clothing/under/proc/toggle if(worn_state) LAZYINITLIST(item_state_slots) item_state_slots[slot_w_uniform_str] = worn_state @@ -1198,61 +1206,64 @@ /obj/item/clothing/under/examine(mob/user, distance, is_adjacent) . = ..() - switch(src.sensor_mode) - if(0) - to_chat(user, "Its sensors appear to be disabled.") - if(1) - to_chat(user, "Its binary life sensors appear to be enabled.") - if(2) - to_chat(user, "Its vital tracker appears to be enabled.") - if(3) - to_chat(user, "Its vital tracker and tracking beacon appear to be enabled.") + if(has_sensor) + switch(src.sensor_mode) + if(SUIT_SENSOR_OFF) + to_chat(user, "Its sensors appear to be disabled.") + if(SUIT_SENSOR_BINARY) + to_chat(user, "Its binary life sensors appear to be enabled.") + if(SUIT_SENSOR_VITAL) + to_chat(user, "Its vitals tracker appears to be enabled.") + if(SUIT_SENSOR_TRACKING) + to_chat(user, "Its vitals tracker and tracking beacon appear to be enabled.") -/obj/item/clothing/under/proc/set_sensors(mob/usr as mob) - var/mob/M = usr - if(M.stat || M.paralysis || M.stunned || M.weakened || M.restrained()) - to_chat(usr, "You cannot reach your suit sensors like this...") +/obj/item/clothing/under/proc/set_sensors(mob/user as mob) + var/mob/M = user + if (isobserver(M) || user.incapacitated()) return - if(has_sensor >= 2) - to_chat(usr, "The controls are locked.") + if(has_sensor >= SUIT_LOCKED_SENSORS) + to_chat(user, "The controls are locked.") return 0 - if(has_sensor <= 0) - to_chat(usr, "This suit does not have any sensors.") + if(has_sensor <= SUIT_NO_SENSORS) + to_chat(user, "This suit does not have any sensors.") return 0 - var/list/modes = list("Off", "Binary sensors", "Vitals tracker", "Tracking beacon") - var/switchMode = tgui_input_list(usr, "Select a sensor mode.", "Suit Sensor Mode", modes) - if(get_dist(usr, src) > 1) - to_chat(usr, "You have moved too far away.") + var/switchMode = tgui_input_list(user, "Select a sensor mode.", "Suit Sensor Mode", SUIT_SENSOR_MODES) + if(get_dist(user, src) > 1) + to_chat(user, "You have moved too far away.") return - sensor_mode = modes.Find(switchMode) - 1 + sensor_mode = SUIT_SENSOR_MODES[switchMode] - if (src.loc == usr) + if (src.loc == user) switch(sensor_mode) - if(0) - to_chat(usr, "You disable your suit's remote sensing equipment.") - if(1) - to_chat(usr, "Your suit will now report whether you are live or dead.") - if(2) - to_chat(usr, "Your suit will now report your vital lifesigns.") - if(3) - to_chat(usr, "Your suit will now report your vital lifesigns as well as your coordinate position.") - else if (istype(src.loc, /mob)) - switch(sensor_mode) - if(0) - for(var/mob/V in viewers(usr, 1)) - V.show_message(SPAN_WARNING("[usr] disables [src.loc]'s remote sensing equipment."), 1) - if(1) - for(var/mob/V in viewers(usr, 1)) - V.show_message("[usr] turns [src.loc]'s remote sensors to binary.", 1) - if(2) - for(var/mob/V in viewers(usr, 1)) - V.show_message("[usr] sets [src.loc]'s sensors to track vitals.", 1) - if(3) - for(var/mob/V in viewers(usr, 1)) - V.show_message("[usr] sets [src.loc]'s sensors to maximum.", 1) + if(SUIT_SENSOR_OFF) + user.visible_message("[user] adjusts the tracking sensor on [get_pronoun("him")] [src.name].", "You disable your suit's remote sensing equipment.") + if(SUIT_SENSOR_BINARY) + user.visible_message("[user] adjusts the tracking sensor on [get_pronoun("him")] [src.name].", "Your suit will now report your pulse.") + if(SUIT_SENSOR_VITAL) + user.visible_message("[user] adjusts the tracking sensor on [get_pronoun("him")] [src.name].", "Your suit will now report your pulse and vital lifesigns.") + if(SUIT_SENSOR_TRACKING) + user.visible_message("[user] adjusts the tracking sensor on [get_pronoun("him")] [src.name].", "Your suit will now report your pulse, vital lifesigns, and your coordinate position.") + else if (ismob(src.loc)) + if(sensor_mode == SUIT_SENSOR_OFF) + user.visible_message(SPAN_WARNING("[user] disables [src.loc]'s remote sensing equipment."), "You disable [src.loc]'s remote sensing equipment.") + else + user.visible_message("[user] adjusts the tracking sensor on [src.loc]'s [src.name].", "You adjust [src.loc]'s sensors.") + else + user.visible_message("[user] adjusts the tracking sensor on [src]", "You adjust the sensor on [src].") -/obj/item/clothing/under/verb/toggle() +/obj/item/clothing/under/emp_act(severity) + ..() + var/new_mode + switch(severity) + if (2) + new_mode = pick(75;SUIT_SENSOR_OFF, 15;SUIT_SENSOR_BINARY, 10;SUIT_SENSOR_VITAL) + if (1) + new_mode = pick(50;SUIT_SENSOR_OFF, 25;SUIT_SENSOR_BINARY, 20;SUIT_SENSOR_VITAL, 5;SUIT_SENSOR_TRACKING) + + sensor_mode = new_mode + +/obj/item/clothing/under/proc/toggle() set name = "Toggle Suit Sensors" set category = "Object" set src in usr @@ -1342,16 +1353,9 @@ to_chat(user, SPAN_NOTICE("You roll down \the [src]'s sleeves.")) update_clothing_icon() -/obj/item/clothing/under/rank/Initialize() - sensor_mode = pick(0,1,2,3) - . = ..() - /obj/item/clothing/under/clothing_class() return "uniform" -/obj/item/clothing/under/AltClick(var/mob/user) - set_sensors(user) - //Rings /obj/item/clothing/ring diff --git a/code/modules/clothing/sets/captain.dm b/code/modules/clothing/sets/captain.dm index 9416986e692..8246df3991e 100644 --- a/code/modules/clothing/sets/captain.dm +++ b/code/modules/clothing/sets/captain.dm @@ -36,6 +36,7 @@ icon_state = "uniform" item_state = "uniform" worn_state = "uniform" + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE var/is_open = FALSE @@ -69,6 +70,7 @@ icon_state = "uniform_fem" item_state = "uniform_fem" worn_state = "uniform_fem" + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS var/is_open = FALSE @@ -194,6 +196,7 @@ icon_state = "uniform" item_state = "uniform" worn_state = "uniform" + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE /obj/item/clothing/suit/captunic @@ -228,5 +231,5 @@ icon = 'icons/obj/item/clothing/department_uniforms/command.dmi' icon_state = "captain" item_state = "captain" - contained_sprite = TRUE + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE diff --git a/code/modules/clothing/under/color.dm b/code/modules/clothing/under/color.dm index 6b75ad5fed1..e7c55fa2999 100644 --- a/code/modules/clothing/under/color.dm +++ b/code/modules/clothing/under/color.dm @@ -20,8 +20,8 @@ desc = "It's standardised prisoner-wear. Its suit sensors are stuck in the \"Fully On\" position." icon_state = "orange" item_state = "orange" - has_sensor = 2 - sensor_mode = 3 + has_sensor = SUIT_LOCKED_SENSORS + sensor_mode = SUIT_SENSOR_TRACKING var/id /obj/item/clothing/under/color/orange/cell1 diff --git a/code/modules/clothing/under/jobs/civilian.dm b/code/modules/clothing/under/jobs/civilian.dm index 2c104cdb507..26ac414c672 100644 --- a/code/modules/clothing/under/jobs/civilian.dm +++ b/code/modules/clothing/under/jobs/civilian.dm @@ -3,8 +3,10 @@ /obj/item/clothing/under/rank/bartender name = "bartender's uniform" desc = "It looks like it could use some more flair." - icon = 'icons/obj/item/clothing/department_uniforms/service.dmi' + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE + icon = 'icons/obj/item/clothing/department_uniforms/service.dmi' + icon_state = "nt_bartender" item_state = "nt_bartender" @@ -17,28 +19,23 @@ item_state = "orion_bartender" /obj/item/clothing/under/rank/chaplain - desc = "It's a black jumpsuit, often worn by religious folk." name = "chaplain's jumpsuit" + desc = "It's a black jumpsuit, often worn by religious folk." + has_sensor = SUIT_HAS_SENSORS icon_state = "chaplain" item_state = "bl_suit" worn_state = "chapblack" /obj/item/clothing/under/rank/chef - desc = "It's an apron which is given only to the most hardcore chefs in space." name = "chef's uniform" - icon_state = "chef" - item_state = "w_suit" - worn_state = "chef" - -/obj/item/clothing/under/rank/chef/nt - icon = 'icons/obj/item/clothing/department_uniforms/service.dmi' + desc = "It's an apron which is given only to the most hardcore chefs in space." + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE + icon = 'icons/obj/item/clothing/department_uniforms/service.dmi' icon_state = "nt_chef" item_state = "nt_chef" /obj/item/clothing/under/rank/chef/idris - icon = 'icons/obj/item/clothing/department_uniforms/service.dmi' - contained_sprite = TRUE icon_state = "idris_chef" item_state = "idris_chef" @@ -49,8 +46,9 @@ item_state = "orion_chef" /obj/item/clothing/under/rank/hydroponics - desc = "It's a jumpsuit designed to protect against minor plant-related hazards." name = "botanist's jumpsuit" + desc = "It's a jumpsuit designed to protect against minor plant-related hazards." + has_sensor = SUIT_HAS_SENSORS icon = 'icons/obj/item/clothing/department_uniforms/service.dmi' icon_state = "nt_gardener" item_state = "nt_gardener" @@ -70,10 +68,11 @@ /obj/item/clothing/under/rank/liaison name = "corporate liaison uniform" desc = "The plain, professional attire of a corporate liaison. The collar is immaculately starched." + has_sensor = SUIT_HAS_SENSORS + contained_sprite = TRUE icon = 'icons/obj/item/clothing/department_uniforms/service.dmi' icon_state = "nt_liaison" item_state = "nt_liaison" - contained_sprite = TRUE /obj/item/clothing/under/rank/liaison/zeng icon_state = "zeng_liaison" @@ -101,12 +100,13 @@ // Janitor /obj/item/clothing/under/rank/janitor - desc = "It's the official uniform of the station's janitor. It has minor protection from biohazards." name = "janitor's jumpsuit" + desc = "It's the official uniform of the station's janitor. It has minor protection from biohazards." + has_sensor = SUIT_HAS_SENSORS + contained_sprite = TRUE icon = 'icons/obj/item/clothing/department_uniforms/service.dmi' icon_state = "nt_janitor" item_state = "nt_janitor" - contained_sprite = TRUE armor = list( bio = ARMOR_BIO_MINOR ) @@ -150,6 +150,7 @@ /obj/item/clothing/under/librarian name = "sensible suit" desc = "It's very... sensible." + has_sensor = SUIT_HAS_SENSORS icon = 'icons/obj/item/clothing/department_uniforms/service.dmi' contained_sprite = TRUE icon_state = "nt_librarian" @@ -166,10 +167,11 @@ // Miner /obj/item/clothing/under/rank/miner - desc = "It's a snappy miner's jumpsuit, complete with overalls and caked-on dirt." name = "miner's jumpsuit" - icon = 'icons/obj/item/clothing/department_uniforms/operations.dmi' + desc = "It's a snappy miner's jumpsuit, complete with overalls and caked-on dirt." + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE + icon = 'icons/obj/item/clothing/department_uniforms/operations.dmi' icon_state = "nt_miner" item_state = "nt_miner" @@ -184,18 +186,20 @@ /obj/item/clothing/under/rank/operations_manager name = "operations manager's jumpsuit" desc = "A uniform worn by the operations manager. It has the SCC insignia on it." + has_sensor = SUIT_HAS_SENSORS + contained_sprite = TRUE icon = 'icons/obj/item/clothing/department_uniforms/command.dmi' icon_state = "operations_manager" item_state = "operations_manager" - contained_sprite = TRUE /obj/item/clothing/under/rank/hangar_technician name = "hangar technician's jumpsuit" desc = "The future of hangar tech apparel: long, stuffy slacks. We never said it was a bright future." + has_sensor = SUIT_HAS_SENSORS + contained_sprite = TRUE icon = 'icons/obj/item/clothing/department_uniforms/operations.dmi' icon_state = "nt_tech" item_state = "nt_tech" - contained_sprite = TRUE /obj/item/clothing/under/rank/hangar_technician/heph icon_state = "heph_tech" @@ -208,6 +212,8 @@ /obj/item/clothing/under/rank/bridge_crew name = "bridge crew's jumpsuit" desc = "The uniform worn by the SCC's bridge crew." + has_sensor = SUIT_HAS_SENSORS + contained_sprite = TRUE icon = 'icons/obj/item/clothing/department_uniforms/command.dmi' icon_state = "bridge_crew" item_state = "bridge_crew" @@ -218,6 +224,7 @@ desc = "The uniform worn by the SCC's bridge crew, featuring a skirt." icon_state = "bridge_crew_alt" item_state = "bridge_crew_alt" + /obj/item/clothing/under/rank/bridge_crew/alt/white icon_state = "bridge_crew_alt_white" item_state = "bridge_crew_alt_white" @@ -241,16 +248,18 @@ /obj/item/clothing/under/rank/xo name = "executive officer's jumpsuit" desc = "The uniform worn by the SCC's executive officers." + has_sensor = SUIT_HAS_SENSORS + contained_sprite = TRUE icon = 'icons/obj/item/clothing/department_uniforms/command.dmi' icon_state = "executive_officer" item_state = "executive_officer" - contained_sprite = TRUE /obj/item/clothing/under/rank/machinist name = "machinist's jumpsuit" desc = "A practical uniform designed for industrial work." - icon = 'icons/obj/item/clothing/department_uniforms/operations.dmi' + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE + icon = 'icons/obj/item/clothing/department_uniforms/operations.dmi' icon_state = "nt_machinist" item_state = "nt_machinist" @@ -265,6 +274,7 @@ /obj/item/clothing/under/rank/captain/hephaestus name = "hephaestus captain's jumpsuit" desc = "It's a green-and-orange jumpsuit with some gold markings denoting the rank of \"Captain\" used by Hephaestus Industries." + has_sensor = SUIT_NO_SENSORS icon = 'icons/clothing/under/uniforms/cyclops_uniforms.dmi' icon_state = "heph_captain" item_state = "heph_captain" diff --git a/code/modules/clothing/under/jobs/engineering.dm b/code/modules/clothing/under/jobs/engineering.dm index 9decbeaabd5..807f9f377e4 100644 --- a/code/modules/clothing/under/jobs/engineering.dm +++ b/code/modules/clothing/under/jobs/engineering.dm @@ -5,6 +5,7 @@ icon = 'icons/obj/item/clothing/department_uniforms/command.dmi' icon_state = "chief_engineer" item_state = "chief_engineer" + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE armor = list( rad = ARMOR_RAD_MINOR @@ -17,6 +18,7 @@ icon = 'icons/obj/item/clothing/department_uniforms/engineering.dmi' icon_state = "nt_atmos" item_state = "nt_atmos" + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE siemens_coefficient = 0.75 @@ -34,6 +36,7 @@ icon = 'icons/obj/item/clothing/department_uniforms/engineering.dmi' icon_state = "nt_engineer" item_state = "nt_engineer" + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE armor = list( rad = ARMOR_RAD_MINOR diff --git a/code/modules/clothing/under/jobs/medsci.dm b/code/modules/clothing/under/jobs/medsci.dm index 0d03f843c7d..a560fe6f76c 100644 --- a/code/modules/clothing/under/jobs/medsci.dm +++ b/code/modules/clothing/under/jobs/medsci.dm @@ -7,6 +7,7 @@ icon = 'icons/obj/item/clothing/department_uniforms/command.dmi' icon_state = "research_director" item_state = "research_director" + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE armor = list( bio = ARMOR_BIO_MINOR @@ -23,6 +24,7 @@ armor = list( bio = ARMOR_BIO_MINOR ) + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE /obj/item/clothing/under/rank/scientist/zeng @@ -107,6 +109,7 @@ icon = 'icons/obj/item/clothing/department_uniforms/command.dmi' icon_state = "chief_medical_officer" item_state = "chief_medical_officer" + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE permeability_coefficient = 0.50 armor = list( @@ -119,6 +122,7 @@ icon = 'icons/clothing/under/uniforms/iac_uniform.dmi' icon_state = "iac" item_state = "iac" + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE permeability_coefficient = 0.50 armor = list( @@ -133,6 +137,7 @@ icon = 'icons/obj/item/clothing/department_uniforms/medical.dmi' icon_state = "nt_phys" item_state = "nt_phys" + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE permeability_coefficient = 0.50 armor = list( @@ -211,6 +216,7 @@ desc = "It's made of a special fiber that provides minor protection against biohazards. Specially fitted to ensure surgical precision." icon_state = "nt_surgeon" item_state = "nt_surgeon" + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE /obj/item/clothing/under/rank/medical/surgeon/zeng diff --git a/code/modules/clothing/under/jobs/security.dm b/code/modules/clothing/under/jobs/security.dm index 55a45334223..6a9a561c556 100644 --- a/code/modules/clothing/under/jobs/security.dm +++ b/code/modules/clothing/under/jobs/security.dm @@ -19,6 +19,7 @@ melee = ARMOR_MELEE_SMALL ) siemens_coefficient = 0.75 + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE /obj/item/clothing/under/rank/security/zavod @@ -83,6 +84,7 @@ melee = ARMOR_MELEE_SMALL ) siemens_coefficient = 0.75 + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE /obj/item/clothing/under/rank/cadet/zavod @@ -106,6 +108,7 @@ icon = 'icons/clothing/under/uniforms/cyclops_uniforms.dmi' icon_state = "heph_security" item_state = "heph_security" + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE /obj/item/clothing/under/rank/warden @@ -118,6 +121,7 @@ melee = ARMOR_MELEE_SMALL ) siemens_coefficient = 0.75 + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE /obj/item/clothing/under/rank/warden/remote @@ -158,6 +162,7 @@ melee = ARMOR_MELEE_SMALL ) siemens_coefficient = 0.75 + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE /obj/item/clothing/under/det/zavod @@ -200,6 +205,7 @@ icon = 'icons/obj/item/clothing/department_uniforms/command.dmi' icon_state = "head_of_security" item_state = "head_of_security" + has_sensor = SUIT_HAS_SENSORS contained_sprite = TRUE armor = list( melee = ARMOR_MELEE_SMALL diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index e8b15f4d7e6..57957cf4151 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -500,8 +500,8 @@ desc = "A loose pieces of clothing, commonly worn by medical patients." icon_state = "medicalgown" item_state = "medicalgown" - has_sensor = 2 - sensor_mode = 3 + has_sensor = SUIT_LOCKED_SENSORS + sensor_mode = SUIT_SENSOR_TRACKING /obj/item/clothing/under/medical_gown/white icon_state = "whitemedicalgown" diff --git a/code/modules/clothing/under/syndicate.dm b/code/modules/clothing/under/syndicate.dm index ca39d635c4d..e8eeec9e953 100644 --- a/code/modules/clothing/under/syndicate.dm +++ b/code/modules/clothing/under/syndicate.dm @@ -20,7 +20,7 @@ item_state = "bl_suit" worn_state = "tactifool" siemens_coefficient = 1 - has_sensor = 1 + has_sensor = SUIT_HAS_SENSORS armor = null /obj/item/clothing/under/syndicate/tracksuit diff --git a/code/modules/modular_computers/file_system/programs/medical/suit_sensors.dm b/code/modules/modular_computers/file_system/programs/medical/suit_sensors.dm index 38dd31ba60a..92ad2016e9d 100644 --- a/code/modules/modular_computers/file_system/programs/medical/suit_sensors.dm +++ b/code/modules/modular_computers/file_system/programs/medical/suit_sensors.dm @@ -9,10 +9,10 @@ requires_ntnet = TRUE network_destination = "crew lifesigns monitoring system" size = 11 - usage_flags = PROGRAM_ALL_REGULAR | PROGRAM_STATIONBOUND + usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP | PROGRAM_STATIONBOUND color = LIGHT_COLOR_CYAN tgui_id = "SuitSensors" - tgui_theme = "zenghu" + tgui_theme = "nanotrasen" /datum/computer_file/program/suit_sensors/ui_data(mob/user) var/list/data = list() @@ -29,6 +29,8 @@ for(var/z_level in current_map.map_levels) data["crewmembers"] += crew_repository.health_data(z_level) + data["security_level"] = seclevel2num(get_security_level()) + return data /datum/computer_file/program/suit_sensors/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) diff --git a/html/changelogs/wezzy_suit_sensor_rebalance.yml b/html/changelogs/wezzy_suit_sensor_rebalance.yml new file mode 100644 index 00000000000..c514f570f2a --- /dev/null +++ b/html/changelogs/wezzy_suit_sensor_rebalance.yml @@ -0,0 +1,45 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +# balance +# admin +# backend +# security +# refactor +################################# + +# Your name. +author: Wowzewow (Wezzy) + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - balance: "Suit sensors are now tiered based on alert level." + - balance: "Suit sensors are now only installed on job uniforms." + - balance: "Suit sensors are no longer able to be installed on PDAs and Tablets." + - rscadd: "You are now able to set your suit sensors on the character creation menu." + - bugfix: "Fixes the weird imbalance with the character creation menu." diff --git a/tgui/packages/tgui/interfaces/SuitSensors.tsx b/tgui/packages/tgui/interfaces/SuitSensors.tsx index 575518550e5..18923326a02 100644 --- a/tgui/packages/tgui/interfaces/SuitSensors.tsx +++ b/tgui/packages/tgui/interfaces/SuitSensors.tsx @@ -6,6 +6,7 @@ import { NtosWindow } from '../layouts'; export type SensorsData = { crewmembers: CrewMember[]; isAI: BooleanLike; + security_level: number; }; type CrewMember = { @@ -37,7 +38,7 @@ export const SuitSensors = (props, context) => { Name - Pulse or Charge + Pulse/Charge Blood Pressure Blood Oxygenation Temperature @@ -48,27 +49,57 @@ export const SuitSensors = (props, context) => { {crewmember.name} {crewmember.cellCharge === -1 ? ( - - {crewmember.pulse} BPM + 0 && data.security_level > 1 + ? getPulseClass(crewmember.tpulse) + : '' + }> + {crewmember.stype > 0 && data.security_level > 1 + ? crewmember.pulse + ' BPM' + : 'N/A'} ) : ( - - {Math.round(crewmember.cellCharge)}% + 0 && data.security_level > 1 + ? getChargeClass(crewmember.cellCharge) + : '' + }> + {crewmember.stype > 0 && data.security_level > 1 + ? Math.round(crewmember.cellCharge) + '%' + : 'N/A'} )} - - {crewmember.stype > 1 ? crewmember.pressure : 'N/A'} + + 1 && data.security_level > 1 + ? getPressureClass(crewmember.tpressure) + : '' + }> + {crewmember.stype > 1 && data.security_level > 1 + ? crewmember.pressure + : 'N/A'} - - {toOxyLabel(crewmember.oxyg)} - - - {crewmember.stype > 1 - ? Math.round(crewmember.bodytemp * 10) / 10 + 'C' + 1 && data.security_level > 1 + ? getOxyClass(crewmember.oxyg) + : '' + }> + {crewmember.stype > 1 && data.security_level > 1 + ? toOxyLabel(crewmember.oxyg) : 'N/A'} - {crewmember.stype > 2 + {crewmember.stype > 1 && data.security_level > 1 + ? Math.round(crewmember.bodytemp * 10) / 10 + 'C' + : 'N/A'} + + + + {crewmember.stype > 2 && data.security_level > 2 ? crewmember.area + ' (' + crewmember.x +