diff --git a/code/_globalvars/tgui.dm b/code/_globalvars/tgui.dm new file mode 100644 index 00000000000..6903af6d913 --- /dev/null +++ b/code/_globalvars/tgui.dm @@ -0,0 +1 @@ +GLOBAL_DATUM(crew_manifest_tgui, /datum/crew_manifest) diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index a6ed82c4176..8ff5fe52ca7 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -169,12 +169,18 @@ if(rank in jobs) if(!manifest_out[department]) manifest_out[department] = list() - manifest_out[department] += list(list( - "name" = name, - "rank" = rank - )) + // Append to beginning of list if captain or department head + if (rank == "Captain" || (department != "Command" && (rank in GLOB.command_positions))) + manifest_out[department] = list(list( + "name" = name, + "rank" = rank + )) + manifest_out[department] + else + manifest_out[department] += list(list( + "name" = name, + "rank" = rank + )) has_department = TRUE - break if(!has_department) if(!manifest_out["Misc"]) manifest_out["Misc"] = list() diff --git a/code/modules/mob/dead/crew_manifest.dm b/code/modules/mob/dead/crew_manifest.dm new file mode 100644 index 00000000000..fafed6bfee3 --- /dev/null +++ b/code/modules/mob/dead/crew_manifest.dm @@ -0,0 +1,52 @@ +/datum/crew_manifest + +/datum/crew_manifest/ui_state(mob/user) + return GLOB.always_state + +/datum/crew_manifest/ui_status(mob/user, datum/ui_state/state) + return (isnewplayer(user) || isobserver(user) || isAI(user) || ispAI(user)) ? UI_INTERACTIVE : UI_CLOSE + +/datum/crew_manifest/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if (!ui) + ui = new(user, src, "CrewManifest") + ui.open() + +/datum/crew_manifest/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + if (..()) + return + +/datum/crew_manifest/ui_data(mob/user) + var/list/positions = list( + "Command" = 0, + "Security" = 0, + "Engineering" = 0, + "Medical" = 0, + "Science" = 0, + "Supply" = 0, + "Service" = 0, + "Silicon" = 0 + ) + var/list/departments = list( + list("flag" = DEPARTMENT_COMMAND, "name" = "Command"), + list("flag" = DEPARTMENT_SECURITY, "name" = "Security"), + list("flag" = DEPARTMENT_ENGINEERING, "name" = "Engineering"), + list("flag" = DEPARTMENT_MEDICAL, "name" = "Medical"), + list("flag" = DEPARTMENT_SCIENCE, "name" = "Science"), + list("flag" = DEPARTMENT_CARGO, "name" = "Supply"), + list("flag" = DEPARTMENT_SERVICE, "name" = "Service"), + list("flag" = DEPARTMENT_SILICON, "name" = "Silicon") + ) + + for(var/job in SSjob.occupations) + for(var/department in departments) + // Check if the job is part of a department using its flag + // Will return true for Research Director if the department is Science or Command, for example + if(job["departments"] & department["flag"]) + // Add open positions to current department + positions[department["name"]] += (job["total_positions"] - job["current_positions"]) + + return list( + "manifest" = GLOB.data_core.get_manifest(), + "positions" = positions + ) diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 53832c03b60..d7f8be8de67 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -36,6 +36,7 @@ /mob/dead/new_player/Destroy() GLOB.new_player_list -= src + return ..() /mob/dead/new_player/prepare_huds() @@ -489,11 +490,10 @@ return client.crew_manifest_delay = world.time + (1 SECONDS) - var/dat = "" - dat += "

Crew Manifest

" - dat += GLOB.data_core.get_manifest_html() + if(!GLOB.crew_manifest_tgui) + GLOB.crew_manifest_tgui = new /datum/crew_manifest(src) - src << browse(dat, "window=manifest;size=387x420;can_close=1") + GLOB.crew_manifest_tgui.ui_interact(src) /mob/dead/new_player/Move() return 0 diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 61b5871729b..c0b12183965 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -681,11 +681,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp return client.crew_manifest_delay = world.time + (1 SECONDS) - var/dat - dat += "

Crew Manifest

