Skip to content

Commit

Permalink
Timelocks and time tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
Watermelon914 authored and Neth Iafin committed Sep 21, 2020
1 parent 338239f commit b875896
Show file tree
Hide file tree
Showing 17 changed files with 147 additions and 56 deletions.
3 changes: 2 additions & 1 deletion #preprocessor/define/job.dm
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,5 @@ var/global/list/JOB_COMMAND_ROLES_LIST = list(JOB_CO, JOB_XO, JOB_SO)
//antag jobs supported by adaptive antag vendors
#define VENDOR_ANTAG_JOBS list(JOB_UPP, JOB_UPP_ENGI, JOB_UPP_MEDIC, JOB_UPP_SPECIALIST, JOB_UPP_LEADER, JOB_CLF, JOB_CLF_ENGI, JOB_CLF_MEDIC, JOB_CLF_SPECIALIST, JOB_CLF_LEADER)

#define JOB_PREDATOR "Predator"
#define JOB_PREDATOR "Predator"
#define JOB_XENOMORPH "Xenomorph"
2 changes: 2 additions & 0 deletions #preprocessor/define/subsystem.dm
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#define SS_INIT_ADMIN -24
#define SS_INIT_DATABASE -25
#define SS_INIT_ENTITYMANAGER -26
#define SS_INIT_PLAYTIME -27
#define SS_INIT_CORPSESPAWNER -30


Expand Down Expand Up @@ -76,6 +77,7 @@
#define SS_PRIORITY_TRACKING 19
#define SS_PRIORITY_PING 10
#define SS_PRIORITY_DATABASE 15
#define SS_PRIORITY_PLAYTIME 5
#define SS_PRIORITY_PERFLOGGING 4
#define SS_PRIORITY_CORPSESPAWNER 3
#define SS_PRIORITY_GARBAGE 2
Expand Down
2 changes: 2 additions & 0 deletions ColonialMarinesALPHA.dme
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@
#include "code\controllers\subsystem\objects.dm"
#include "code\controllers\subsystem\perf_logging.dm"
#include "code\controllers\subsystem\ping.dm"
#include "code\controllers\subsystem\playtime.dm"
#include "code\controllers\subsystem\police_clues.dm"
#include "code\controllers\subsystem\power.dm"
#include "code\controllers\subsystem\quadtrees.dm"
Expand Down Expand Up @@ -327,6 +328,7 @@
#include "code\datums\entities\player.dm"
#include "code\datums\entities\player_job_ban.dm"
#include "code\datums\entities\player_note.dm"
#include "code\datums\entities\player_times.dm"
#include "code\datums\entities\vending_stat.dm"
#include "code\datums\event_system\args.dm"
#include "code\datums\event_system\datum_events.dm"
Expand Down
46 changes: 46 additions & 0 deletions code/controllers/subsystem/playtime.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
var/datum/subsystem/playtime/SSplaytime


/datum/subsystem/playtime
name = "Playtime"
wait = 1 MINUTES
priority = SS_PRIORITY_PLAYTIME
init_order = SS_INIT_PLAYTIME
flags = SS_NO_INIT | SS_KEEP_TIMING

var/list/currentrun = list()

/datum/subsystem/playtime/New()
NEW_SS_GLOBAL(SSplaytime)

/datum/subsystem/playtime/fire(resumed = FALSE)
if (!resumed)
src.currentrun = clients.Copy()

var/list/currentrun = src.currentrun

while (currentrun.len)
var/client/C = currentrun[currentrun.len]
currentrun.len--

var/mob/M = C.mob
var/datum/entity/player/P = C.player_data

if(!M || !M.job || M.stat == DEAD || M.statistic_exempt || !P || !P.playtime_loaded)
if(MC_TICK_CHECK)
return
continue

var/datum/entity/player_time/PTime = LAZYACCESS(P.playtimes, M.job)

if(!PTime)
PTime = DB_ENTITY(/datum/entity/player_time)
PTime.player_id = P.id
PTime.role_id = M.job
LAZYSET(P.playtimes, M.job, PTime)

PTime.total_minutes += 1
PTime.save()

if (MC_TICK_CHECK)
return
13 changes: 13 additions & 0 deletions code/datums/entities/player.dm
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
var/refs_loaded = FALSE
var/notes_loaded = FALSE
var/jobbans_loaded = FALSE
var/playtime_loaded = FALSE
var/migrating_notes = FALSE
var/migrating_bans = FALSE
var/migrating_jobbans = FALSE
Expand All @@ -36,6 +37,7 @@
var/datum/entity/player/time_ban_admin
var/list/datum/entity/player_note/notes
var/list/datum/entity/player_job_ban/job_bans
var/list/datum/entity/player_time/playtimes
var/client/owning_client

