From 14b3fa22ce8c0b2df78021786c3cec56b889e845 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Tue, 8 Oct 2019 00:34:07 -0700 Subject: [PATCH 1/4] Merge pull request #9404 from Poojawa/qm-is-a-head QM is a head of staff, Cargo ID Console added --- _maps/map_files/BoxStation/BoxStation.dmm | 1 + .../map_files/Deltastation/DeltaStation2.dmm | 4 +++- _maps/map_files/PubbyStation/PubbyStation.dmm | 6 +++--- code/game/machinery/computer/card.dm | 12 ++++++++++-- .../circuitboards/computer_circuitboards.dm | 2 +- icons/obj/computer.dmi | Bin 114704 -> 114337 bytes 6 files changed, 18 insertions(+), 7 deletions(-) diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index a0d765e3..3ffb1606 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -62592,6 +62592,7 @@ /obj/effect/turf_decal/tile/brown{ dir = 1 }, +/obj/machinery/computer/card/minor/qm, /turf/open/floor/plasteel/dark, /area/quartermaster/qm) "tDj" = ( diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index cd8b6140..d04c2394 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -27550,7 +27550,6 @@ /turf/open/floor/plasteel, /area/quartermaster/qm) "aZh" = ( -/obj/structure/table/reinforced, /obj/machinery/light{ dir = 4 }, @@ -27561,6 +27560,9 @@ /obj/effect/turf_decal/tile/brown{ dir = 8 }, +/obj/machinery/computer/card/minor/qm{ + dir = 8 + }, /turf/open/floor/plasteel, /area/quartermaster/qm) "aZi" = ( diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm index 18c4c646..c15ca5ac 100644 --- a/_maps/map_files/PubbyStation/PubbyStation.dmm +++ b/_maps/map_files/PubbyStation/PubbyStation.dmm @@ -687,7 +687,7 @@ "ank" = (/obj/machinery/computer/card/minor/hos{dir = 8},/turf/open/floor/carpet,/area/crew_quarters/heads/hos) "anl" = (/obj/structure/transit_tube/diagonal,/turf/open/space/basic,/area/space/nearstation) "anm" = (/obj/machinery/door/airlock/maintenance/abandoned{name = "Pete's Speakeasy"; req_access_txt = "0"},/turf/open/floor/plating,/area/maintenance/department/crew_quarters/dorms) -"ann" = (/obj/structure/table,/obj/machinery/requests_console{department = "Cargo Bay"; departmentType = 2; pixel_x = -30},/obj/item/paper_bin{layer = 2.9},/obj/item/pen,/obj/effect/turf_decal/tile/brown{dir = 1},/obj/effect/turf_decal/tile/brown,/obj/effect/turf_decal/tile/brown{dir = 8},/obj/item/book/lorebooks/welcome_to_kinaris,/turf/open/floor/plasteel,/area/quartermaster/qm) +"ann" = (/obj/structure/table,/obj/machinery/requests_console{department = "Cargo Bay"; departmentType = 2; pixel_x = -30},/obj/effect/turf_decal/tile/brown{dir = 1},/obj/effect/turf_decal/tile/brown,/obj/effect/turf_decal/tile/brown{dir = 8},/obj/machinery/computer/card/minor/qm{dir = 1},/turf/open/floor/plasteel,/area/quartermaster/qm) "ano" = (/obj/machinery/button/door{desc = "A remote control-switch for the engineering security doors."; id = "Engineering"; name = "Engineering Lockdown"; pixel_x = -24; pixel_y = -10; req_access_txt = "10"},/obj/machinery/button/door{desc = "A remote control-switch for secure storage."; id = "Secure Storage"; name = "Engineering Secure Storage"; pixel_x = -24; req_access_txt = "11"},/obj/machinery/button/door{id = "atmos"; name = "Atmospherics Lockdown"; pixel_x = -24; pixel_y = 10; req_access_txt = "24"},/obj/structure/table/reinforced,/obj/item/folder/yellow,/obj/item/paper/monitorkey,/obj/item/pen,/obj/effect/turf_decal/tile/yellow{dir = 1},/obj/effect/turf_decal/tile/yellow{dir = 8},/obj/item/book/lorebooks/welcome_to_kinaris,/mob/living/simple_animal/parrot/Poly,/turf/open/floor/plasteel,/area/crew_quarters/heads/chief) "anp" = (/obj/structure/closet/secure_closet/personal,/obj/item/toy/poolnoodle/red,/obj/item/toy/poolnoodle/yellow,/obj/item/toy/poolnoodle/blue,/obj/effect/turf_decal/tile/neutral{dir = 4},/obj/effect/turf_decal/tile/neutral{dir = 1},/turf/open/floor/plasteel,/area/crew_quarters/fitness/pool) "anq" = (/obj/structure/grille/broken,/turf/open/floor/plating,/area/maintenance/department/security/brig) @@ -2943,7 +2943,7 @@ "beG" = (/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/camera{c_tag = "Bar Starboard"; dir = 1},/obj/machinery/light{light_color = "#c9d3e8"},/turf/open/floor/plasteel/dark,/area/crew_quarters/bar) "beH" = (/obj/machinery/disposal/bin,/obj/structure/disposalpipe/trunk{dir = 8},/obj/effect/turf_decal/tile/neutral{dir = 1},/obj/effect/turf_decal/tile/neutral,/obj/effect/turf_decal/tile/neutral{dir = 4},/obj/effect/turf_decal/tile/neutral{dir = 8},/turf/open/floor/plasteel/dark,/area/crew_quarters/bar) "beI" = (/turf/closed/wall,/area/science/robotics/mechbay) -"beJ" = (/obj/structure/filingcabinet,/obj/effect/turf_decal/tile/brown{dir = 1},/obj/effect/turf_decal/tile/brown{dir = 8},/obj/machinery/keycard_auth{pixel_x = -23; pixel_y = 0},/turf/open/floor/plasteel,/area/quartermaster/qm) +"beJ" = (/obj/effect/turf_decal/tile/brown{dir = 1},/obj/effect/turf_decal/tile/brown{dir = 8},/obj/machinery/keycard_auth{pixel_x = -23; pixel_y = 0},/turf/open/floor/plasteel,/area/quartermaster/qm) "beK" = (/obj/structure/chair/office/dark{dir = 4},/obj/effect/landmark/start/quartermaster,/turf/open/floor/plasteel,/area/quartermaster/qm) "beL" = (/obj/machinery/computer/cargo{dir = 8},/obj/effect/turf_decal/tile/brown,/obj/effect/turf_decal/tile/brown{dir = 4},/turf/open/floor/plasteel,/area/quartermaster/qm) "beM" = (/obj/machinery/mineral/equipment_vendor,/obj/effect/turf_decal/tile/brown{dir = 1},/turf/open/floor/plasteel,/area/quartermaster/miningdock) @@ -2988,7 +2988,7 @@ "bfz" = (/turf/open/floor/plasteel/dark,/area/science/robotics/mechbay) "bfA" = (/obj/machinery/computer/mech_bay_power_console,/obj/structure/cable{icon_state = "0-2"},/turf/open/floor/plasteel/dark,/area/science/robotics/mechbay) "bfB" = (/obj/effect/turf_decal/tile/red{dir = 8},/obj/effect/turf_decal/tile/red{dir = 1},/obj/effect/turf_decal/tile/red,/turf/open/floor/plasteel,/area/security/range) -"bfC" = (/obj/structure/table,/obj/item/clipboard,/obj/machinery/light,/obj/machinery/camera{c_tag = "Cargo Quartermaster's Office"; dir = 1},/obj/machinery/light_switch{pixel_y = -24},/obj/item/cartridge/quartermaster{pixel_x = 6; pixel_y = 5},/obj/item/cartridge/quartermaster,/obj/item/cartridge/quartermaster{pixel_x = -4; pixel_y = 7},/obj/item/coin/silver,/obj/item/stamp/qm,/obj/effect/turf_decal/tile/brown,/obj/effect/turf_decal/tile/brown{dir = 8},/turf/open/floor/plasteel,/area/quartermaster/qm) +"bfC" = (/obj/structure/table,/obj/item/clipboard,/obj/machinery/light,/obj/machinery/camera{c_tag = "Cargo Quartermaster's Office"; dir = 1},/obj/machinery/light_switch{pixel_y = -24},/obj/item/cartridge/quartermaster{pixel_x = 6; pixel_y = 5},/obj/item/cartridge/quartermaster,/obj/item/cartridge/quartermaster{pixel_x = -4; pixel_y = 7},/obj/item/coin/silver,/obj/item/stamp/qm,/obj/effect/turf_decal/tile/brown,/obj/effect/turf_decal/tile/brown{dir = 8},/obj/item/paper_bin{layer = 2.9},/obj/item/pen,/turf/open/floor/plasteel,/area/quartermaster/qm) "bfD" = (/obj/item/radio/intercom{name = "Station Intercom (General)"; pixel_y = -35},/obj/machinery/computer/security/qm{dir = 8},/obj/effect/turf_decal/tile/brown,/obj/effect/turf_decal/tile/brown{dir = 4},/obj/effect/turf_decal/tile/brown{dir = 8},/turf/open/floor/plasteel,/area/quartermaster/qm) "bfE" = (/obj/structure/rack,/obj/item/storage/toolbox/mechanical{pixel_x = -2; pixel_y = -1},/obj/item/pickaxe{pixel_x = 5},/obj/item/shovel{pixel_x = -5},/obj/machinery/camera{c_tag = "Cargo Mining Dock"; dir = 4},/obj/effect/turf_decal/tile/brown{dir = 1},/turf/open/floor/plasteel,/area/quartermaster/miningdock) "bfF" = (/obj/structure/cable{icon_state = "1-2"},/obj/effect/landmark/start/shaft_miner,/obj/structure/disposalpipe/segment,/obj/machinery/atmospherics/pipe/manifold/supply/hidden{dir = 8},/turf/open/floor/plasteel,/area/quartermaster/miningdock) diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm index d008219c..d45c3506 100644 --- a/code/game/machinery/computer/card.dm +++ b/code/game/machinery/computer/card.dm @@ -374,7 +374,6 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) else if((ACCESS_HOP in scan.access) && ((target_dept==1) || !target_dept)) region_access |= 1 - region_access |= 6 get_subordinates("Head of Personnel") if((ACCESS_HOS in scan.access) && ((target_dept==2) || !target_dept)) region_access |= 2 @@ -388,6 +387,9 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) if((ACCESS_CE in scan.access) && ((target_dept==5) || !target_dept)) region_access |= 5 get_subordinates("Chief Engineer") + if((ACCESS_QM in scan.access) && ((target_dept==6) || !target_dept)) + region_access |= 6 + get_subordinates("Quartermaster") if(region_access) authenticated = 1 else if ((!( authenticated ) && issilicon(usr)) && (!modify)) @@ -607,7 +609,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) typed_circuit.target_dept = target_dept else target_dept = typed_circuit.target_dept - var/list/dept_list = list("general","security","medical","science","engineering") + var/list/dept_list = list("civilian","security","medical","science","engineering","cargo") name = "[dept_list[target_dept]] department console" /obj/machinery/computer/card/minor/hos @@ -631,3 +633,9 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) icon_screen = "idce" light_color = LIGHT_COLOR_YELLOW + +/obj/machinery/computer/card/minor/qm + target_dept = 6 + icon_screen = "idqm" + + light_color = LIGHT_COLOR_ORANGE diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm index 335f1da7..832dae31 100644 --- a/code/game/objects/items/circuitboards/computer_circuitboards.dm +++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm @@ -63,7 +63,7 @@ name = "Department Management Console (Computer Board)" build_path = /obj/machinery/computer/card/minor var/target_dept = 1 - var/list/dept_list = list("General","Security","Medical","Science","Engineering") + var/list/dept_list = list("Civilian","Security","Medical","Science","Engineering","Cargo") /obj/item/circuitboard/computer/card/minor/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/screwdriver)) diff --git a/icons/obj/computer.dmi b/icons/obj/computer.dmi index c3374e9c1c56ed17c31aa85163836030cb05f47c..1307f063a81686d2de7530b79a716b3b8eb882cc 100644 GIT binary patch delta 26426 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 From c59c9e88aed78377b31baf9ff50c780fed4932d0 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Sun, 10 Nov 2019 11:43:41 -0700 Subject: [PATCH 2/4] Merge pull request #9746 from Ghommie/Ghommie-cit328 Ports "Cleans up the new alt clicking functionality" from /tg/ --- code/game/machinery/_machinery.dm | 81 ----- code/game/machinery/computer/_computer.dm | 1 + code/game/machinery/computer/card.dm | 302 +++++++++--------- .../machinery/computer/gulag_teleporter.dm | 163 ---------- code/game/machinery/computer/medical.dm | 6 - code/game/machinery/computer/security.dm | 3 +- code/modules/mining/machine_redemption.dm | 4 +- tgstation.dme | 1 - 8 files changed, 156 insertions(+), 405 deletions(-) delete mode 100644 code/game/machinery/computer/gulag_teleporter.dm diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index 938a4d92..ddb12dd4 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -113,11 +113,6 @@ Class Procs: var/atom/movable/occupant = null var/speed_process = FALSE // Process as fast as possible? var/obj/item/circuitboard/circuit // Circuit to be created and inserted when the machinery is created - var/obj/item/card/id/inserted_scan_id - var/obj/item/card/id/inserted_modify_id - var/list/region_access = null // For the identification console (card.dm) - var/list/head_subordinates = null // For the identification console (card.dm) - var/authenticated = 0 // For the identification console (card.dm) var/interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_SET_MACHINE @@ -472,8 +467,6 @@ Class Procs: . += "It's falling apart!" if(user.research_scanner && component_parts) . += display_parts(user, TRUE) - if(inserted_scan_id || inserted_modify_id) - . += "Alt-click to eject the ID card." //called on machinery construction (i.e from frame to machinery) but not on initialization /obj/machinery/proc/on_construction() @@ -507,77 +500,3 @@ Class Procs: . = . % 9 AM.pixel_x = -8 + ((.%3)*8) AM.pixel_y = -8 + (round( . / 3)*8) - -/obj/machinery/CanPass(atom/movable/mover, turf/target) - . = ..() - if(istype(mover) && (mover.pass_flags & PASSMACHINES)) - return TRUE -/obj/machinery/proc/id_insert_scan(mob/user, obj/item/card/id/I) - I = user.get_active_held_item() - if(istype(I)) - if(inserted_scan_id) - to_chat(user, "There's already an ID card in the console!") - return - if(!user.transferItemToLoc(I, src)) - return - inserted_scan_id = I - user.visible_message("[user] inserts an ID card into the console.", \ - "You insert the ID card into the console.") - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) - updateUsrDialog() - -/obj/machinery/proc/id_eject_scan(mob/user) - if(!inserted_scan_id) - to_chat(user, "There's no ID card in the console!") - return - if(inserted_scan_id) - inserted_scan_id.forceMove(drop_location()) - if(!issilicon(user) && Adjacent(user)) - user.put_in_hands(inserted_scan_id) - inserted_scan_id = null - user.visible_message("[user] gets an ID card from the console.", \ - "You get the ID card from the console.") - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) - updateUsrDialog() - -/obj/machinery/proc/id_eject_modify(mob/user) - if(inserted_modify_id) - GLOB.data_core.manifest_modify(inserted_modify_id.registered_name, inserted_modify_id.assignment) - inserted_modify_id.update_label() - inserted_modify_id.forceMove(drop_location()) - if(!issilicon(user) && Adjacent(user)) - user.put_in_hands(inserted_modify_id) - user.visible_message("[user] gets an ID card from the console.", \ - "You get the ID card from the console.") - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) - inserted_modify_id = null - region_access = null - head_subordinates = null - updateUsrDialog() - -/obj/machinery/proc/id_insert_modify(mob/user) - var/obj/item/card/id/I = user.get_active_held_item() - if(istype(I)) - if(inserted_modify_id) - to_chat(user, "There's already an ID card in the console!") - return - if(!user.transferItemToLoc(I, src)) - return - inserted_modify_id = I - user.visible_message("[user] inserts an ID card into the console.", \ - "You insert the ID card into the console.") - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) - updateUsrDialog() - -/obj/machinery/AltClick(mob/user) - . = ..() - if(!user.canUseTopic(src, !issilicon(user)) || !is_operational()) - return - if(inserted_modify_id) - id_eject_modify(user) - authenticated = FALSE - return - if(inserted_scan_id) - id_eject_scan(user) - authenticated = FALSE - return diff --git a/code/game/machinery/computer/_computer.dm b/code/game/machinery/computer/_computer.dm index 3c3f0e7f..24824dbb 100644 --- a/code/game/machinery/computer/_computer.dm +++ b/code/game/machinery/computer/_computer.dm @@ -13,6 +13,7 @@ var/icon_keyboard = "generic_key" var/icon_screen = "generic" var/clockwork = FALSE + var/authenticated = FALSE /obj/machinery/computer/Initialize(mapload, obj/item/circuitboard/C) . = ..() diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm index d45c3506..acca6633 100644 --- a/code/game/machinery/computer/card.dm +++ b/code/game/machinery/computer/card.dm @@ -11,8 +11,6 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) icon_keyboard = "id_key" req_one_access = list(ACCESS_HEADS, ACCESS_CHANGE_IDS) circuit = /obj/item/circuitboard/computer/card - var/obj/item/card/id/scan = null - var/obj/item/card/id/modify = null var/mode = 0 var/printing = null var/target_dept = 0 //Which department this computer has access to. 0=all departments @@ -38,68 +36,63 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) //This is used to keep track of opened positions for jobs to allow instant closing //Assoc array: "JobName" = (int) - var/list/opened_positions = list(); + var/list/opened_positions = list() + var/obj/item/card/id/inserted_scan_id + var/obj/item/card/id/inserted_modify_id + var/list/region_access = null + var/list/head_subordinates = null light_color = LIGHT_COLOR_BLUE /obj/machinery/computer/card/examine(mob/user) . = ..() - if(scan || modify) + if(inserted_scan_id || inserted_modify_id) . += "Alt-click to eject the ID card." /obj/machinery/computer/card/Initialize() . = ..() change_position_cooldown = CONFIG_GET(number/id_console_jobslot_delay) -/obj/machinery/computer/card/attackby(obj/O, mob/user, params)//TODO:SANITY - if(istype(O, /obj/item/card/id)) - var/obj/item/card/id/idcard = O - if(check_access(idcard)) - if(!scan) - if (!user.transferItemToLoc(idcard,src)) - return - scan = idcard - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0) - else if(!modify) - if (!user.transferItemToLoc(idcard,src)) - return - modify = idcard - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0) +/obj/machinery/computer/card/attackby(obj/I, mob/user, params) + if(istype(I, /obj/item/card/id)) + if(!inserted_scan_id) + if(id_insert(user, I, inserted_scan_id)) + inserted_scan_id = I + return + if(!inserted_modify_id) + if(id_insert(user, I, inserted_modify_id)) + inserted_modify_id = I + return else - if(!modify) - if (!user.transferItemToLoc(idcard,src)) - return - modify = idcard - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0) - updateUsrDialog() + to_chat(user, "There's already an ID card in the console!") else return ..() /obj/machinery/computer/card/Destroy() - if(scan) - qdel(scan) - scan = null - if(modify) - qdel(modify) - modify = null + if(inserted_scan_id) + qdel(inserted_scan_id) + inserted_scan_id = null + if(inserted_modify_id) + qdel(inserted_modify_id) + inserted_modify_id = null return ..() /obj/machinery/computer/card/handle_atom_del(atom/A) ..() - if(A == scan) - scan = null + if(A == inserted_scan_id) + inserted_scan_id = null updateUsrDialog() - if(A == modify) - modify = null + if(A == inserted_modify_id) + inserted_modify_id = null updateUsrDialog() /obj/machinery/computer/card/on_deconstruction() - if(scan) - scan.forceMove(drop_location()) - scan = null - if(modify) - modify.forceMove(drop_location()) - modify = null + if(inserted_scan_id) + inserted_scan_id.forceMove(drop_location()) + inserted_scan_id = null + if(inserted_modify_id) + inserted_modify_id.forceMove(drop_location()) + inserted_modify_id = null //Check if you can't open a new position for a certain job /obj/machinery/computer/card/proc/job_blacklisted(jobtitle) @@ -130,9 +123,50 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) return -1 return 0 +/obj/machinery/computer/card/proc/id_insert(mob/user, obj/item/card/id/I, target) + if(istype(I)) + if(target) + to_chat(user, "There's already an ID card in the console!") + return FALSE + if(!user.transferItemToLoc(I, src)) + return FALSE + user.visible_message("[user] inserts an ID card into the console.", \ + "You insert the ID card into the console.") + playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) + updateUsrDialog() + return TRUE + +/obj/machinery/computer/card/proc/id_eject(mob/user, obj/target) + if(!target) + to_chat(user, "There's no ID card in the console!") + return FALSE + else + target.forceMove(drop_location()) + if(!issilicon(user) && Adjacent(user)) + user.put_in_hands(target) + user.visible_message("[user] gets an ID card from the console.", \ + "You get the ID card from the console.") + playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) + updateUsrDialog() + return TRUE + +/obj/machinery/computer/card/AltClick(mob/user) + ..() + if(!user.canUseTopic(src, !issilicon(user)) || !is_operational()) + return + if(inserted_modify_id) + if(id_eject(user, inserted_modify_id)) + inserted_modify_id = null + authenticated = FALSE + return + if(inserted_scan_id) + if(id_eject(user, inserted_scan_id)) + inserted_scan_id = null + authenticated = FALSE + return + /obj/machinery/computer/card/ui_interact(mob/user) . = ..() - var/dat if(!SSticker) return @@ -147,15 +181,15 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) dat = "Return" dat += " || Confirm Identity: " var/S - if(scan) - S = html_encode(scan.name) + if(inserted_scan_id) + S = html_encode(inserted_scan_id.name) else S = "--------" - dat += "[S]" + dat += "[S]" dat += "" dat += "" var/ID - if(scan && (ACCESS_CHANGE_IDS in scan.access) && !target_dept) + if(inserted_scan_id && (ACCESS_CHANGE_IDS in inserted_scan_id.access) && !target_dept) ID = 1 else ID = 0 @@ -221,33 +255,33 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) var/target_name var/target_owner var/target_rank - if(modify) - target_name = html_encode(modify.name) + if(inserted_modify_id) + target_name = html_encode(inserted_modify_id.name) else target_name = "--------" - if(modify && modify.registered_name) - target_owner = html_encode(modify.registered_name) + if(inserted_modify_id && inserted_modify_id.registered_name) + target_owner = html_encode(inserted_modify_id.registered_name) else target_owner = "--------" - if(modify && modify.assignment) - target_rank = html_encode(modify.assignment) + if(inserted_modify_id && inserted_modify_id.assignment) + target_rank = html_encode(inserted_modify_id.assignment) else target_rank = "Unassigned" var/scan_name - if(scan) - scan_name = html_encode(scan.name) + if(inserted_scan_id) + scan_name = html_encode(inserted_scan_id.name) else scan_name = "--------" if(!authenticated) header += "
Please insert the cards into the slots
" - header += "Target: [target_name]
" - header += "Confirm Identity: [scan_name]
" + header += "Target: [target_name]
" + header += "Confirm Identity: [scan_name]
" else header += "

