diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index ae58d61b3ca..a72563541d5 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -129,6 +129,7 @@ var/use_exp_tracking = 0 var/use_exp_restrictions_heads = 0 + var/use_exp_restrictions_heads_hours = 0 var/use_exp_restrictions_other = 0 var/simultaneous_pm_warning_timeout = 100 @@ -249,6 +250,9 @@ if("use_exp_restrictions_heads") config.use_exp_restrictions_heads = 1 + if("use_exp_restrictions_heads_hours") + config.use_exp_restrictions_heads_hours = value + if("use_exp_restrictions_other") config.use_exp_restrictions_other = 1 diff --git a/code/game/jobs/job/engineering.dm b/code/game/jobs/job/engineering.dm index 5a2200c7690..3e42c3daa32 100644 --- a/code/game/jobs/job/engineering.dm +++ b/code/game/jobs/job/engineering.dm @@ -18,7 +18,7 @@ access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_minisat, access_mechanic, access_mineral_storeroom) minimal_player_age = 21 exp_requirements = 600 - exp_type = "eng" + exp_type = "Engineering" equip(var/mob/living/carbon/human/H) if(!H) return 0 @@ -56,7 +56,7 @@ alt_titles = list("Maintenance Technician","Engine Technician","Electrician") minimal_player_age = 7 exp_requirements = 180 - exp_type = "all" + exp_type = "Crew" equip(var/mob/living/carbon/human/H) if(!H) return 0 H.equip_or_collect(new /obj/item/device/radio/headset/headset_eng(H), slot_l_ear) @@ -92,7 +92,7 @@ alt_titles = list("Atmospheric Technician") minimal_player_age = 7 exp_requirements = 180 - exp_type = "all" + exp_type = "Crew" equip(var/mob/living/carbon/human/H) if(!H) return 0 H.equip_or_collect(new /obj/item/device/radio/headset/headset_eng(H), slot_l_ear) diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm index 8310e716d38..b27bc4586be 100644 --- a/code/game/jobs/job/medical.dm +++ b/code/game/jobs/job/medical.dm @@ -16,7 +16,7 @@ access_keycard_auth, access_sec_doors, access_psychiatrist, access_maint_tunnels, access_paramedic, access_mineral_storeroom) minimal_player_age = 21 exp_requirements = 600 - exp_type = "med" + exp_type = "Medical" equip(var/mob/living/carbon/human/H) if(!H) return 0 @@ -54,7 +54,7 @@ alt_titles = list("Surgeon","Nurse","Coroner") minimal_player_age = 3 exp_requirements = 60 - exp_type = "all" + exp_type = "Crew" equip(var/mob/living/carbon/human/H) if(!H) return 0 @@ -119,7 +119,7 @@ alt_titles = list("Pharmacist","Pharmacologist") minimal_player_age = 7 exp_requirements = 180 - exp_type = "all" + exp_type = "Crew" equip(var/mob/living/carbon/human/H) if(!H) return 0 @@ -152,7 +152,7 @@ minimal_access = list(access_medical, access_morgue, access_genetics, access_research, access_maint_tunnels) minimal_player_age = 3 exp_requirements = 60 - exp_type = "all" + exp_type = "Crew" equip(var/mob/living/carbon/human/H) if(!H) return 0 @@ -184,7 +184,7 @@ alt_titles = list("Pathologist","Microbiologist") minimal_player_age = 7 exp_requirements = 180 - exp_type = "all" + exp_type = "Crew" equip(var/mob/living/carbon/human/H) if(!H) return 0 diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm index cc34e92bfce..5f9c0b94103 100644 --- a/code/game/jobs/job/science.dm +++ b/code/game/jobs/job/science.dm @@ -18,7 +18,7 @@ access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_minisat, access_maint_tunnels, access_mineral_storeroom) minimal_player_age = 21 exp_requirements = 600 - exp_type = "sci" + exp_type = "Science" // All science-y guys get bonuses for maxing out their tech. required_objectives=list( @@ -58,7 +58,7 @@ alt_titles = list("Xenoarcheologist", "Anomalist", "Plasma Researcher", "Xenobiologist", "Chemical Researcher") minimal_player_age = 3 exp_requirements = 60 - exp_type = "all" + exp_type = "Crew" // All science-y guys get bonuses for maxing out their tech. required_objectives=list( @@ -96,7 +96,7 @@ alt_titles = list("Biomechanical Engineer","Mechatronic Engineer") minimal_player_age = 3 exp_requirements = 60 - exp_type = "all" + exp_type = "Crew" required_objectives=list( /datum/job_objective/make_cyborg, diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm index 0466834aec0..d13c38d0548 100644 --- a/code/game/jobs/job/security.dm +++ b/code/game/jobs/job/security.dm @@ -18,7 +18,7 @@ access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway, access_pilot, access_weapons) minimal_player_age = 21 exp_requirements = 600 - exp_type = "sec" + exp_type = "Security" equip(var/mob/living/carbon/human/H) if(!H) return 0 @@ -63,7 +63,7 @@ minimal_access = list(access_security, access_sec_doors, access_brig, access_armory, access_court, access_maint_tunnels, access_weapons) minimal_player_age = 21 exp_requirements = 300 - exp_type = "sec" + exp_type = "Security" equip(var/mob/living/carbon/human/H) if(!H) return 0 @@ -111,7 +111,7 @@ alt_titles = list("Forensic Technician") minimal_player_age = 14 exp_requirements = 300 - exp_type = "all" + exp_type = "Crew" equip(var/mob/living/carbon/human/H) if(!H) return 0 H.equip_or_collect(new /obj/item/device/radio/headset/headset_sec/alt(H), slot_l_ear) @@ -169,7 +169,7 @@ minimal_access = list(access_security, access_sec_doors, access_brig, access_court, access_maint_tunnels, access_weapons) minimal_player_age = 14 exp_requirements = 300 - exp_type = "all" + exp_type = "Crew" equip(var/mob/living/carbon/human/H) if(!H) return 0 H.equip_or_collect(new /obj/item/device/radio/headset/headset_sec/alt(H), slot_l_ear) diff --git a/code/game/jobs/job/silicon.dm b/code/game/jobs/job/silicon.dm index 1eb62dea3da..41d6cb974e7 100644 --- a/code/game/jobs/job/silicon.dm +++ b/code/game/jobs/job/silicon.dm @@ -9,7 +9,7 @@ req_admin_notify = 1 minimal_player_age = 30 exp_requirements = 300 - exp_type = "sil" + exp_type = "Silicon" equip(var/mob/living/carbon/human/H) if(!H) return 0 @@ -29,7 +29,7 @@ selection_color = "#ddffdd" minimal_player_age = 21 exp_requirements = 300 - exp_type = "all" + exp_type = "Crew" alt_titles = list("Android", "Robot") equip(var/mob/living/carbon/human/H) diff --git a/code/game/jobs/job/supervisor.dm b/code/game/jobs/job/supervisor.dm index 2462f139fc0..4ee2720162c 100644 --- a/code/game/jobs/job/supervisor.dm +++ b/code/game/jobs/job/supervisor.dm @@ -13,7 +13,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1) minimal_access = list() //See get_access() minimal_player_age = 30 exp_requirements = 600 - exp_type = "com" + exp_type = "Command" equip(var/mob/living/carbon/human/H) if(!H) return 0 H.equip_or_collect(new /obj/item/device/radio/headset/heads/captain/alt(H), slot_l_ear) @@ -62,7 +62,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1) req_admin_notify = 1 minimal_player_age = 21 exp_requirements = 600 - exp_type = "sup" + exp_type = "Supply" access = list(access_security, access_sec_doors, access_brig, access_court, access_forensics_lockers, access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads, access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue, @@ -243,7 +243,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1) alt_titles = list("Lawyer","Public Defender") minimal_player_age = 30 exp_requirements = 300 - exp_type = "sec" + exp_type = "Security" idtype = /obj/item/weapon/card/id/security equip(var/mob/living/carbon/human/H) diff --git a/code/game/jobs/job_exp.dm b/code/game/jobs/job_exp.dm index f789fcdb695..535da5303d4 100644 --- a/code/game/jobs/job_exp.dm +++ b/code/game/jobs/job_exp.dm @@ -1,30 +1,49 @@ +// Globals, Defines, Etc + +var/global/list/exp_jobsmap = list( + "Crew" = list(), // all playtime from all jobs, together + "Command" = list(titles = command_positions), + "Engineering" = list(titles = engineering_positions), + "Security" = list(titles = security_positions), + "Silicon" = list(titles = nonhuman_positions), + "Service" = list(titles = service_positions), + "Medical" = list(titles = medical_positions), + "Science" = list(titles = science_positions), + "Supply" = list(titles = supply_positions), + "Special" = list(), // special_role + "Ghost" = list(), // dead/observer + "Exempt" = list() // special grandfather setting +) + // Admin Verbs + /client/proc/cmd_admin_check_player_exp() //Allows admins to determine who the newer players are. set category = "Admin" - set name = "Check Player XP" + set name = "Check Player Playtime" if(!check_rights(R_ADMIN)) return - var/msg = "EXP Report
" + var/msg = "Playtime Report
Playtime:
" for(var/client/C in clients) var/list/play_records = params2list(C.prefs.exp) - var/gen_exp_time = text2num(play_records["gen"]) + var/gen_exp_time = text2num(play_records["Crew"]) gen_exp_time = num2text(round(gen_exp_time / 60)) + "h" - msg += "
- [key_name_admin(C.mob)]: " + C.get_exp_general() + " " + msg += "
- [key_name_admin(C.mob)]: " + C.get_exp_general() + " " if(msg != "") - src << browse(msg, "window=Player_exp_check") - log_admin("[key_name(usr)] checked player EXP") - feedback_add_details("admin_verb","MEXP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + src << browse(msg, "window=Player_playtime_check") + log_admin("[key_name(usr)] checked player playtime") + feedback_add_details("admin_verb","MCPP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + /client/proc/cmd_show_exp_panel(var/client/C in clients) if(!check_rights(R_ADMIN)) return - var/body = "EXP for [C.key]
" + var/body = "Playtime for [C.key]
Playtime:" body += C.get_exp_report() body += "" - src << browse(body, "window=playerexp;size=550x615") + src << browse(body, "window=playerplaytime;size=550x615") // Procs @@ -42,11 +61,14 @@ if(check_rights(R_ADMIN, 0, M)) return 1 var/list/play_records = params2list(M.client.prefs.exp) - var/imm = text2num(play_records["imm"]) - if(imm) + var/isexempt = text2num(play_records["Exempt"]) + if(isexempt) return 1 var/my_exp = text2num(play_records[job.exp_type]) - if(my_exp >= text2num(job.exp_requirements)) + var/job_requirement = text2num(job.exp_requirements) + if(config.use_exp_restrictions_heads_hours && ((rank in command_positions) || rank == "AI")) + job_requirement = text2num(config.use_exp_restrictions_heads_hours) * 60 + if(my_exp >= job_requirement) return 1 else return 0 @@ -67,68 +89,55 @@ /client/proc/get_exp_report() if(!config.use_exp_tracking) - return "EXP tracking is disabled in the server configuration file." - var/return_text = "" + return "Tracking is disabled in the server configuration file." + var/list/play_records = params2list(prefs.exp) - var/exp_gen = text2num(play_records["gen"]) - var/exp_com = text2num(play_records["com"]) - var/exp_sec = text2num(play_records["sec"]) - var/exp_sci = text2num(play_records["sci"]) - var/exp_eng = text2num(play_records["eng"]) - var/exp_med = text2num(play_records["med"]) - var/exp_sup = text2num(play_records["sup"]) - var/exp_sil = text2num(play_records["sil"]) - var/exp_ant = text2num(play_records["ant"]) - var/exp_gho = text2num(play_records["gho"]) - var/exp_imm = text2num(play_records["imm"]) - if(play_records.len) - if(exp_gen > 0) - return_text += "Experience:
- General: " + get_exp_format(exp_gen) - if(exp_com > 0) - return_text += "
- Command: " + get_exp_format(exp_com) + " (" + num2text(round(exp_com/exp_gen*100)) + "%)" - if(exp_sec > 0) - return_text += "
- Security: " + get_exp_format(exp_sec) + " (" + num2text(round(exp_sec/exp_gen*100)) + "%)" - if(exp_sci > 0) - return_text += "
- Science: " + get_exp_format(exp_sci) + " (" + num2text(round(exp_sci/exp_gen*100)) + "%)" - if(exp_eng > 0) - return_text += "
- Engineering: " + get_exp_format(exp_eng) + " (" + num2text(round(exp_eng/exp_gen*100)) + "%)" - if(exp_med > 0) - return_text += "
- Medical: " + get_exp_format(exp_med) + " (" + num2text(round(exp_med/exp_gen*100)) + "%)" - if(exp_sup > 0) - return_text += "
- Support: " + get_exp_format(exp_sup) + " (" + num2text(round(exp_sup/exp_gen*100)) + "%)" - if(exp_sil > 0) - return_text += "
- Silicon: " + get_exp_format(exp_sil) + " (" + num2text(round(exp_sil/exp_gen*100)) + "%)" - if(exp_ant > 0) - return_text += "
- Special: " + get_exp_format(exp_ant) + " (" + num2text(round(exp_ant/exp_gen*100)) + "%)" - if(exp_gho > 0) - return_text += "
- Ghost: " + get_exp_format(exp_gho) + " (" + num2text(round(exp_gho/exp_gen*100)) + "%)" - if(exp_imm > 0) - return_text += "
- Grandfathered: YES" - var/list/jobs_locked = list() - var/list/jobs_unlocked = list() - for(var/datum/job/job in job_master.occupations) - if(job.exp_requirements && job.exp_type) - if(!job_is_xp_locked(job.title)) - continue - else if(has_exp_for_job(mob, job.title)) - jobs_unlocked += "
- " + job.title - else - jobs_locked += "
- " + job.title + " (" + get_exp_format(text2num(play_records[job.exp_type])) + " / " + get_exp_format(job.exp_requirements) + " [job.exp_type] EXP)" - if(jobs_unlocked.len) - return_text += "

Jobs Unlocked: " - for(var/text in jobs_unlocked) - return_text += text - if(jobs_locked.len) - return_text += "

Jobs Not Unlocked: " - for(var/text in jobs_locked) - return_text += text - return return_text - else - return "[src] has no EXP records." + if(!play_records.len) + return "[src] has no records." + + var/return_text = "" + + var/list/exp_data = list() + for(var/cat in exp_jobsmap) + if(text2num(play_records[cat])) + exp_data[cat] = text2num(play_records[cat]) + else + exp_data[cat] = 0 + + for(var/dep in exp_data) + if(exp_data[dep] > 0) + if(dep == "Exempt") + return_text += "
- Exempt (all jobs auto-unlocked)" + else + return_text += "
- [dep] " + get_exp_format(exp_data[dep]) + " (" + num2text(round(exp_data[dep]/exp_data["Crew"]*100)) + "%)" + + var/list/jobs_locked = list() + var/list/jobs_unlocked = list() + for(var/datum/job/job in job_master.occupations) + if(job.exp_requirements && job.exp_type) + if(!job_is_xp_locked(job.title)) + continue + else if(has_exp_for_job(mob, job.title)) + jobs_unlocked += "
- " + job.title + else + var/xp_req = job.exp_requirements + if(config.use_exp_restrictions_heads_hours && ((job.title in command_positions) || job.title == "AI")) + xp_req = text2num(config.use_exp_restrictions_heads_hours) * 60 + jobs_locked += "
- " + job.title + " (" + get_exp_format(text2num(play_records[job.exp_type])) + " / " + get_exp_format(xp_req) + " [job.exp_type] EXP)" + if(jobs_unlocked.len) + return_text += "

Jobs Unlocked: " + for(var/text in jobs_unlocked) + return_text += text + if(jobs_locked.len) + return_text += "

Jobs Not Unlocked: " + for(var/text in jobs_locked) + return_text += text + return return_text + /client/proc/get_exp_general() var/list/play_records = params2list(prefs.exp) - var/exp_gen = text2num(play_records["gen"]) + var/exp_gen = text2num(play_records["Crew"]) return get_exp_format(exp_gen) /client/proc/get_exp_format(var/expnum) @@ -146,54 +155,36 @@ var/DBQuery/exp_read = dbcon.NewQuery("SELECT exp FROM [format_table_name("player")] WHERE ckey='[C.ckey]'") exp_read.Execute() - var/list/play_records = list() + var/list/read_records = list() while(exp_read.NextRow()) - play_records = params2list(exp_read.item[1]) + read_records = params2list(exp_read.item[1]) - for(var/rtype in list("gen","com","sec","sci","eng","med","sup","sil","ant", "gho", "imm")) - if(!text2num(play_records[rtype])) - play_records[rtype] = 0 + var/list/play_records = list() + for(var/rtype in exp_jobsmap) + if(text2num(read_records[rtype])) + play_records[rtype] = text2num(read_records[rtype]) else - play_records[rtype] = text2num(play_records[rtype]) + play_records[rtype] = 0 if(C.mob.stat == CONSCIOUS && C.mob.mind.assigned_role) - play_records["gen"] += minutes + play_records["Crew"] += minutes if(announce_changes) to_chat(C.mob,"You got: [minutes] General EXP!") - if(C.mob.mind.assigned_role in command_positions) - play_records["com"] += minutes - if(announce_changes) - to_chat(C.mob,"You got: [minutes] Command EXP!") - if(C.mob.mind.assigned_role in security_positions) - play_records["sec"] += minutes - if(announce_changes) - to_chat(C.mob,"You got: [minutes] Security EXP!") - if(C.mob.mind.assigned_role in science_positions) - play_records["sci"] += minutes - if(announce_changes) - to_chat(C.mob,"You got: [minutes] Science EXP!") - if(C.mob.mind.assigned_role in engineering_positions) - play_records["eng"] += minutes - if(announce_changes) - to_chat(C.mob,"You got: [minutes] Engineering EXP!") - if(C.mob.mind.assigned_role in medical_positions) - play_records["med"] += minutes - if(announce_changes) - to_chat(C.mob,"You got: [minutes] Medical EXP!") - if(C.mob.mind.assigned_role in support_positions) - play_records["sup"] += minutes - if(announce_changes) - to_chat(C.mob,"You got: [minutes] Support EXP!") - if(C.mob.mind.assigned_role in nonhuman_positions) - play_records["sil"] += minutes - if(announce_changes) - to_chat(C.mob,"You got: [minutes] Silicon EXP!") + + for(var/cat in exp_jobsmap) + if(exp_jobsmap[cat]["titles"]) + if(C.mob.mind.assigned_role in exp_jobsmap[cat]["titles"]) + play_records[cat] += minutes + if(announce_changes) + to_chat(C.mob,"You got: [minutes] [cat] EXP!") + if(C.mob.mind.special_role) - play_records["ant"] += minutes + play_records["Special"] += minutes if(announce_changes) to_chat(C.mob,"You got: [minutes] Special EXP!") + else if(isobserver(C.mob)) - play_records["gho"] += minutes + play_records["Ghost"] += minutes if(announce_changes) to_chat(C.mob,"You got: [minutes] Ghost EXP!") else diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index af3469e55fb..f0faa025854 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -43,7 +43,7 @@ var/global/nologevent = 0 if(M.client) body += " played by [M.client] " body += "\[[M.client.holder ? M.client.holder.rank : "Player"]\] " - body += "\[" + M.client.get_exp_general() + "\]" + body += "\[" + M.client.get_exp_general() + "\]" if(istype(M, /mob/new_player)) body += " Hasn't Entered Game " diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 5270e4750e5..d71b4ca690e 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -75,7 +75,7 @@ var/list/admin_verbs_admin = list( /client/proc/debug_variables, /client/proc/show_snpc_verbs, /client/proc/reset_all_tcs, /*resets all telecomms scripts*/ - /client/proc/cmd_admin_check_player_exp + /client/proc/cmd_admin_check_player_exp /* shows players by playtime */ ) var/list/admin_verbs_ban = list( /client/proc/unban_panel, diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 51577089940..a32da447050 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -2016,10 +2016,10 @@ fax_panel(usr) - else if(href_list["getexpwindow"]) + else if(href_list["getplaytimewindow"]) if(!check_rights(R_ADMIN)) return - var/mob/M = locate(href_list["getexpwindow"]) + var/mob/M = locate(href_list["getplaytimewindow"]) usr.client.cmd_show_exp_panel(M.client) else if(href_list["jumpto"]) diff --git a/config/example/config.txt b/config/example/config.txt index 2e5e50e72bb..350c59b079d 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -17,9 +17,12 @@ JOBS_HAVE_MINIMAL_ACCESS ## you have noone older than 0 days, since noone has been logged yet. Only turn this on once you have had the database up for 30 days. #USE_AGE_RESTRICTION_FOR_JOBS -## Unhash the first to track playtime in database. Unhash the second to restrict job access based on playtime for head jobs and the AI. Unhash the second to do so for other non-civ jobs. Playtime is based on actual playtime on this server. All of these require database to be enabled. +## USE_EXP_TRACKING enables playtime/exp tracking. REQUIRES DATABASE TO BE ENABLED. +## USE_EXP_RESTRICTIONS_HEADS enables playtime/exp requirements for head jobs. If USE_EXP_RESTRICTIONS_HEADS_HOURS is enabled also, it uses that value for their time requirements. If not, it goes by the values defined on their job definitions in code. +## USE_EXP_RESTRICTIONS_OTHER enables playtime/exp requirements for some dangerous non-head jobs, like engineer, scientist, security officer, etc. The requirements for these jobs are always taken from code. #USE_EXP_TRACKING #USE_EXP_RESTRICTIONS_HEADS +#USE_EXP_RESTRICTIONS_HEADS_HOURS 15 #USE_EXP_RESTRICTIONS_OTHER ## Unhash this entry to have certain antagonist roles require your account to be at least a certain number of days old to select. You can configure the exact age requirement for different antag roles by editing special_role_times in /code/modules/client/preferences.dm.