BSQL_PROTECT_DATUM(/datum/entity/player)
Expand Down Expand Up @@ -318,6 +320,8 @@ BSQL_PROTECT_DATUM(/datum/entity/player)
player.notes = list()
player.notes_loaded = FALSE
player.jobbans_loaded = FALSE
player.playtime_loaded = FALSE

player.is_permabanned = text2num(player.is_permabanned)
player.is_time_banned = text2num(player.is_time_banned)
player.time_ban_expiration = text2num(player.time_ban_expiration)
Expand All @@ -335,6 +339,7 @@ BSQL_PROTECT_DATUM(/datum/entity/player)
player.notes = list()
player.notes_loaded = FALSE
player.jobbans_loaded = FALSE
player.playtime_loaded = FALSE

player.load_rels()

Expand All @@ -351,6 +356,8 @@ BSQL_PROTECT_DATUM(/datum/entity/player)
migrating_jobbans = TRUE
INVOKE_ASYNC(src, /datum/entity/player.proc/migrate_jobbans)

DB_FILTER(/datum/entity/player_time, DB_COMP("player_id", DB_EQUALS, id), CALLBACK(src, /datum/entity/player.proc/on_read_timestat))

if(!migrated_bans && !migrating_bans)
migrating_bans = TRUE
INVOKE_ASYNC(src, /datum/entity/player.proc/migrate_bans)
Expand All @@ -376,6 +383,12 @@ BSQL_PROTECT_DATUM(/datum/entity/player)

auto_unjobban()

/datum/entity/player/proc/on_read_timestat(var/list/datum/entity/player_time/_stat)
playtime_loaded = TRUE
if(_stat)
for(var/datum/entity/player_time/S in _stat)
LAZYSET(playtimes, S.role_id, S)

/proc/get_player_from_key(key)
var/safe_key = ckey(key)
if(!safe_key)
Expand Down
30 changes: 30 additions & 0 deletions code/datums/entities/player_times.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/datum/entity/player_time
var/player_id
var/role_id
var/total_minutes

BSQL_PROTECT_DATUM(/datum/entity/player_time)

/datum/entity_meta/player_time
entity_type = /datum/entity/player_time
table_name = "player_playtime"
field_types = list(
"player_id" = DB_FIELDTYPE_BIGINT,
"role_id" = DB_FIELDTYPE_STRING_LARGE,
"total_minutes" = DB_FIELDTYPE_BIGINT
)

/datum/entity_meta/player_time/on_insert(var/datum/entity/player_time/player)
player.total_minutes = 0

/datum/entity_link/player_to_time
parent_entity = /datum/entity/player
child_entity = /datum/entity/player_time
child_field = "player_id"

parent_name = "player"
child_name = "player_times"

#define MINUTES_TO_DECISECOND *600 // Converting to decisecond makes it easier to do in calculations

#define get_job_playtime(client, job) (client.player_data? LAZYACCESS(client.player_data.playtimes, job)? client.player_data.playtimes[job].total_minutes MINUTES_TO_DECISECOND : 0 : 0)
6 changes: 3 additions & 3 deletions code/game/gamemodes/gameticker.dm
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,9 @@ var/global/datum/controller/gameticker/ticker = new()
if(player.job)
RoleAuthority.equip_role(player, RoleAuthority.roles_by_name[player.job])
EquipCustomItems(player)
if(player.mind.player_entity)
var/datum/entity/player_entity/PE = player.mind.player_entity
if(PE.get_playtime(STATISTIC_HUMAN) == 0 && PE.get_playtime(STATISTIC_XENO) == 0)
if(player.client)
var/client/C = player.client
if(C.player_data && C.player_data.playtime_loaded && length(C.player_data.playtimes) == 0)
msg_admin_niche("NEW PLAYER: <b>[key_name(player, 1, 1, 0)] (<A HREF='?_src_=admin_holder;ahelp=adminmoreinfo;extra=\ref[player]'>?</A>)</b>. IP: [player.lastKnownIP], CID: [player.computer_id]")
if(captainless)
for(var/mob/M in player_list)
Expand Down
28 changes: 20 additions & 8 deletions code/game/jobs/job/job.dm
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
JOB_SQUAD_ROLES = HOURS_3
)

var/minimum_playtime_as_job = HOURS_3

var/gear_preset //Gear preset name used for this job
var/list/gear_preset_whitelist = list()//Gear preset name used for council snowflakes ;)