" - dat += GLOB.data_core.get_manifest_html() + if(!GLOB.crew_manifest_tgui) + GLOB.crew_manifest_tgui = new /datum/crew_manifest(src) - src << browse(dat, "window=manifest;size=387x420;can_close=1") + GLOB.crew_manifest_tgui.ui_interact(src) //this is called when a ghost is drag clicked to something. /mob/dead/observer/MouseDrop(atom/over) diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index f3e8e5759a6..837381c47ea 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -83,7 +83,7 @@ /mob/living/silicon/proc/freeCamera() return - + /mob/living/silicon/proc/triggerAlarm() return @@ -355,9 +355,10 @@ return client.crew_manifest_delay = world.time + (1 SECONDS) - var/datum/browser/popup = new(src, "airoster", "Crew Manifest", 387, 420) - popup.set_content(GLOB.data_core.get_manifest_html()) - popup.open() + if(!GLOB.crew_manifest_tgui) + GLOB.crew_manifest_tgui = new /datum/crew_manifest(src) + + GLOB.crew_manifest_tgui.ui_interact(src) /mob/living/silicon/proc/set_autosay() //For allowing the AI and borgs to set the radio behavior of auto announcements (state laws, arrivals). if(!radio) diff --git a/tgstation.dme b/tgstation.dme index 24655671e59..0d28f663264 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -241,6 +241,7 @@ #include "code\_globalvars\misc.dm" #include "code\_globalvars\regexes.dm" #include "code\_globalvars\religion.dm" +#include "code\_globalvars\tgui.dm" #include "code\_globalvars\traits.dm" #include "code\_globalvars\lists\achievements.dm" #include "code\_globalvars\lists\admin.dm" @@ -2452,6 +2453,7 @@ #include "code\modules\mob\status_procs.dm" #include "code\modules\mob\transform_procs.dm" #include "code\modules\mob\camera\camera.dm" +#include "code\modules\mob\dead\crew_manifest.dm" #include "code\modules\mob\dead\dead.dm" #include "code\modules\mob\dead\new_player\login.dm" #include "code\modules\mob\dead\new_player\logout.dm" diff --git a/tgui/packages/tgui/interfaces/CrewManifest.js b/tgui/packages/tgui/interfaces/CrewManifest.js new file mode 100644 index 00000000000..fa109d90065 --- /dev/null +++ b/tgui/packages/tgui/interfaces/CrewManifest.js @@ -0,0 +1,64 @@ +import { useBackend } from "../backend"; +import { Icon, Section, Table } from "../components"; +import { Window } from "../layouts"; + +const commandJobs = [ + "Captain", + "Head of Personnel", + "Head of Security", + "Chief Engineer", + "Research Director", + "Chief Medical Officer", +]; + +export const CrewManifest = (props, context) => { + const { data: { manifest, positions } } = useBackend(context); + + return ( + + + {Object.entries(manifest).map(([department, crew]) => ( +
+ + {Object.entries(crew).map(([crewIndex, crewMember]) => ( + + + {crewMember.name} + + + {commandJobs.includes(crewMember.rank) && ( + + )} + + + {crewMember.rank} + + + ))} +
+
+ ))} +
+
+ ); +}; diff --git a/tgui/packages/tgui/styles/interfaces/CrewManifest.scss b/tgui/packages/tgui/styles/interfaces/CrewManifest.scss new file mode 100644 index 00000000000..8291cbbd50f --- /dev/null +++ b/tgui/packages/tgui/styles/interfaces/CrewManifest.scss @@ -0,0 +1,41 @@ +@use '../colors.scss'; + +$department_map: ( + 'Command': colors.$yellow, + 'Security': colors.$red, + 'Engineering': colors.$orange, + 'Medical': colors.$teal, + 'Science': colors.$purple, + 'Supply': colors.$brown, + 'Service': colors.$green, + 'Silicon': colors.$pink +); + +.CrewManifest { + @each $department-name, $color-value in $department_map { + &--#{$department-name} { + .Section { + &__title { + border-color: $color-value; + } + &__titleText { + color: $color-value; + } + } + } + } + + &__Cell { + padding: 3px 0; + + &--Captain { + color: colors.$yellow; + padding: 3px 8px; + } + + &--Command { + color: colors.$yellow; + padding: 3px 9px; + } + } +} diff --git a/tgui/packages/tgui/styles/main.scss b/tgui/packages/tgui/styles/main.scss index 6124d863dee..a98b3e60f77 100644 --- a/tgui/packages/tgui/styles/main.scss +++ b/tgui/packages/tgui/styles/main.scss @@ -45,6 +45,7 @@ @include meta.load-css('./interfaces/ListInput.scss'); @include meta.load-css('./interfaces/AlertModal.scss'); @include meta.load-css('./interfaces/CameraConsole.scss'); +@include meta.load-css('./interfaces/CrewManifest.scss'); @include meta.load-css('./interfaces/ExperimentConfigure.scss'); @include meta.load-css('./interfaces/NuclearBomb.scss'); @include meta.load-css('./interfaces/Paper.scss');