diff --git a/code/controllers/subsystems/persist_vr.dm b/code/controllers/subsystems/persist_vr.dm new file mode 100644 index 00000000000..baae12c955f --- /dev/null +++ b/code/controllers/subsystems/persist_vr.dm @@ -0,0 +1,73 @@ +//////////////////////////////// +//// Paid Leave Subsystem +//// For tracking how much department PTO time players have accured +//////////////////////////////// + +SUBSYSTEM_DEF(persist) + name = "Persist" + priority = 20 + wait = 15 MINUTES + flags = SS_BACKGROUND|SS_NO_INIT|SS_KEEP_TIMING + runlevels = RUNLEVEL_GAME|RUNLEVEL_POSTGAME + var/list/currentrun = list() + +/datum/controller/subsystem/persist/fire(var/resumed = FALSE) + update_department_hours(resumed) + +// Do PTO Accruals +/datum/controller/subsystem/persist/proc/update_department_hours(var/resumed = FALSE) + establish_db_connection() + if(!dbcon.IsConnected()) + src.currentrun.Cut() + return + if(!resumed) + src.currentrun = human_mob_list.Copy() + + //cache for sanic speed (lists are references anyways) + var/list/currentrun = src.currentrun + while (currentrun.len) + var/mob/M = currentrun[currentrun.len] + currentrun.len-- + if (QDELETED(M) || !istype(M) || !M.mind || !M.client) + continue + + // Try and detect job and department of mob + var/datum/job/J = detect_job(M) + if(!istype(J) || !J.department || !J.timeoff_factor) + if (MC_TICK_CHECK) + return + continue + + // Update client whatever + var/client/C = M.client + var/wait_in_hours = (wait / (1 HOUR)) * J.timeoff_factor + LAZYINITLIST(C.department_hours) + if(isnum(C.department_hours[J.department])) + C.department_hours[J.department] += wait_in_hours + else + C.department_hours[J.department] = wait_in_hours + + // Okay we figured it out, lets update database! + var/sql_ckey = sql_sanitize_text(C.ckey) + var/sql_dpt = sql_sanitize_text(J.department) + var/sql_bal = text2num("[C.department_hours[J.department]]") + var/DBQuery/query = dbcon.NewQuery("INSERT INTO vr_player_hours (ckey, department, hours) VALUES ('[sql_ckey]', '[sql_dpt]', [sql_bal]) ON DUPLICATE KEY UPDATE hours = VALUES(hours)") + query.Execute() + + if (MC_TICK_CHECK) + return + +// This proc tries to find the job datum of an arbitrary mob. +/datum/controller/subsystem/persist/proc/detect_job(var/mob/M) + // Records are usually the most reliable way to get what job someone is. + var/datum/data/record/R = find_general_record("name", M.real_name) + if(R) // We found someone with a record. + var/recorded_rank = R.fields["real_rank"] + if(recorded_rank) + . = job_master.GetJob(recorded_rank) + if(.) return + + // They have a custom title, aren't crew, or someone deleted their record, so we need a fallback method. + // Let's check the mind. + if(M.mind && M.mind.assigned_role) + . = job_master.GetJob(M.mind.assigned_role) diff --git a/code/game/jobs/job/job_vr.dm b/code/game/jobs/job/job_vr.dm index d1bb79e7cc3..71cb74a950a 100644 --- a/code/game/jobs/job/job_vr.dm +++ b/code/game/jobs/job/job_vr.dm @@ -3,4 +3,11 @@ var/whitelist_only = 0 //Does not display this job on the occupation setup screen - var/latejoin_only = 0 \ No newline at end of file + var/latejoin_only = 0 + + //Every hour playing this role gains this much time off. (Can be negative for off duty jobs!) + var/timeoff_factor = 3 + +// Check client-specific availability rules. +/datum/job/proc/player_has_enough_pto(client/C) + return timeoff_factor >= 0 || (C && LAZYACCESS(C.department_hours, department) > 0) diff --git a/code/game/jobs/job/offduty_vr.dm b/code/game/jobs/job/offduty_vr.dm new file mode 100644 index 00000000000..cd287716d26 --- /dev/null +++ b/code/game/jobs/job/offduty_vr.dm @@ -0,0 +1,81 @@ +// +// "Off-duty" jobs are for people who want to do nothing and have earned it. +// + +/datum/job/offduty_civilian + title = "Off-Duty Worker" + latejoin_only = TRUE + timeoff_factor = -1 + total_positions = -1 + faction = "Station" + department = "Civilian" + supervisors = "the quartermaster and the head of personnel" + selection_color = "#9b633e" + access = list(access_maint_tunnels) + minimal_access = list(access_maint_tunnels) + outfit_type = /decl/hierarchy/outfit/costume/cowboy + +/datum/job/offduty_cargo + title = "Off-duty Cargo" + latejoin_only = TRUE + timeoff_factor = -1 + total_positions = -1 + faction = "Station" + department = "Cargo" + supervisors = "the quartermaster and the head of personnel" + selection_color = "#9b633e" + access = list(access_maint_tunnels) + minimal_access = list(access_maint_tunnels) + outfit_type = /decl/hierarchy/outfit/costume/cowboy + +/datum/job/offduty_engineering + title = "Off-duty Engineer" + latejoin_only = TRUE + timeoff_factor = -1 + total_positions = -1 + faction = "Station" + department = "Engineering" + supervisors = "the chief engineer" + selection_color = "#5B4D20" + access = list(access_maint_tunnels, access_external_airlocks, access_construction) + minimal_access = list(access_maint_tunnels, access_external_airlocks) + outfit_type = /decl/hierarchy/outfit/costume/cowboy + +/datum/job/offduty_medical + title = "Off-duty Medic" + latejoin_only = TRUE + timeoff_factor = -1 + total_positions = -1 + faction = "Station" + department = "Medical" + supervisors = "the chief medical officer" + selection_color = "#013D3B" + access = list(access_maint_tunnels, access_external_airlocks) + minimal_access = list(access_maint_tunnels, access_external_airlocks) + outfit_type = /decl/hierarchy/outfit/costume/cowboy + +/datum/job/offduty_science + title = "Off-duty Scientist" + latejoin_only = TRUE + timeoff_factor = -1 + total_positions = -1 + faction = "Station" + department = "Science" + supervisors = "the research director" + selection_color = "#633D63" + access = list(access_maint_tunnels) + minimal_access = list(access_maint_tunnels) + outfit_type = /decl/hierarchy/outfit/costume/cowboy + +/datum/job/offduty_security + title = "Off-duty Officer" + latejoin_only = TRUE + timeoff_factor = -1 + total_positions = -1 + faction = "Station" + department = "Security" + supervisors = "the head of security" + selection_color = "#601C1C" + access = list(access_maint_tunnels) + minimal_access = list(access_maint_tunnels) + outfit_type = /decl/hierarchy/outfit/costume/cowboy diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm index e4c5a10d356..3dc5642a81a 100644 --- a/code/modules/client/client defines.dm +++ b/code/modules/client/client defines.dm @@ -48,8 +48,8 @@ var/player_age = "Requires database" //So admins know why it isn't working - Used to determine how old the account is - in days. var/related_accounts_ip = "Requires database" //So admins know why it isn't working - Used to determine what other accounts previously logged in from this ip var/related_accounts_cid = "Requires database" //So admins know why it isn't working - Used to determine what other accounts previously logged in from this computer id + var/list/department_hours // VOREStation Edit - Track hours of leave accured for each department. preload_rsc = PRELOAD_RSC var/global/obj/screen/click_catcher/void - diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 012a74ef6c4..488c827eda5 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -258,6 +258,14 @@ qdel(src) return 0 + // VOREStation Edit Start - Department Hours + var/DBQuery/query_hours = dbcon.NewQuery("SELECT department, hours FROM vr_player_hours WHERE ckey = '[sql_ckey]'") + query_hours.Execute() + while(query_hours.NextRow()) + LAZYINITLIST(department_hours) + department_hours[query_hours.item[1]] = text2num(query_hours.item[2]) + // VOREStation Edit End - Department Hours + if(sql_id) //Player already identified previously, we need to just update the 'lastseen', 'ip' and 'computer_id' variables var/DBQuery/query_update = dbcon.NewQuery("UPDATE erro_player SET lastseen = Now(), ip = '[sql_ip]', computerid = '[sql_computerid]', lastadminrank = '[sql_admin_rank]' WHERE id = [sql_id]") diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 9b8a9aa4577..1cdb98eaa78 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -318,6 +318,7 @@ if(jobban_isbanned(src,rank)) return 0 if(!job.player_old_enough(src.client)) return 0 if(!is_job_whitelisted(src,rank)) return 0 //VOREStation Code + if(!job.player_has_enough_pto(src.client)) return 0 //VOREStation Code return 1 diff --git a/vorestation.dme b/vorestation.dme index ac98718777d..6ea6cf7276b 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -202,6 +202,7 @@ #include "code\controllers\subsystems\mapping_vr.dm" #include "code\controllers\subsystems\mobs.dm" #include "code\controllers\subsystems\orbits.dm" +#include "code\controllers\subsystems\persist_vr.dm" #include "code\controllers\subsystems\transcore_vr.dm" #include "code\datums\ai_law_sets.dm" #include "code\datums\ai_laws.dm" @@ -612,6 +613,7 @@ #include "code\game\jobs\job\job.dm" #include "code\game\jobs\job\job_vr.dm" #include "code\game\jobs\job\medical.dm" +#include "code\game\jobs\job\offduty_vr.dm" #include "code\game\jobs\job\science.dm" #include "code\game\jobs\job\security.dm" #include "code\game\jobs\job\silicon.dm"