diff --git a/SQL/migrate/V034__better_antag_stats.sql b/SQL/migrate/V034__better_antag_stats.sql
new file mode 100644
index 00000000000..d62e00a41a3
--- /dev/null
+++ b/SQL/migrate/V034__better_antag_stats.sql
@@ -0,0 +1,23 @@
+--
+-- Adds a new table specifically for tracking antagonist assignments
+--
+
+ALTER TABLE `ss13_characters_log`
+ DROP COLUMN `special_role`;
+
+CREATE TABLE `ss13_antag_log` (
+ `id` INT(11) NOT NULL AUTO_INCREMENT,
+ `ckey` VARCHAR(32) NOT NULL,
+ `char_id` INT(11) NULL DEFAULT NULL,
+ `game_id` VARCHAR(50) NOT NULL,
+ `char_name` VARCHAR(50) NOT NULL,
+ `datetime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `special_role_name` VARCHAR(50) NOT NULL,
+ `special_role_added` TIME NOT NULL,
+ `special_role_removed` TIME NULL DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ INDEX `FK_ss13_antag_log_ss13_characters` (`char_id`),
+ CONSTRAINT `FK_ss13_antag_log_ss13_characters` FOREIGN KEY (`char_id`) REFERENCES `ss13_characters` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
+)
+COLLATE='utf8_general_ci'
+ENGINE=InnoDB;
\ No newline at end of file
diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm
index 4815abe27f1..d3a0f0151a6 100644
--- a/code/game/antagonist/antagonist.dm
+++ b/code/game/antagonist/antagonist.dm
@@ -50,6 +50,7 @@
var/bantype = "Syndicate" // Ban to check when spawning this antag.
var/suspicion_chance = 50 // Prob of being on the initial Command report
var/flags = 0 // Various runtime options.
+ var/db_log_id = null // ID of the db entry used to track that antagonist
// Used for setting appearance.
var/list/valid_species = list("Unathi","Tajara","Skrell","Human")
diff --git a/code/game/antagonist/antagonist_add.dm b/code/game/antagonist/antagonist_add.dm
index 26c38f93dd3..6e567886132 100644
--- a/code/game/antagonist/antagonist_add.dm
+++ b/code/game/antagonist/antagonist_add.dm
@@ -48,6 +48,9 @@
if(nonstandard_role_msg)
player.current << "[nonstandard_role_msg]"
update_icons_added(player)
+
+ // Log it
+ log_antagonist_add(player)
return 1
/datum/antagonist/proc/remove_antagonist(var/datum/mind/player, var/show_message = TRUE, var/implanted)
@@ -58,6 +61,7 @@
player.current.verbs -= faction_verb
if(player in current_antagonists)
+ log_antagonist_remove()
if (show_message)
player.current << "You are no longer a [role_text]!"
current_antagonists -= player
@@ -68,10 +72,53 @@
if (!is_special_character(player) && !check_rights(R_ADMIN|R_MOD|R_CCIAA, 0, player.current))
player.current.client.verbs -= /client/proc/aooc
- return 1
if(!is_special_character(player))
player.current.verbs -= /mob/living/proc/write_ambition
player.ambitions = ""
+ return 1
return 0
+
+
+/datum/antagonist/proc/log_antagonist_add(var/datum/mind/player)
+ if(!config.sql_enabled)
+ return
+
+ if(!establish_db_connection(dbcon))
+ log_debug("AntagLog: SQL ERROR - Failed to connect.")
+ return
+
+ //Try to get the char id
+ var/char_id = null
+ if(player.current.character_id) //To make sure char_id is null and not 0
+ char_id = player.current.character_id
+
+ //Run the query to insert the antagonist into the db
+ var/DBQuery/new_log = dbcon.NewQuery("INSERT INTO ss13_antag_log ( ckey, char_id, game_id, char_name, special_role_name, special_role_added) VALUES ( :ckey:, :char_id:, :game_id:, :char_name:, :special_role_name:, :special_role_added:)")
+ new_log.Execute(list("ckey" = ckey(player.key) , "char_id" = char_id, "game_id" = game_id, "char_name" = player.current.name, "special_role_name"=role_text,"special_role_added" = "[get_round_duration_formatted()]:00"))
+
+ //Run the query to get the inserted id
+ var/DBQuery/log_id = dbcon.NewQuery("SELECT LAST_INSERT_ID() AS log_id")
+ log_id.Execute()
+
+ //Save the inserted it to the antagonist datum
+ if (log_id.NextRow())
+ db_log_id = text2num(log_id.item[1])
+
+ return
+
+/datum/antagonist/proc/log_antagonist_remove(var/datum/mind/player)
+ if(!config.sql_enabled)
+ return
+
+ if(!establish_db_connection(dbcon))
+ log_debug("AntagLog: SQL ERROR - Failed to connect.")
+ return
+
+ if(!db_log_id)
+ return
+
+ //Run the query to update the db entry with the removal time
+ var/DBQuery/update_query = dbcon.NewQuery("UPDATE ss13_antag_log SET special_role_removed = :special_role_removed: WHERE id = :id:")
+ update_query.Execute(list("id"=db_log_id,"special_role_removed"="[get_round_duration_formatted()]:00"))
\ No newline at end of file
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 50570215101..3b1bd2abea6 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -461,8 +461,8 @@ datum/preferences
if(!H.mind.assigned_role)
log_debug("Char-Log: Char [current_character] - [H.name] has joined with mind.assigned_role set to NULL")
- var/DBQuery/query = dbcon.NewQuery("INSERT INTO ss13_characters_log (char_id, game_id, datetime, job_name, special_role, alt_title) VALUES (:char_id:, :game_id:, NOW(), :job:, :special_role:, :alt_title:)")
- query.Execute(list("char_id" = current_character, "game_id" = game_id, "job" = H.mind.assigned_role, "special_role" = H.mind.special_role, "alt_title" = H.mind.role_alt_title))
+ var/DBQuery/query = dbcon.NewQuery("INSERT INTO ss13_characters_log (char_id, game_id, datetime, job_name, alt_title) VALUES (:char_id:, :game_id:, NOW(), :job:, :special_role:, :alt_title:)")
+ query.Execute(list("char_id" = current_character, "game_id" = game_id, "job" = H.mind.assigned_role, "alt_title" = H.mind.role_alt_title))
// Turned into a proc so we could reuse it for SQL shenanigans.
/datum/preferences/proc/new_setup(var/re_initialize = 0)