" - header += "Remove [target_name] || " - header += "Remove [scan_name]
" + header += "Remove [target_name] || " + header += "Remove [scan_name]
" header += "Access Crew Manifest
" header += "Log Out
" @@ -262,7 +296,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) var/body - if (authenticated && modify) + if (authenticated && inserted_modify_id) var/carddesc = text("") var/jobs = text("") @@ -303,7 +337,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) if(istype(src, /obj/machinery/computer/card/centcom)) accesses += "
Central Command:
" for(var/A in get_all_centcom_access()) - if(A in modify.access) + if(A in inserted_modify_id.access) accesses += "[replacetext(get_centcom_access_desc(A), " ", " ")] " else accesses += "[replacetext(get_centcom_access_desc(A), " ", " ")] " @@ -321,7 +355,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) continue accesses += "
JobSlotsOpen jobClose jobPrioritize
" for(var/A in get_region_accesses(i)) - if(A in modify.access) + if(A in inserted_modify_id.access) accesses += "[replacetext(get_access_desc(A), " ", " ")] " else accesses += "[replacetext(get_access_desc(A), " ", " ")] " @@ -353,52 +387,66 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) usr.set_machine(src) switch(href_list["choice"]) - if ("modify") - eject_id_modify(usr) - if ("scan") - eject_id_scan(usr) + if ("inserted_modify_id") + if (inserted_modify_id) + if(id_eject(usr, inserted_modify_id)) + inserted_modify_id = null + else + var/mob/M = usr + var/obj/item/card/id/I = M.get_idcard(TRUE) + if(id_insert(usr, I, inserted_modify_id)) + inserted_modify_id = I + if ("inserted_scan_id") + if (inserted_scan_id) + if(id_eject(usr, inserted_scan_id)) + inserted_scan_id = null + else + var/mob/M = usr + var/obj/item/card/id/I = M.get_idcard(TRUE) + if(id_insert(usr, I, inserted_scan_id)) + inserted_scan_id = I if ("auth") - if ((!( authenticated ) && (scan || issilicon(usr)) && (modify || mode))) - if (check_access(scan)) + if ((!( authenticated ) && (inserted_scan_id || issilicon(usr)) && (inserted_modify_id || mode))) + if (check_access(inserted_scan_id)) region_access = list() head_subordinates = list() - if(ACCESS_CHANGE_IDS in scan.access) + if(ACCESS_CHANGE_IDS in inserted_scan_id.access) if(target_dept) head_subordinates = get_all_jobs() region_access |= target_dept authenticated = 1 else authenticated = 2 - playsound(src, 'sound/machines/terminal_on.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE) else - if((ACCESS_HOP in scan.access) && ((target_dept==1) || !target_dept)) + if((ACCESS_HOP in inserted_scan_id.access) && ((target_dept==1) || !target_dept)) region_access |= 1 get_subordinates("Head of Personnel") - if((ACCESS_HOS in scan.access) && ((target_dept==2) || !target_dept)) + if((ACCESS_HOS in inserted_scan_id.access) && ((target_dept==2) || !target_dept)) region_access |= 2 get_subordinates("Head of Security") - if((ACCESS_CMO in scan.access) && ((target_dept==3) || !target_dept)) + if((ACCESS_CMO in inserted_scan_id.access) && ((target_dept==3) || !target_dept)) region_access |= 3 get_subordinates("Chief Medical Officer") - if((ACCESS_RD in scan.access) && ((target_dept==4) || !target_dept)) + if((ACCESS_RD in inserted_scan_id.access) && ((target_dept==4) || !target_dept)) region_access |= 4 get_subordinates("Research Director") - if((ACCESS_CE in scan.access) && ((target_dept==5) || !target_dept)) + if((ACCESS_CE in inserted_scan_id.access) && ((target_dept==5) || !target_dept)) region_access |= 5 get_subordinates("Chief Engineer") - if((ACCESS_QM in scan.access) && ((target_dept==6) || !target_dept)) + if((ACCESS_QM in inserted_scan_id.access) && ((target_dept==6) || !target_dept)) region_access |= 6 get_subordinates("Quartermaster") if(region_access) authenticated = 1 - else if ((!( authenticated ) && issilicon(usr)) && (!modify)) + else if ((!( authenticated ) && issilicon(usr)) && (!inserted_modify_id)) to_chat(usr, "You can't modify an ID without an ID inserted to modify! Once one is in the modify slot on the computer, you can log in.") if ("logout") region_access = null head_subordinates = null authenticated = 0 - playsound(src, 'sound/machines/terminal_off.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE) if("access") if(href_list["allowed"]) @@ -406,20 +454,20 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) var/access_type = text2num(href_list["access_target"]) var/access_allowed = text2num(href_list["allowed"]) if(access_type in (istype(src, /obj/machinery/computer/card/centcom)?get_all_centcom_access() : get_all_accesses())) - modify.access -= access_type + inserted_modify_id.access -= access_type if(access_allowed == 1) - modify.access += access_type - playsound(src, "terminal_type", 50, 0) + inserted_modify_id.access += access_type + playsound(src, "terminal_type", 50, FALSE) if ("assign") if (authenticated == 2) var/t1 = href_list["assign_target"] if(t1 == "Custom") - var/newJob = reject_bad_text(input("Enter a custom job assignment.", "Assignment", modify ? modify.assignment : "Unassigned"), MAX_NAME_LEN) + var/newJob = reject_bad_text(input("Enter a custom job assignment.", "Assignment", inserted_modify_id ? inserted_modify_id.assignment : "Unassigned"), MAX_NAME_LEN) if(newJob) t1 = newJob else if(t1 == "Unassigned") - modify.access -= get_all_accesses() + inserted_modify_id.access -= get_all_accesses() else var/datum/job/jobdatum @@ -434,24 +482,24 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) updateUsrDialog() return - modify.access = ( istype(src, /obj/machinery/computer/card/centcom) ? get_centcom_access(t1) : jobdatum.get_access() ) - if (modify) - modify.assignment = t1 - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + inserted_modify_id.access = ( istype(src, /obj/machinery/computer/card/centcom) ? get_centcom_access(t1) : jobdatum.get_access() ) + if (inserted_modify_id) + inserted_modify_id.assignment = t1 + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) if ("demote") - if(modify.assignment in head_subordinates || modify.assignment == "Assistant") - modify.assignment = "Unassigned" - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + if(inserted_modify_id.assignment in head_subordinates || inserted_modify_id.assignment == "Assistant") + inserted_modify_id.assignment = "Unassigned" + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) else to_chat(usr, "You are not authorized to demote this position.") if ("reg") if (authenticated) - var/t2 = modify - if ((authenticated && modify == t2 && (in_range(src, usr) || issilicon(usr)) && isturf(loc))) + var/t2 = inserted_modify_id + if ((authenticated && inserted_modify_id == t2 && (in_range(src, usr) || issilicon(usr)) && isturf(loc))) var/newName = reject_bad_name(href_list["reg"]) if(newName) - modify.registered_name = newName - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + inserted_modify_id.registered_name = newName + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) else to_chat(usr, "Invalid name entered.") updateUsrDialog() @@ -462,11 +510,11 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) if("return") //DISPLAY MAIN MENU mode = 3; - playsound(src, "terminal_type", 25, 0) + playsound(src, "terminal_type", 25, FALSE) if("make_job_available") // MAKE ANOTHER JOB POSITION AVAILABLE FOR LATE JOINERS - if(scan && (ACCESS_CHANGE_IDS in scan.access) && !target_dept) + if(inserted_scan_id && (ACCESS_CHANGE_IDS in inserted_scan_id.access) && !target_dept) var/edit_job_target = href_list["job"] var/datum/job/j = SSjob.GetJob(edit_job_target) if(!j) @@ -479,11 +527,11 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) GLOB.time_last_changed_position = world.time / 10 j.total_positions++ opened_positions[edit_job_target]++ - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) if("make_job_unavailable") // MAKE JOB POSITION UNAVAILABLE FOR LATE JOINERS - if(scan && (ACCESS_CHANGE_IDS in scan.access) && !target_dept) + if(inserted_scan_id && (ACCESS_CHANGE_IDS in inserted_scan_id.access) && !target_dept) var/edit_job_target = href_list["job"] var/datum/job/j = SSjob.GetJob(edit_job_target) if(!j) @@ -497,11 +545,11 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) GLOB.time_last_changed_position = world.time / 10 j.total_positions-- opened_positions[edit_job_target]-- - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE) if ("prioritize_job") // TOGGLE WHETHER JOB APPEARS AS PRIORITIZED IN THE LOBBY - if(scan && (ACCESS_CHANGE_IDS in scan.access) && !target_dept) + if(inserted_scan_id && (ACCESS_CHANGE_IDS in inserted_scan_id.access) && !target_dept) var/priority_target = href_list["job"] var/datum/job/j = SSjob.GetJob(priority_target) if(!j) @@ -518,7 +566,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) else SSjob.prioritized_jobs += j to_chat(usr, "[j.title] has been successfully [priority ? "prioritized" : "unprioritized"]. Potential employees will notice your request.") - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) if ("print") if (!( printing )) @@ -531,59 +579,9 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) P.info = t1 P.name = "paper- 'Crew Manifest'" printing = null - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0) - if (modify) - modify.update_label() - updateUsrDialog() - -/obj/machinery/computer/card/AltClick(mob/user) - if(!user.canUseTopic(src, !issilicon(user)) || !is_operational()) - return - if(scan) - eject_id_scan(user) - if(modify) - eject_id_modify(user) - -/obj/machinery/computer/card/proc/eject_id_scan(mob/user) - if(scan) - scan.forceMove(drop_location()) - if(!issilicon(user) && Adjacent(user)) - user.put_in_hands(scan) - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0) - scan = null - else //switching the ID with the one you're holding - if(issilicon(user) || !Adjacent(user)) - return - var/obj/item/I = user.get_active_held_item() - if(istype(I, /obj/item/card/id)) - if(!user.transferItemToLoc(I,src)) - return - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0) - scan = I - authenticated = FALSE - updateUsrDialog() - -/obj/machinery/computer/card/proc/eject_id_modify(mob/user) - if(modify) - GLOB.data_core.manifest_modify(modify.registered_name, modify.assignment) - modify.update_label() - modify.forceMove(drop_location()) - if(!issilicon(user) && Adjacent(user)) - user.put_in_hands(modify) - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0) - modify = null - region_access = null - head_subordinates = null - else //switching the ID with the one you're holding - if(issilicon(user) || !Adjacent(user)) - return - var/obj/item/I = user.get_active_held_item() - if(istype(I, /obj/item/card/id)) - if (!user.transferItemToLoc(I,src)) - return - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0) - modify = I - authenticated = FALSE + playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) + if (inserted_modify_id) + inserted_modify_id.update_label() updateUsrDialog() /obj/machinery/computer/card/proc/get_subordinates(rank) diff --git a/code/game/machinery/computer/gulag_teleporter.dm b/code/game/machinery/computer/gulag_teleporter.dm deleted file mode 100644 index 68cbf03f..00000000 --- a/code/game/machinery/computer/gulag_teleporter.dm +++ /dev/null @@ -1,163 +0,0 @@ -//computer that handle the points and teleports the prisoner -/obj/machinery/computer/gulag_teleporter_computer - name = "labor camp teleporter console" - desc = "Used to send criminals to the Labor Camp." - icon_screen = "explosive" - icon_keyboard = "security_key" - req_access = list(ACCESS_ARMORY) - circuit = /obj/item/circuitboard/computer/gulag_teleporter_console - var/default_goal = 200 - var/obj/item/card/id/prisoner/id = null - var/obj/machinery/gulag_teleporter/teleporter = null - var/obj/structure/gulag_beacon/beacon = null - var/mob/living/carbon/human/prisoner = null - var/datum/data/record/temporary_record = null - - light_color = LIGHT_COLOR_RED - -/obj/machinery/computer/gulag_teleporter_computer/Initialize() - . = ..() - scan_machinery() - -/obj/machinery/computer/gulag_teleporter_computer/Destroy() - if(id) - id.forceMove(get_turf(src)) - return ..() - -/obj/machinery/computer/gulag_teleporter_computer/attackby(obj/item/W, mob/user) - if(istype(W, /obj/item/card/id/prisoner)) - if(!id) - if (!user.transferItemToLoc(W,src)) - return - id = W - to_chat(user, "You insert [W].") - return - else - to_chat(user, "There's an ID inserted already.") - return ..() - -/obj/machinery/computer/gulag_teleporter_computer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ - datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "gulag_console", name, 455, 440, master_ui, state) - ui.open() - -/obj/machinery/computer/gulag_teleporter_computer/ui_data(mob/user) - var/list/data = list() - - var/list/prisoner_list = list() - var/can_teleport = FALSE - - if(teleporter && (teleporter.occupant && ishuman(teleporter.occupant))) - prisoner = teleporter.occupant - prisoner_list["name"] = prisoner.real_name - if(id) - can_teleport = TRUE - if(!isnull(GLOB.data_core.general)) - for(var/r in GLOB.data_core.security) - var/datum/data/record/R = r - if(R.fields["name"] == prisoner_list["name"]) - temporary_record = R - prisoner_list["crimstat"] = temporary_record.fields["criminal"] - - data["prisoner"] = prisoner_list - - if(teleporter) - data["teleporter"] = teleporter - data["teleporter_location"] = "([teleporter.x], [teleporter.y], [teleporter.z])" - data["teleporter_lock"] = teleporter.locked - data["teleporter_state_open"] = teleporter.state_open - if(beacon) - data["beacon"] = beacon - data["beacon_location"] = "([beacon.x], [beacon.y], [beacon.z])" - if(id) - data["id"] = id - data["id_name"] = id.registered_name - data["goal"] = id.goal - data["can_teleport"] = can_teleport - - return data - -/obj/machinery/computer/gulag_teleporter_computer/ui_act(action, list/params) - if(..()) - return - if(!allowed(usr)) - to_chat(usr, "Access denied.") - return - switch(action) - if("scan_teleporter") - teleporter = findteleporter() - if("scan_beacon") - beacon = findbeacon() - if("handle_id") - if(id) - usr.put_in_hands(id) - id = null - else - var/obj/item/I = usr.is_holding_item_of_type(/obj/item/card/id/prisoner) - if(I) - if(!usr.transferItemToLoc(I, src)) - return - id = I - if("set_goal") - var/new_goal = input("Set the amount of points:", "Points", id.goal) as num|null - if(!isnum(new_goal)) - return - if(!new_goal) - new_goal = default_goal - if (new_goal > 1000) - to_chat(usr, "The entered amount of points is too large. Points have instead been set to the maximum allowed amount.") - id.goal = CLAMP(new_goal, 0, 1000) //maximum 1000 points - if("toggle_open") - if(teleporter.locked) - to_chat(usr, "The teleporter is locked") - return - teleporter.toggle_open() - if("teleporter_lock") - if(teleporter.state_open) - to_chat(usr, "Close the teleporter before locking!") - return - teleporter.locked = !teleporter.locked - if("teleport") - if(!teleporter || !beacon) - return - addtimer(CALLBACK(src, .proc/teleport, usr), 5) - -/obj/machinery/computer/gulag_teleporter_computer/proc/scan_machinery() - teleporter = findteleporter() - beacon = findbeacon() - -/obj/machinery/computer/gulag_teleporter_computer/proc/findteleporter() - var/obj/machinery/gulag_teleporter/teleporterf = null - - for(var/direction in GLOB.cardinals) - teleporterf = locate(/obj/machinery/gulag_teleporter, get_step(src, direction)) - if(teleporterf && teleporterf.is_operational()) - return teleporterf - -/obj/machinery/computer/gulag_teleporter_computer/proc/findbeacon() - return locate(/obj/structure/gulag_beacon) - -/obj/machinery/computer/gulag_teleporter_computer/proc/teleport(mob/user) - if(!id) //incase the ID was removed after the transfer timer was set. - say("Warning: Unable to transfer prisoner without a valid Prisoner ID inserted!") - return - var/id_goal_not_set - if(!id.goal) - id_goal_not_set = TRUE - id.goal = default_goal - say("[id]'s ID card goal defaulting to [id.goal] points.") - log_game("[key_name(user)] teleported [key_name(prisoner)] to the Labor Camp [COORD(beacon)] for [id_goal_not_set ? "default goal of ":""][id.goal] points.") - teleporter.handle_prisoner(id, temporary_record) - playsound(src, 'sound/weapons/emitter.ogg', 50, 1) - prisoner.forceMove(get_turf(beacon)) - prisoner.Knockdown(40) // small travel dizziness - to_chat(prisoner, "The teleportation makes you a little dizzy.") - new /obj/effect/particle_effect/sparks(get_turf(prisoner)) - playsound(src, "sparks", 50, 1) - if(teleporter.locked) - teleporter.locked = FALSE - teleporter.toggle_open() - id = null - temporary_record = null diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index e4af7acd..ff7311c8 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -22,12 +22,6 @@ /obj/machinery/computer/med_data/syndie icon_keyboard = "syndie_key" -/obj/machinery/computer/med_data/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/card/id)) - id_insert_scan(user) - else - return ..() - /obj/machinery/computer/med_data/ui_interact(mob/user) . = ..() var/dat diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 2e80aab6..705f4673 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -35,7 +35,8 @@ //Someone needs to break down the dat += into chunks instead of long ass lines. /obj/machinery/computer/secure_data/ui_interact(mob/user) . = ..() - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) + if(isliving(user)) + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) if(src.z > 6) to_chat(user, "Unable to establish a connection: \black You're too far away from the station!") return diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm index 6c1a00b0..c13408b2 100644 --- a/code/modules/mining/machine_redemption.dm +++ b/code/modules/mining/machine_redemption.dm @@ -304,7 +304,9 @@ return var/alloy_id = params["id"] var/datum/design/alloy = stored_research.isDesignResearchedID(alloy_id) - if((check_access(inserted_scan_id) || allowed(usr)) && alloy) + var/mob/M = usr + var/obj/item/card/id/I = M.get_idcard(TRUE) + if((check_access(I) || allowed(usr)) && alloy) var/smelt_amount = can_smelt_alloy(alloy) var/desired = 0 if (params["sheets"]) diff --git a/tgstation.dme b/tgstation.dme index 77cbdddc..a6158571 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -665,7 +665,6 @@ #include "code\game\machinery\computer\communications.dm" #include "code\game\machinery\computer\crew.dm" #include "code\game\machinery\computer\dna_console.dm" -#include "code\game\machinery\computer\gulag_teleporter.dm" #include "code\game\machinery\computer\launchpad_control.dm" #include "code\game\machinery\computer\law.dm" #include "code\game\machinery\computer\medical.dm" From c7db7cb2bec2dfbb7656fb71c8b36f9a5c9a19b0 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Sat, 16 Nov 2019 01:17:23 -0700 Subject: [PATCH 3/4] The ID Code Cleanup and Fixening (tm) --- code/__DEFINES/access.dm | 2 + code/__DEFINES/is_helpers.dm | 2 + code/game/machinery/computer/apc_control.dm | 4 +- code/game/machinery/computer/card.dm | 310 +++++++++--------- .../game/machinery/computer/communications.dm | 8 +- code/game/objects/items/cards_ids.dm | 153 +++++++-- code/game/objects/items/devices/PDA/PDA.dm | 60 +++- code/game/objects/items/storage/wallets.dm | 15 + code/modules/cargo/bounty_console.dm | 58 ++-- code/modules/cargo/console.dm | 10 +- code/modules/cargo/expressconsole.dm | 5 +- code/modules/jobs/access.dm | 14 +- code/modules/jobs/job_types/security.dm | 12 +- code/modules/mob/living/carbon/human/human.dm | 2 +- .../mob/living/carbon/human/human_helpers.dm | 19 +- .../mob/living/simple_animal/simple_animal.dm | 4 +- code/modules/mob/mob.dm | 4 - code/modules/mob/mob_helpers.dm | 14 + .../computers/item/computer.dm | 15 + .../modular_computers/file_system/program.dm | 13 +- .../file_system/programs/card.dm | 2 +- .../modular_computers/hardware/card_slot.dm | 11 + code/modules/shuttle/emergency.dm | 4 +- code/modules/shuttle/special.dm | 2 +- .../code/game/machinery/computer/card.dm | 3 - modular_citadel/code/game/objects/ids.dm | 83 ----- tgstation.dme | 2 - 27 files changed, 467 insertions(+), 364 deletions(-) delete mode 100644 modular_citadel/code/game/machinery/computer/card.dm delete mode 100644 modular_citadel/code/game/objects/ids.dm diff --git a/code/__DEFINES/access.dm b/code/__DEFINES/access.dm index c9d545fc..d9eb48d7 100644 --- a/code/__DEFINES/access.dm +++ b/code/__DEFINES/access.dm @@ -64,6 +64,8 @@ #define ACCESS_WEAPONS 66 //Weapon authorization for secbots #define ACCESS_NETWORK 67 //NTnet diagnostics/monitoring software #define ACCESS_CLONING 68 //Cloning room and clone pod ejection +#define ACCESS_ENTER_GENPOP 69 +#define ACCESS_LEAVE_GENPOP 70 //BEGIN CENTCOM ACCESS /*Should leave plenty of room if we need to add more access levels. diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 2dbc63aa..5f5903e2 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -221,6 +221,8 @@ GLOBAL_LIST_INIT(heavyfootmob, typecacheof(list( #define isitem(A) (istype(A, /obj/item)) +#define isidcard(I) (istype(I, /obj/item/card/id)) + #define isstructure(A) (istype(A, /obj/structure)) #define ismachinery(A) (istype(A, /obj/machinery)) diff --git a/code/game/machinery/computer/apc_control.dm b/code/game/machinery/computer/apc_control.dm index d433c557..1101034c 100644 --- a/code/game/machinery/computer/apc_control.dm +++ b/code/game/machinery/computer/apc_control.dm @@ -92,9 +92,7 @@ if(!usr || !usr.canUseTopic(src) || stat || QDELETED(src)) return if(href_list["authenticate"]) - var/obj/item/card/id/ID = usr.get_active_held_item() - if(!istype(ID)) - ID = usr.get_idcard() + var/obj/item/card/id/ID = usr.get_idcard(TRUE) if(ID && istype(ID)) if(check_access(ID)) authenticated = TRUE diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm index acca6633..eaecc9a9 100644 --- a/code/game/machinery/computer/card.dm +++ b/code/game/machinery/computer/card.dm @@ -4,6 +4,11 @@ //increase the slots of many jobs. GLOBAL_VAR_INIT(time_last_changed_position, 0) +#define JOB_ALLOWED 1 +#define JOB_COOLDOWN -2 +#define JOB_MAX_POSITIONS -1 // Trying to reduce the number of slots below that of current holders of that job, or trying to open more slots than allowed +#define JOB_DENIED 0 + /obj/machinery/computer/card name = "identification console" desc = "You can use this to manage jobs and ID access." @@ -29,7 +34,8 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) "Head of Security", "Chief Engineer", "Research Director", - "Chief Medical Officer") + "Chief Medical Officer", + "Quartermaster") //The scaling factor of max total positions in relation to the total amount of people on board the station in % var/max_relative_positions = 30 //30%: Seems reasonable, limit of 6 @ 20 players @@ -44,27 +50,30 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) light_color = LIGHT_COLOR_BLUE -/obj/machinery/computer/card/examine(mob/user) - . = ..() - if(inserted_scan_id || inserted_modify_id) - . += "Alt-click to eject the ID card." +/obj/machinery/computer/card/proc/get_jobs() + return get_all_jobs() + +/obj/machinery/computer/card/centcom/get_jobs() + return get_all_centcom_jobs() /obj/machinery/computer/card/Initialize() . = ..() change_position_cooldown = CONFIG_GET(number/id_console_jobslot_delay) +/obj/machinery/computer/card/examine(mob/user) + . = ..() + if(inserted_scan_id || inserted_modify_id) + . += "Alt-click to eject the ID card." + /obj/machinery/computer/card/attackby(obj/I, mob/user, params) - if(istype(I, /obj/item/card/id)) - if(!inserted_scan_id) + if(isidcard(I)) + if(check_access(I) && !inserted_scan_id) if(id_insert(user, I, inserted_scan_id)) inserted_scan_id = I - return - if(!inserted_modify_id) - if(id_insert(user, I, inserted_modify_id)) - inserted_modify_id = I - return - else - to_chat(user, "There's already an ID card in the console!") + updateUsrDialog() + else if(id_insert(user, I, inserted_modify_id)) + inserted_modify_id = I + updateUsrDialog() else return ..() @@ -106,10 +115,10 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) if((job.total_positions <= GLOB.player_list.len * (max_relative_positions / 100))) var/delta = (world.time / 10) - GLOB.time_last_changed_position if((change_position_cooldown < delta) || (opened_positions[job.title] < 0)) - return 1 - return -2 - return -1 - return 0 + return JOB_ALLOWED + return JOB_COOLDOWN + return JOB_MAX_POSITIONS + return JOB_DENIED //Logic check for Topic() if you can close the job /obj/machinery/computer/card/proc/can_close_job(datum/job/job) @@ -118,34 +127,44 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) if(job.total_positions > job.current_positions) var/delta = (world.time / 10) - GLOB.time_last_changed_position if((change_position_cooldown < delta) || (opened_positions[job.title] > 0)) - return 1 - return -2 - return -1 - return 0 + return JOB_ALLOWED + return JOB_COOLDOWN + return JOB_MAX_POSITIONS + return JOB_DENIED -/obj/machinery/computer/card/proc/id_insert(mob/user, obj/item/card/id/I, target) - if(istype(I)) - if(target) - to_chat(user, "There's already an ID card in the console!") - return FALSE - if(!user.transferItemToLoc(I, src)) - return FALSE - user.visible_message("[user] inserts an ID card into the console.", \ - "You insert the ID card into the console.") - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) - updateUsrDialog() - return TRUE +/obj/machinery/computer/card/proc/id_insert(mob/user, obj/item/inserting_item, obj/item/target) + var/obj/item/card/id/card_to_insert = inserting_item + var/holder_item = FALSE + + if(!isidcard(card_to_insert)) + card_to_insert = inserting_item.RemoveID() + holder_item = TRUE + + if(!card_to_insert || !user.transferItemToLoc(card_to_insert, src)) + return FALSE + + if(target) + if(holder_item && inserting_item.InsertID(target)) + playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) + else + id_eject(user, target) + + user.visible_message("[user] inserts \the [card_to_insert] into \the [src].", + "You insert \the [card_to_insert] into \the [src].") + playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) + updateUsrDialog() + return TRUE /obj/machinery/computer/card/proc/id_eject(mob/user, obj/target) if(!target) - to_chat(user, "There's no ID card in the console!") + to_chat(user, "That slot is empty!") return FALSE else target.forceMove(drop_location()) if(!issilicon(user) && Adjacent(user)) user.put_in_hands(target) - user.visible_message("[user] gets an ID card from the console.", \ - "You get the ID card from the console.") + user.visible_message("[user] gets \the [target] from \the [src].", \ + "You get \the [target] from \the [src].") playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) updateUsrDialog() return TRUE @@ -157,86 +176,68 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) if(inserted_modify_id) if(id_eject(user, inserted_modify_id)) inserted_modify_id = null - authenticated = FALSE + updateUsrDialog() return if(inserted_scan_id) if(id_eject(user, inserted_scan_id)) inserted_scan_id = null - authenticated = FALSE + updateUsrDialog() return /obj/machinery/computer/card/ui_interact(mob/user) . = ..() - var/dat - if(!SSticker) - return + var/list/dat = list() if (mode == 1) // accessing crew manifest - var/crew = "" + dat += "Crew Manifest:
Please use security record computer to modify entries.

