diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm
index 01e8a26cb31..eb8c996d9b0 100644
--- a/code/game/machinery/computer/card.dm
+++ b/code/game/machinery/computer/card.dm
@@ -97,12 +97,12 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
return formatted
-/obj/machinery/computer/card/proc/format_job_slots()
+/obj/machinery/computer/card/proc/format_job_slots(check_department, is_admin)
var/list/formatted = list()
for(var/datum/job/job in SSjobs.occupations)
if(job_blacklisted_full(job))
continue
- if(!job_in_department(job))
+ if(check_department && !job_in_department(job))
continue
formatted.Add(list(list(
"title" = job.title,
@@ -110,7 +110,8 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
"total_positions" = job.total_positions,
"can_open" = can_open_job(job),
"can_close" = can_close_job(job),
- "can_prioritize" = can_prioritize_job(job)
+ "can_prioritize" = can_prioritize_job(job, is_admin),
+ "is_priority" = (job in SSjobs.prioritized_jobs)
)))
return formatted
@@ -212,11 +213,11 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
return TRUE
return FALSE
-/obj/machinery/computer/card/proc/can_prioritize_job(datum/job/job)
+/obj/machinery/computer/card/proc/can_prioritize_job(datum/job/job, is_admin)
if(job)
if(job_blacklisted_full(job))
return FALSE
- if(!job_in_department(job, FALSE))
+ if(!is_admin && !job_in_department(job, FALSE))
return FALSE
if(job in SSjobs.prioritized_jobs)
return TRUE // because this also lets us un-prioritize the job
@@ -319,8 +320,10 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
data["scan_rank"] = scan ? scan.rank : FALSE
data["authenticated"] = is_authenticated(user) ? TRUE : FALSE
+ data["auth_or_ghost"] = data["authenticated"] || isobserver(user)
data["target_dept"] = target_dept
data["iscentcom"] = is_centcom() ? TRUE : FALSE
+ data["isadmin"] = user.can_admin_interact()
switch(mode)
if(IDCOMPUTER_SCREEN_TRANSFER) // JOB TRANSFER
@@ -348,7 +351,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
data["all_centcom_skins"] = is_centcom() ? format_card_skins(get_centcom_card_skins()) : FALSE
if(IDCOMPUTER_SCREEN_SLOTS) // JOB SLOTS
- data["job_slots"] = format_job_slots()
+ data["job_slots"] = format_job_slots(!isobserver(user), data["isadmin"])
data["priority_jobs"] = list()
for(var/datum/job/a in SSjobs.prioritized_jobs)
data["priority_jobs"] += a.title
@@ -690,17 +693,15 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
var/datum/job/j = SSjobs.GetJob(priority_target)
if(!j)
return FALSE
- if(!job_in_department(j))
+ if(!can_prioritize_job(j, usr.can_admin_interact()))
return FALSE
var/priority = TRUE
if(j in SSjobs.prioritized_jobs)
SSjobs.prioritized_jobs -= j
priority = FALSE
- else if(SSjobs.prioritized_jobs.len < 3)
- SSjobs.prioritized_jobs += j
else
- return FALSE
- log_game("[key_name(usr)] ([scan.assignment]) [priority ? "prioritized" : "unprioritized"] the job \"[j.title]\".")
+ SSjobs.prioritized_jobs += j
+ log_game("[key_name(usr)] ([scan ? scan.assignment : "ADMIN"]) [priority ? "prioritized" : "unprioritized"] the job \"[j.title]\".")
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
return
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index 2cceb39b778..d250cc60319 100644
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -3,8 +3,9 @@
#define COMM_SCREEN_MESSAGES 3
#define COMM_AUTHENTICATION_NONE 0
-#define COMM_AUTHENTICATION_MIN 1
-#define COMM_AUTHENTICATION_MAX 2
+#define COMM_AUTHENTICATION_HEAD 1
+#define COMM_AUTHENTICATION_CAPT 2
+#define COMM_AUTHENTICATION_AGHOST 3
#define COMM_MSGLEN_MINIMUM 6
#define COMM_CCMSGLEN_MINIMUM 20
@@ -45,16 +46,15 @@
crew_announcement.newscast = 0
/obj/machinery/computer/communications/proc/is_authenticated(var/mob/user, var/message = 1)
- if(authenticated == COMM_AUTHENTICATION_MAX)
- return COMM_AUTHENTICATION_MAX
- else if(user.can_admin_interact())
- return COMM_AUTHENTICATION_MAX
- else if(authenticated)
- return COMM_AUTHENTICATION_MIN
- else
- if(message)
- to_chat(user, "Access denied.")
- return COMM_AUTHENTICATION_NONE
+ if(user.can_admin_interact())
+ return COMM_AUTHENTICATION_AGHOST
+ if(authenticated == COMM_AUTHENTICATION_CAPT)
+ return COMM_AUTHENTICATION_CAPT
+ if(authenticated)
+ return COMM_AUTHENTICATION_HEAD
+ if(message)
+ to_chat(user, "Access denied.")
+ return COMM_AUTHENTICATION_NONE
/obj/machinery/computer/communications/proc/change_security_level(var/new_level)
tmp_alertlevel = new_level
@@ -80,7 +80,7 @@
if(action == "auth")
if(!ishuman(usr))
- to_chat(usr, "Access denied.")
+ to_chat(usr, "Access denied, no humanoid lifesign detected.")
return FALSE
// Logout function.
if(authenticated != COMM_AUTHENTICATION_NONE)
@@ -91,15 +91,15 @@
// Login function.
var/list/access = usr.get_access()
if(allowed(usr))
- authenticated = COMM_AUTHENTICATION_MIN
+ authenticated = COMM_AUTHENTICATION_HEAD
if(ACCESS_CAPTAIN in access)
- authenticated = COMM_AUTHENTICATION_MAX
+ authenticated = COMM_AUTHENTICATION_CAPT
var/mob/living/carbon/human/H = usr
var/obj/item/card/id = H.get_idcard(TRUE)
if(istype(id))
crew_announcement.announcer = GetNameAndAssignmentFromId(id)
if(authenticated == COMM_AUTHENTICATION_NONE)
- to_chat(usr, "You need to wear your ID.")
+ to_chat(usr, "You need to wear a command or Captain-level ID.")
return
// All functions below this point require authentication.
@@ -133,12 +133,12 @@
to_chat(usr, "You need to wear your ID.")
if("announce")
- if(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)
+ if(is_authenticated(usr) >= COMM_AUTHENTICATION_CAPT)
if(message_cooldown > world.time)
to_chat(usr, "Please allow at least one minute to pass between announcements.")
return
var/input = input(usr, "Please write a message to announce to the station crew.", "Priority Announcement")
- if(!input || message_cooldown > world.time || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX))
+ if(!input || message_cooldown > world.time || ..() || !(is_authenticated(usr) >= COMM_AUTHENTICATION_CAPT))
return
if(length(input) < COMM_MSGLEN_MINIMUM)
to_chat(usr, "Message '[input]' is too short. [COMM_MSGLEN_MINIMUM] character minimum.")
@@ -217,12 +217,12 @@
setMenuState(usr, COMM_SCREEN_STAT)
if("nukerequest")
- if(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)
+ if(is_authenticated(usr) >= COMM_AUTHENTICATION_CAPT)
if(centcomm_message_cooldown > world.time)
to_chat(usr, "Arrays recycling. Please stand by.")
return
var/input = stripped_input(usr, "Please enter the reason for requesting the nuclear self-destruct codes. Misuse of the nuclear request system will not be tolerated under any circumstances. Transmission does not guarantee a response.", "Self Destruct Code Request.","")
- if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX))
+ if(!input || ..() || !(is_authenticated(usr) >= COMM_AUTHENTICATION_CAPT))
return
if(length(input) < COMM_CCMSGLEN_MINIMUM)
to_chat(usr, "Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.")
@@ -235,12 +235,12 @@
setMenuState(usr, COMM_SCREEN_MAIN)
if("MessageCentcomm")
- if(is_authenticated(usr) == COMM_AUTHENTICATION_MAX)
+ if(is_authenticated(usr) >= COMM_AUTHENTICATION_CAPT)
if(centcomm_message_cooldown > world.time)
to_chat(usr, "Arrays recycling. Please stand by.")
return
var/input = stripped_input(usr, "Please choose a message to transmit to Centcomm via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "")
- if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX))
+ if(!input || ..() || !(is_authenticated(usr) >= COMM_AUTHENTICATION_CAPT))
return
if(length(input) < COMM_CCMSGLEN_MINIMUM)
to_chat(usr, "Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.")
@@ -254,12 +254,12 @@
// OMG SYNDICATE ...LETTERHEAD
if("MessageSyndicate")
- if((is_authenticated(usr) == COMM_AUTHENTICATION_MAX) && (src.emagged))
+ if((is_authenticated(usr) >= COMM_AUTHENTICATION_CAPT) && (src.emagged))
if(centcomm_message_cooldown > world.time)
to_chat(usr, "Arrays recycling. Please stand by.")
return
var/input = stripped_input(usr, "Please choose a message to transmit to \[ABNORMAL ROUTING CORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "")
- if(!input || ..() || !(is_authenticated(usr) == COMM_AUTHENTICATION_MAX))
+ if(!input || ..() || !(is_authenticated(usr) >= COMM_AUTHENTICATION_CAPT))
return
if(length(input) < COMM_CCMSGLEN_MINIMUM)
to_chat(usr, "Message '[input]' is too short. [COMM_CCMSGLEN_MINIMUM] character minimum.")
@@ -320,10 +320,12 @@
/obj/machinery/computer/communications/ui_data(mob/user)
var/list/data = list()
data["is_ai"] = isAI(user) || isrobot(user)
+ data["noauthbutton"] = !ishuman(user)
data["menu_state"] = data["is_ai"] ? ai_menu_state : menu_state
data["emagged"] = emagged
data["authenticated"] = is_authenticated(user, 0)
- data["authmax"] = data["authenticated"] == COMM_AUTHENTICATION_MAX ? TRUE : FALSE
+ data["authhead"] = data["authenticated"] >= COMM_AUTHENTICATION_HEAD && (data["authenticated"] == COMM_AUTHENTICATION_AGHOST || !isobserver(user))
+ data["authcapt"] = data["authenticated"] >= COMM_AUTHENTICATION_CAPT && (data["authenticated"] == COMM_AUTHENTICATION_AGHOST || !isobserver(user))
data["stat_display"] = list(
"type" = display_type,
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index 62c3583bb4e..dd466654884 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -510,6 +510,10 @@
if(ishuman(user))
H = user
C = H.get_idcard(TRUE)
+ if(!C && istype(H.wear_pda, /obj/item/pda))
+ var/obj/item/pda/P = H.wear_pda
+ if(istype(P.id, /obj/item/card/id))
+ C = P.id
var/obj/item/stack/spacecash/S = H.get_active_hand()
if(istype(S))
data["userMoney"] = S.amount
diff --git a/code/modules/paperwork/faxmachine.dm b/code/modules/paperwork/faxmachine.dm
index bcf6bcc07db..2aba7f854b6 100644
--- a/code/modules/paperwork/faxmachine.dm
+++ b/code/modules/paperwork/faxmachine.dm
@@ -104,7 +104,9 @@ GLOBAL_LIST_EMPTY(fax_blacklist)
/obj/machinery/photocopier/faxmachine/ui_data(mob/user)
var/list/data = list()
data["authenticated"] = is_authenticated(user)
+ data["realauth"] = authenticated
data["scan_name"] = scan ? scan.name : FALSE
+ data["nologin"] = !data["scan_name"] && !data["realauth"]
if(!data["authenticated"])
data["network"] = "Disconnected"
else if(!emagged)
diff --git a/tgui/packages/tgui/interfaces/CardComputer.js b/tgui/packages/tgui/interfaces/CardComputer.js
index 7e460fe1869..0dcd44e8b2c 100644
--- a/tgui/packages/tgui/interfaces/CardComputer.js
+++ b/tgui/packages/tgui/interfaces/CardComputer.js
@@ -3,11 +3,13 @@ import { useBackend } from '../backend';
import { Button, LabeledList, Box, Section, Table, Tabs } from '../components';
import { Window } from '../layouts';
import { AccessList } from './common/AccessList';
+import { COLORS } from '../constants';
+
+const deptCols = COLORS.department;
export const CardComputer = (props, context) => {
const { act, data } = useBackend(context);
-
let menuBlock = (
{
onClick={() => act("assign", { assign_target: v })} />
))}
-
+
{data.jobs_engineering.map(v => (
-
+
{data.jobs_medical.map(v => (
-
+
{data.jobs_science.map(v => (
-
+
{data.jobs_security.map(v => (
-
+
{data.jobs_service.map(v => (
-
+
{data.jobs_supply.map(v => (
{!!data.iscentcom && (
-
+
{data.jobs_centcom.map(v => (