From e1dccb435b81b8e8ff84356ede292704d2430d5e Mon Sep 17 00:00:00 2001 From: Kyep Date: Sat, 6 Aug 2016 14:39:35 -0700 Subject: [PATCH] Update 6 - Split EXP_TYPE_CREW into EXP_TYPE_LIVING (all living mobs) and EXP_TYPE_CREW (actual crew positions). Job unlocks use EXP_TYPE_CREW. General playtime reports use EXP_TYPE_LIVING. Playing corgi doesn't help unlock jobs, but it does show in your stats. - Added tracking for karma-locked jobs as a department in stats. - Added quite a few safety checks. - Split the per-client part of update_exp into update_exp_client - Added new config option to let admins bypass the system, intended for testing - Moved defines to code\__DEFINES\preferences.dm --- code/__DEFINES/preferences.dm | 16 ++++ code/controllers/configuration.dm | 4 + code/game/jobs/job_exp.dm | 131 ++++++++++++++---------------- code/game/jobs/jobs.dm | 14 ++-- code/modules/admin/admin.dm | 2 +- code/modules/admin/topic.dm | 4 +- config/example/config.txt | 2 + 7 files changed, 93 insertions(+), 80 deletions(-) diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index 8ac165cec6a..24c8235c83a 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -27,3 +27,19 @@ #define CHAT_NO_ADMINLOGS 16384 #define TOGGLES_DEFAULT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_ATTACKLOGS|CHAT_LOOC|MEMBER_PUBLIC) + +// Playtime tracking system, see jobs_exp.dm +#define EXP_TYPE_LIVING "Living" +#define EXP_TYPE_CREW "Crew" +#define EXP_TYPE_COMMAND "Command" +#define EXP_TYPE_ENGINEERING "Engineering" +#define EXP_TYPE_MEDICAL "Medical" +#define EXP_TYPE_SCIENCE "Science" +#define EXP_TYPE_SUPPLY "Supply" +#define EXP_TYPE_SECURITY "Security" +#define EXP_TYPE_SILICON "Silicon" +#define EXP_TYPE_SERVICE "Service" +#define EXP_TYPE_WHITELIST "Whitelist" +#define EXP_TYPE_SPECIAL "Special" +#define EXP_TYPE_GHOST "Ghost" +#define EXP_TYPE_EXEMPT "Exempt" \ No newline at end of file diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index c3779ab095d..67939f227b5 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -131,6 +131,7 @@ var/use_exp_restrictions_heads = 0 var/use_exp_restrictions_heads_hours = 0 var/use_exp_restrictions_other = 0 + var/use_exp_restrictions_admin_bypass = 0 var/simultaneous_pm_warning_timeout = 100 @@ -256,6 +257,9 @@ if("use_exp_restrictions_other") config.use_exp_restrictions_other = 1 + if("use_exp_restrictions_admin_bypass") + config.use_exp_restrictions_admin_bypass = 1 + if("jobs_have_minimal_access") config.jobs_have_minimal_access = 1 diff --git a/code/game/jobs/job_exp.dm b/code/game/jobs/job_exp.dm index 7d312b43319..dfeb9520502 100644 --- a/code/game/jobs/job_exp.dm +++ b/code/game/jobs/job_exp.dm @@ -1,27 +1,5 @@ - -// Defines - -#define EXP_TYPE_CREW "Crew" -#define EXP_TYPE_COMMAND "Command" -#define EXP_TYPE_ENGINEERING "Engineering" -#define EXP_TYPE_SECURITY "Security" -#define EXP_TYPE_SILICON "Silicon" -#define EXP_TYPE_SERVICE "Service" -#define EXP_TYPE_MEDICAL "Medical" -#define EXP_TYPE_SCIENCE "Science" -#define EXP_TYPE_SUPPLY "Supply" -#define EXP_TYPE_SPECIAL "Special" -#define EXP_TYPE_GHOST "Ghost" -#define EXP_TYPE_EXEMPT "Exempt" - -// Globals, Defines, Etc - - - - // 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 Playtime" @@ -29,20 +7,21 @@ return var/msg = "Playtime ReportPlaytime:
" src << browse(msg, "window=Player_playtime_check") /datum/admins/proc/cmd_show_exp_panel(var/client/C) - if (!C) + if(!C) + to_chat(usr, "ERROR: Mob not found.") return if(!check_rights(R_ADMIN)) return var/body = "Playtime for [C.key]
Playtime:" body += C.get_exp_report() body += "" - usr << browse(body, "window=playerplaytime;size=550x615") + usr << browse(body, "window=playerplaytime[C.ckey];size=550x615") // Procs @@ -55,7 +34,7 @@ return 0 if(!job_is_xp_locked(src.title)) return 0 - if(check_rights(R_ADMIN, 0, C.mob)) + if(config.use_exp_restrictions_admin_bypass && check_rights(R_ADMIN, 0, C.mob)) return 0 var/list/play_records = params2list(C.prefs.exp) var/isexempt = text2num(play_records[EXP_TYPE_EXEMPT]) @@ -107,12 +86,13 @@ if(exp_data[dep] > 0) if(dep == EXP_TYPE_EXEMPT) return_text += "
  • Exempt (all jobs auto-unlocked)
  • " - else if(exp_data[EXP_TYPE_CREW] > 0) - var/my_pc = num2text(round(exp_data[dep]/exp_data[EXP_TYPE_CREW]*100)) + else if(exp_data[EXP_TYPE_LIVING] > 0) + var/my_pc = num2text(round(exp_data[dep]/exp_data[EXP_TYPE_LIVING]*100)) return_text += "
  • [dep] [get_exp_format(exp_data[dep])] ([my_pc]%)
  • " else return_text += "
  • [dep] [get_exp_format(exp_data[dep])]
  • " - + if(config.use_exp_restrictions_admin_bypass && check_rights(R_ADMIN, 0, mob)) + return_text += "
  • Admin (all jobs auto-unlocked)
  • " return_text += "" var/list/jobs_locked = list() var/list/jobs_unlocked = list() @@ -140,9 +120,9 @@ return return_text -/client/proc/get_exp_general() +/client/proc/get_exp_living() var/list/play_records = params2list(prefs.exp) - var/exp_gen = text2num(play_records[EXP_TYPE_CREW]) + var/exp_gen = text2num(play_records[EXP_TYPE_LIVING]) return get_exp_format(exp_gen) /proc/get_exp_format(var/expnum) @@ -153,53 +133,60 @@ else return "0h" -/proc/update_exp(var/minutes, var/announce_changes = 0) +/proc/update_exp(var/mins, var/ann = 0) if(!establish_db_connection()) return -1 spawn(0) - for(var/client/C in clients) - if(C.inactivity >= (10 MINUTES)) + for(var/client/L in clients) + if(L.inactivity >= (10 MINUTES)) continue - - var/DBQuery/exp_read = dbcon.NewQuery("SELECT exp FROM [format_table_name("player")] WHERE ckey='[C.ckey]'") - exp_read.Execute() - var/list/read_records = list() - while(exp_read.NextRow()) - read_records = params2list(exp_read.item[1]) - - 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] = 0 - if(C.mob.stat == CONSCIOUS && C.mob.mind.assigned_role) - play_records[EXP_TYPE_CREW] += minutes - if(announce_changes) - to_chat(C.mob,"You got: [minutes] General 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[EXP_TYPE_SPECIAL] += minutes - if(announce_changes) - to_chat(C.mob,"You got: [minutes] Special EXP!") - else if(isobserver(C.mob)) - play_records[EXP_TYPE_GHOST] += minutes - if(announce_changes) - to_chat(C.mob,"You got: [minutes] Ghost EXP!") - else - return - var/new_exp = list2params(play_records) - C.prefs.exp = new_exp - new_exp = sanitizeSQL(new_exp) - var/DBQuery/update_query = dbcon.NewQuery("UPDATE [format_table_name("player")] SET exp = '[new_exp]' WHERE ckey='[C.ckey]'") - update_query.Execute() + spawn(0) + update_exp_client(L, mins, ann) sleep(10) +/proc/update_exp_client(var/client/C, var/minutes, var/announce_changes = 0) + if(!C ||!C.ckey) + return + var/DBQuery/exp_read = dbcon.NewQuery("SELECT exp FROM [format_table_name("player")] WHERE ckey='[C.ckey]'") + exp_read.Execute() + var/list/read_records = list() + var/hasread = 0 + while(exp_read.NextRow()) + read_records = params2list(exp_read.item[1]) + hasread = 1 + if(!hasread) + return + 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] = 0 + if(C.mob.stat == CONSCIOUS && C.mob.mind.assigned_role) + play_records[EXP_TYPE_LIVING] += minutes + if(announce_changes) + to_chat(C.mob,"You got: [minutes] Living 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[EXP_TYPE_SPECIAL] += minutes + if(announce_changes) + to_chat(C.mob,"You got: [minutes] Special EXP!") + else if(isobserver(C.mob)) + play_records[EXP_TYPE_GHOST] += minutes + if(announce_changes) + to_chat(C.mob,"You got: [minutes] Ghost EXP!") + else + return + var/new_exp = list2params(play_records) + C.prefs.exp = new_exp + new_exp = sanitizeSQL(new_exp) + var/DBQuery/update_query = dbcon.NewQuery("UPDATE [format_table_name("player")] SET exp = '[new_exp]' WHERE ckey='[C.ckey]'") + update_query.Execute() /hook/roundstart/proc/exptimer() if(!config.sql_enabled || !config.use_exp_tracking) diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm index 0c8f6a5d47d..0604ec0f428 100644 --- a/code/game/jobs/jobs.dm +++ b/code/game/jobs/jobs.dm @@ -184,16 +184,18 @@ var/list/whitelisted_positions = list( return titles var/global/list/exp_jobsmap = list( - EXP_TYPE_CREW = list(), // all playtime from all jobs, together + EXP_TYPE_LIVING = list(), // all living mobs + EXP_TYPE_CREW = list(titles = command_positions + engineering_positions + medical_positions + science_positions + support_positions + supply_positions + security_positions + civilian_positions + whitelisted_positions), // crew positions EXP_TYPE_COMMAND = list(titles = command_positions), EXP_TYPE_ENGINEERING = list(titles = engineering_positions), - EXP_TYPE_SECURITY = list(titles = security_positions), - EXP_TYPE_SILICON = list(titles = nonhuman_positions), - EXP_TYPE_SERVICE = list(titles = service_positions), EXP_TYPE_MEDICAL = list(titles = medical_positions), EXP_TYPE_SCIENCE = list(titles = science_positions), EXP_TYPE_SUPPLY = list(titles = supply_positions), - EXP_TYPE_SPECIAL = list(), // special_role - EXP_TYPE_GHOST = list(), // dead/observer + EXP_TYPE_SECURITY = list(titles = security_positions), + EXP_TYPE_SILICON = list(titles = nonhuman_positions), + EXP_TYPE_SERVICE = list(titles = service_positions), + EXP_TYPE_WHITELIST = list(titles = whitelisted_positions), // karma-locked jobs + EXP_TYPE_SPECIAL = list(), // antags, ERT, etc + EXP_TYPE_GHOST = list(), // dead people, observers EXP_TYPE_EXEMPT = list() // special grandfather setting ) \ No newline at end of file diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index f0faa025854..be3fe24259c 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_living() + "\]" if(istype(M, /mob/new_player)) body += " Hasn't Entered Game " diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 85c826a5594..71a2c81011e 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -2017,9 +2017,11 @@ fax_panel(usr) else if(href_list["getplaytimewindow"]) - if(!check_rights(R_ADMIN)) return + if(!check_rights(R_ADMIN)) + return var/mob/M = locate(href_list["getplaytimewindow"]) if(!M) + to_chat(usr, "ERROR: Mob not found.") return cmd_show_exp_panel(M.client) diff --git a/config/example/config.txt b/config/example/config.txt index 350c59b079d..9a0fe069c77 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -20,10 +20,12 @@ JOBS_HAVE_MINIMAL_ACCESS ## 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_RESTRICTIONS_ADMIN_BYPASS lets admins always bypass the restrictions. Useful to turn off for testing. #USE_EXP_TRACKING #USE_EXP_RESTRICTIONS_HEADS #USE_EXP_RESTRICTIONS_HEADS_HOURS 15 #USE_EXP_RESTRICTIONS_OTHER +#USE_EXP_RESTRICTIONS_ADMIN_BYPASS ## 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. ## See USE_AGE_RESTRICTION_FOR_JOBS for more information