" for(var/datum/data/record/t in sortRecord(GLOB.data_core.general)) - crew += t.fields["name"] + " - " + t.fields["rank"] + "
" - dat = "Crew Manifest:
Please use security record computer to modify entries.

[crew]Print

Access ID modification console.
" + dat += {"[t.fields["name"]] - [t.fields["rank"]]
"} + dat += "Print

Access ID modification console.
" else if(mode == 2) // JOB MANAGEMENT - dat = "Return" - dat += " || Confirm Identity: " - var/S - if(inserted_scan_id) - S = html_encode(inserted_scan_id.name) - else - S = "--------" - dat += "[S]" - dat += "" - dat += "" - var/ID - if(inserted_scan_id && (ACCESS_CHANGE_IDS in inserted_scan_id.access) && !target_dept) - ID = 1 - else - ID = 0 + dat += {"Return +
JobSlotsOpen jobClose jobPrioritize
+ "} for(var/datum/job/job in SSjob.occupations) dat += "" if(job.title in blacklisted) continue - dat += "" - dat += "" - dat += " + + " dat += "
JobSlotsOpen jobClose jobPrioritize
[job.title][job.current_positions]/[job.total_positions]" + dat += {"[job.title][job.current_positions]/[job.total_positions]"} switch(can_open_job(job)) - if(1) - if(ID) + if(JOB_ALLOWED) + if(authenticated == 2) dat += "Open Position
" else dat += "Open Position" - if(-1) - dat += "Denied" - if(-2) + if(JOB_COOLDOWN) var/time_to_wait = round(change_position_cooldown - ((world.time / 10) - GLOB.time_last_changed_position), 1) var/mins = round(time_to_wait / 60) var/seconds = time_to_wait - (60*mins) dat += "Cooldown ongoing: [mins]:[(seconds < 10) ? "0[seconds]" : "[seconds]"]" - if(0) + else dat += "Denied" dat += "
" switch(can_close_job(job)) - if(1) - if(ID) + if(JOB_ALLOWED) + if(authenticated == 2) dat += "Close Position" else dat += "Close Position" - if(-1) - dat += "Denied" - if(-2) + if(JOB_COOLDOWN) var/time_to_wait = round(change_position_cooldown - ((world.time / 10) - GLOB.time_last_changed_position), 1) var/mins = round(time_to_wait / 60) var/seconds = time_to_wait - (60*mins) dat += "Cooldown ongoing: [mins]:[(seconds < 10) ? "0[seconds]" : "[seconds]"]" - if(0) + else dat += "Denied" dat += "" switch(job.total_positions) if(0) dat += "Denied" else - if(ID) + if(authenticated == 2) if(job in SSjob.prioritized_jobs) dat += "Deprioritize" else @@ -250,57 +251,35 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) dat += "
" else - var/header = "" - - var/target_name - var/target_owner - var/target_rank - if(inserted_modify_id) - target_name = html_encode(inserted_modify_id.name) - else - target_name = "--------" - if(inserted_modify_id && inserted_modify_id.registered_name) - target_owner = html_encode(inserted_modify_id.registered_name) - else - target_owner = "--------" - if(inserted_modify_id && inserted_modify_id.assignment) - target_rank = html_encode(inserted_modify_id.assignment) - else - target_rank = "Unassigned" - - var/scan_name - if(inserted_scan_id) - scan_name = html_encode(inserted_scan_id.name) - else - scan_name = "--------" + var/list/header = list() + var/scan_name = inserted_scan_id ? html_encode(inserted_scan_id.name) : "--------" + var/target_name = inserted_modify_id ? html_encode(inserted_modify_id.name) : "--------" + var/target_owner = (inserted_modify_id && inserted_modify_id.registered_name) ? html_encode(inserted_modify_id.registered_name) : "--------" + var/target_rank = (inserted_modify_id && inserted_modify_id.assignment) ? html_encode(inserted_modify_id.assignment) : "Unassigned" if(!authenticated) - header += "
Please insert the cards into the slots
" - header += "Target: [target_name]
" - header += "Confirm Identity: [scan_name]
" + header += {"
Please insert the cards into the slots
+ Target: [target_name]
+ Confirm Identity: [scan_name]
"} else - header += "

