diff --git a/SQL/paradise_schema.sql b/SQL/paradise_schema.sql index 1e509dc8149..eb9c08af9ea 100644 --- a/SQL/paradise_schema.sql +++ b/SQL/paradise_schema.sql @@ -250,7 +250,7 @@ CREATE TABLE `player` ( `nanoui_fancy` smallint(4) DEFAULT '1', `show_ghostitem_attack` smallint(4) DEFAULT '1', `lastchangelog` varchar(32) NOT NULL DEFAULT '0', - `exp` mediumtext NOT NULL DEFAULT '', + `exp` mediumtext, PRIMARY KEY (`id`), UNIQUE KEY `ckey` (`ckey`) ) ENGINE=InnoDB AUTO_INCREMENT=32446 DEFAULT CHARSET=latin1; diff --git a/SQL/paradise_schema_prefixed.sql b/SQL/paradise_schema_prefixed.sql index 20efd87c90a..802c3fd352b 100644 --- a/SQL/paradise_schema_prefixed.sql +++ b/SQL/paradise_schema_prefixed.sql @@ -250,7 +250,7 @@ CREATE TABLE `SS13_player` ( `nanoui_fancy` smallint(4) DEFAULT '1', `show_ghostitem_attack` smallint(4) DEFAULT '1', `lastchangelog` varchar(32) NOT NULL DEFAULT '0', - `exp` mediumtext NOT NULL DEFAULT '', + `exp` mediumtext, PRIMARY KEY (`id`), UNIQUE KEY `ckey` (`ckey`) ) ENGINE=InnoDB AUTO_INCREMENT=32446 DEFAULT CHARSET=latin1; diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index a72563541d5..c3779ab095d 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -251,7 +251,7 @@ config.use_exp_restrictions_heads = 1 if("use_exp_restrictions_heads_hours") - config.use_exp_restrictions_heads_hours = value + config.use_exp_restrictions_heads_hours = text2num(value) if("use_exp_restrictions_other") config.use_exp_restrictions_other = 1 diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index 26c037fe7f5..7d6ea9b4e7d 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -67,12 +67,6 @@ var/round_start_time = 0 initialtpass = 1 votetimer() -/datum/controller/gameticker/proc/exptimer() - spawn(0) - while(TRUE) - update_exp(5,0) - sleep(5 MINUTES) - /datum/controller/gameticker/proc/setup() //Create and announce mode if(master_mode=="secret") @@ -234,8 +228,6 @@ var/round_start_time = 0 if(config.sql_enabled) spawn(3000) statistic_cycle() // Polls population totals regularly and stores them in an SQL DB - if(config.use_exp_tracking) - exptimer() votetimer() diff --git a/code/game/jobs/job/engineering.dm b/code/game/jobs/job/engineering.dm index 3e42c3daa32..dd88a6496ab 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 = "Engineering" + exp_type = 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 = "Crew" + exp_type = 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 = "Crew" + exp_type = 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 b27bc4586be..d623a79a3d1 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 = "Medical" + exp_type = 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 = "Crew" + exp_type = 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 = "Crew" + exp_type = 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 = "Crew" + exp_type = 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 = "Crew" + exp_type = 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 5f9c0b94103..090b6a2adef 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 = "Science" + exp_type = 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 = "Crew" + exp_type = 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 = "Crew" + exp_type = 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 d13c38d0548..22661bcb35b 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 = "Security" + exp_type = 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 = "Crew" + exp_type = 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 = "Crew" + exp_type = 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 41d6cb974e7..5461fb1d9b9 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 = "Silicon" + exp_type = 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 = "Crew" + exp_type = 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 4ee2720162c..876706d114d 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 = "Command" + exp_type = 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 = "Supply" + exp_type = 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 = "Security" + exp_type = EXP_TYPE_SECURITY idtype = /obj/item/weapon/card/id/security equip(var/mob/living/carbon/human/H) diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 3a556f6d2e5..ba2e5be5d46 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -123,7 +123,7 @@ var/global/datum/controller/occupations/job_master if(job.admin_only) // No admin positions either. continue - if(!has_exp_for_job(player, job.title)) + if(job.available_in_playtime(player.client)) continue if(jobban_isbanned(player, job.title)) diff --git a/code/game/jobs/job_exp.dm b/code/game/jobs/job_exp.dm index 535da5303d4..caa59a57fa5 100644 --- a/code/game/jobs/job_exp.dm +++ b/code/game/jobs/job_exp.dm @@ -1,20 +1,22 @@ +// 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 -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 @@ -25,53 +27,51 @@ var/global/list/exp_jobsmap = list( set name = "Check Player Playtime" if(!check_rights(R_ADMIN)) return - var/msg = "Playtime Report
Playtime:
" + var/msg = "Playtime ReportPlaytime:
" + src << browse(msg, "window=Player_playtime_check") /client/proc/cmd_show_exp_panel(var/client/C in clients) if(!check_rights(R_ADMIN)) return - var/body = "Playtime for [C.key]
Playtime:" + var/body = "Playtime for [C.key]
Playtime:" body += C.get_exp_report() - body += "" + body += "" src << browse(body, "window=playerplaytime;size=550x615") // Procs -/proc/has_exp_for_job(mob/M, rank) - var/datum/job/job = job_master.GetJob(rank) - if(!job) - return 1 - if(!job.exp_requirements || !job.exp_type) - return 1 - if(!job_is_xp_locked(rank)) - return 1 - if(!M.client) + +/datum/job/proc/available_in_playtime(client/C) + if(!C) return 0 - if(check_rights(R_ADMIN, 0, M)) + if(!exp_requirements || !exp_type) + return 0 + if(!job_is_xp_locked(src.title)) + return 0 + if(check_rights(R_ADMIN, 0, C.mob)) return 1 - var/list/play_records = params2list(M.client.prefs.exp) - var/isexempt = text2num(play_records["Exempt"]) + var/list/play_records = params2list(C.prefs.exp) + var/isexempt = text2num(play_records[EXP_TYPE_EXEMPT]) if(isexempt) - return 1 - var/my_exp = text2num(play_records[job.exp_type]) - 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 + var/my_exp = text2num(play_records[exp_type]) + var/job_requirement = text2num(exp_requirements) + if(config.use_exp_restrictions_heads_hours && ((title in command_positions) || title == "AI")) + job_requirement = config.use_exp_restrictions_heads_hours * 60 + if(my_exp >= job_requirement) + return 0 + else + return (job_requirement - my_exp) + + /proc/job_is_xp_locked(jobtitle) if(!config.use_exp_restrictions_heads && ((jobtitle in command_positions) || jobtitle == "AI")) @@ -93,9 +93,9 @@ var/global/list/exp_jobsmap = list( var/list/play_records = params2list(prefs.exp) if(!play_records.len) - return "[src] has no records." + return "[key] has no records." - var/return_text = "" + var/return_text = "" 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 if(!job.available_in_playtime(mob.client)) + 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)" + xp_req = 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: " + return_text += "

