Skip to content

Commit

Permalink
Fixes a blacklisted job is forcefully removed from the game (#10976)
Browse files Browse the repository at this point in the history
* fixes

* Don't show config option

* changes var name to job_manager_blacklisted

* Forgot to remove

* Minor touch to lock_reason proc
  • Loading branch information
EvilDragonfiend authored May 19, 2024
1 parent 67f9a37 commit 38bbfae
Show file tree
Hide file tree
Showing 13 changed files with 123 additions and 71 deletions.
7 changes: 7 additions & 0 deletions code/__DEFINES/jobs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
#define JOB_UNAVAILABLE_PLAYTIME 3
#define JOB_UNAVAILABLE_ACCOUNTAGE 4
#define JOB_UNAVAILABLE_SLOTFULL 5
#define JOB_UNAVAILABLE_LOCKED 6

// reasons why you can't play this job
#define JOB_LOCK_REASON_ABSTRACT (1<<0)
#define JOB_LOCK_REASON_MAP (1<<1)
#define JOB_LOCK_REASON_CONFIG (1<<2)


#define DEFAULT_RELIGION "Christianity"
#define DEFAULT_DEITY "Space Jesus"
Expand Down
77 changes: 46 additions & 31 deletions code/controllers/subsystem/job.dm
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,21 @@ SUBSYSTEM_DEF(job)
var/list/crew_obj_list = list()
var/list/crew_obj_jobs = list()

/// jobs that are not allowed in HoP job manager
var/list/job_manager_blacklisted = list(
JOB_NAME_AI,
JOB_NAME_ASSISTANT,
JOB_NAME_CYBORG,
JOB_NAME_CAPTAIN,
JOB_NAME_HEADOFPERSONNEL,
JOB_NAME_HEADOFSECURITY,
JOB_NAME_CHIEFENGINEER,
JOB_NAME_RESEARCHDIRECTOR,
JOB_NAME_CHIEFMEDICALOFFICER,
JOB_NAME_BRIGPHYSICIAN,
JOB_NAME_DEPUTY,
JOB_NAME_GIMMICK)

/datum/controller/subsystem/job/Initialize(timeofday)
SSmapping.HACK_LoadMapConfig()
if(!occupations.len)
Expand All @@ -53,8 +68,28 @@ SUBSYSTEM_DEF(job)

return ..()

/datum/controller/subsystem/job/Recover()
occupations = SSjob.occupations
name_occupations = SSjob.name_occupations
type_occupations = SSjob.type_occupations
unassigned = SSjob.unassigned
initial_players_to_assign = SSjob.initial_players_to_assign

prioritized_jobs = SSjob.prioritized_jobs
latejoin_trackers = SSjob.latejoin_trackers

overflow_role = SSjob.overflow_role

spare_id_safe_code = SSjob.spare_id_safe_code
crew_obj_list = SSjob.crew_obj_list
crew_obj_jobs = SSjob.crew_obj_jobs

job_manager_blacklisted = SSjob.job_manager_blacklisted

/datum/controller/subsystem/job/proc/set_overflow_role(new_overflow_role)
var/datum/job/new_overflow = GetJob(new_overflow_role)
if(!new_overflow || new_overflow.lock_flags)
CRASH("[new_overflow_role] was used for an overflow role, but it's not allowed. BITFLAG: [new_overflow?.lock_flags]")
var/cap = CONFIG_GET(number/overflow_cap)

new_overflow.allow_bureaucratic_error = FALSE
Expand All @@ -76,20 +111,13 @@ SUBSYSTEM_DEF(job)
to_chat(world, "<span class='boldannounce'>Error setting up jobs, no job datums found.</span>")
return 0

for(var/J in all_jobs)
var/datum/job/job = new J()
if(!job)
continue
if(job.faction != faction)
for(var/datum/job/each_job as anything in all_jobs)
each_job = new each_job()
if(each_job.faction != faction)
continue
if(!job.config_check())
continue
if(!job.map_check()) //Even though we initialize before mapping, this is fine because the config is loaded at new
testing("Removed [job.type] due to map config")
continue
occupations += job
name_occupations[job.title] = job
type_occupations[J] = job
occupations += each_job
name_occupations[each_job.title] = each_job
type_occupations[each_job.type] = each_job

return 1

Expand Down Expand Up @@ -128,7 +156,7 @@ SUBSYSTEM_DEF(job)
JobDebug("Running AR, Player: [player], Rank: [rank], LJ: [latejoin]")
if(player?.mind && rank)
var/datum/job/job = GetJob(rank)
if(!job)
if(!job || job.lock_flags)
return FALSE
if(QDELETED(player) || is_banned_from(player.ckey, rank))
return FALSE
Expand Down Expand Up @@ -181,7 +209,7 @@ SUBSYSTEM_DEF(job)
JobDebug("GRJ Giving random job, Player: [player]")
. = FALSE
for(var/datum/job/job in shuffle(occupations))
if(!job)
if(!job || job.lock_flags)
continue

if(istype(job, GetJob(SSjob.overflow_role))) // We don't want to give him assistant, that's boring!
Expand Down Expand Up @@ -368,7 +396,7 @@ SUBSYSTEM_DEF(job)

// Loop through all jobs
for(var/datum/job/job in shuffledoccupations) // SHUFFLE ME BABY
if(!job)
if(!job || job.lock_flags)
continue

if(is_banned_from(player.ckey, job.title))
Expand Down Expand Up @@ -612,6 +640,8 @@ SUBSYSTEM_DEF(job)
var/banned = 0 //banned
var/young = 0 //account too young
for(var/mob/dead/new_player/player in GLOB.player_list)
if(job.lock_flags)
continue
if(!(player.ready == PLAYER_READY_TO_PLAY && player.mind && !player.mind.assigned_role))
continue //This player is not ready
if(is_banned_from(player.ckey, job.title) || QDELETED(player))
Expand Down Expand Up @@ -659,21 +689,6 @@ SUBSYSTEM_DEF(job)
player.ready = PLAYER_NOT_READY


/datum/controller/subsystem/job/Recover()
set waitfor = FALSE
var/oldjobs = SSjob.occupations
sleep(20)
for (var/datum/job/J in oldjobs)
INVOKE_ASYNC(src, PROC_REF(RecoverJob), J)

/datum/controller/subsystem/job/proc/RecoverJob(datum/job/J)
var/datum/job/newjob = GetJob(J.title)
if (!istype(newjob))
return
newjob.total_positions = J.total_positions
newjob.spawn_positions = J.spawn_positions
newjob.current_positions = J.current_positions

/atom/proc/JoinPlayerHere(mob/M, buckle)
// By default, just place the mob on the same turf as the marker or whatever.
M.forceMove(get_turf(src))
Expand Down
26 changes: 7 additions & 19 deletions code/game/machinery/computer/card.dm
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,13 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
//if set to -1: No cooldown... probably a bad idea
//if set to 0: Not able to close "original" positions. You can only close positions that you have opened before
var/change_position_cooldown = 30
//Jobs you cannot open new positions for
var/list/blacklisted = list(
JOB_NAME_AI,
JOB_NAME_ASSISTANT,
JOB_NAME_CYBORG,
JOB_NAME_CAPTAIN,
JOB_NAME_HEADOFPERSONNEL,
JOB_NAME_HEADOFSECURITY,
JOB_NAME_CHIEFENGINEER,
JOB_NAME_RESEARCHDIRECTOR,
JOB_NAME_CHIEFMEDICALOFFICER,
JOB_NAME_BRIGPHYSICIAN,
JOB_NAME_DEPUTY)

//The scaling factor of max total positions in relation to the total amount of people on board the station in %
var/max_relative_positions = 30 //30%: Seems reasonable, limit of 6 @ 20 players

//This is used to keep track of opened positions for jobs to allow instant closing
//Assoc array: "JobName" = (int)<Opened Positions>
var/list/opened_positions = list();
var/list/opened_positions = list()
var/obj/item/card/id/inserted_scan_id
var/obj/item/card/id/inserted_modify_id
var/list/region_access = null
Expand All @@ -60,9 +47,6 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
/obj/machinery/computer/card/Initialize(mapload)
. = ..()
change_position_cooldown = CONFIG_GET(number/id_console_jobslot_delay)
for(var/G in typesof(/datum/job/gimmick))
var/datum/job/gimmick/J = new G
blacklisted += J.title

// This determines which department payment list the console will show to you.
if(!target_dept)
Expand Down Expand Up @@ -127,7 +111,11 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)