" - header += "Remove [target_name] || " - header += "Remove [scan_name]
" - header += "Access Crew Manifest
" - header += "Log Out
" + header += {"

+ Target: Remove [target_name] || + Confirm Identity: Remove [scan_name]
+ Access Crew Manifest
+ [!target_dept ? "Job Management
" : ""] + Log Out
"} header += "
" - var/jobs_all = "" - var/list/alljobs = list("Unassigned") - alljobs += (istype(src, /obj/machinery/computer/card/centcom)? get_all_centcom_jobs() : get_all_jobs()) + "Custom" - for(var/job in alljobs) - jobs_all += "[replacetext(job, " ", " ")] " //make sure there isn't a line break in the middle of a job - - var/body if (authenticated && inserted_modify_id) - - var/carddesc = text("") - var/jobs = text("") - if( authenticated == 2) + var/list/carddesc = list() + var/list/jobs = list() + if (authenticated == 2) + var/list/jobs_all = list() + for(var/job in (list("Unassigned") + get_jobs() + "Custom")) + jobs_all += "[replacetext(job, " ", " ")] " //make sure there isn't a line break in the middle of a job carddesc += {""} - carddesc += "
" - carddesc += "" - carddesc += "" - carddesc += "registered name: " - carddesc += "" - carddesc += "
" - carddesc += "Assignment: " + carddesc += {"
+ + + registered name: + +
+ Assignment: "} jobs += "[target_rank]" //CHECK THIS @@ -333,18 +312,18 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) carddesc += "registered_name: [target_owner]" jobs += "Assignment: [target_rank] (Demote)" - var/accesses = "" - if(istype(src, /obj/machinery/computer/card/centcom)) + var/list/accesses = list() + if(istype(src, /obj/machinery/computer/card/centcom)) //REE accesses += "
Central Command:
" for(var/A in get_all_centcom_access()) if(A in inserted_modify_id.access) - accesses += "[replacetext(get_centcom_access_desc(A), " ", " ")] " + accesses += "[replacetext(get_centcom_access_desc(A), " ", " ")] " else accesses += "[replacetext(get_centcom_access_desc(A), " ", " ")] " else - accesses += "
Access
" - accesses += "" - accesses += "" + accesses += {"
Access
+
+ "} for(var/i = 1; i <= 7; i++) if(authenticated == 1 && !(i in region_access)) continue @@ -356,23 +335,23 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) accesses += "" accesses += "
" for(var/A in get_region_accesses(i)) if(A in inserted_modify_id.access) - accesses += "[replacetext(get_access_desc(A), " ", " ")] " + accesses += "[replacetext(get_access_desc(A), " ", " ")] " else accesses += "[replacetext(get_access_desc(A), " ", " ")] " accesses += "
" accesses += "
" - body = "[carddesc]
[jobs]

[accesses]" //CHECK THIS + body = "[carddesc.Join()]
[jobs.Join()]

[accesses.Join()]
" //CHECK THIS - else - body = "{Log in}

" - body += "Access Crew Manifest" + else if (!authenticated) + body = {"Log In

+ Access Crew Manifest

"} if(!target_dept) - body += "

Job Management" + body += "Job Management
" - dat = "[header][body]

" + dat = list("", header.Join(), body, "
") var/datum/browser/popup = new(user, "id_com", src.name, 900, 620) - popup.set_content(dat) + popup.set_content(dat.Join()) popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() @@ -388,25 +367,31 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) usr.set_machine(src) switch(href_list["choice"]) if ("inserted_modify_id") - if (inserted_modify_id) + if(inserted_modify_id && !usr.get_active_held_item()) if(id_eject(usr, inserted_modify_id)) inserted_modify_id = null - else - var/mob/M = usr - var/obj/item/card/id/I = M.get_idcard(TRUE) - if(id_insert(usr, I, inserted_modify_id)) - inserted_modify_id = I + updateUsrDialog() + return + if(usr.get_id_in_hand()) + var/obj/item/held_item = usr.get_active_held_item() + var/obj/item/card/id/id_to_insert = held_item.GetID() + if(id_insert(usr, held_item, inserted_modify_id)) + inserted_modify_id = id_to_insert + updateUsrDialog() if ("inserted_scan_id") - if (inserted_scan_id) + if(inserted_scan_id && !usr.get_active_held_item()) if(id_eject(usr, inserted_scan_id)) inserted_scan_id = null - else - var/mob/M = usr - var/obj/item/card/id/I = M.get_idcard(TRUE) - if(id_insert(usr, I, inserted_scan_id)) - inserted_scan_id = I + updateUsrDialog() + return + if(usr.get_id_in_hand()) + var/obj/item/held_item = usr.get_active_held_item() + var/obj/item/card/id/id_to_insert = held_item.GetID() + if(id_insert(usr, held_item, inserted_scan_id)) + inserted_scan_id = id_to_insert + updateUsrDialog() if ("auth") - if ((!( authenticated ) && (inserted_scan_id || issilicon(usr)) && (inserted_modify_id || mode))) + if ((!( authenticated ) && (inserted_scan_id || issilicon(usr)) || mode)) if (check_access(inserted_scan_id)) region_access = list() head_subordinates = list() @@ -478,7 +463,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) updateUsrDialog() break if(!jobdatum) - to_chat(usr, "No log exists for this job.") + to_chat(usr, "No log exists for this job.") updateUsrDialog() return @@ -491,7 +476,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) inserted_modify_id.assignment = "Unassigned" playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) else - to_chat(usr, "You are not authorized to demote this position.") + to_chat(usr, "You are not authorized to demote this position.") if ("reg") if (authenticated) var/t2 = inserted_modify_id @@ -501,7 +486,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) inserted_modify_id.registered_name = newName playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) else - to_chat(usr, "Invalid name entered.") + to_chat(usr, "Invalid name entered.") updateUsrDialog() return if ("mode") @@ -514,7 +499,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) if("make_job_available") // MAKE ANOTHER JOB POSITION AVAILABLE FOR LATE JOINERS - if(inserted_scan_id && (ACCESS_CHANGE_IDS in inserted_scan_id.access) && !target_dept) + if(authenticated && !target_dept) var/edit_job_target = href_list["job"] var/datum/job/j = SSjob.GetJob(edit_job_target) if(!j) @@ -531,7 +516,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) if("make_job_unavailable") // MAKE JOB POSITION UNAVAILABLE FOR LATE JOINERS - if(inserted_scan_id && (ACCESS_CHANGE_IDS in inserted_scan_id.access) && !target_dept) + if(authenticated && !target_dept) var/edit_job_target = href_list["job"] var/datum/job/j = SSjob.GetJob(edit_job_target) if(!j) @@ -549,7 +534,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) if ("prioritize_job") // TOGGLE WHETHER JOB APPEARS AS PRIORITIZED IN THE LOBBY - if(inserted_scan_id && (ACCESS_CHANGE_IDS in inserted_scan_id.access) && !target_dept) + if(authenticated && !target_dept) var/priority_target = href_list["job"] var/datum/job/j = SSjob.GetJob(priority_target) if(!j) @@ -565,7 +550,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) return else SSjob.prioritized_jobs += j - to_chat(usr, "[j.title] has been successfully [priority ? "prioritized" : "unprioritized"]. Potential employees will notice your request.") + to_chat(usr, "[j.title] has been successfully [priority ? "prioritized" : "unprioritized"]. Potential employees will notice your request.") playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) if ("print") @@ -637,3 +622,8 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0) icon_screen = "idqm" light_color = LIGHT_COLOR_ORANGE + +#undef JOB_ALLOWED +#undef JOB_COOLDOWN +#undef JOB_MAX_POSITIONS +#undef JOB_DENIED diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 2c3d7f63..71c84f9a 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -70,9 +70,7 @@ if("login") var/mob/M = usr - var/obj/item/card/id/I = M.get_active_held_item() - if(!istype(I)) - I = M.get_idcard() + var/obj/item/card/id/I = M.get_idcard(TRUE) if(I && istype(I)) if(check_access(I)) @@ -335,7 +333,7 @@ Nuke_request(input, usr) to_chat(usr, "Request sent.") usr.log_message("has requested the nuclear codes from CentCom", LOG_SAY) - priority_announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested",'sound/ai/commandreport.ogg') + priority_announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested","commandreport") CM.lastTimeUsed = world.time @@ -431,6 +429,7 @@ return ..() /obj/machinery/computer/communications/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return obj_flags |= EMAGGED @@ -439,6 +438,7 @@ authenticated = 2 to_chat(user, "You scramble the communication routing circuits!") playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0) + return TRUE /obj/machinery/computer/communications/ui_interact(mob/user) . = ..() diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index ef47445c..9422a979 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -80,6 +80,7 @@ righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi' item_flags = NO_MAT_REDEMPTION | NOBLUDGEON var/prox_check = TRUE //If the emag requires you to be in range + var/uses = 10 /obj/item/card/emag/bluespace name = "bluespace cryptographic sequencer" @@ -93,39 +94,55 @@ /obj/item/card/emag/afterattack(atom/target, mob/user, proximity) . = ..() var/atom/A = target - if(!proximity && prox_check) + if(!proximity && prox_check || !(isobj(A) || issilicon(A) || isbot(A) || isdrone(A))) + return + if(istype(A, /obj/item/storage) && !(istype(A, /obj/item/storage/lockbox) || istype(A, /obj/item/storage/pod))) return - //Citadel changes: modular code misfiring, so we're bypassing into main code. if(!uses) user.visible_message("[src] emits a weak spark. It's burnt out!") playsound(src, 'sound/effects/light_flicker.ogg', 100, 1) return else if(uses <= 3) playsound(src, 'sound/effects/light_flicker.ogg', 30, 1) //Tiiiiiiny warning sound to let ya know your emag's almost dead - - if(isturf(A)) + if(!A.emag_act(user)) return - if(istype(A,/obj/item/storage/lockbox) || istype(A, /obj/item/storage/pod)) - A.emag_act(user) - uses = max(uses - 1, 0) - if(!uses) - user.visible_message("[src] fizzles and sparks. It seems like it's out of charges.") - playsound(src, 'sound/effects/light_flicker.ogg', 100, 1) - if(istype(A,/obj/item/storage)) - return - if(!(isobj(A) || issilicon(A) || isbot(A) || isdrone(A))) - return - else - A.emag_act(user) - uses = max(uses - 1, 0) - if(!uses) - user.visible_message("[src] fizzles and sparks. It seems like it's out of charges.") - playsound(src, 'sound/effects/light_flicker.ogg', 100, 1) + uses = max(uses - 1, 0) + if(!uses) + user.visible_message("[src] fizzles and sparks. It seems like it's out of charges.") + playsound(src, 'sound/effects/light_flicker.ogg', 100, 1) /obj/item/card/emag/examine(mob/user) . = ..() . += "It has [uses ? uses : "no"] charges left." +/obj/item/card/emag/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/emagrecharge)) + var/obj/item/emagrecharge/ER = W + if(ER.uses) + uses += ER.uses + to_chat(user, "You have added [ER.uses] charges to [src]. It now has [uses] charges.") + playsound(src, "sparks", 100, 1) + ER.uses = 0 + else + to_chat(user, "[ER] has no charges left.") + return + . = ..() + +/obj/item/emagrecharge + name = "electromagnet charging device" + desc = "A small cell with two prongs lazily jabbed into it. It looks like it's made for charging the small batteries found in electromagnetic devices, sadly this can't be recharged like a normal cell." + icon = 'icons/obj/module.dmi' + icon_state = "cell_mini" + item_flags = NOBLUDGEON + var/uses = 5 //Dictates how many charges the device adds to compatible items + +/obj/item/emagrecharge/examine(mob/user) + . = ..() + if(uses) + . += "It can add up to [uses] charges to compatible devices" + else + . += "It has a small, red, blinking light coming from inside of it. It's spent." + /obj/item/card/emagfake desc = "It's a card with a magnetic strip attached to some circuitry. Closer inspection shows that this card is a poorly made replica, with a \"DonkCo\" logo stamped on the back." name = "cryptographic sequencer" @@ -186,6 +203,9 @@ /obj/item/card/id/GetID() return src +/obj/item/card/id/RemoveID() + return src + /* Usage: update_label() @@ -357,12 +377,41 @@ update_label("John Doe", "Clowny") lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi' assignment = "Prisoner" - registered_name = "Scum" + access = list(ACCESS_ENTER_GENPOP) + + //Lavaland labor camp var/goal = 0 //How far from freedom? var/points = 0 + //Genpop + var/sentence = 0 //When world.time is greater than this number, the card will have its ACCESS_ENTER_GENPOP access replaced with ACCESS_LEAVE_GENPOP the next time it's checked, unless this value is 0/null + var/crime= "\[REDACTED\]" -/obj/item/card/id/prisoner/attack_self(mob/user) - to_chat(usr, "You have accumulated [points] out of the [goal] points you need for freedom.") +/obj/item/card/id/prisoner/GetAccess() + if((sentence && world.time >= sentence) || (goal && points >= goal)) + access = list(ACCESS_LEAVE_GENPOP) + return ..() + +/obj/item/card/id/prisoner/process() + if(!sentence) + STOP_PROCESSING(SSobj, src) + return + if(world.time >= sentence) + playsound(loc, 'sound/machines/ping.ogg', 50, 1) + if(isliving(loc)) + to_chat(loc, "[src] buzzes: You have served your sentence! You may now exit prison through the turnstiles and collect your belongings.") + STOP_PROCESSING(SSobj, src) + return + +/obj/item/card/id/prisoner/examine(mob/user) + . = ..() + if(sentence && world.time < sentence) + . += "You're currently serving a sentence for [crime]. [DisplayTimeText(sentence - world.time)] left." + else if(goal) + . += "You have accumulated [points] out of the [goal] points you need for freedom." + else if(!sentence) + . += "You are currently serving a permanent sentence for [crime]." + else + . += "Your sentence is up! You're free!" /obj/item/card/id/prisoner/one name = "Prisoner #13-001" @@ -438,10 +487,60 @@ update_label("John Doe", "Clowny") desc = "A special ID card that allows access to APC terminals." access = list(ACCESS_ENGINE_EQUIP) -/obj/item/card/id/away/snowdin - name = "a perfectly generic identification card" - desc = "A perfectly generic identification card. Looks like it could use some flavor." - icon_state = "centcom" +//Polychromatic Knight Badge + +/obj/item/card/id/knight + var/id_color = "#00FF00" //defaults to green + name = "knight badge" + icon_state = "knight" + desc = "A badge denoting the owner as a knight! It has a strip for swiping like an ID" + +/obj/item/card/id/knight/update_label(newname, newjob) + if(newname || newjob) + name = "[(!newname) ? "knight badge" : "[newname]'s Knight Badge"][(!newjob) ? "" : " ([newjob])"]" + return + + name = "[(!registered_name) ? "knight badge" : "[registered_name]'s Knight Badge"][(!assignment) ? "" : " ([assignment])"]" + +/obj/item/card/id/knight/update_icon() + var/mutable_appearance/id_overlay = mutable_appearance(icon, "knight_overlay") + + if(id_color) + id_overlay.color = id_color + cut_overlays() + + add_overlay(id_overlay) + +/obj/item/card/id/knight/AltClick(mob/living/user) + . = ..() + if(!in_range(src, user)) //Basic checks to prevent abuse + return + if(user.incapacitated() || !istype(user)) + to_chat(user, "You can't do that right now!") + return + if(alert("Are you sure you want to recolor your id?", "Confirm Repaint", "Yes", "No") == "Yes") + var/energy_color_input = input(usr,"","Choose Energy Color",id_color) as color|null + if(!in_range(src, user) || !energy_color_input) + return + if(user.incapacitated() || !istype(user)) + to_chat(user, "You can't do that right now!") + return + id_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1) + update_icon() + +/obj/item/card/id/knight/Initialize() + . = ..() + update_icon() + +/obj/item/card/id/knight/examine(mob/user) + . = ..() + . += "Alt-click to recolor it." + +/obj/item/card/id/knight/blue + id_color = "#0000FF" + +/obj/item/card/id/knight/captain + id_color = "#FFD700" /obj/item/card/id/away/snowdin/eng name = "Arctic Station Engineer's ID card" diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index c4b86f04..37b8e3ff 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -139,7 +139,7 @@ GLOBAL_LIST_EMPTY(PDAs) var/choice = input(M, "Choose the a reskin for [src]","Reskin Object") as null|anything in GLOB.pda_reskins var/new_icon = GLOB.pda_reskins[choice] - if(QDELETED(src) || isnull(new_icon) || new_icon == icon || M.incapacitated() || !in_range(M,src)) + if(QDELETED(src) || isnull(new_icon) || new_icon == icon || !M.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) return icon = new_icon update_icon(FALSE, TRUE) @@ -199,6 +199,18 @@ GLOBAL_LIST_EMPTY(PDAs) /obj/item/pda/GetID() return id +/obj/item/pda/RemoveID() + return do_remove_id() + +/obj/item/pda/InsertID(obj/item/inserting_item) + var/obj/item/card/inserting_id = inserting_item.RemoveID() + if(!inserting_id) + return + insert_id(inserting_id) + if(id == inserting_id) + return TRUE + return FALSE + /obj/item/pda/update_icon(alert = FALSE, new_overlays = FALSE) if(new_overlays) set_new_overlays() @@ -273,7 +285,7 @@ GLOBAL_LIST_EMPTY(PDAs) dat += text("
[id ? "Update PDA Info" : ""]

