diff --git a/code/modules/admin/modify_robot.dm b/code/modules/admin/modify_robot.dm index 86ae8d0398b..9afef619cf1 100644 --- a/code/modules/admin/modify_robot.dm +++ b/code/modules/admin/modify_robot.dm @@ -11,10 +11,15 @@ /datum/eventkit/modify_robot var/mob/living/silicon/robot/target + var/mob/living/silicon/robot/source /datum/eventkit/modify_robot/New() . = ..() +/datum/eventkit/modify_robot/tgui_close() + if(source) + qdel(source) + /datum/eventkit/modify_robot/tgui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) @@ -22,9 +27,11 @@ ui.open() /datum/eventkit/modify_robot/Destroy() + if(source) + qdel(source) . = ..() -/datum/eventkit/modify_robot/tgui_data() +/datum/eventkit/modify_robot/tgui_data(mob/user) . = list() if(target) .["target"] = list() @@ -42,11 +49,36 @@ .["target"]["front"] = icon2base64(get_flat_icon(target,dir=SOUTH,no_anim=TRUE)) .["target"]["side"] = icon2base64(get_flat_icon(target,dir=WEST,no_anim=TRUE)) .["target"]["back"] = icon2base64(get_flat_icon(target,dir=NORTH,no_anim=TRUE)) - var/list/all_players = list() + var/list/target_items = list() + for(var/obj/item in target.module.modules) + target_items += list(list("item" = item.name, "ref" = "\ref[item]", "icon" = icon2html(item, user, sourceonly=TRUE))) + .["target"]["modules"] = target_items + var/list/module_options = list() + for(var/module in robot_modules) + module_options += module + .["model_options"] = module_options + if(source) + .["source"] = list() + .["source"]["model"] = source.module + .["source"]["front"] = icon2base64(get_flat_icon(source,dir=SOUTH,no_anim=TRUE)) + var/list/source_items = list() + for(var/obj/item in (source.module.modules | source.module.emag)) + var/exists + for(var/obj/has_item in (target.module.modules + target.module.emag)) + if(has_item.name == item.name) + exists = TRUE + break + if(exists) + continue + source_items += list(list("item" = item.name, "ref" = "\ref[item]", "icon" = icon2html(item, user, sourceonly=TRUE))) + .["source"]["modules"] = source_items + var/list/all_robots = list() for(var/mob/living/silicon/robot/R in silicon_mob_list) + if(!R.loc) + continue var/list/info = list("displayText" = "[R]", "value" = "\ref[R]") - all_players.Add(list(info)) - .["all_players"] = all_players + all_robots.Add(list(info)) + .["all_robots"] = all_robots /datum/eventkit/modify_robot/tgui_state(mob/user) @@ -65,5 +97,86 @@ return TRUE if("add_restriction") target.restrict_modules_to += params["new_restriction"] + return TRUE if("remove_restriction") target.restrict_modules_to -= params["rem_restriction"] + return TRUE + if("select_source") + if(source) + qdel(source) + source = new /mob/living/silicon/robot(null) + var/module_type = robot_modules[params["new_source"]] + source.modtype = params["new_source"] + var/obj/item/weapon/robot_module/robot/robot_type = new module_type(source) + source.sprite_datum = pick(SSrobot_sprites.get_module_sprites(source.modtype, source)) + source.update_icon() + source.emag_items = 1 + if(!istype(robot_type, /obj/item/weapon/robot_module/robot)) + QDEL_NULL(source) + return TRUE + return TRUE + if("reset_module") + target.module_reset(FALSE) + return TRUE + if("add_module") + var/obj/item/add_item = locate(params["new_module"]) + if(!add_item) + return TRUE + source.module.emag.Remove(add_item) + source.module.modules.Remove(add_item) + source.module.contents.Remove(add_item) + target.module.modules.Add(add_item) + target.module.contents.Add(add_item) + spawn(0) + SEND_SIGNAL(add_item, COMSIG_OBSERVER_MOVED) + target.hud_used.update_robot_modules_display() + if(istype(add_item, /obj/item/stack/)) + var/obj/item/stack/item_with_synth = add_item + for(var/synth in item_with_synth.synths) + var/found = target.module.synths.Find(synth) + if(!found) + source.module.synths.Remove(synth) + target.module.synths.Add(synth) + else + item_with_synth.synths = list(target.module.synths[found]) + return TRUE + if(istype(add_item, /obj/item/weapon/matter_decompiler/) || istype(add_item, /obj/item/device/dogborg/sleeper/compactor/decompiler/)) + var/obj/item/weapon/matter_decompiler/item_with_matter = add_item + if(item_with_matter.metal) + var/found = target.module.synths.Find(item_with_matter.metal) + if(!found) + source.module.synths.Remove(item_with_matter.metal) + target.module.synths.Add(item_with_matter.metal) + else + item_with_matter.metal = target.module.synths[found] + if(item_with_matter.glass) + var/found = target.module.synths.Find(item_with_matter.glass) + if(!found) + source.module.synths.Remove(item_with_matter.glass) + target.module.synths.Add(item_with_matter.glass) + else + item_with_matter.glass = target.module.synths[found] + if(item_with_matter.wood) + var/found = target.module.synths.Find(item_with_matter.wood) + if(!found) + source.module.synths.Remove(item_with_matter.wood) + target.module.synths.Add(item_with_matter.wood) + else + item_with_matter.wood = target.module.synths[found] + if(item_with_matter.plastic) + var/found = target.module.synths.Find(item_with_matter.plastic) + if(!found) + source.module.synths.Remove(item_with_matter.plastic) + target.module.synths.Add(item_with_matter.plastic) + else + item_with_matter.plastic = target.module.synths[found] + return TRUE + if("rem_module") + var/obj/item/rem_item = locate(params["old_module"]) + target.uneq_all() + target.hud_used.update_robot_modules_display(TRUE) + target.module.emag.Remove(rem_item) + target.module.modules.Remove(rem_item) + target.module.contents.Remove(rem_item) + qdel(rem_item) + return TRUE diff --git a/tgui/packages/tgui/interfaces/ModifyRobot/ModifyRobotNoModule.tsx b/tgui/packages/tgui/interfaces/ModifyRobot/ModifyRobotNoModule.tsx index ccb262b3d21..364bd2ff2d6 100644 --- a/tgui/packages/tgui/interfaces/ModifyRobot/ModifyRobotNoModule.tsx +++ b/tgui/packages/tgui/interfaces/ModifyRobot/ModifyRobotNoModule.tsx @@ -3,11 +3,13 @@ import { Button, Divider, Flex, + Icon, NoticeBox, Section, Stack, } from 'tgui/components'; +import { RankIcon } from '../common/RankIcon'; import { Target } from './types'; export const ModifyRobotNoModule = (props: { target: Target }) => { @@ -24,8 +26,20 @@ export const ModifyRobotNoModule = (props: { target: Target }) => { fluid color={target.crisis_override ? 'red' : 'green'} onClick={() => act('toggle_crisis')} + tooltip={ + (target.crisis_override ? 'Disables' : 'Enables') + + ' combat module option for this unit!' + } > - {(target.crisis_override ? 'Disable' : 'Enable') + ' Crisis Override'} + + + + + + {(target.crisis_override ? 'Disable' : 'Enable') + + ' Crisis Override'} + + @@ -46,7 +60,12 @@ export const ModifyRobotNoModule = (props: { target: Target }) => { }) } > - {active_restriction} + + + {RankIcon({ rank: active_restriction, color: '' })} + + {active_restriction} + ); })} @@ -70,7 +89,12 @@ export const ModifyRobotNoModule = (props: { target: Target }) => { }) } > - {possible_restriction} + + + {RankIcon({ rank: possible_restriction, color: '' })} + + {possible_restriction} + ); })} diff --git a/tgui/packages/tgui/interfaces/ModifyRobot/ModifyRobotTabs/ModifyRobotModules.tsx b/tgui/packages/tgui/interfaces/ModifyRobot/ModifyRobotTabs/ModifyRobotModules.tsx index 89bc913c5aa..1fd665ae9b3 100644 --- a/tgui/packages/tgui/interfaces/ModifyRobot/ModifyRobotTabs/ModifyRobotModules.tsx +++ b/tgui/packages/tgui/interfaces/ModifyRobot/ModifyRobotTabs/ModifyRobotModules.tsx @@ -1,11 +1,144 @@ import { useBackend } from 'tgui/backend'; +import { + Box, + Button, + Divider, + Dropdown, + Flex, + Icon, + Image, + Section, + Stack, +} from 'tgui/components'; -import { Box } from '../../../components'; -import { Target } from '../types'; +import { Source, Target } from '../types'; -export const ModifyRobotModules = (props: { target: Target }) => { - const { target } = props; +export const ModifyRobotModules = (props: { + target: Target; + source: Source; + model_options: string[]; +}) => { + const { target, source, model_options } = props; const { act } = useBackend(); - return ; + return ( + + +
+ Robot to salvage + + act('select_source', { + new_source: value, + }) + } + /> + {!!source && ( + <> + + + + + + {source.modules.map((modul_option, i) => { + return ( + + ); + })} + + + + )} +
+
+ + +
+ {target ? target.module : ''} + act('reset_module')} + > + Reset Module + + + + + + + {target.modules.map((modul_option, i) => { + return ( + + ); + })} + + +
+
+
+ ); }; diff --git a/tgui/packages/tgui/interfaces/ModifyRobot/index.tsx b/tgui/packages/tgui/interfaces/ModifyRobot/index.tsx index efcd305eb9d..438d89f5b71 100644 --- a/tgui/packages/tgui/interfaces/ModifyRobot/index.tsx +++ b/tgui/packages/tgui/interfaces/ModifyRobot/index.tsx @@ -17,21 +17,28 @@ import { Data } from './types'; export const ModifyRobot = (props) => { const { act, data } = useBackend(); - const { target, all_players } = data; + const { target, all_robots, source, model_options } = data; const [tab, setTab] = useState(0); const tabs: React.JSX.Element[] = []; - tabs[0] = ; + tabs[0] = ( + + ); tabs[1] = ; tabs[2] = ; tabs[3] = ; tabs[4] = ; tabs[5] = ; + tabs[6] = ; return ( - + {target ? ( @@ -45,7 +52,7 @@ export const ModifyRobot = (props) => { act('select_target', { new_target: value, @@ -79,6 +86,9 @@ export const ModifyRobot = (props) => { setTab(5)}> Law Manager + setTab(6)}> + Law Sets + {tabs[tab]} diff --git a/tgui/packages/tgui/interfaces/ModifyRobot/types.ts b/tgui/packages/tgui/interfaces/ModifyRobot/types.ts index 9e4b3d57a37..a90b58e29d3 100644 --- a/tgui/packages/tgui/interfaces/ModifyRobot/types.ts +++ b/tgui/packages/tgui/interfaces/ModifyRobot/types.ts @@ -1,8 +1,10 @@ import { BooleanLike } from 'common/react'; export type Data = { + source: Source; target: Target | null; - all_players: DropdownEntry[]; + all_robots: DropdownEntry[]; + model_options: string[] | null; }; export type DropdownEntry = { @@ -20,4 +22,13 @@ export type Target = { front: string | null; side: string | null; back: string | null; + modules: Module[]; }; + +export type Source = { + model: string; + front: string; + modules: Module[]; +} | null; + +export type Module = { item: string; ref: string; icon: string }; diff --git a/tgui/packages/tgui/interfaces/common/RankIcon.tsx b/tgui/packages/tgui/interfaces/common/RankIcon.tsx index 646a4e43ad7..76d5dd46b9f 100644 --- a/tgui/packages/tgui/interfaces/common/RankIcon.tsx +++ b/tgui/packages/tgui/interfaces/common/RankIcon.tsx @@ -1,103 +1,637 @@ import { Icon } from '../../components'; const rank2icon = { - // Command - 'Colony Director': 'user-tie', + // Command Site Manager 'Site Manager': 'user-tie', Overseer: 'user-tie', + 'Facility Director': 'user-tie', + 'Chief Supervisor': 'user-tie', + Captain: 'user-tie', + 'Colony Director': 'user-tie', + // HOP 'Head of Personnel': 'briefcase', 'Crew Resources Officer': 'briefcase', 'Deputy Director': 'briefcase', - 'Command Secretary': 'user-tie', - // Security + 'Staff Manager': 'briefcase', + 'Facility Steward': 'briefcase', + 'First Mate': 'briefcase', + 'Performance Management Supervisor': 'briefcase', + // Secretary + 'Command Secretary': 'address-card', + 'Command Liaison': 'address-card', + 'Command Assistant': 'address-card', + 'Command Intern': 'address-card', + 'Bridge Secretary': 'address-card', + 'Bridge Assistant': 'address-card', + 'Bridge Officer': 'address-card', + // Security HOS 'Head of Security': 'user-shield', 'Security Commander': 'user-shield', 'Chief of Security': 'user-shield', - Warden: ['city', 'shield-alt'], - Detective: 'search', - 'Forensic Technician': 'search', - 'Security Officer': 'user-shield', - 'Junior Officer': 'user-shield', - // Engineering - 'Chief Engineer': 'toolbox', + 'Security Managery': 'user-shield', + // Warden + Warden: ['city', 'shield-halved'], + 'Brig Sentry': ['city', 'shield-halved'], + 'Armory Superintendent': ['city', 'shield-halved'], + 'Master-at-Arms': ['city', 'shield-halved'], + // Detective + Detective: 'magnifying-glass', + Investigator: 'magnifying-glass', + 'Security Inspector': 'magnifying-glass', + 'Forensic Technician': 'magnifying-glass', + // Security Officer + 'Security Officer': 'shield', + 'Patrol Officer': 'shield', + 'Security Guard': 'shield', + 'Security Deputy': 'shield', + 'Junior Officer': 'shield', + 'Security Contractor': 'shield', + // Engineering CE + 'Chief Engineer': 'screwdriver-wrench', + 'Head Engineer': 'screwdriver-wrench', + Foreman: 'screwdriver-wrench', + 'Maintenance Manager': 'screwdriver-wrench', + // Atmospheric Technician 'Atmospheric Technician': 'wind', - 'Station Engineer': 'toolbox', + 'Atmospheric Engineer': 'wind', + 'Atmospheric Maintainer': 'wind', + 'Disposals Technician': 'wind', + 'Fuel Technician': 'wind', + // Engineer + Engineer: 'toolbox', 'Maintenance Technician': 'wrench', 'Engine Technician': 'toolbox', - Electrician: 'toolbox', - // Medical - 'Chief Medical Officer': 'user-md', + Electrician: 'screwdriver', + 'Construction Engineer': 'trowel-bricks', + 'Engineering Contractor': 'ruler', + // Medical CMO + 'Chief Medical Officer': 'user-doctor', + 'Chief Physician': 'user-doctor', + 'Medical Director': 'user-doctor', + 'Healthcare Manager': 'user-doctor', + // Chemist Chemist: 'mortar-pestle', Pharmacist: 'mortar-pestle', - 'Medical Doctor': 'user-md', - Surgeon: 'user-md', - 'Emergency Physician': 'user-md', - Nurse: 'user-md', + Pharmacologist: 'mortar-pestle', + // Medical Doctor + 'Medical Doctor': 'suitcase-medical', + Physician: 'suitcase-medical', + 'Medical Practitioner': 'suitcase-medical', + Surgeon: 'syringe', + 'Emergency Physician': 'suitcase-medical', + Nurse: 'user-nurse', + Orderly: 'book-medical', Virologist: 'disease', - Paramedic: 'ambulance', - 'Emergency Medical Technician': 'ambulance', + 'Medical Contractor': 'notes-medical', + // Paramedic + Paramedic: 'truck-medical', + 'Emergency Medical Technician': 'truck-medical', + 'Medical Responder': 'truck-medical', + 'Search and Rescue': 'truck-droplet', + // Psychiatrist Psychiatrist: 'couch', Psychologist: 'couch', - // Science + Psychoanalyst: 'couch', + Psychotherapist: 'couch', + // Genetecist + Geneticist: 'dna', + // Brig Physician + 'Brig Physician': ['kit-medical', 'shield-halved'], + 'Security Medic': ['kit-medical', 'shield-halved'], + 'Security Medic Care Unit': ['kit-medical', 'shield-halved'], + 'Penitentiary Medical Care Unit': ['kit-medical', 'shield-halved'], + 'Junior Brig Physician': ['kit-medical', 'shield-halved'], + 'Detention Health Officer': ['kit-medical', 'shield-halved'], + // Science RD 'Research Director': 'user-graduate', 'Research Supervisor': 'user-graduate', + 'Research Manager': 'user-graduate', + 'Head of Development': 'user-graduate', + 'Head Scientist': 'user-graduate', + // Roboticist Roboticist: 'robot', + 'Assembly Technician': 'screwdriver', 'Biomechanical Engineer': ['wrench', 'heartbeat'], 'Mechatronic Engineer': 'wrench', + // Scientist Scientist: 'flask', - Xenoarchaeologist: 'flask', - Anomalist: 'flask', - 'Phoron Researcher': 'flask', + Researcher: 'flask-vial', + 'Lab Assistant': 'flask', + Xenoarchaeologist: 'bone', + Xenopaleontologist: 'bone', + Anomalist: 'atom', + 'Phoron Researcher': 'vials', + 'Gas Physicist': 'microscope', 'Circuit Designer': 'car-battery', + 'Circuit Programmer': 'laptop-file', + // Xenobiologist Xenobiologist: 'meteor', + Xenozoologist: 'locust', + Xenoanthropologist: 'bugs', + // Xenobotanist Xenobotanist: ['biohazard', 'seedling'], - // Cargo + Xenohydroponicist: ['biohazard', 'droplet'], + Xenoflorist: ['biohazard', 'clover'], + // Cargo QM Quartermaster: 'box-open', 'Supply Chief': 'warehouse', - 'Cargo Technician': 'box-open', - 'Shaft Miner': 'hard-hat', - 'Drill Technician': 'hard-hat', - // Exploration + 'Logistics Manager': 'warehouse', + 'Cargo Supervisor': 'box-open', + // Cargo Technician + 'Cargo Technician': 'box', + 'Cargo Loader': 'dolly', + 'Cargo Handler': 'boxes-stacked', + 'Supply Courier': 'people-carry-box', + 'Disposals Sorter': 'recycle', + Mailman: 'envelopes-bulk', + // Shaft Miner + 'Shaft Miner': 'helmet-safety', + 'Deep Space Miner': 'bore-hole', + 'Drill Technician': 'oil-well', + Prospector: 'helmet-safety', + Excavator: 'bore-hole', + // Exploration Lead Pathfinder: 'binoculars', + 'Expedition Lead': 'binoculars', + 'Exploration Manager': 'binoculars', + // Explorer Explorer: 'user-astronaut', - 'Field Medic': ['user-md', 'user-astronaut'], - Pilot: 'space-shuttle', - // Civvies + Surveyor: 'user-astronaut', + 'Offsite Scout': 'user-astronaut', + 'Explorer Medic': ['user-astronaut', 'kit-medical'], + 'Explorer Technician': ['user-astronaut', 'screwdriver'], + // Field Medic + 'Field Medic': ['suitcase-medical', 'user-astronaut'], + 'Expedition Medic': ['suitcase-medical', 'user-astronaut'], + 'Offsite Medic': ['suitcase-medical', 'user-astronaut'], + // Pilot + Pilot: 'shuttle-space', + 'Co-Pilot': 'shuttle-space', + Navigator: 'shuttle-space', + Helmsman: 'shuttle-space', + // Barkeeper Bartender: 'glass-martini', + Barkeeper: 'wine-glass', + Barmaid: 'whiskey-glass', Barista: 'coffee', + Mixologist: 'martini-glass-citrus', + // Botanist Botanist: 'leaf', + Hydroponicist: 'droplet', Gardener: 'leaf', - Chaplain: 'place-of-worship', - Counselor: 'couch', + Cultivator: 'spa', + Farmer: 'plant-wilt', + Florist: 'spa', + Rancher: 'leaf', + // Chef Chef: 'utensils', + 'Sous-chef': 'spoon', Cook: 'utensils', + 'Kitchen Worker': 'kitchen-set', + // Chaplain + Chaplain: 'place-of-worship', + Counselor: 'cross', + Preacher: 'cross', + Missionary: 'cross', + Priest: 'cross', + Nun: 'church', + Monk: 'place-of-worship', + Guru: 'place-of-worship', + // Entertainer Entertainer: 'smile-beam', Performer: 'smile-beam', Musician: 'guitar', Stagehand: 'smile-beam', + Actor: 'face-laugh-wink', + Dancer: 'face-smile', + Singer: 'smusic', + Magician: 'wand-magic-sparkles', + Comedian: 'face-laugh-wink', + Tragedian: 'face-sad-tear', + Artist: 'smile-beam', + 'Game Master': 'dice', + // Entrepreneur + Entrepreneur: 'building', + Lawyer: 'gavel', + 'Private Eye': 'user-secret', + Bodyguard: 'person-military-pointing', + 'Personal Physician': 'star-of-life', + Dentist: 'teeth', + 'Fitness Instructor': 'dumbbell', + 'Yoga Teacher': 'person-walking', + Masseuse: 'bottle-droplet', + Tradesperson: 'money-bill-trend-up', + Streamer: 'desktop', + Influencer: 'computer', + 'Paranormal Investigator': 'magnifying-glass-arrow-right', + 'Personal Secretary': 'pen-to-square', + Stylist: 'hat-cowboy-side', + Fisher: 'fish-fins', + 'Fortune Teller': 'golf-ball-tee', + 'Spirit Healer': 'ghost', // All of the interns Intern: 'school', 'Apprentice Engineer': ['school', 'wrench'], - 'Medical Intern': ['school', 'user-md'], - 'Lab Assistant': ['school', 'flask'], - 'Security Cadet': ['school', 'shield-alt'], + 'Research Intern': ['school', 'flask'], + 'Security Cadet': ['school', 'shield-halved'], 'Jr. Cargo Tech': ['school', 'box'], 'Jr. Explorer': ['school', 'user-astronaut'], + Assistant: ['school', 'address-card'], Server: ['school', 'utensils'], - // Back to civvies + 'Technical Assistant': ['school', 'screwdriver'], + 'Medical Intern': ['school', 'user-nurse'], + 'Research Assistant"': ['school', 'flask'], + Visitor: 'user', + Resident: 'user', + // IAA 'Internal Affairs Agent': 'balance-scale', + 'Internal Affairs Liaison': 'balance-scale', + 'Internal Affairs Delegate': 'balance-scale', + 'Internal Affairs Investigator': 'balance-scale', + // Janitor Janitor: 'broom', Custodian: 'broom', 'Sanitation Technician': 'hand-sparkles', Maid: 'broom', + 'Garbage Collector': 'dumpster', + // Librarian Librarian: 'book', Journalist: 'newspaper', + Reporter: 'newspaper', Writer: 'book', Historian: 'chalkboard-teacher', + Archivist: 'book', Professor: 'chalkboard-teacher', - Visitor: 'user', + Academic: 'chalkboard-teacher', + Philosopher: 'book', + Curator: 'book', + // Off duty + 'Off-duty Officer': 'tree-city', + 'Off-duty Engineer': 'tree-city', + 'Off-duty Medic': 'tree-city', + 'Off-duty Scientist': 'tree-city', + 'Off-duty Cargo': 'tree-city', + 'Off-duty Explorer': 'tree-city', + 'Off-duty Worker': 'tree-city', + // AI / Robot + AI: 'display', + Cyborg: 'robot', + Robot: 'robot', + Drone: 'robot', + // Clown / Mime + Clown: 'bullhorn', + Jester: 'bullhorn', + Fool: 'bullhorn', + Mime: 'face-grin-tears', + Poseur: 'face-grin-tears', // Special roles 'Emergency Responder': 'fighter-jet', + // Talon + 'Talon Captain': ['location-arrow', 'user-tie'], + 'Talon Commander': ['location-arrow', 'user-tie'], + 'Talon Doctor': ['location-arrow', 'suitcase-medical'], + 'Talon Medic': ['location-arrow', 'suitcase-medical'], + 'Talon Engineer': ['location-arrow', 'wrench'], + 'Talon Technician': ['location-arrow', 'screwdriver'], + 'Talon Guard': ['location-arrow', 'shield'], + 'Talon Security': ['location-arrow', 'shield'], + 'Talon Marine': ['location-arrow', 'shield'], + 'Talon Pilot': ['location-arrow', 'shuttle-space'], + 'Talon Helmsman': ['location-arrow', 'shuttle-space'], + 'Talon Miner': ['location-arrow', 'helmet-safety'], + 'Talon Excavator': ['location-arrow', 'helmet-safety'], + // Robot Modules + Standard: 'robot', + Service: 'glass-martini', + Clerical: 'pen-to-square', + Research: 'flask', + Miner: 'helmet-safety', + Crisis: 'kit-medical', + Security: 'shield', + Combat: 'gun', + Engineering: 'wrench', + Gravekeeper: 'square-xmark', + Lost: 'location-crosshairs', + Protector: 'building-shield', + Mechanist: 'gears', + 'Combat Medic': 'x-ray', +}; + +const rank2color = { + // Command Site Manager + 'Site Manager': 'blue', + Overseer: 'blue', + 'Facility Director': 'blue', + 'Chief Supervisor': 'blue', + Captain: 'blue', + 'Colony Director': 'blue', + // HOP + 'Head of Personnel': 'blue', + 'Crew Resources Officer': 'blue', + 'Deputy Director': 'blue', + 'Staff Manager': 'blue', + 'Facility Steward': 'blue', + 'First Mate': 'blue', + 'Performance Management Supervisor': 'blue', + // Secretary + 'Command Secretary': 'blue', + 'Command Liaison': 'blue', + 'Command Assistant': 'blue', + 'Command Intern': 'blue', + 'Bridge Secretary': 'blue', + 'Bridge Assistant': 'blue', + 'Bridge Officer': 'blue', + // Security HOS + 'Head of Security': 'blue', + 'Security Commander': 'blue', + 'Chief of Security': 'blue', + 'Security Managery': 'blue', + // Warden + Warden: 'red', + 'Brig Sentry': 'red', + 'Armory Superintendent': 'red', + 'Master-at-Arms': 'red', + // Detective + Detective: 'red', + Investigator: 'red', + 'Security Inspector': 'red', + 'Forensic Technician': 'red', + // Security Officer + 'Security Officer': 'red', + 'Patrol Officer': 'red', + 'Security Guard': 'red', + 'Security Deputy': 'red', + 'Junior Officer': 'red', + 'Security Contractor': 'red', + // Engineering CE + 'Chief Engineer': 'blue', + 'Head Engineer': 'blue', + Foreman: 'blue', + 'Maintenance Manager': 'blue', + // Atmospheric Technician + 'Atmospheric Technician': 'orange', + 'Atmospheric Engineer': 'orange', + 'Atmospheric Maintainer': 'orange', + 'Disposals Technician': 'orange', + 'Fuel Technician': 'orange', + // Engineer + Engineer: 'orange', + 'Maintenance Technician': 'orange', + 'Engine Technician': 'orange', + Electrician: 'orange', + 'Construction Engineer': 'orange', + 'Engineering Contractor': 'orange', + // Medical CMO + 'Chief Medical Officer': 'blue', + 'Chief Physician': 'blue', + 'Medical Director': 'blue', + 'Healthcare Manager': 'blue', + // Chemist + Chemist: 'teal', + Pharmacist: 'teal', + Pharmacologist: 'teal', + // Medical Doctor + 'Medical Doctor': 'teal', + Physician: 'teal', + 'Medical Practitioner': 'teal', + Surgeon: 'teal', + 'Emergency Physician': 'teal', + Nurse: 'teal', + Orderly: 'teal', + Virologist: 'teal', + 'Medical Contractor': 'teal', + // Paramedic + Paramedic: 'teal', + 'Emergency Medical Technician': 'teal', + 'Medical Responder': 'teal', + 'Search and Rescue': 'teal', + // Psychiatrist + Psychiatrist: 'teal', + Psychologist: 'teal', + Psychoanalyst: 'teal', + Psychotherapist: 'teal', + // Genetecist + Geneticist: 'teal', + // Brig Physician + 'Brig Physician': 'teal', + 'Security Medic': 'teal', + 'Security Medic Care Unit': 'teal', + 'Penitentiary Medical Care Unit': 'teal', + 'Junior Brig Physician': 'teal', + 'Detention Health Officer': 'teal', + // Science RD + 'Research Director': 'blue', + 'Research Supervisor': 'blue', + 'Research Manager': 'blue', + 'Head of Development': 'blue', + 'Head Scientist': 'blue', + // Roboticist + Roboticist: 'purple', + 'Assembly Technician': 'purple', + 'Biomechanical Engineer': 'purple', + 'Mechatronic Engineer': 'purple', + // Scientist + Scientist: 'purple', + Researcher: 'purple', + 'Lab Assistant': 'purple', + Xenoarchaeologist: 'purple', + Xenopaleontologist: 'purple', + Anomalist: 'purple', + 'Phoron Researcher': 'purple', + 'Gas Physicist': 'purple', + 'Circuit Designer': 'purple', + 'Circuit Programmer': 'purple', + // Xenobiologist + Xenobiologist: 'purple', + Xenozoologist: 'purple', + Xenoanthropologist: 'purple', + // Xenobotanist + Xenobotanist: 'purple', + Xenohydroponicist: 'purple', + Xenoflorist: 'purple', + // Cargo QM + Quartermaster: 'brown', + 'Supply Chief': 'brown', + 'Logistics Manager': 'brown', + 'Cargo Supervisor': 'brown', + // Cargo Technician + 'Cargo Technician': 'brown', + 'Cargo Loader': 'brown', + 'Cargo Handler': 'brown', + 'Supply Courier': 'brown', + 'Disposals Sorter': 'brown', + Mailman: 'brown', + // Shaft Miner + 'Shaft Miner': 'brown', + 'Deep Space Miner': 'brown', + 'Drill Technician': 'brown', + Prospector: 'brown', + Excavator: 'brown', + // Exploration Lead + Pathfinder: 'blue', + 'Expedition Lead': 'blue', + 'Exploration Manager': 'blue', + // Explorer + Explorer: 'grey', + Surveyor: 'grey', + 'Offsite Scout': 'grey', + 'Explorer Medic': 'grey', + 'Explorer Technician': 'grey', + // Field Medic + 'Field Medic': 'grey', + 'Expedition Medic': 'grey', + 'Offsite Medic': 'grey', + // Pilot + Pilot: 'grey', + 'Co-Pilot': 'grey', + Navigator: 'grey', + Helmsman: 'grey', + // Barkeeper + Bartender: 'green', + Barkeeper: 'green', + Barmaid: 'green', + Barista: 'green', + Mixologist: 'green', + // Botanist + Botanist: 'green', + Hydroponicist: 'green', + Gardener: 'green', + Cultivator: 'green', + Farmer: 'green', + Florist: 'green', + Rancher: 'green', + // Chef + Chef: 'green', + 'Sous-chef': 'green', + Cook: 'green', + 'Kitchen Worker': 'green', + // Chaplain + Chaplain: 'green', + Counselor: 'green', + Preacher: 'green', + Missionary: 'green', + Priest: 'green', + Nun: 'green', + Monk: 'green', + Guru: 'green', + // Entertainer + Entertainer: 'green', + Performer: 'green', + Musician: 'green', + Stagehand: 'green', + Actor: 'green', + Dancer: 'green', + Singer: 'green', + Magician: 'green', + Comedian: 'green', + Tragedian: 'green', + Artist: 'green', + 'Game Master': 'green', + // Entrepreneur + Entrepreneur: 'green', + Lawyer: 'green', + 'Private Eye': 'green', + Bodyguard: 'green', + 'Personal Physician': 'green', + Dentist: 'green', + 'Fitness Instructor': 'green', + 'Yoga Teacher': 'green', + Masseuse: 'green', + Tradesperson: 'green', + Streamer: 'green', + Influencer: 'green', + 'Paranormal Investigator': 'green', + 'Personal Secretary': 'green', + Stylist: 'green', + Fisher: 'green', + 'Fortune Teller': 'green', + 'Spirit Healer': 'green', + // All of the interns + Intern: 'green', + 'Apprentice Engineer': 'green', + 'Research Intern': 'green', + 'Security Cadet': 'green', + 'Jr. Cargo Tech': 'green', + 'Jr. Explorer': 'green', + Assistant: 'green', + Server: 'green', + 'Technical Assistant': 'green', + 'Medical Intern': 'green', + 'Research Assistant"': 'green', + Visitor: 'green', + Resident: 'green', + // IAA + 'Internal Affairs Agent': 'blue', + 'Internal Affairs Liaison': 'blue', + 'Internal Affairs Delegate': 'blue', + 'Internal Affairs Investigator': 'blue', + // Janitor + Janitor: 'green', + Custodian: 'green', + 'Sanitation Technician': 'green', + Maid: 'green', + 'Garbage Collector': 'green', + // Librarian + Librarian: 'green', + Journalist: 'green', + Reporter: 'green', + Writer: 'green', + Historian: 'green', + Archivist: 'green', + Professor: 'green', + Academic: 'green', + Philosopher: 'green', + Curator: 'green', + // Off duty + 'Off-duty Officer': 'white', + 'Off-duty Engineer': 'white', + 'Off-duty Medic': 'white', + 'Off-duty Scientist': 'white', + 'Off-duty Cargo': 'white', + 'Off-duty Explorer': 'white', + 'Off-duty Worker': 'white', + // AI / Robot + AI: 'darkgrey', + Cyborg: 'darkgrey', + Robot: 'darkgrey', + Drone: 'darkgrey', + // Clown / Mime + Clown: 'green', + Jester: 'green', + Fool: 'green', + Mime: 'green', + Poseur: 'green', + // Special roles + 'Emergency Responder': 'yellow', + // Talon + 'Talon Captain': 'grey', + 'Talon Commander': 'grey', + 'Talon Doctor': 'grey', + 'Talon Medic': 'grey', + 'Talon Engineer': 'grey', + 'Talon Technician': 'grey', + 'Talon Guard': 'grey', + 'Talon Security': 'grey', + 'Talon Marine': 'grey', + 'Talon Pilot': 'grey', + 'Talon Helmsman': 'grey', + 'Talon Miner': 'grey', + 'Talon Excavator': 'grey', + // Robot Modules + Standard: 'grey', + Service: 'green', + Clerical: 'blue', + Research: 'purple', + Miner: 'brown', + Crisis: 'teal', + Security: 'red', + Combat: 'yellow', + Engineering: 'orange', + Gravekeeper: 'dark-grey', + Lost: 'grey', + Protector: 'darkred', + Mechanist: 'darkred', + 'Combat Medic': 'darkred', }; type rank_icon = { rank: string; color: string };