Jobs Unlocked:" if(jobs_locked.len) - return_text += "

Jobs Not Unlocked: " + return_text += "

Jobs Not Unlocked:" return return_text /client/proc/get_exp_general() var/list/play_records = params2list(prefs.exp) - var/exp_gen = text2num(play_records["Crew"]) + var/exp_gen = text2num(play_records[EXP_TYPE_CREW]) return get_exp_format(exp_gen) -/client/proc/get_exp_format(var/expnum) - if(expnum > 0) +/proc/get_exp_format(var/expnum) + if(expnum > 60) return num2text(round(expnum / 60)) + "h" + else if(expnum > 0) + return num2text(expnum) + "m" else return "0h" @@ -151,47 +155,53 @@ var/global/list/exp_jobsmap = list( return -1 spawn(0) for(var/client/C in clients) - if(C.inactivity < (10 MINUTES)) + if(C.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/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["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["Special"] += minutes - if(announce_changes) - to_chat(C.mob,"You got: [minutes] Special EXP!") - - else if(isobserver(C.mob)) - play_records["Ghost"] += minutes - if(announce_changes) - to_chat(C.mob,"You got: [minutes] Ghost EXP!") + var/list/play_records = list() + for(var/rtype in exp_jobsmap) + if(text2num(read_records[rtype])) + play_records[rtype] = text2num(read_records[rtype]) 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() - sleep(10) \ No newline at end of file + 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() + sleep(10) + + +/hook/roundstart/proc/exptimer() + if(!config.sql_enabled || !config.use_exp_tracking) + return 0 + spawn(0) + while(TRUE) + sleep(5 MINUTES) + update_exp(5,0) diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm index 6af69ebed9d..0c8f6a5d47d 100644 --- a/code/game/jobs/jobs.dm +++ b/code/game/jobs/jobs.dm @@ -183,3 +183,17 @@ 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_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_EXEMPT = list() // special grandfather setting +) \ No newline at end of file diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index a32da447050..4d965ab38f8 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -2018,8 +2018,9 @@ else if(href_list["getplaytimewindow"]) if(!check_rights(R_ADMIN)) return - var/mob/M = locate(href_list["getplaytimewindow"]) + if(!M) + return usr.client.cmd_show_exp_panel(M.client) else if(href_list["jumpto"]) diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index 50fd26b929c..8832e3fc3e4 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -552,8 +552,9 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if(jobban_isbanned(user, rank)) HTML += "[rank] \[BANNED]" continue - if(!has_exp_for_job(user, job.title)) - HTML += "[rank] \[TIME]" + var/available_in_playtime = job.available_in_playtime(user.client) + if(available_in_playtime) + HTML += "[rank] \[ " + get_exp_format(available_in_playtime) + " as [job.exp_type] ]" continue if(!job.player_old_enough(user.client)) var/available_in_days = job.available_in_days(user.client) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 6665bb54982..97e07a71fb0 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -246,7 +246,7 @@ if(!is_job_whitelisted(src, rank)) return 0 if(!job.player_old_enough(src.client)) return 0 if(job.admin_only && !(check_rights(R_EVENT, 0))) return 0 - if(!has_exp_for_job(src, rank)) + if(job.available_in_playtime(src.client)) return 0 if(config.assistantlimit)