") dat += "[STATION_TIME_TIMESTAMP("hh:mm:ss")]
" //:[world.time / 100 % 6][world.time / 100 % 10]" - dat += "[time2text(world.realtime, "MMM DD")] [GLOB.year_integer+540]" + dat += "[time2text(world.realtime, "MMM DD")] [GLOB.year_integer]" dat += "

" @@ -687,15 +699,27 @@ GLOBAL_LIST_EMPTY(PDAs) return /obj/item/pda/proc/remove_id() - if(issilicon(usr) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) return + do_remove_id(usr) - if (id) - usr.put_in_hands(id) - to_chat(usr, "You remove the ID from the [name].") - id = null - update_icon() +/obj/item/pda/proc/do_remove_id(mob/user) + if(!id) + return + if(user) + user.put_in_hands(id) + to_chat(user, "You remove the ID from the [name].") + else + id.forceMove(get_turf(src)) + + . = id + id = null + update_icon() + + if(ishuman(loc)) + var/mob/living/carbon/human/H = loc + if(H.wear_id == src) + H.sec_hud_set_ID() /obj/item/pda/proc/msg_input(mob/living/U = usr) var/t = stripped_input(U, "Please enter message", name) @@ -877,17 +901,27 @@ GLOBAL_LIST_EMPTY(PDAs) if(istype(C)) I = C - if(I && I.registered_name) + if(I?.registered_name) if(!user.transferItemToLoc(I, src)) return FALSE - var/obj/old_id = id - id = I - if(old_id) - user.put_in_hands(old_id) + insert_id(I, user) update_icon() playsound(src, 'sound/machines/button.ogg', 50, 1) return TRUE +/obj/item/pda/proc/insert_id(obj/item/card/id/inserting_id, mob/user) + var/obj/old_id = id + id = inserting_id + if(ishuman(loc)) + var/mob/living/carbon/human/human_wearer = loc + if(human_wearer.wear_id == src) + human_wearer.sec_hud_set_ID() + if(old_id) + if(user) + user.put_in_hands(old_id) + else + old_id.forceMove(get_turf(src)) + // access to status display signals /obj/item/pda/attackby(obj/item/C, mob/user, params) if(istype(C, /obj/item/cartridge) && !cartridge) diff --git a/code/game/objects/items/storage/wallets.dm b/code/game/objects/items/storage/wallets.dm index 0adf4604..0b026e99 100644 --- a/code/game/objects/items/storage/wallets.dm +++ b/code/game/objects/items/storage/wallets.dm @@ -67,6 +67,21 @@ /obj/item/storage/wallet/GetID() return front_id +/obj/item/storage/wallet/RemoveID() + if(!front_id) + return + . = front_id + front_id.forceMove(get_turf(src)) + +/obj/item/storage/wallet/InsertID(obj/item/inserting_item) + var/obj/item/card/inserting_id = inserting_item.RemoveID() + if(!inserting_id) + return FALSE + attackby(inserting_id) + if(inserting_id in contents) + return TRUE + return FALSE + /obj/item/storage/wallet/GetAccess() if(LAZYLEN(combined_access)) return combined_access diff --git a/code/modules/cargo/bounty_console.dm b/code/modules/cargo/bounty_console.dm index 39465df7..e0f97c7c 100644 --- a/code/modules/cargo/bounty_console.dm +++ b/code/modules/cargo/bounty_console.dm @@ -1,5 +1,7 @@ #define PRINTER_TIMEOUT 10 + + /obj/machinery/computer/bounty name = "Kinaris.Co bounty console" desc = "Used to check and claim bounties offered by Kinaris" @@ -24,9 +26,9 @@ for(var/datum/bounty/B in GLOB.bounties_list) if(B.claimed) continue - info += "