Expand All @@ -44,20 +46,30 @@
/datum/job/proc/can_play_role(var/client/client)
if(!config.use_timelocks)
return TRUE
var/datum/entity/player_entity/selected_entity = client.player_entity
if(!minimum_playtimes.len || (client.admin_holder && (client.admin_holder.rights & R_ADMIN)) || selected_entity.get_playtime(STATISTIC_HUMAN, title) > 0)

if((client.admin_holder && (client.admin_holder.rights & R_ADMIN)))
return TRUE

if(get_job_playtime(client, title) > minimum_playtime_as_job)
return TRUE

for(var/prereq in minimum_playtimes)
if(selected_entity.get_playtime(STATISTIC_HUMAN, prereq) < minimum_playtimes[prereq])
return FALSE
if(islist(prereq))
for(var/prequisite_only_one in prereq)
if(get_job_playtime(client, prequisite_only_one) >= LAZYACCESS(prereq, prequisite_only_one))
return TRUE
else
if(get_job_playtime(client, prereq) < LAZYACCESS(minimum_playtimes, prereq))
return FALSE

return TRUE

/datum/job/proc/get_role_requirements(var/datum/entity/player_entity/selected_entity)
/datum/job/proc/get_role_requirements(var/client/C)
var/list/return_requirements = list()
for(var/prereq in minimum_playtimes)
var/playtime = selected_entity.get_playtime(STATISTIC_HUMAN, prereq)
if(playtime < minimum_playtimes[prereq])
return_requirements[prereq] = minimum_playtimes[prereq] - playtime
var/playtime = get_job_playtime(C, title)
if(playtime < LAZYACCESS(minimum_playtimes, prereq))
return_requirements[prereq] = LAZYACCESS(minimum_playtimes, prereq) - playtime
return return_requirements

/datum/job/proc/get_access()
Expand Down
2 changes: 1 addition & 1 deletion code/game/jobs/whitelist.dm
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ var/list/whitelist = list()
return TRUE
if(job == CASTE_QUEEN)
var/datum/caste_datum/C = RoleAuthority.castes_by_name[CASTE_QUEEN]
return C.can_play_caste(client, CASTE_QUEEN)
return C.can_play_caste(client)
if(job == JOB_SURVIVOR)
var/datum/job/J = RoleAuthority.roles_by_path[/datum/job/civilian/survivor]
return J.can_play_role(client)
Expand Down
4 changes: 2 additions & 2 deletions code/modules/admin/verbs/select_equipment.dm
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,10 @@
//a rank that matches a job title unless you want the human to bypass the skill system.
/proc/arm_equipment(var/mob/living/carbon/human/M, var/dresscode, var/randomise = FALSE, var/count_participant = FALSE)
if(!gear_presets_list)
error("arm_equipment !gear_presets_list")
CRASH("arm_equipment !gear_presets_list")
return
if(!gear_presets_list[dresscode])
error("arm_equipment !gear_presets_list[dresscode]")
CRASH("arm_equipment !gear_presets_list[dresscode]")
return
gear_presets_list[dresscode].load_preset(M, randomise, count_participant)
return
15 changes: 7 additions & 8 deletions code/modules/client/preferences.dm
Original file line number Diff line number Diff line change
Expand Up @@ -264,13 +264,14 @@ var/const/MAX_SAVE_SLOTS = 10
if("Xenomorph Queen")
ban_check_name = "Queen"
var/datum/caste_datum/C = RoleAuthority.castes_by_name[CASTE_QUEEN]
missing_requirements = C.get_caste_requirements(user.client)

LAZYSET(missing_requirements, JOB_XENOMORPH, C.get_caste_requirement(user.client))

if("Survivor")
ban_check_name = "Survivor"
var/datum/entity/player_entity = user.client.player_entity
var/client/C = user.client
var/datum/job/J = RoleAuthority.roles_by_path[/datum/job/civilian/survivor]
missing_requirements = J.get_role_requirements(player_entity)
missing_requirements = J.get_role_requirements(C)

if("Predator")
ban_check_name = "Predator"
Expand Down Expand Up @@ -495,7 +496,7 @@ var/const/MAX_SAVE_SLOTS = 10
HTML += "<b><del>[job.disp_title]</del></b></td><td>WHITELISTED</td></tr>"
continue
else if(!job.can_play_role(user.client))
var/list/missing_requirements = job.get_role_requirements(user.client.player_entity)
var/list/missing_requirements = job.get_role_requirements(user.client)
HTML += "<b><del>[job.disp_title]</del></b></td><td>TIMELOCKED</td></tr>"
for(var/requirement in missing_requirements)
HTML += "<tr class='[job.selection_class]'><td width='40%' align='right'>[requirement]</td><td>[duration2text(missing_requirements[requirement])] Hours</td></tr>"
Expand Down Expand Up @@ -1035,8 +1036,7 @@ var/const/MAX_SAVE_SLOTS = 10
return

