Merge branch 'master' of https://github.com/tgstation/tgstation into upstream-23-10-2025

This commit is contained in:
Roxy
2025-10-23 17:38:23 -04:00
453 changed files with 20635 additions and 15897 deletions
+7 -11
View File
@@ -57,17 +57,13 @@
// SKYRAT EDIT END
outfit.accessory = item_path
/datum/loadout_item/accessory/on_equip_item(
obj/item/clothing/accessory/equipped_item,
datum/preferences/preference_source,
list/preference_list,
mob/living/carbon/human/equipper,
visuals_only = FALSE,
)
/datum/loadout_item/accessory/on_equip_item(obj/item/equipped_item, list/item_details, mob/living/carbon/human/equipper, datum/outfit/job/outfit, visuals_only = FALSE)
. = ..()
if(istype(equipped_item))
equipped_item.above_suit = !!preference_list[item_path]?[INFO_LAYER]
. |= (ITEM_SLOT_OCLOTHING|ITEM_SLOT_ICLOTHING)
if(isnull(equipped_item))
return .
var/obj/item/clothing/accessory/accessory_item = equipped_item
accessory_item.above_suit = !!item_details[INFO_LAYER]
return . | ITEM_SLOT_OCLOTHING | ITEM_SLOT_ICLOTHING
/datum/loadout_item/accessory/maid_apron
name = "Maid Apron"
@@ -88,4 +84,4 @@
/datum/loadout_item/accessory/pride
name = "Pride Pin"
item_path = /obj/item/clothing/accessory/pride
can_be_reskinned = TRUE
loadout_flags = LOADOUT_FLAG_ALLOW_RESKIN
+13 -35
View File
@@ -31,13 +31,7 @@
abstract_type = /datum/loadout_item/pocket_items
can_be_named = TRUE // BUBBER EDIT ADDITION
/datum/loadout_item/pocket_items/on_equip_item(
obj/item/equipped_item,
datum/preferences/preference_source,
list/preference_list,
mob/living/carbon/human/equipper,
visuals_only = FALSE,
)
/datum/loadout_item/pocket_items/on_equip_item(obj/item/equipped_item, list/item_details, mob/living/carbon/human/equipper, datum/outfit/job/outfit, visuals_only = FALSE)
// Backpack items aren't created if it's a visual equipping, so don't do any on equip stuff. It doesn't exist.
if(visuals_only)
return NONE
@@ -48,7 +42,7 @@
/datum/loadout_item/pocket_items/plush
group = "Plushies"
abstract_type = /datum/loadout_item/pocket_items/plush
can_be_named = TRUE
loadout_flags = LOADOUT_FLAG_ALLOW_NAMING
/datum/loadout_item/pocket_items/plush/bee
name = "Plush (Bee)"
@@ -64,7 +58,7 @@
/datum/loadout_item/pocket_items/plush/lizard_random
name = "Plush (Lizard, Random)"
can_be_greyscale = DONT_GREYSCALE
loadout_flags = parent_type::loadout_flags | LOADOUT_FLAG_BLOCK_GREYSCALING
ui_icon = 'icons/obj/fluff/previews.dmi'
ui_icon_state = "plushie_lizard_random"
item_path = /obj/item/toy/plush/lizard_plushie
@@ -182,19 +176,15 @@
.[FA_ICON_PALETTE] = "Recolorable"
/* SKYRAT EDIT REMOVAL
/datum/loadout_item/pocket_items/lipstick/on_equip_item(
obj/item/lipstick/equipped_item,
datum/preferences/preference_source,
list/preference_list,
mob/living/carbon/human/equipper,
visuals_only,
)
/datum/loadout_item/pocket_items/lipstick/on_equip_item(obj/item/equipped_item, list/item_details, mob/living/carbon/human/equipper, datum/outfit/job/outfit, visuals_only = FALSE)
. = ..()
var/picked_style = style_to_style(preference_list[item_path]?[INFO_LAYER])
var/picked_color = preference_list[item_path]?[INFO_GREYSCALE] || /obj/item/lipstick::lipstick_color
if(istype(equipped_item)) // can be null for visuals_only
equipped_item.style = picked_style
equipped_item.lipstick_color = picked_color
if(isnull(equipped_item))
return
var/picked_style = style_to_style(item_details[INFO_LAYER])
var/picked_color = item_details[INFO_GREYSCALE] || /obj/item/lipstick::lipstick_color
var/obj/item/lipstick/lipstick_item = equipped_item
lipstick_item.style = picked_style
lipstick_item.lipstick_color = picked_color
equipper.update_lips(picked_style, picked_color)
/// Converts style (readable) to style (internal)
@@ -292,13 +282,7 @@
/datum/loadout_item/pocket_items/wallet/insert_path_into_outfit(datum/outfit/outfit, mob/living/carbon/human/equipper, visuals_only = FALSE)
return
/datum/loadout_item/pocket_items/wallet/on_equip_item(
obj/item/equipped_item,
datum/preferences/preference_source,
list/preference_list,
mob/living/carbon/human/equipper,
visuals_only = FALSE,
)
/datum/loadout_item/pocket_items/wallet/on_equip_item(obj/item/equipped_item, list/item_details, mob/living/carbon/human/equipper, datum/outfit/job/outfit, visuals_only = FALSE)
// Do this at the very end of the setup process so we can insert quirk items and such
if(!visuals_only && !isdummy(equipper))
RegisterSignal(equipper, COMSIG_HUMAN_CHARACTER_SETUP_FINISHED, PROC_REF(apply_after_setup), override = TRUE)
@@ -337,13 +321,7 @@
/datum/loadout_item/pocket_items/borg_me_dogtag
item_path = /obj/item/clothing/accessory/dogtag/borg_ready
/datum/loadout_item/pocket_items/borg_me_dogtag/on_equip_item(
obj/item/equipped_item,
datum/preferences/preference_source,
list/preference_list,
mob/living/carbon/human/equipper,
visuals_only = FALSE,
)
/datum/loadout_item/pocket_items/borg_me_dogtag/on_equip_item(obj/item/equipped_item, list/item_details, mob/living/carbon/human/equipper, datum/outfit/job/outfit, visuals_only)
// We're hooking this datum to add an extra bit of flavor to the dogtag - a pregenerated medical record
if(!visuals_only && !isdummy(equipper))
RegisterSignal(equipper, COMSIG_HUMAN_CHARACTER_SETUP_FINISHED, PROC_REF(apply_after_setup), override = TRUE)
+1 -1
View File
@@ -12,7 +12,7 @@
outfit.shoes = item_path
/datum/loadout_item/shoes/sneakers
name = "Sneakers (Colourable)"
name = "Sneakers"
item_path = /obj/item/clothing/shoes/sneakers
/datum/loadout_item/shoes/sandals_laced
+42
View File
@@ -0,0 +1,42 @@
/datum/loadout_category/suits
category_name = "Suits"
category_ui_icon = FA_ICON_USER_SECRET
type_to_generate = /datum/loadout_item/suit
tab_order = /datum/loadout_category/head::tab_order + 3
/datum/loadout_item/suit
abstract_type = /datum/loadout_item/suit
/datum/loadout_item/suit/insert_path_into_outfit(datum/outfit/outfit, mob/living/carbon/human/equipper, visuals_only = FALSE)
if(outfit.suit)
LAZYADD(outfit.backpack_contents, outfit.suit)
if(outfit.suit_store)
if(outfit.suit_store::w_class <= WEIGHT_CLASS_NORMAL)
LAZYADD(outfit.backpack_contents, outfit.suit_store)
else if((!outfit.belt || (outfit.belt::w_class <= WEIGHT_CLASS_NORMAL)) && (outfit.suit_store::slot_flags & ITEM_SLOT_BELT))
if(outfit.belt)
LAZYADD(outfit.backpack_contents, outfit.belt)
outfit.belt = outfit.suit_store
else if(!outfit.r_hand)
outfit.r_hand = outfit.suit_store
else if(!outfit.l_hand)
outfit.l_hand = outfit.suit_store
// no else condition - if every check failed, we just nuke whatever was there
// which is fine, suitstore generally contains replaceable items like pens, tanks, or weapons
outfit.suit_store = null
outfit.suit = item_path
/datum/loadout_item/suit/overall
name = "Overall"
item_path = /obj/item/clothing/suit/apron/overalls
loadout_flags = LOADOUT_FLAG_JOB_GREYSCALING
job_greyscale_palettes = list(
/datum/job/assistant = COLOR_JOB_DEFAULT,
/datum/job/botanist = /obj/item/clothing/suit/apron/overalls::greyscale_colors,
/datum/job/captain = COLOR_JOB_COMMAND_GENERIC,
/datum/job/head_of_personnel = COLOR_JOB_COMMAND_GENERIC,
/datum/job/head_of_security = COLOR_JOB_DEFAULT,
/datum/job/paramedic = "#28324b",
/datum/job/prisoner = "#ff8b00",
)
+3 -3
View File
@@ -77,14 +77,14 @@
// SKYRAT EDIT END
// Handle any snowflake on_equips.
var/list/new_contents = get_all_gear()
var/list/new_contents = get_all_gear(INCLUDE_PROSTHETICS|INCLUDE_ABSTRACT|INCLUDE_ACCESSORIES)
var/update = NONE
for(var/datum/loadout_item/item as anything in loadout_datums)
update |= item.on_equip_item(
equipped_item = (loadout_placement_preference == LOADOUT_OVERRIDE_CASE && !visuals_only) ? locate(item.item_path) in travel_suitcase : locate(item.item_path) in new_contents, // BUBBER EDIT CHANGE - ORIGINAL: equipped_item = locate(item.item_path) in new_contents,
preference_source = preference_source,
preference_list = preference_list,
item_details = preference_list?[item.item_path] || list(),
equipper = src,
outfit = equipped_outfit,
visuals_only = visuals_only,
)
if(update)
+124 -57
View File
@@ -40,17 +40,8 @@ GLOBAL_LIST_INIT(all_loadout_categories, init_loadout_categories())
/// Title of a group that this item will be bundled under
/// Defaults to parent category's title if unset
var/group = null
/// Whether this item has greyscale support.
/// Only works if the item is compatible with the GAGS system of coloring.
/// Set automatically to TRUE for all items that have the flag [IS_PLAYER_COLORABLE_1].
/// If you really want it to not be colorable set this to [DONT_GREYSCALE]
var/can_be_greyscale = FALSE
/// Whether this item can be renamed.
/// I recommend you apply this sparingly becuase it certainly can go wrong (or get reset / overridden easily)
var/can_be_named = TRUE // SKYRAT EDIT
/// Whether this item can be reskinned.
/// Only works if the item has a "unique reskin" list set.
var/can_be_reskinned = FALSE
/// Loadout flags, see LOADOUT_FLAG_* defines
var/loadout_flags = LOADOUT_FLAG_ALLOW_NAMING // BUBBER EDIT CHANGE - Original: var/loadout_flags = NONE
/// The actual item path of the loadout item.
var/obj/item/item_path
/// Icon file (DMI) for the UI to use for preview icons.
@@ -61,6 +52,28 @@ GLOBAL_LIST_INIT(all_loadout_categories, init_loadout_categories())
var/ui_icon_state
/// Reskin options of this item if it can be reskinned.
VAR_FINAL/list/cached_reskin_options
/// A list of greyscale colors that are used for items that have greyscale support, but don't allow full customization.
/// This is an assoc list of /datum/job_department -> colors, or /datum/job -> colors, allowing for preset colors based on player chosen job.
/// Jobs are prioritized over departments.
/// Note: You don't need to set a color for every job or department!
var/list/job_greyscale_palettes
// BUBBER EDIT ADDITION START
/// If set, it's a list containing ckeys which only can get the item
var/list/ckeywhitelist
/// If set, is a list of job names of which can get the loadout item
var/list/restricted_roles
/// If set, is a list of job names of which can't get the loadout item
var/list/blacklisted_roles
/// If set, is a list of species which can get the loadout item
var/list/restricted_species
/// Whether the item is restricted to supporters
var/donator_only
/// Whether the item requires a specific season in order to be available
var/required_season = null
/// If the item won't appear when the ERP config is disabled
var/erp_item = FALSE
// BUBBER EDIT END
// BUBBER EDIT ADDITION START
/// If set, it's a list containing ckeys which only can get the item
@@ -82,10 +95,18 @@ GLOBAL_LIST_INIT(all_loadout_categories, init_loadout_categories())
/datum/loadout_item/New(category)
src.category = category
if(can_be_greyscale == DONT_GREYSCALE)
can_be_greyscale = FALSE
else if((item_path::flags_1 & IS_PLAYER_COLORABLE_1) && item_path::greyscale_config && item_path::greyscale_colors)
can_be_greyscale = TRUE
if(!(loadout_flags & LOADOUT_FLAG_BLOCK_GREYSCALING) && is_greyscale_item())
loadout_flags |= LOADOUT_FLAG_GREYSCALING_ALLOWED
if(loadout_flags & LOADOUT_FLAG_JOB_GREYSCALING)
var/default_colors = SSgreyscale.ParseColorString(item_path::greyscale_colors)
var/list/final_palette = LAZYLISTDUPLICATE(job_greyscale_palettes)
switch(length(default_colors))
if(1)
LAZYOR(final_palette, default_one_color_job_palette())
if(2 to INFINITY)
stack_trace("[length(default_colors)] color job palettes are not implemented yet, please do so.")
job_greyscale_palettes = final_palette
if(isnull(name))
name = item_path::name
@@ -94,11 +115,11 @@ GLOBAL_LIST_INIT(all_loadout_categories, init_loadout_categories())
ui_icon = item_path::icon_preview || item_path::icon
ui_icon_state = item_path::icon_state_preview || item_path::icon_state
if(can_be_reskinned)
if(loadout_flags & LOADOUT_FLAG_ALLOW_RESKIN)
var/obj/item/dummy_item = new item_path()
if(!length(dummy_item.unique_reskin))
can_be_reskinned = FALSE
stack_trace("Loadout item [item_path] has can_be_reskinned set to TRUE but has no unique reskins.")
loadout_flags &= ~LOADOUT_FLAG_ALLOW_RESKIN
stack_trace("Loadout item [item_path] has LOADOUT_FLAG_ALLOW_RESKIN but has no unique reskins.")
else
cached_reskin_options = dummy_item.unique_reskin.Copy()
qdel(dummy_item)
@@ -111,13 +132,21 @@ GLOBAL_LIST_INIT(all_loadout_categories, init_loadout_categories())
// SKYRAT EDIT END
/datum/loadout_item/Destroy(force, ...)
if(force)
if(!force)
stack_trace("QDEL called on loadout item [type]. This shouldn't ever happen. (Use FORCE if necessary.)")
return QDEL_HINT_LETMELIVE
GLOB.all_loadout_datums -= item_path
return ..()
/// Checks if the item is capable of being recolored / is a GAGS item.
/datum/loadout_item/proc/is_greyscale_item()
if(!(item_path::flags_1 & IS_PLAYER_COLORABLE_1))
return FALSE
if(!item_path::greyscale_config || !item_path::greyscale_colors)
return FALSE
return TRUE
/**
* Takes in an action from a loadout manager and applies it
*
@@ -130,21 +159,22 @@ GLOBAL_LIST_INIT(all_loadout_categories, init_loadout_categories())
switch(action)
if("select_color")
if(can_be_greyscale)
if((loadout_flags & LOADOUT_FLAG_GREYSCALING_ALLOWED) && !(loadout_flags & LOADOUT_FLAG_JOB_GREYSCALING))
return set_item_color(manager, user)
if("set_name")
if(can_be_named)
// SKYRAT EDIT BEGIN - Description
return set_name(manager, user, INFO_NAMED)
if(loadout_flags & LOADOUT_FLAG_ALLOW_NAMING)
return set_name(manager, user, INFO_NAMED) // BUBBER EDIT CHANGE - Original: return set_name(manager, user)
// BUBBER EDIT ADDITION BEGIN
if("set_desc")
if(can_be_named)
if(loadout_flags & LOADOUT_FLAG_ALLOW_NAMING)
return set_name(manager, user, INFO_DESCRIBED)
// SKYRAT EDIT END
// BUBBER EDIT ADDITION END
if("set_skin")
return set_skin(manager, user, params)
if(loadout_flags & LOADOUT_FLAG_ALLOW_RESKIN)
return set_skin(manager, user, params)
return TRUE
@@ -226,9 +256,6 @@ GLOBAL_LIST_INIT(all_loadout_categories, init_loadout_categories())
/// Used for reskinning an item to an alt skin.
/datum/loadout_item/proc/set_skin(datum/preference_middleware/loadout/manager, mob/user, params)
if(!can_be_reskinned)
return FALSE
var/reskin_to = params["skin"]
if(!cached_reskin_options[reskin_to])
return FALSE
@@ -241,6 +268,26 @@ GLOBAL_LIST_INIT(all_loadout_categories, init_loadout_categories())
manager.save_current_loadout(loadout) // BUBBER EDIT: Multiple loadout presets: ORIGINAL: manager.preferences.update_preference(GLOB.preference_entries[/datum/preference/loadout], loadout)
return TRUE // always update UI
/// When passed an outfit, attempts to select a job-appropriate color from job_greyscale_palettes
/datum/loadout_item/proc/get_job_color(datum/outfit/base_outfit)
if(!istype(base_outfit, /datum/outfit/job))
return job_greyscale_palettes[/datum/job] // default color
var/datum/outfit/job/job_outfit = base_outfit
var/jobtype = job_outfit.jobtype
if(job_greyscale_palettes[jobtype])
return job_greyscale_palettes[jobtype]
var/datum/job/job = SSjob.get_job_type(jobtype)
if(job.department_for_prefs && job_greyscale_palettes[job.department_for_prefs])
return job_greyscale_palettes[job.department_for_prefs]
for(var/job_dept in job.departments_list)
if(job_greyscale_palettes[job_dept])
return job_greyscale_palettes[job_dept]
return job_greyscale_palettes[/datum/job] // default color
/**
* Place our [item_path] into the passed [outfit].
*
@@ -262,48 +309,43 @@ GLOBAL_LIST_INIT(all_loadout_categories, init_loadout_categories())
*
* Arguments:
* * preference_source - the datum/preferences our loadout item originated from - cannot be null
* * item_details - the details of the item in the loadout preferences, such as greyscale, name, reskin, etc
* * equipper - the mob we're equipping this item onto
* * outfit - the rest of the outfit being equipped, may be null
* * visuals_only - whether or not this is only concerned with visual things (not backpack, not renaming, etc)
* * preference_list - what the raw loadout list looks like in the preferences
*
* Return a bitflag of slot flags to update
*/
/datum/loadout_item/proc/on_equip_item(
obj/item/equipped_item,
datum/preferences/preference_source,
list/preference_list,
mob/living/carbon/human/equipper,
visuals_only = FALSE,
)
/datum/loadout_item/proc/on_equip_item(obj/item/equipped_item, list/item_details, mob/living/carbon/human/equipper, datum/outfit/outfit, visuals_only = FALSE)
if(isnull(equipped_item))
return NONE
if(!visuals_only)
ADD_TRAIT(equipped_item, TRAIT_ITEM_OBJECTIVE_BLOCKED, TRAIT_SOURCE_LOADOUT)
var/list/item_details = preference_list[item_path]
var/update_flag = NONE
if(can_be_greyscale && item_details?[INFO_GREYSCALE])
equipped_item.set_greyscale(item_details[INFO_GREYSCALE])
if((loadout_flags & LOADOUT_FLAG_GREYSCALING_ALLOWED) && ((loadout_flags & LOADOUT_FLAG_JOB_GREYSCALING) || item_details?[INFO_GREYSCALE]))
var/item_color = (loadout_flags & LOADOUT_FLAG_JOB_GREYSCALING) ? get_job_color(outfit) : item_details?[INFO_GREYSCALE]
equipped_item.set_greyscale(item_color)
update_flag |= equipped_item.slot_flags
// SKYRAT EDIT BEGIN - DESCRIPTIONS~
if(can_be_named && !visuals_only)
var/renamed = 0
// BUBBER EDIT CHANGE BEGIN - Descriptions
if((loadout_flags & LOADOUT_FLAG_ALLOW_NAMING) && !visuals_only)
var/renamed = FALSE
if(item_details?[INFO_NAMED])
equipped_item.name = trim(item_details[INFO_NAMED], PREVENT_CHARACTER_TRIM_LOSS(MAX_NAME_LEN))
renamed = 1
renamed = TRUE
if(item_details?[INFO_DESCRIBED])
equipped_item.desc = trim(item_details[INFO_DESCRIBED], PREVENT_CHARACTER_TRIM_LOSS(MAX_DESC_LEN))
renamed = 1
renamed = TRUE
if(renamed)
ADD_TRAIT(equipped_item, TRAIT_WAS_RENAMED, TRAIT_SOURCE_LOADOUT)
equipped_item.AddElement(/datum/element/examined_when_worn)
SEND_SIGNAL(equipped_item, COMSIG_NAME_CHANGED)
// SKYRAT EDIT END
// BUBBER EDIT CHANGE END - Descriptions
if(can_be_reskinned && item_details?[INFO_RESKIN])
if((loadout_flags & LOADOUT_FLAG_ALLOW_RESKIN) && item_details?[INFO_RESKIN])
var/skin_chosen = item_details[INFO_RESKIN]
if(skin_chosen in equipped_item.unique_reskin)
equipped_item.current_skin = skin_chosen
@@ -317,11 +359,6 @@ GLOBAL_LIST_INIT(all_loadout_categories, init_loadout_categories())
else
update_flag |= equipped_item.slot_flags
else
// Not valid, update the preference
item_details -= INFO_RESKIN
preference_source.write_preference(GLOB.preference_entries[/datum/preference/loadout], preference_list)
return update_flag
/**
@@ -360,10 +397,10 @@ GLOBAL_LIST_INIT(all_loadout_categories, init_loadout_categories())
// Mothblocks is hellbent on recolorable and reskinnable being only tooltips for items for visual clarity, so ask her before changing these
var/list/displayed_text = list()
if(can_be_greyscale)
if((loadout_flags & LOADOUT_FLAG_GREYSCALING_ALLOWED) && !(loadout_flags & LOADOUT_FLAG_JOB_GREYSCALING))
displayed_text[FA_ICON_PALETTE] = "Recolorable"
if(can_be_reskinned)
if(loadout_flags & LOADOUT_FLAG_ALLOW_RESKIN)
displayed_text[FA_ICON_SWATCHBOOK] = "Reskinnable"
// SKYRAT EDIT ADDITION
@@ -404,7 +441,7 @@ GLOBAL_LIST_INIT(all_loadout_categories, init_loadout_categories())
var/list/button_list = list()
if(can_be_greyscale)
if((loadout_flags & LOADOUT_FLAG_GREYSCALING_ALLOWED) && !(loadout_flags & LOADOUT_FLAG_JOB_GREYSCALING))
UNTYPED_LIST_ADD(button_list, list(
"label" = "Recolor",
"act_key" = "select_color",
@@ -412,7 +449,7 @@ GLOBAL_LIST_INIT(all_loadout_categories, init_loadout_categories())
"active_key" = INFO_GREYSCALE,
))
if(can_be_named)
if(loadout_flags & LOADOUT_FLAG_ALLOW_NAMING)
UNTYPED_LIST_ADD(button_list, list(
"label" = "Rename",
"act_key" = "set_name",
@@ -433,7 +470,7 @@ GLOBAL_LIST_INIT(all_loadout_categories, init_loadout_categories())
* Returns a list of options this item can be reskinned into.
*/
/datum/loadout_item/proc/get_reskin_options() as /list
if(!can_be_reskinned)
if(!(loadout_flags & LOADOUT_FLAG_ALLOW_RESKIN))
return null
var/list/reskins = list()
@@ -446,3 +483,33 @@ GLOBAL_LIST_INIT(all_loadout_categories, init_loadout_categories())
))
return reskins
/// Default job gags colors for one color gags items
/datum/loadout_item/proc/default_one_color_job_palette()
return list(
/datum/job/assistant = COLOR_JOB_ASSISTANT,
/datum/job/bitrunner = COLOR_JOB_DEFAULT,
/datum/job/botanist = COLOR_JOB_BOTANIST,
/datum/job/chemist = COLOR_JOB_CHEMIST,
/datum/job/chief_engineer = COLOR_JOB_CE,
/datum/job/chief_medical_officer = COLOR_JOB_CMO,
/datum/job/clown = COLOR_JOB_CLOWN,
/datum/job/cook = COLOR_JOB_CHEF,
/datum/job/coroner = COLOR_JOB_DEFAULT,
/datum/job/curator = COLOR_DRIED_TAN,
/datum/job/detective = COLOR_DRIED_TAN,
/datum/job/geneticist = COLOR_BLUE_GRAY,
/datum/job/janitor = COLOR_JOB_JANITOR,
/datum/job/lawyer = COLOR_JOB_LAWYER,
/datum/job/prisoner = COLOR_PRISONER_ORANGE,
/datum/job/psychologist = COLOR_DRIED_TAN,
/datum/job/roboticist = COLOR_JOB_DEFAULT,
/datum/job/shaft_miner = COLOR_DARK_BROWN,
/datum/job_department/command = COLOR_JOB_COMMAND_GENERIC,
/datum/job_department/engineering = COLOR_JOB_ENGI_GENERIC,
/datum/job_department/medical = COLOR_JOB_MED_GENERIC,
/datum/job_department/security = COLOR_JOB_SEC_GENERIC,
/datum/job_department/science = COLOR_JOB_SCI_GENERIC,
/datum/job_department/cargo = COLOR_JOB_CARGO_GENERIC,
/datum/job = COLOR_JOB_DEFAULT, // default for any job not listed above
)