[B.name]

" - info += "
  • Reward: [B.reward_string()]
  • " - info += "
  • Completed: [B.completion_string()]
" + info += {"

[B.name]

+
  • Reward: [B.reward_string()]
  • +
  • Completed: [B.completion_string()]
"} /obj/machinery/computer/bounty/ui_interact(mob/user) . = ..() @@ -34,39 +36,36 @@ if(!GLOB.bounties_list.len) setup_bounties() - var/dat = "" - dat += "Refresh" - dat += "Print Paper" - dat += "

Credits: [SSshuttle.points]

" - dat += {""} - dat += "" + var/list/dat = list({"Refresh + Print Paper +

Credits: [SSshuttle.points]

+
NameDescriptionRewardCompletionStatus
+ "}) for(var/datum/bounty/B in GLOB.bounties_list) - var/background - if(B.can_claim()) - background = "'background-color:#4F7529;'" - else if(B.claimed) - background = "'background-color:#294675;'" + if(B.claimed) + dat += "" + else if(B.can_claim()) + dat += "" else - background = "'background-color:#990000;'" - dat += "" + dat += "" if(B.high_priority) - dat += text("", B.name) - dat += text("", B.description) - dat += text("", B.reward_string()) + dat += {" + + "} else - dat += text("", B.name) - dat += text("", B.description) - dat += text("", B.reward_string()) - dat += text("", B.completion_string()) - if(B.can_claim()) - dat += text("") - else if(B.claimed) - dat += text("") + dat += {" + + "} + dat += "" + if(B.claimed) + dat += "" + else if(B.can_claim()) + dat += "" else - dat += text("") + dat += "" dat += "" dat += "
NameDescriptionRewardCompletionStatus
[]High Priority: [][][B.name]High Priority: [B.description][B.reward_string()][][][][]ClaimClaimed[B.name][B.description][B.reward_string()][B.completion_string()]ClaimedClaimUnclaimedUnclaimed
" - + dat = dat.Join() var/datum/browser/popup = new(user, "bounties", "Kinaris Bounties", 700, 600) popup.set_content(dat) popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) @@ -91,4 +90,3 @@ playsound(src, "terminal_type", 25, 0) updateUsrDialog() - diff --git a/code/modules/cargo/console.dm b/code/modules/cargo/console.dm index 1ad0d569..526062d0 100644 --- a/code/modules/cargo/console.dm +++ b/code/modules/cargo/console.dm @@ -3,6 +3,7 @@ desc = "Used to order supplies, approve requests, and control the shuttle." icon_screen = "supply" circuit = /obj/item/circuitboard/computer/cargo + req_access = list(ACCESS_CARGO) var/requestonly = FALSE var/contraband = FALSE var/safety_warning = "For safety reasons, the automated supply shuttle \ @@ -17,6 +18,7 @@ desc = "Used to request supplies from cargo." icon_screen = "request" circuit = /obj/item/circuitboard/computer/cargo/request + req_access = list() requestonly = TRUE /obj/machinery/computer/cargo/Initialize() @@ -36,6 +38,7 @@ . |= EXPORT_EMAG /obj/machinery/computer/cargo/emag_act(mob/user) + . = ..() if(obj_flags & EMAGGED) return user.visible_message("[user] swipes a suspicious card through [src]!", @@ -48,6 +51,8 @@ var/obj/item/circuitboard/computer/cargo/board = circuit board.contraband = TRUE board.obj_flags |= EMAGGED + req_access = list() + return TRUE /obj/machinery/computer/cargo/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) @@ -111,6 +116,9 @@ /obj/machinery/computer/cargo/ui_act(action, params, datum/tgui/ui) if(..()) return + if(!allowed(usr)) + to_chat(usr, "Access denied.") + return if(action != "add" && requestonly) return switch(action) @@ -159,7 +167,7 @@ if(ishuman(usr)) var/mob/living/carbon/human/H = usr name = H.get_authentification_name() - rank = H.get_assignment() + rank = H.get_assignment(hand_first = TRUE) else if(issilicon(usr)) name = usr.real_name rank = "Silicon" diff --git a/code/modules/cargo/expressconsole.dm b/code/modules/cargo/expressconsole.dm index 186b55a6..049ba8c8 100644 --- a/code/modules/cargo/expressconsole.dm +++ b/code/modules/cargo/expressconsole.dm @@ -54,6 +54,7 @@ ..() /obj/machinery/computer/cargo/express/emag_act(mob/living/user) + . = SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT) if(obj_flags & EMAGGED) return user.visible_message("[user] swipes a suspicious card through [src]!", @@ -63,6 +64,8 @@ var/obj/item/circuitboard/computer/cargo/board = circuit board.obj_flags |= EMAGGED packin_up() + req_access = list() + return TRUE /obj/machinery/computer/cargo/express/proc/packin_up() // oh shit, I'm sorry meme_pack_data = list() // sorry for what? @@ -153,7 +156,7 @@ if(ishuman(usr)) var/mob/living/carbon/human/H = usr name = H.get_authentification_name() - rank = H.get_assignment() + rank = H.get_assignment(hand_first = TRUE) else if(issilicon(usr)) name = usr.real_name rank = "Silicon" diff --git a/code/modules/jobs/access.dm b/code/modules/jobs/access.dm index b3e9ef2c..29234a2b 100644 --- a/code/modules/jobs/access.dm +++ b/code/modules/jobs/access.dm @@ -35,6 +35,12 @@ /obj/item/proc/GetID() return null +/obj/item/proc/RemoveID() + return null + +/obj/item/proc/InsertID() + return FALSE + /obj/proc/text2access(access_text) . = list() if(!access_text) @@ -121,7 +127,7 @@ return list(ACCESS_CENT_GENERAL, ACCESS_CENT_LIVING, ACCESS_CENT_BAR) /proc/get_all_accesses() - return list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_FORENSICS_LOCKERS, ACCESS_COURT, + return list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_FORENSICS_LOCKERS, ACCESS_COURT, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP, ACCESS_MEDICAL, ACCESS_GENETICS, ACCESS_MORGUE, ACCESS_RD, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_CHEMISTRY, ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_MAINT_TUNNELS, ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CHANGE_IDS, ACCESS_AI_UPLOAD, @@ -157,7 +163,7 @@ if(1) //station general return list(ACCESS_KITCHEN,ACCESS_BAR, ACCESS_HYDROPONICS, ACCESS_JANITOR, ACCESS_CHAPEL_OFFICE, ACCESS_CREMATORIUM, ACCESS_LIBRARY, ACCESS_THEATRE, ACCESS_LAWYER) if(2) //security - return list(ACCESS_SEC_DOORS, ACCESS_WEAPONS, ACCESS_SECURITY, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_FORENSICS_LOCKERS, ACCESS_COURT, ACCESS_HOS) + return list(ACCESS_SEC_DOORS, ACCESS_WEAPONS, ACCESS_SECURITY, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_FORENSICS_LOCKERS, ACCESS_COURT, ACCESS_HOS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP) if(3) //medbay return list(ACCESS_MEDICAL, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_MORGUE, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_SURGERY, ACCESS_CMO) if(4) //research @@ -312,6 +318,10 @@ return "Gateway" if(ACCESS_SEC_DOORS) return "Brig" + if(ACCESS_ENTER_GENPOP) + return "Prison Turnstile Entrance" + if(ACCESS_LEAVE_GENPOP) + return "Prison Turnstile Exit" if(ACCESS_MINERAL_STOREROOM) return "Mineral Storage" if(ACCESS_MINISAT) diff --git a/code/modules/jobs/job_types/security.dm b/code/modules/jobs/job_types/security.dm index b2b0271f..4600fce9 100644 --- a/code/modules/jobs/job_types/security.dm +++ b/code/modules/jobs/job_types/security.dm @@ -26,11 +26,11 @@ Head of Security outfit = /datum/outfit/job/hos - access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_WEAPONS, + access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_WEAPONS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP, ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_RESEARCH, ACCESS_ENGINE, ACCESS_MINING, ACCESS_MEDICAL, ACCESS_CONSTRUCTION, ACCESS_MAILSORTING, ACCESS_HEADS, ACCESS_HOS, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_MAINT_TUNNELS, ACCESS_MINERAL_STOREROOM) - minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_WEAPONS, + minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_WEAPONS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP, ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_RESEARCH, ACCESS_ENGINE, ACCESS_MINING, ACCESS_MEDICAL, ACCESS_CONSTRUCTION, ACCESS_MAILSORTING, ACCESS_HEADS, ACCESS_HOS, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_MAINT_TUNNELS, ACCESS_MINERAL_STOREROOM) @@ -94,8 +94,8 @@ Warden outfit = /datum/outfit/job/warden - access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_MAINT_TUNNELS, ACCESS_MORGUE, ACCESS_WEAPONS, ACCESS_FORENSICS_LOCKERS, ACCESS_MINERAL_STOREROOM) - minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM) //SEE /DATUM/JOB/WARDEN/GET_ACCESS() + access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_MAINT_TUNNELS, ACCESS_MORGUE, ACCESS_WEAPONS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP, ACCESS_FORENSICS_LOCKERS, ACCESS_MINERAL_STOREROOM) + minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_WEAPONS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP, ACCESS_MINERAL_STOREROOM) //SEE /DATUM/JOB/WARDEN/GET_ACCESS() mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM) blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/nonviolent, /datum/quirk/paraplegic) @@ -210,8 +210,8 @@ Security Officer outfit = /datum/outfit/job/security - access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_MAINT_TUNNELS, ACCESS_MORGUE, ACCESS_WEAPONS, ACCESS_FORENSICS_LOCKERS, ACCESS_MINERAL_STOREROOM) - minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM) //BUT SEE /DATUM/JOB/WARDEN/GET_ACCESS() + access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_MAINT_TUNNELS, ACCESS_MORGUE, ACCESS_WEAPONS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP, ACCESS_FORENSICS_LOCKERS, ACCESS_MINERAL_STOREROOM) + minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_WEAPONS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP, ACCESS_MINERAL_STOREROOM) //BUT SEE /DATUM/JOB/WARDEN/GET_ACCESS() mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM) blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/nonviolent, /datum/quirk/paraplegic) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 89765081..1f993f38 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -584,7 +584,7 @@ return threatcount //Check for ID - var/obj/item/card/id/idcard = get_idcard() + var/obj/item/card/id/idcard = get_idcard(FALSE) if( (judgement_criteria & JUDGE_IDCHECK) && !idcard && name=="Unknown") threatcount += 4 diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index d489c2e3..6bb9dd6e 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -11,8 +11,8 @@ //gets assignment from ID or ID inside PDA or PDA itself //Useful when player do something with computers -/mob/living/carbon/human/proc/get_assignment(if_no_id = "No id", if_no_job = "No job") - var/obj/item/card/id/id = get_idcard() +/mob/living/carbon/human/proc/get_assignment(if_no_id = "No id", if_no_job = "No job", hand_first = TRUE) + var/obj/item/card/id/id = get_idcard(hand_first) if(id) . = id.assignment else @@ -27,7 +27,7 @@ //gets name from ID or ID inside PDA or PDA itself //Useful when player do something with computers /mob/living/carbon/human/proc/get_authentification_name(if_no_id = "Unknown") - var/obj/item/card/id/id = get_idcard() + var/obj/item/card/id/id = get_idcard(FALSE) if(id) return id.registered_name var/obj/item/pda/pda = wear_id @@ -86,10 +86,15 @@ return //gets ID card object from special clothes slot or null. -/mob/living/carbon/human/get_idcard() - if(wear_id) - return wear_id.GetID() - +/mob/living/carbon/human/get_idcard(hand_first = TRUE) + . = ..() + if(. && hand_first) + return + //Check inventory slots + var/obj/item/card/id/id_card = wear_id?.GetID() + if(!id_card) + id_card = belt?.GetID() + return id_card || . /mob/living/carbon/human/IsAdvancedToolUser() if(HAS_TRAIT(src, TRAIT_MONKEYLIKE)) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 689cb51f..36041b02 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -462,8 +462,8 @@ return sync_lighting_plane_alpha() -/mob/living/simple_animal/get_idcard() - return access_card +/mob/living/simple_animal/get_idcard(hand_first = TRUE) + return ..() || access_card /mob/living/simple_animal/OpenCraftingMenu() if(dextrous) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 1d14e084..4918e378 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -942,10 +942,6 @@ /mob/proc/can_hold_items() return FALSE -/mob/proc/get_idcard() - return - - /mob/vv_get_dropdown() . = ..() . += "---" diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 04a0aa40..80f999f8 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -506,3 +506,17 @@ It's fairly easy to fix if dealing with single letters but not so much with comp . = BLOOD_COLOR_BUG //add more stuff to the switch if you have more blood colors for different types // the defines are in _DEFINES/misc.dm + +//gets ID card object from special clothes slot or null. +/mob/proc/get_idcard(hand_first = TRUE) + var/obj/item/held_item = get_active_held_item() + . = held_item?.GetID() + if(!.) //If so, then check the inactive hand + held_item = get_inactive_held_item() + . = held_item?.GetID() + +/mob/proc/get_id_in_hand() + var/obj/item/held_item = get_active_held_item() + if(!held_item) + return + return held_item.GetID() diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm index daaf8a9e..8a8dbbc0 100644 --- a/code/modules/modular_computers/computers/item/computer.dm +++ b/code/modules/modular_computers/computers/item/computer.dm @@ -157,6 +157,21 @@ return card_slot.GetID() return ..() +/obj/item/modular_computer/RemoveID() + var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD] + if(!card_slot) + return + return card_slot.RemoveID() + +/obj/item/modular_computer/InsertID(obj/item/inserting_item) + var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD] + if(!card_slot) + return FALSE + var/obj/item/card/inserting_id = inserting_item.RemoveID() + if(!inserting_id) + return FALSE + return card_slot.try_insert(inserting_id) + /obj/item/modular_computer/MouseDrop(obj/over_object, src_location, over_location) var/mob/M = usr if((!istype(over_object, /obj/screen)) && usr.canUseTopic(src)) diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm index 051b12ea..f74b53dd 100644 --- a/code/modules/modular_computers/file_system/program.dm +++ b/code/modules/modular_computers/file_system/program.dm @@ -97,14 +97,8 @@ card_slot = computer.all_components[MC_CARD] D = card_slot.GetID() var/mob/living/carbon/human/h = user - var/obj/item/card/id/I = h.get_idcard() - var/obj/item/card/id/C = h.get_active_held_item() - if(C) - C = C.GetID() - if(!(C && istype(C))) - C = null - - if(!I && !C && !D) + var/obj/item/card/id/I = h.get_idcard(TRUE) + if(!I && !D) if(loud) to_chat(user, "\The [computer] flashes an \"RFID Error - Unable to scan ID\" warning.") return 0 @@ -112,9 +106,6 @@ if(I) if(access_to_check in I.GetAccess()) return 1 - else if(C) - if(access_to_check in C.GetAccess()) - return 1 else if(D) if(access_to_check in D.GetAccess()) return 1 diff --git a/code/modules/modular_computers/file_system/programs/card.dm b/code/modules/modular_computers/file_system/programs/card.dm index f8372dd2..243ae89d 100644 --- a/code/modules/modular_computers/file_system/programs/card.dm +++ b/code/modules/modular_computers/file_system/programs/card.dm @@ -117,7 +117,7 @@ else if(ishuman(user)) var/mob/living/carbon/human/h = user - user_id_card = h.get_idcard() + user_id_card = h.get_idcard(TRUE) switch(action) if("PRG_switchm") diff --git a/code/modules/modular_computers/hardware/card_slot.dm b/code/modules/modular_computers/hardware/card_slot.dm index 7eef8eb1..c68e1ad1 100644 --- a/code/modules/modular_computers/hardware/card_slot.dm +++ b/code/modules/modular_computers/hardware/card_slot.dm @@ -29,6 +29,17 @@ return stored_card2 return ..() +/obj/item/computer_hardware/card_slot/RemoveID() + if(stored_card) + . = stored_card + if(!try_eject(1)) + return null + return + if(stored_card2) + . = stored_card2 + if(!try_eject(2)) + return null + /obj/item/computer_hardware/card_slot/on_install(obj/item/modular_computer/M, mob/living/user = null) M.add_verb(device_type) diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index 020b4b29..435db75f 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -57,7 +57,7 @@ var/mob/user = usr . = FALSE - var/obj/item/card/id/ID = user.get_idcard() + var/obj/item/card/id/ID = user.get_idcard(TRUE) if(!ID) to_chat(user, "You don't have an ID.") @@ -93,7 +93,7 @@ minor_announce("Early launch authorization revoked, [remaining] authorizations needed") /obj/machinery/computer/emergency_shuttle/proc/authorize(mob/user, source) - var/obj/item/card/id/ID = user.get_idcard() + var/obj/item/card/id/ID = user.get_idcard(TRUE) if(ID in authorized) return FALSE diff --git a/code/modules/shuttle/special.dm b/code/modules/shuttle/special.dm index 4b3cabd9..4ee94c05 100644 --- a/code/modules/shuttle/special.dm +++ b/code/modules/shuttle/special.dm @@ -199,7 +199,7 @@ if(H.mind && H.mind.assigned_role == "Bartender") return TRUE - var/obj/item/card/id/ID = user.get_idcard() + var/obj/item/card/id/ID = user.get_idcard(FALSE) if(ID && (ACCESS_CENT_BAR in ID.access)) return TRUE diff --git a/modular_citadel/code/game/machinery/computer/card.dm b/modular_citadel/code/game/machinery/computer/card.dm deleted file mode 100644 index b9dd049d..00000000 --- a/modular_citadel/code/game/machinery/computer/card.dm +++ /dev/null @@ -1,3 +0,0 @@ -/obj/machinery/computer/card - list/blacklisted = list( - "Quartermaster") diff --git a/modular_citadel/code/game/objects/ids.dm b/modular_citadel/code/game/objects/ids.dm deleted file mode 100644 index 76469547..00000000 --- a/modular_citadel/code/game/objects/ids.dm +++ /dev/null @@ -1,83 +0,0 @@ - -//Polychromatic Knight Badge - -/obj/item/card/id/knight - var/id_color = "#00FF00" //defaults to green - name = "knight badge" - icon = 'modular_citadel/icons/obj/id.dmi' - icon_state = "knight" - desc = "A badge denoting the owner as a knight! It has a strip for swiping like an ID" - -/obj/item/card/id/knight/update_label(newname, newjob) - . = ..() - if(newname || newjob) - name = "[(!newname) ? "identification card" : "[newname]'s Knight Badge"][(!newjob) ? "" : " ([newjob])"]" - return - - name = "[(!registered_name) ? "identification card" : "[registered_name]'s Knight Badge"][(!assignment) ? "" : " ([assignment])"]" - -/obj/item/card/id/knight/update_icon() - var/mutable_appearance/id_overlay = mutable_appearance('modular_citadel/icons/obj/id.dmi', "knight_overlay") - - if(id_color) - id_overlay.color = id_color - cut_overlays() - - add_overlay(id_overlay) - -/obj/item/card/id/knight/AltClick(mob/living/user) - if(!in_range(src, user)) //Basic checks to prevent abuse - return - if(user.incapacitated() || !istype(user)) - to_chat(user, "You can't do that right now!") - return - if(alert("Are you sure you want to recolor your id?", "Confirm Repaint", "Yes", "No") == "Yes") - var/energy_color_input = input(usr,"","Choose Energy Color",id_color) as color|null - if(energy_color_input) - id_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1) - update_icon() - -/obj/item/card/id/knight/Initialize() - . = ..() - update_icon() - -/obj/item/card/id/knight/examine(mob/user) - . = ..() - . += "Alt-click to recolor it." - -//================================================= - -/obj/item/emagrecharge - name = "electromagnet charging device" - desc = "A small cell with two prongs lazily jabbed into it. It looks like it's made for charging the small batteries found in electromagnetic devices." - icon = 'icons/obj/module.dmi' - icon_state = "cell_mini" - item_flags = NOBLUDGEON - var/uses = 5 //Dictates how many charges the device adds to compatible items - -/obj/item/emagrecharge/examine(mob/user) - . = ..() - if(uses) - to_chat(user, "It can add up to [uses] charges to compatible devices") - else - to_chat(user, "It has a small, red, blinking light coming from inside of it. It's spent.") - -/obj/item/card/emag - var/uses = 10 - -/obj/item/card/emag/examine(mob/user) - . = ..() - to_chat(user, "It has [uses ? uses : "no"] charges left.") - -/obj/item/card/emag/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/emagrecharge)) - var/obj/item/emagrecharge/ER = W - if(ER.uses) - uses += ER.uses - to_chat(user, "You have added [ER.uses] charges to [src]. It now has [uses] charges.") - playsound(src, "sparks", 100, 1) - ER.uses = 0 - else - to_chat(user, "[ER] has no charges left.") - return - . = ..() diff --git a/tgstation.dme b/tgstation.dme index a6158571..0984a6d5 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3064,11 +3064,9 @@ #include "modular_citadel\code\game\machinery\toylathe.dm" #include "modular_citadel\code\game\machinery\vending.dm" #include "modular_citadel\code\game\machinery\wishgranter.dm" -#include "modular_citadel\code\game\machinery\computer\card.dm" #include "modular_citadel\code\game\machinery\doors\airlock.dm" #include "modular_citadel\code\game\machinery\doors\airlock_types.dm" #include "modular_citadel\code\game\objects\cit_screenshake.dm" -#include "modular_citadel\code\game\objects\ids.dm" #include "modular_citadel\code\game\objects\items.dm" #include "modular_citadel\code\game\objects\tools.dm" #include "modular_citadel\code\game\objects\effects\spawner\spawners.dm" From 1b529c1ca167507e0ae4494a5c143724dd141074 Mon Sep 17 00:00:00 2001 From: Dip Date: Fri, 20 Nov 2020 21:01:24 -0300 Subject: [PATCH 4/4] errr --- code/game/machinery/computer/communications.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 71c84f9a..bfa9a87c 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -333,7 +333,7 @@ Nuke_request(input, usr) to_chat(usr, "Request sent.") usr.log_message("has requested the nuclear codes from CentCom", LOG_SAY) - priority_announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested","commandreport") + priority_announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested",'sound/ai/commandreport.ogg') CM.lastTimeUsed = world.time