if(prefix_length==3)
var/datum/entity/player_entity/selected_entity = user.client.player_entity
var/playtime = selected_entity.get_playtime(STATISTIC_XENO)
var/playtime = get_job_playtime(user.client, JOB_XENOMORPH)
if(playtime < 124 HOURS)
to_chat(user, SPAN_WARNING(FONT_SIZE_BIG("You need to play [Ceiling((124 HOURS - playtime)/HOURS_1)] more hours to unlock xeno three letter prefix.")))
return
Expand Down Expand Up @@ -1065,8 +1065,7 @@ var/const/MAX_SAVE_SLOTS = 10
to_chat(user, SPAN_WARNING(FONT_SIZE_BIG("You are banned from xeno name picking.")))
xeno_postfix = ""
return
var/datum/entity/player_entity/selected_entity = user.client.player_entity
var/playtime = selected_entity.get_playtime(STATISTIC_XENO)
var/playtime = get_job_playtime(user.client, JOB_XENOMORPH)
if(playtime < 24 HOURS)
to_chat(user, SPAN_WARNING(FONT_SIZE_BIG("You need to play [Ceiling((24 HOURS - playtime)/HOURS_1)] more hours to unlock xeno postfix.")))
return
Expand Down
10 changes: 4 additions & 6 deletions code/modules/gear_presets/uscm.dm
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,8 @@
H.equip_to_slot_or_del(new backItem(H), WEAR_BACK)

/datum/equipment_preset/uscm/pfc/load_rank(mob/living/carbon/human/H)
if(H.mind && H.mind.player_entity)
var/datum/entity/player_entity/player = H.mind.player_entity
if(player.get_playtime(STATISTIC_HUMAN, rank) < HOURS_9)
if(H.client)
if(get_job_playtime(H.client, rank) < HOURS_9)
return "E1"
return paygrade

Expand Down Expand Up @@ -367,9 +366,8 @@
skills = /datum/skills/pfc/crafty

/datum/equipment_preset/uscm/private_equipped/load_rank(mob/living/carbon/human/H)
if(H.mind && H.mind.player_entity)
var/datum/entity/player_entity/player = H.mind.player_entity
if(player.get_playtime(STATISTIC_HUMAN, rank) < HOURS_9)
if(H.client)
if(get_job_playtime(H.client, rank) < HOURS_9)
return "E1"
return paygrade

Expand Down
10 changes: 4 additions & 6 deletions code/modules/gear_presets/uscm_ship.dm
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,8 @@
H.equip_to_slot_or_del(new backItem(H), WEAR_BACK)

/datum/equipment_preset/uscm_ship/liaison/load_rank(mob/living/carbon/human/H)
if(H.mind && H.mind.player_entity)
var/datum/entity/player_entity/player = H.mind.player_entity
var/playtime = player.get_playtime(STATISTIC_HUMAN, rank)
if(H.client)
var/playtime = get_job_playtime(H.client, rank)

if(playtime > 64 HOURS)
return "WY-XE"
Expand Down Expand Up @@ -444,9 +443,8 @@
H.hud_set_squad()

/datum/equipment_preset/uscm_ship/sea/load_rank(mob/living/carbon/human/H)
if(H.mind && H.mind.player_entity)
var/datum/entity/player_entity/player = H.mind.player_entity
if(player.get_playtime(STATISTIC_HUMAN, rank) >= HOURS_9)
if(H.client)
if(get_job_playtime(H.client, JOB_SEA) >= HOURS_9)
return "E9"
return paygrade

Expand Down
4 changes: 1 addition & 3 deletions code/modules/mob/living/carbon/xenomorph/Castes/Queen.dm
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@
tacklestrength_min = 5
tacklestrength_max = 6

minimum_playtimes = list(
FACTION_XENOMORPH = HOURS_9
)
minimum_xeno_playtime = 9 HOURS

/proc/update_living_queens() // needed to update when you change a queen to a different hive
outer_loop:
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/living/carbon/xenomorph/Xenomorph.dm
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@
if (hive && hive.hive_ui)
hive.hive_ui.update_all_xeno_data()

job = "Xenomorph"
job = JOB_XENOMORPH

/mob/living/carbon/Xenomorph/initialize_pass_flags(var/datum/pass_flags_container/PF)
..()
Expand Down
Loading

0 comments on commit b875896

Please sign in to comment.