diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 548151a00cc..9a7702eda5e 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -9,6 +9,8 @@ datum/mind var/assigned_role var/special_role + var/datum/job/assigned_job + var/list/datum/objective/objectives = list() var/list/datum/objective/special_verbs = list() diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm index d87ff1a1997..1bb856cbfa8 100644 --- a/code/game/jobs/jobs.dm +++ b/code/game/jobs/jobs.dm @@ -7,6 +7,13 @@ //and other items. This datum will be used for all jobs and code will reference it. //adding new jobs will be a matter of adding this datum.to a list of jobs. +#define VITAL_PRIORITY_JOB 5 +#define HIGH_PRIORITY_JOB 4 +#define PRIORITY_JOB 3 +#define LOW_PRIORITY_JOB 2 +#define ASSISTANT_PRIORITY_JOB 1 +#define NO_PRIORITY_JOB 0 + /datum/job //Basic information var/title = "Untitled" //The main (default) job title/name @@ -17,6 +24,29 @@ var/admin_only = 0 //If this is set to 1, the job is not available on the spawn screen var/description = "" //A description of the job to be displayed when requested on the spawn screen var/guides = "" //A string with links to relevent guides (likely the wiki) + var/department = "" //This is used to group jobs into departments, which means that if you don't get your desired jobs, you get another job from the same department + var/job_type = "SS13" //SS13, NT or ANTAGONIST + var/can_be_traitor = 1 + var/can_be_changeling = 1 + var/can_be_wizard = 1 + var/can_be_cultist = 1 + var/can_be_rev_head = 1 + var/is_head_position = 0 + + //Job conditions + var/change_to_mob = "Human" //The type of mob which this job will change you to (alien,cyborg,human...) + var/change_to_mutantrace = "" //What mutantrace you will be once you get this job + + //Random job assignment priority + var/assignment_priority = NO_PRIORITY_JOB //This variable determins the priority of assignment + //VITAL_PRIORITY_JOB = Absolutely vital (Someone will get assigned every round) - Use VERY, VERY lightly + //HIGH_PRIORITY_JOB = High priority - Assibned before the other jobs, candidates compete on equal terms + //PRIORITY_JOB = Priorized (Standard priority) - Candidates compete by virtue of priority (choice 1 > choice 2 > choice 3...) + //LOW_PRIORITY_JOB = Low priority (Low-priority (librarian)) + //ASSISTANT_PRIORITY_JOB = Assistant-level (Only filled when all the other jobs have been assigned) + //NO_PRIORITY_JOB = Skipped om assignment (Admin-only jobs should have this level) + + //Available equipment - The first thing listed is understood as the default setup. var/list/equipment_ears = list() //list of possible ear-wear items @@ -94,6 +124,38 @@ employees += J return employees + //This proc returns the chosen vital and high priority jobs that the person selected. It goes from top to bottom of the list, until it finds a job which does not have such priority. + //Example: Choosing (in this order): CE, Captain, Engineer, RD will only return CE and Captain, as RD is assumed as being an unwanted choice. + //This proc is used in the allocation algorithm when deciding vital and high priority jobs. + proc/get_prefered_high_priority_jobs() + var/list/datum/job/hp_jobs = list() + for(var/datum/job/J in all_jobs) + if(J.assignment_priority == HIGH_PRIORITY_JOB || J.assignment_priority == VITAL_PRIORITY_JOB) + hp_jobs += J + else + break + return hp_jobs + + //If only priority is given, it will return the jobs of only that priority, if end_priority is set it will return the jobs with their priority higher or equal to var/priority and lower or equal to end_priority. end_priority must be higher than 0. + proc/get_jobs_by_priority(var/priority, var/end_priority = 0) + var/list/datum/job/priority_jobs = list() + if(end_priority) + if(end_priority < priority) + return + for(var/datum/job/J in all_jobs) + if(J.assignment_priority >= priority && J.assignment_priority <= end_priority) + priority_jobs += J + else + for(var/datum/job/J in all_jobs) + if(J.assignment_priority == priority) + priority_jobs += J + return priority_jobs + +//This datum is used in the plb allocation algorithm to make life easier, not used anywhere else. +/datum/player_jobs + var/mob/new_player/player + var/datum/jobs/selected_jobs + var/datum/jobs/jobs = new/datum/jobs() proc/setup_jobs() @@ -127,7 +189,7 @@ proc/dress_for_job_default(var/mob/living/carbon/human/employee as mob, var/job_ if(!ishuman(employee)) return - //UNFINISHED + //TODO ERRORAGE - UNFINISHED var/datum/job/JOB = jobs.get_job(job_alias) if(JOB) var/item = JOB.equipment_ears[1] @@ -149,6 +211,83 @@ proc/dress_for_job_default(var/mob/living/carbon/human/employee as mob, var/job_ src.equip_if_possible(new /obj/item/device/t_scanner(src), slot_r_store) */ + +//This algorithm works in 5 steps: +//1: Assignment of wizard / nuke members (if appropriate game mode) +//2: Assignment of jobs based on preferenes +// 2.1: Assignment of vital and high priority jobs. Candidates compete on equal terms. If the vital jobs are not filled, a random candidate is chosen to fill them, +// 2.2: Assignment of the rest of the jobs based on player preference, +//3: Assignment of remaining jobs for remaining players based on chosen departments +//4: Random assignment of remaining jobs for remaining players based on assignment priority +//5: Assignment of traitor / changeling to assigned roles (if appropriate game mode) +proc/assignment_algorithm(var/list/mob/new_player/players) + for(var/mob/new_player/PLAYER in players) + if(!PLAYER.client) + players -= PLAYER + continue + if(!PLAYER.ready) + players -= PLAYER + continue + + var/list/datum/job/vital_jobs = list() + var/list/datum/job/high_priority_jobs = list() + var/list/datum/job/priority_jobs = list() + var/list/datum/job/low_priority_jobs = list() + var/list/datum/job/assistant_jobs = list() + var/list/datum/job/not_assigned_jobs = list() + + for(var/datum/job/J in jobs) + switch(J.assignment_priority) + if(5) + vital_jobs += J + if(4) + high_priority_jobs += J + if(3) + priority_jobs += J + if(2) + low_priority_jobs += J + if(1) + assistant_jobs += J + if(0) + not_assigned_jobs += J + + var/list/datum/player_jobs/player_jobs = list() //This datum only holds a mob/new_player and a datum/jobs. The first is the player, the 2nd is the player's selected jobs, from the preferences datum. + + for(var/mob/new_player/NP in players) + var/datum/player_jobs/PJ = new/datum/player_jobs + PJ.player = NP + PJ.selected_jobs = NP.preferences.wanted_jobs + player_jobs += PJ + + //At this point we have the player_jobs list filled. Next up we have to assign all vital and high priority positions. + + var/list/datum/job/hp_jobs = jobs.get_jobs_by_priority( HIGH_PRIORITY_JOB, VITAL_PRIORITY_JOB ) + + for(var/datum/job/J in hp_jobs) + var/list/mob/new_player/candidates = list() + for(var/datum/player_jobs/PJ in player_jobs) + if(J in PJ.selected_jobs) + candidates += PJ.player + var/mob/new_player/chosen_player + if(candidates) + chosen_player = pick(candidates) + else + if(J.assignment_priority == VITAL_PRIORITY_JOB) + if(players) //Just in case there are more vital jobs than there are players. + chosen_player = pick(players) + if(chosen_player) + chosen_player.mind.assigned_job = J + players -= chosen_player + //TODO ERRORAGE - add capability for hp jobs with more than one slots. + + + + + //1: vital and high priority jobs, assigned on equal terms + + //TODO ERRORAGE - UNFINISHED + + //END OF WORK IN PROGRESS CONTENT diff --git a/code/modules/mob/new_player/preferences.dm b/code/modules/mob/new_player/preferences.dm index 4808193c931..6436992a80a 100644 --- a/code/modules/mob/new_player/preferences.dm +++ b/code/modules/mob/new_player/preferences.dm @@ -42,6 +42,7 @@ datum/preferences var/underwear = 1 var/occupation[] = list("No Preference", "No Preference", "No Preference") + var/datum/jobs/wanted_jobs = list() var/h_style = "Short Hair" var/f_style = "Shaved"