//Check if you can't open a new position for a certain job
/obj/machinery/computer/card/proc/job_blacklisted(jobtitle)
return (jobtitle in blacklisted)
return jobtitle == SSjob.overflow_role ? TRUE : (jobtitle in SSjob.job_manager_blacklisted)

// CentCom is powerful
/obj/machinery/computer/card/centcom/job_blacklisted(jobtitle)
return jobtitle == SSjob.overflow_role ? TRUE : FALSE

//Logic check for Topic() if you can open the job
/obj/machinery/computer/card/proc/can_open_job(datum/job/job)
Expand Down Expand Up @@ -241,7 +229,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
ID = 0
for(var/datum/job/job in SSjob.occupations)
dat += "<tr>"
if(job.title in blacklisted)
if(job_blacklisted(job.title))
continue
dat += "<td>[job.title]</td>"
dat += "<td>[job.current_positions]/[job.total_positions]</td>"
Expand Down
1 change: 1 addition & 0 deletions code/game/objects/effects/landmarks.dm
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark)
var/datum/job/J = SSjob.GetJob(job)
J.total_positions += 1
J.spawn_positions += 1
SSjob.job_manager_blacklisted -= J.title

/obj/effect/landmark/start/randommaint/backalley_doc
name = "Barber"
Expand Down
6 changes: 6 additions & 0 deletions code/modules/client/preferences/middleware/jobs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
if (isnull(job))
return FALSE

