Skip to content

Commit

Permalink
Adds tracking amount of time spent playing departments 2: The fall of…
Browse files Browse the repository at this point in the history
… the Assistants. (tgstation#29105)

* Ports Paradise Job exp system

* changed to use json_decode and json_encode as recommended by oranges

* updates changelog

* Reee cyberboss

* Changes to use a seperate table

* Updates database changelog
Changes to use mediumint

* Back to wip we go.
Changes sql stuff to how mso suggested
Attempts the changes requested in the other pr.

* work on stuff.

* work on stuff.

* Renamed proc for time remaining.
Fixed updating time amounts.
Added delay to fix firing at roundstart

* exp is now stored in a global list, and only updated to the db at round end.

* some stuff

* Added button to toggle exempt status on a player.
Still need to make it update the db

* REEE Jordie.
Undoes delaying exp updating to round end.
Adds the updating filtering to the update_exp_client proc which is used again

* Lowers a bunch of the times needed.

* Makes tracking per job instead of per department.
Department time is now calculated from job time.

* Whoops forgot to update master first. Lemme save this

Reverb should play cheeki breeki to people

* I think I did this right.
Too tired to test atm.
Busy rewatching twintails ni narimasu

* Removes var from proc arguments
Fixes database stuff

* Does some requested changes.
Makes special_role be tracked instead of bundled under special.

* Done, but need to refactor how it handles ghost roles.

* Less false data wew

* Changes

* Updates db version
More changes

* More changes

* More changes

* revision fix

* OOPS

* fix schemas

* Makes SQL error logging handled by Execute
Gang role tracking now strips out the gang name and is generic.
  • Loading branch information
Shadowlight213 authored and optimumtact committed Aug 20, 2017
1 parent b6902b4 commit e458845
Show file tree
Hide file tree
Showing 28 changed files with 558 additions and 8 deletions.
17 changes: 15 additions & 2 deletions SQL/database_changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@

20th July 2017, by Shadowlight213
Added role_time table to track time spent playing departments.
Also, added flags column to the player table.

CREATE TABLE `role_time` ( `ckey` VARCHAR(32) NOT NULL , `job` VARCHAR(128) NOT NULL , `minutes` INT UNSIGNED NOT NULL, PRIMARY KEY (`ckey`, `job`) ) ENGINE = InnoDB;

ALTER TABLE `player` ADD `flags` INT NOT NULL default '0' AFTER `accountjoindate`;

UPDATE `schema_revision` SET minor = 1;

Remember to add a prefix to the table name if you use them.

----------------------------------------------------

Any time you make a change to the schema files, remember to increment the database schema version. Generally increment the minor number, major should be reserved for significant changes to the schema. Both values go up to 255.

The latest database version is 3.0; The query to update the schema revision table is:
Expand All @@ -7,7 +22,6 @@ or
INSERT INTO `SS13_schema_revision` (`major`, `minor`) VALUES (3, 0);

----------------------------------------------------

28 June 2017, by oranges
Added schema_revision to store the current db revision, why start at 3.0?

Expand Down Expand Up @@ -112,7 +126,6 @@ ALTER TABLE `player` DROP COLUMN `id`, ADD COLUMN `accountjoindate` DATE NULL AF
Remember to add a prefix to the table name if you use them.

----------------------------------------------------

10 March 2017, by Jordie0608

Modified table 'death', adding the columns 'toxloss', 'cloneloss', and 'staminaloss' and table 'legacy_population', adding the columns 'server_ip' and 'server_port'.
Expand Down
16 changes: 16 additions & 0 deletions SQL/tgstation_schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,21 @@ CREATE TABLE `messages` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Table structure for table `role_time`
--

DROP TABLE IF EXISTS `role_time`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;

CREATE TABLE `role_time`
( `ckey` VARCHAR(32) NOT NULL ,
`job` VARCHAR(32) NOT NULL ,
`minutes` INT UNSIGNED NOT NULL,
PRIMARY KEY (`ckey`, `job`)
) ENGINE = InnoDB;

--
-- Table structure for table `player`
--
Expand All @@ -268,6 +283,7 @@ CREATE TABLE `player` (
`computerid` varchar(32) NOT NULL,
`lastadminrank` varchar(32) NOT NULL DEFAULT 'Player',
`accountjoindate` DATE DEFAULT NULL,
`flags` smallint(5) unsigned DEFAULT '0' NOT NULL,
PRIMARY KEY (`ckey`),
KEY `idx_player_cid_ckey` (`computerid`,`ckey`),
KEY `idx_player_ip_ckey` (`ip`,`ckey`)
Expand Down
16 changes: 16 additions & 0 deletions SQL/tgstation_schema_prefixed.sql
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,21 @@ CREATE TABLE `SS13_messages` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Table structure for table `SS13_role_time`
--

DROP TABLE IF EXISTS `SS13_role_time`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;

CREATE TABLE `SS13_role_time`
( `ckey` VARCHAR(32) NOT NULL ,
`job` VARCHAR(32) NOT NULL ,
`minutes` INT UNSIGNED NOT NULL,
PRIMARY KEY (`ckey`, `job`)
) ENGINE = InnoDB;

--
-- Table structure for table `SS13_player`
--
Expand All @@ -268,6 +283,7 @@ CREATE TABLE `SS13_player` (
`computerid` varchar(32) NOT NULL,
`lastadminrank` varchar(32) NOT NULL DEFAULT 'Player',
`accountjoindate` DATE DEFAULT NULL,
`flags` smallint(5) unsigned DEFAULT '0' NOT NULL,
PRIMARY KEY (`ckey`),
KEY `idx_player_cid_ckey` (`computerid`,`ckey`),
KEY `idx_player_ip_ckey` (`ip`,`ckey`)
Expand Down
20 changes: 19 additions & 1 deletion code/__DEFINES/preferences.dm
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,22 @@
#define SEC_DEPT_ENGINEERING "Engineering"
#define SEC_DEPT_MEDICAL "Medical"
#define SEC_DEPT_SCIENCE "Science"
#define SEC_DEPT_SUPPLY "Supply"
#define SEC_DEPT_SUPPLY "Supply"

// 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_ANTAG "Antag"
#define EXP_TYPE_SPECIAL "Special"
#define EXP_TYPE_GHOST "Ghost"

//Flags in the players table in the db
#define DB_FLAG_EXEMPT 1
2 changes: 1 addition & 1 deletion code/_compile_options.dm
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,4 @@
//Update this whenever the db schema changes
//make sure you add an update to the schema_version stable in the db changelog
#define DB_MAJOR_VERSION 3
#define DB_MINOR_VERSION 0
#define DB_MINOR_VERSION 1
19 changes: 19 additions & 0 deletions code/controllers/configuration.dm
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@
var/use_account_age_for_jobs = 0 //Uses the time they made the account for the job restriction stuff. New player joining alerts should be unaffected.
var/see_own_notes = 0 //Can players see their own admin notes (read-only)? Config option in config.txt

var/use_exp_tracking = FALSE
var/use_exp_restrictions_heads = FALSE
var/use_exp_restrictions_heads_hours = 0
var/use_exp_restrictions_heads_department = FALSE
var/use_exp_restrictions_other = FALSE
var/use_exp_restrictions_admin_bypass = FALSE

//Population cap vars
var/soft_popcap = 0
var/hard_popcap = 0
Expand Down Expand Up @@ -335,6 +342,18 @@
use_age_restriction_for_jobs = 1
if("use_account_age_for_jobs")
use_account_age_for_jobs = 1
if("use_exp_tracking")
use_exp_tracking = TRUE
if("use_exp_restrictions_heads")
use_exp_restrictions_heads = TRUE
if("use_exp_restrictions_heads_hours")
use_exp_restrictions_heads_hours = text2num(value)
if("use_exp_restrictions_heads_department")
use_exp_restrictions_heads_department = TRUE
if("use_exp_restrictions_other")
use_exp_restrictions_other = TRUE
if("use_exp_restrictions_admin_bypass")
use_exp_restrictions_admin_bypass = TRUE
if("lobby_countdown")
lobby_countdown = text2num(value)
if("round_end_countdown")
Expand Down
14 changes: 12 additions & 2 deletions code/controllers/subsystem/blackbox.dm
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
SUBSYSTEM_DEF(blackbox)
name = "Blackbox"
wait = 6000
flags = SS_NO_TICK_CHECK | SS_NO_INIT
flags = SS_NO_TICK_CHECK
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
init_order = INIT_ORDER_BLACKBOX

Expand All @@ -18,9 +18,14 @@ SUBSYSTEM_DEF(blackbox)
var/list/msg_other = list()

var/list/feedback = list() //list of datum/feedback_variable

var/triggertime = 0
var/sealed = FALSE //time to stop tracking stats?


/datum/controller/subsystem/blackbox/Initialize()
triggertime = world.time
. = ..()

//poll population
/datum/controller/subsystem/blackbox/fire()
if(!SSdbcore.Connect())
Expand All @@ -33,6 +38,11 @@ SUBSYSTEM_DEF(blackbox)
var/datum/DBQuery/query_record_playercount = SSdbcore.NewQuery("INSERT INTO [format_table_name("legacy_population")] (playercount, admincount, time, server_ip, server_port) VALUES ([playercount], [admincount], '[SQLtime()]', INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]')")
query_record_playercount.Execute()

if(config.use_exp_tracking)
if((triggertime < 0) || (world.time > (triggertime +3000))) //subsystem fires once at roundstart then once every 10 minutes. a 5 min check skips the first fire. The <0 is midnight rollover check
update_exp(10,FALSE)


/datum/controller/subsystem/blackbox/Recover()
msg_common = SSblackbox.msg_common
msg_science = SSblackbox.msg_science
Expand Down
16 changes: 16 additions & 0 deletions code/controllers/subsystem/job.dm
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ SUBSYSTEM_DEF(job)
return 0
if(!job.player_old_enough(player.client))
return 0
if(job.required_playtime_remaining(player.client))
return 0
var/position_limit = job.total_positions
if(!latejoin)
position_limit = job.spawn_positions
Expand All @@ -95,6 +97,9 @@ SUBSYSTEM_DEF(job)
if(!job.player_old_enough(player.client))
Debug("FOC player not old enough, Player: [player]")
continue
if(job.required_playtime_remaining(player.client))
Debug("FOC player not enough xp, Player: [player]")
continue
if(flag && (!(flag in player.client.prefs.be_special)))
Debug("FOC flag failed, Player: [player], Flag: [flag], ")
continue
Expand Down Expand Up @@ -130,6 +135,10 @@ SUBSYSTEM_DEF(job)
Debug("GRJ player not old enough, Player: [player]")
continue

if(job.required_playtime_remaining(player.client))
Debug("GRJ player not enough xp, Player: [player]")
continue

if(player.mind && job.title in player.mind.restricted_roles)
Debug("GRJ incompatible with antagonist role, Player: [player], Job: [job.title]")
continue
Expand Down Expand Up @@ -300,6 +309,10 @@ SUBSYSTEM_DEF(job)
Debug("DO player not old enough, Player: [player], Job:[job.title]")
continue

if(job.required_playtime_remaining(player.client))
Debug("DO player not enough xp, Player: [player], Job:[job.title]")
continue

if(player.mind && job.title in player.mind.restricted_roles)
Debug("DO incompatible with antagonist role, Player: [player], Job:[job.title]")
continue
Expand Down Expand Up @@ -463,6 +476,9 @@ SUBSYSTEM_DEF(job)
if(!job.player_old_enough(player.client))
level6++
continue
if(job.required_playtime_remaining(player.client))
level6++
continue
if(player.client.prefs.GetJobDepartment(job, 1) & job.flag)
level1++
else if(player.client.prefs.GetJobDepartment(job, 2) & job.flag)
Expand Down
3 changes: 2 additions & 1 deletion code/datums/mind.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1458,6 +1458,7 @@
if(!(src in SSticker.mode.syndicates))
SSticker.mode.syndicates += src
SSticker.mode.update_synd_icons_added(src)
assigned_role = "Syndicate"
special_role = "Syndicate"
SSticker.mode.forge_syndicate_objectives(src)
SSticker.mode.greet_syndicate(src)
Expand Down Expand Up @@ -1705,7 +1706,7 @@
/mob/living/carbon/human/mind_initialize()
..()
if(!mind.assigned_role)
mind.assigned_role = "Assistant" //defualt
mind.assigned_role = "Unassigned" //default

//XENO
/mob/living/carbon/alien/mind_initialize()
Expand Down
1 change: 1 addition & 0 deletions code/game/gamemodes/antag_spawner.dm
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
new_objective.explanation_text = "Protect [usr.real_name], the wizard."
M.mind.objectives += new_objective
SSticker.mode.apprentices += M.mind
M.mind.assigned_role = "Apprentice"
M.mind.special_role = "apprentice"
SSticker.mode.update_wiz_icons_added(M.mind)
SEND_SOUND(M, sound('sound/effects/magic.ogg'))
Expand Down
2 changes: 2 additions & 0 deletions code/modules/admin/admin.dm
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
if(M.client)
body += " played by <b>[M.client]</b> "
body += "\[<A href='?_src_=holder;editrights=rank;ckey=[M.ckey]'>[M.client.holder ? M.client.holder.rank : "Player"]</A>\]"
if(config.use_exp_tracking)
body += "\[<A href='?_src_=holder;getplaytimewindow=\ref[M]'>" + M.client.get_exp_living() + "</a>\]"

if(isnewplayer(M))
body += " <B>Hasn't Entered Game</B> "
Expand Down
1 change: 1 addition & 0 deletions code/modules/admin/admin_verbs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin())
/client/proc/cmd_admin_local_narrate, /*sends text to all mobs within view of atom*/
/client/proc/cmd_admin_create_centcom_report,
/client/proc/cmd_change_command_name,
/client/proc/cmd_admin_check_player_exp, /* shows players by playtime */
/client/proc/toggle_antag_hud, /*toggle display of the admin antag hud*/
/client/proc/toggle_AI_interact, /*toggle admin ability to interact with machines as an AI*/
/client/proc/customiseSNPC, /* Customise any interactive crewmembers in the world */
Expand Down
18 changes: 18 additions & 0 deletions code/modules/admin/topic.dm
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,24 @@
else if(href_list["stickyban"])
stickyban(href_list["stickyban"],href_list)

else if(href_list["getplaytimewindow"])
if(!check_rights(R_ADMIN))
return
var/mob/M = locate(href_list["getplaytimewindow"]) in GLOB.mob_list
if(!M)
to_chat(usr, "<span class='danger'>ERROR: Mob not found.</span>")
return
cmd_show_exp_panel(M.client)

else if(href_list["toggleexempt"])
if(!check_rights(R_ADMIN))
return
var/client/C = locate(href_list["toggleexempt"]) in GLOB.clients
if(!C)
to_chat(usr, "<span class='danger'>ERROR: Client not found.</span>")
return
toggle_exempt_status(C)

else if(href_list["makeAntag"])
if (!SSticker.mode)
to_chat(usr, "<span class='danger'>Not until the round starts!</span>")
Expand Down
49 changes: 49 additions & 0 deletions code/modules/admin/verbs/randomverbs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1211,3 +1211,52 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
message_admins("[key_name_admin(usr)] triggered a CentCom recall, with the admiral message of: [message]")
log_game("[key_name(usr)] triggered a CentCom recall, with the message of: [message]")
SSshuttle.centcom_recall(SSshuttle.emergency.timer, message)

/client/proc/cmd_admin_check_player_exp() //Allows admins to determine who the newer players are.
set category = "Admin"
set name = "Check Player Playtime"
if(!check_rights(R_ADMIN))
return

var/list/msg = list()
msg += "<html><head><title>Playtime Report</title></head><body>Playtime:<BR><UL>"
for(var/client/C in GLOB.clients)
msg += "<LI> - [key_name_admin(C)]: <A href='?_src_=holder;getplaytimewindow=\ref[C.mob]'>" + C.get_exp_living() + "</a></LI>"
msg += "</UL></BODY></HTML>"
src << browse(msg.Join(), "window=Player_playtime_check")

/datum/admins/proc/cmd_show_exp_panel(client/C)
if(!check_rights(R_ADMIN))
return
if(!C)
to_chat(usr, "<span class='danger'>ERROR: Client not found.</span>")
return

var/list/body = list()
body += "<html><head><title>Playtime for [C.key]</title></head><BODY><BR>Playtime:"
body += C.get_exp_report()
body += "<A href='?_src_=holder;toggleexempt=\ref[C]'>Toggle Exempt status</a>"
body += "</BODY></HTML>"
usr << browse(body.Join(), "window=playerplaytime[C.ckey];size=550x615")

/datum/admins/proc/toggle_exempt_status(client/C)
if(!check_rights(R_ADMIN))
return
if(!C)
to_chat(usr, "<span class='danger'>ERROR: Client not found.</span>")
return

if(!C.set_db_player_flags())
to_chat(usr, "<span class='danger'>ERROR: Unable read player flags from database. Please check logs.</span>")
var/dbflags = C.prefs.db_flags
var/newstate = FALSE
if(dbflags & DB_FLAG_EXEMPT)
newstate = FALSE
else
newstate = TRUE

if(C.update_flag_db(DB_FLAG_EXEMPT, newstate))
to_chat(usr, "<span class='danger'>ERROR: Unable to update player flags. Please check logs.</span>")
else
message_admins("[key_name_admin(usr)] has [newstate ? "activated" : "deactivated"] job exp exempt status on [key_name_admin(C)]")
log_admin("[key_name(usr)] has [newstate ? "activated" : "deactivated"] job exp exempt status on [key_name(C)]")
Loading

0 comments on commit e458845

Please sign in to comment.