diff --git a/code/__DEFINES/jobs.dm b/code/__DEFINES/jobs.dm index d6e456a9627..5f1ce8856e0 100644 --- a/code/__DEFINES/jobs.dm +++ b/code/__DEFINES/jobs.dm @@ -219,6 +219,7 @@ #define JOB_UNAVAILABLE_SLOTFULL 5 #define JOB_UNAVAILABLE_SPECIESLOCK 6 #define JOB_UNAVAILABLE_WHITELIST 7 +#define JOB_UNAVAILABLE_SPECIAL 8 #define DEFAULT_RELIGION "Christianity" #define DEFAULT_DEITY "Space Jesus" diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index 8636f9789c4..61a1a8d4b68 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -102,6 +102,8 @@ SUBSYSTEM_DEF(job) var/datum/job/job = GetJob(rank) if(!job) return FALSE + if(job.special_stat_check(player.client?.prefs)) + return FALSE if(jobban_isbanned(player, rank) || QDELETED(player)) return FALSE if(!job.player_old_enough(player.client)) @@ -124,6 +126,9 @@ SUBSYSTEM_DEF(job) JobDebug("Running FOC, Job: [job], Level: [level], Flag: [flag]") var/list/candidates = list() for(var/mob/dead/new_player/player in unassigned) + if(job.special_stat_check(player.client?.prefs)) + JobDebug("FOC special stat failed, player: [player]") + continue if(jobban_isbanned(player, job.title) || QDELETED(player)) JobDebug("FOC isbanned failed, Player: [player]") continue @@ -163,6 +168,10 @@ SUBSYSTEM_DEF(job) if((job.title in GLOB.faction_whitelist_positions) && (CONFIG_GET(flag/use_role_whitelist))) //If you want a whitelist position, get a whitelist and choose it. continue + if(job.special_stat_check(player.client?.prefs)) + JobDebug("GRJ special stat failed, player: [player]") + continue + if(jobban_isbanned(player, job.title) || QDELETED(player)) if(QDELETED(player)) JobDebug("GRJ isbanned failed, Player deleted") @@ -344,6 +353,10 @@ SUBSYSTEM_DEF(job) if(!job) continue + if(job.special_stat_check(player.client?.prefs)) + JobDebug("DO special stat failed, player: [player]") + continue + if(jobban_isbanned(player, job.title)) JobDebug("DO isbanned failed, Player: [player], Job:[job.title]") continue diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 8ad2c0fff55..42fd5b75661 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -908,6 +908,9 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(jobban_isbanned(user, rank)) HTML += "[rank] BANNED" continue + if(job.special_stat_check(src)) + HTML += "[rank]\[SPECIAL [job.special_stat_check(src)]\]" + continue var/required_playtime_remaining = job.required_playtime_remaining(user.client) if(required_playtime_remaining) HTML += "[rank] \[ [get_exp_format(required_playtime_remaining)] as [job.get_exp_req_type()] \] " diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm index d582c1dc816..90893f0dccb 100644 --- a/code/modules/jobs/job_types/_job.dm +++ b/code/modules/jobs/job_types/_job.dm @@ -100,6 +100,33 @@ /// the value should be something like "strings/names/cow.txt" var/whitelist_path + var/list/min_required_special + + /* //!Template for pasting into job defines, leave only needed fields: + min_required_special = list( + "special_s" = 0, + "special_p" = 0, + "special_e" = 0, + "special_c" = 0, + "special_i" = 0, + "special_a" = 0, + "special_l" = 0, + ) + */ + + var/list/modify_special + + /* //!Template for pasting into job defines, leave only needed fields: + modify_special = list( + "special_s" = 0, + "special_p" = 0, + "special_e" = 0, + "special_c" = 0, + "special_i" = 0, + "special_a" = 0, + "special_l" = 0, + ) + */ /datum/job/proc/after_spawn(mob/living/spawner, mob/client_holder, latejoin = FALSE) SHOULD_CALL_PARENT(TRUE) @@ -170,6 +197,15 @@ //Equip the rest of the gear H.dna.species.before_equip_job(src, H, visualsOnly) + if(islist(modify_special)) + H.special_s = clamp(H.special_s + modify_special["special_s"], SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + H.special_p = clamp(H.special_p + modify_special["special_p"], SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + H.special_e = clamp(H.special_e + modify_special["special_e"], SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + H.special_c = clamp(H.special_c + modify_special["special_c"], SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + H.special_i = clamp(H.special_i + modify_special["special_i"], SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + H.special_a = clamp(H.special_a + modify_special["special_a"], SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + H.special_l = clamp(H.special_l + modify_special["special_l"], SPECIAL_MIN_ATTR_VALUE, SPECIAL_MAX_ATTR_VALUE) + var/datum/outfit/job/O = outfit_override || outfit if(O) H.equipOutfit(O, visualsOnly, preference_source) //mob doesn't have a client yet. @@ -383,3 +419,27 @@ if(CONFIG_GET(flag/security_has_maint_access)) return list(ACCESS_MAINT_TUNNELS) return list() + +/datum/job/proc/special_stat_check(datum/preferences/prefs) + var/output = "" + var/sum = prefs.special_s + prefs.special_p + prefs.special_e + prefs.special_c + prefs.special_i + prefs.special_a + prefs.special_l + if(sum > SPECIAL_MAX_POINT_SUM_CAP) + return "\[SPECIAL CAP\]" + if(islist(min_required_special)) + if(min_required_special["special_s"] && min_required_special["special_s"] > prefs.special_s) + output += "S: [min_required_special["special_s"]], " + if(min_required_special["special_p"] && min_required_special["special_p"] > prefs.special_p) + output += "P: [min_required_special["special_p"]], " + if(min_required_special["special_e"] && min_required_special["special_e"] > prefs.special_e) + output += "E: [min_required_special["special_e"]], " + if(min_required_special["special_c"] && min_required_special["special_c"] > prefs.special_c) + output += "C: [min_required_special["special_c"]], " + if(min_required_special["special_i"] && min_required_special["special_i"] > prefs.special_i) + output += "I: [min_required_special["special_i"]], " + if(min_required_special["special_a"] && min_required_special["special_a"] > prefs.special_a) + output += "A: [min_required_special["special_a"]], " + if(min_required_special["special_l"] && min_required_special["special_l"] > prefs.special_l) + output += "L: [min_required_special["special_l"]], " + if(length(output)) + output = copytext_char(output, 1, length(output) - 1) + return output diff --git a/code/modules/jobs/job_types/bos.dm b/code/modules/jobs/job_types/bos.dm index 054511ee464..d96e93c9aef 100644 --- a/code/modules/jobs/job_types/bos.dm +++ b/code/modules/jobs/job_types/bos.dm @@ -173,6 +173,10 @@ Paladin Commander /datum/outfit/loadout/sentmini //Minigun ) + min_required_special = list( + "special_c" = 4, + ) + access = list(ACCESS_BROTHERHOOD_COMMAND, ACCESS_ROBOTICS, ACCESS_BOS, ACCESS_ENGINE_EQUIP, ACCESS_ENGINE, ACCESS_HYDROPONICS, ACCESS_KITCHEN, ACCESS_BAR, ACCESS_SEC_DOORS, ACCESS_CHANGE_IDS) minimal_access = list(ACCESS_BROTHERHOOD_COMMAND, ACCESS_ROBOTICS, ACCESS_BOS, ACCESS_ENGINE_EQUIP, ACCESS_ENGINE, ACCESS_HYDROPONICS, ACCESS_KITCHEN, ACCESS_BAR, ACCESS_SEC_DOORS, ACCESS_CHANGE_IDS) @@ -328,6 +332,10 @@ Knight-Captain access = list(ACCESS_BROTHERHOOD_COMMAND, ACCESS_ROBOTICS, ACCESS_BOS, ACCESS_ENGINE_EQUIP, ACCESS_ENGINE, ACCESS_HYDROPONICS, ACCESS_KITCHEN, ACCESS_BAR, ACCESS_SEC_DOORS, ACCESS_ARMORY, ACCESS_BRIG, ACCESS_CHANGE_IDS) minimal_access = list(ACCESS_BROTHERHOOD_COMMAND, ACCESS_ROBOTICS, ACCESS_BOS, ACCESS_ENGINE_EQUIP, ACCESS_ENGINE, ACCESS_HYDROPONICS, ACCESS_KITCHEN, ACCESS_BAR, ACCESS_SEC_DOORS, ACCESS_ARMORY, ACCESS_BRIG, ACCESS_CHANGE_IDS) + min_required_special = list( + "special_c" = 4, + ) + /datum/outfit/job/bos/f13knightcap/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() if(visualsOnly) @@ -462,6 +470,10 @@ Paladin ), ) + min_required_special = list( + "special_c" = 4, + ) + /datum/outfit/job/bos/f13paladin/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() if(visualsOnly) diff --git a/code/modules/jobs/job_types/legion.dm b/code/modules/jobs/job_types/legion.dm index e767ea12819..cf3cb19a03b 100644 --- a/code/modules/jobs/job_types/legion.dm +++ b/code/modules/jobs/job_types/legion.dm @@ -210,6 +210,10 @@ Weapons Lever shotgun, Grease gun, Repeater carbines, Revolvers, simple guns al /datum/outfit/loadout/centurion, // 14mm Pistol, GOliath ) + min_required_special = list( + "special_c" = 4, + ) + /datum/outfit/job/CaesarsLegion/Legionnaire/f13centurion/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() if(visualsOnly) @@ -300,6 +304,10 @@ Weapons Lever shotgun, Grease gun, Repeater carbines, Revolvers, simple guns al /datum/outfit/loadout/decvetbrave, // trench shotgun, 44 revolver, ballistic fist ) + min_required_special = list( + "special_c" = 4, + ) + /datum/outfit/job/CaesarsLegion/Legionnaire/f13decanvet/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() @@ -405,6 +413,10 @@ Weapons Lever shotgun, Grease gun, Repeater carbines, Revolvers, simple guns al ), ) + min_required_special = list( + "special_c" = 4, + ) + /datum/outfit/job/CaesarsLegion/Legionnaire/f13decan/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() if(visualsOnly) @@ -498,6 +510,10 @@ Weapons Lever shotgun, Grease gun, Repeater carbines, Revolvers, simple guns al ), ) + min_required_special = list( + "special_c" = 4, + ) + /datum/outfit/job/CaesarsLegion/Legionnaire/f13decanrec/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() if(visualsOnly) diff --git a/code/modules/jobs/job_types/ncr.dm b/code/modules/jobs/job_types/ncr.dm index 06726a0f621..a97205e771a 100644 --- a/code/modules/jobs/job_types/ncr.dm +++ b/code/modules/jobs/job_types/ncr.dm @@ -156,6 +156,10 @@ Weapons Service Rifle, Grease Gun, 9mm pistol, all good. /datum/outfit/loadout/captainfrontline, // AR Service Rifle ) + min_required_special = list( + "special_c" = 4, + ) + /datum/outfit/job/ncr/f13captain/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() if(visualsOnly) @@ -236,6 +240,10 @@ Weapons Service Rifle, Grease Gun, 9mm pistol, all good. ), ) + min_required_special = list( + "special_c" = 4, + ) + /datum/outfit/job/ncr/f13lieutenant // AR Service Rifle, Binoculars, Bayonet, M1911 custom name = "NCR Lieutenant" jobtype = /datum/job/ncr/f13lieutenant @@ -536,6 +544,10 @@ Weapons Service Rifle, Grease Gun, 9mm pistol, all good. /datum/outfit/loadout/vrcqc // 2 x .45 Long colt revolvers ) + min_required_special = list( + "special_c" = 4, + ) + /datum/outfit/job/ncr/f13vetranger/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) ..() if(visualsOnly) diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 2dd3b5be982..680a77677eb 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -405,6 +405,8 @@ return "Your species cannot play as a [jobtitle]." if(JOB_UNAVAILABLE_WHITELIST) return "[jobtitle] requires a whitelist." + if(JOB_UNAVAILABLE_SPECIAL) + return "[jobtitle] requires certain SPECIAL stats high enough." return "Error: Unknown job availability." /mob/dead/new_player/proc/IsJobUnavailable(rank, latejoin = FALSE) @@ -422,6 +424,8 @@ return JOB_UNAVAILABLE_SLOTFULL if(jobban_isbanned(src,rank)) return JOB_UNAVAILABLE_BANNED + if(job.special_stat_check(client?.prefs)) + return JOB_UNAVAILABLE_SPECIAL if(QDELETED(src)) return JOB_UNAVAILABLE_GENERIC if(!job.player_old_enough(client)) @@ -711,4 +715,3 @@ // Add verb for re-opening the interview panel, and re-init the verbs for the stat panel add_verb(src, /mob/dead/new_player/proc/open_interview) -