if(job.lock_flags)
return FALSE

if (job.faction != "Station")
return FALSE

Expand All @@ -40,6 +43,8 @@
for (var/datum/job/job as anything in SSjob.occupations)
if(!job.show_in_prefs)
continue
if(job.lock_flags & ~JOB_LOCK_REASON_MAP) // anything but map reason shouldn't be visible
continue

var/department_flag = job.department_for_prefs
if (isnull(department_flag))
Expand All @@ -63,6 +68,7 @@
departments[department_name] = list()

jobs[job.title] = list(
"lock_reason" = job.get_lock_reason(),
"description" = job.description,
"department" = department_name,
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/datum/preferences/proc/set_job_preference_level(datum/job/job, level)
if (!job)
if (!job || job.lock_flags)
return FALSE

log_preferences("[parent?.ckey]: Set [job.title] preference to level [level].")
Expand Down
14 changes: 13 additions & 1 deletion code/modules/events/bureaucratic_error.dm
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,21 @@

/datum/round_event/bureaucratic_error
announceWhen = 1
var/datum/job/chosen_job

/datum/round_event/bureaucratic_error/setup()
var/error_count = 10
while(error_count--)
var/datum/job/J = SSjob.GetJob(pick(get_all_jobs()))
if(!J || J.lock_flags)
continue
chosen_job = J
break
if(!chosen_job)
return kill()

/datum/round_event/bureaucratic_error/announce(fake)
priority_announce("A recent bureaucratic error in the Organic Resources Department may result in personnel shortages in some departments and redundant staffing in others.", "Paperwork Mishap Alert", SSstation.announcer.get_rand_alert_sound())

/datum/round_event/bureaucratic_error/start()
SSjob.set_overflow_role(pick(get_all_jobs()))
SSjob.set_overflow_role(chosen_job)
20 changes: 20 additions & 0 deletions code/modules/jobs/job_types/_job.dm
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
var/flag = NONE //Deprecated //Except not really, still used throughout the codebase
var/auto_deadmin_role_flags = NONE

/// flags with the job lock reasons. If this flag exists, it's not available anyway.
var/lock_flags = NONE

/// If this job should show in the preferences menu
var/show_in_prefs = TRUE

Expand Down Expand Up @@ -120,6 +123,13 @@
lightup_areas = typecacheof(lightup_areas)
minimal_lightup_areas = typecacheof(minimal_lightup_areas)

if(!config_check())
lock_flags |= JOB_LOCK_REASON_CONFIG
if(!map_check())
lock_flags |= JOB_LOCK_REASON_MAP
if(lock_flags || gimmick)
SSjob.job_manager_blacklisted |= title

/// Only override this proc, unless altering loadout code. Loadouts act on H but get info from M
/// H is usually a human unless an /equip override transformed it
/// do actions on H but send messages to M as the key may not have been transferred_yet
Expand Down Expand Up @@ -331,6 +341,16 @@
/datum/job/proc/map_check()
return TRUE

/datum/job/proc/get_lock_reason()
if(lock_flags & JOB_LOCK_REASON_ABSTRACT)
return "Not a real job"
else if(lock_flags & JOB_LOCK_REASON_CONFIG)
return "Disabled by server configuration"
else if(lock_flags & JOB_LOCK_REASON_MAP)
return "Not available on this map"
else if(lock_flags) // somehow flag exists
return "Unknown: [lock_flags]"

/datum/job/proc/radio_help_message(mob/M)
to_chat(M, "<b>Prefix your message with :h to speak on your department's radio. To see other prefixes, look closely at your headset.</b>")

Expand Down
1 change: 1 addition & 0 deletions code/modules/jobs/job_types/deputy.dm
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/datum/job/deputy
title = JOB_NAME_DEPUTY
description = "Follow orders and do your best to maintain order on the station while following Space Law."
lock_flags = JOB_LOCK_REASON_ABSTRACT
department_for_prefs = DEPT_BITFLAG_SEC
department_head = list(JOB_NAME_HEADOFSECURITY)
supervisors = "the head of security"
Expand Down
4 changes: 4 additions & 0 deletions code/modules/mob/dead/new_player/new_player.dm
Original file line number Diff line number Diff line change
Expand Up @@ -261,12 +261,16 @@
return "Your account is not old enough for [jobtitle]."
if(JOB_UNAVAILABLE_SLOTFULL)
return "[jobtitle] is already filled to capacity."
if(JOB_UNAVAILABLE_LOCKED)
return "[jobtitle] is locked by the system."
return "Error: Unknown job availability."

/mob/dead/new_player/proc/IsJobUnavailable(rank, latejoin = FALSE)
var/datum/job/job = SSjob.GetJob(rank)
if(!job)
return JOB_UNAVAILABLE_GENERIC
if(job.lock_flags)
return JOB_UNAVAILABLE_LOCKED
if((job.current_positions >= job.total_positions) && job.total_positions != -1)
if(job.title == JOB_NAME_ASSISTANT)
if(isnum_safe(client.player_age) && client.player_age <= 14) //Newbies can always be assistants
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,7 @@
tgui_id = "NtosJobManager"
program_icon = "address-book"



var/change_position_cooldown = 30
//Jobs you cannot open new positions for
var/list/blacklisted = list(
JOB_NAME_AI,
JOB_NAME_ASSISTANT,
JOB_NAME_CYBORG,
JOB_NAME_CAPTAIN,
JOB_NAME_HEADOFPERSONNEL,
JOB_NAME_HEADOFSECURITY,
JOB_NAME_CHIEFENGINEER,
JOB_NAME_RESEARCHDIRECTOR,
JOB_NAME_CHIEFMEDICALOFFICER,
JOB_NAME_BRIGPHYSICIAN,
JOB_NAME_DEPUTY)

//The scaling factor of max total positions in relation to the total amount of people on board the station in %
var/max_relative_positions = 30 //30%: Seems reasonable, limit of 6 @ 20 players
Expand All @@ -38,16 +23,19 @@
..()
change_position_cooldown = CONFIG_GET(number/id_console_jobslot_delay)

/datum/computer_file/program/proc/job_blacklisted(jobtitle)
return jobtitle == SSjob.overflow_role ? TRUE : (jobtitle in SSjob.job_manager_blacklisted)

/datum/computer_file/program/job_management/proc/can_open_job(datum/job/job)
if(!(job?.title in blacklisted))
if(!job_blacklisted(job?.title))
if((job.total_positions <= length(GLOB.player_list) * (max_relative_positions / 100)))
var/delta = (world.time / 10) - GLOB.time_last_changed_position
if((change_position_cooldown < delta) || (opened_positions[job.title] < 0))
return TRUE
return FALSE

/datum/computer_file/program/job_management/proc/can_close_job(datum/job/job)
if(!(job?.title in blacklisted))
if(!job_blacklisted(job?.title))
if(job.total_positions > length(GLOB.player_list) * (max_relative_positions / 100))
var/delta = (world.time / 10) - GLOB.time_last_changed_position
if((change_position_cooldown < delta) || (opened_positions[job.title] > 0))
Expand Down Expand Up @@ -120,7 +108,7 @@
var/list/pos = list()
for(var/j in SSjob.occupations)
var/datum/job/job = j
if(job.title in blacklisted)
if(job_blacklisted(job.title))
continue

pos += list(list(
Expand Down
Loading

0 comments on commit 38bbfae

Please sign in to comment.