diff --git a/SQL/database_changelog.txt b/SQL/database_changelog.txt
index 95e1e0f4c38..74a1dcceec1 100644
--- a/SQL/database_changelog.txt
+++ b/SQL/database_changelog.txt
@@ -10,6 +10,7 @@ In any query remember to add a prefix to the table names if you use one.
-----------------------------------------------------
+<<<<<<< HEAD
Version 5.13, 9 March, 2021, by Useroth
Implemented some features to help with running multiple servers on the same database and easily differentiate
@@ -38,6 +39,34 @@ ALTER TABLE `messages`
ALTER TABLE `round`
ADD COLUMN `server_name` VARCHAR(32) DEFAULT NULL AFTER `end_datetime`;
+=======
+Version 5.13, 30 April 2021, by Atlanta Ned
+Added the `citation` table for tracking security citations in the database.
+
+```
+CREATE TABLE `citation` (
+ `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `round_id` INT(11) UNSIGNED NOT NULL,
+ `server_ip` INT(11) UNSIGNED NOT NULL,
+ `server_port` INT(11) UNSIGNED NOT NULL,
+ `citation` TEXT NOT NULL COLLATE 'utf8mb4_general_ci',
+ `action` VARCHAR(20) NOT NULL DEFAULT '' COLLATE 'utf8mb4_general_ci',
+ `sender` VARCHAR(32) NOT NULL DEFAULT '' COLLATE 'utf8mb4_general_ci',
+ `sender_ic` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'Longer because this is the character name, not the ckey' COLLATE 'utf8mb4_general_ci',
+ `recipient` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'Longer because this is the character name, not the ckey' COLLATE 'utf8mb4_general_ci',
+ `crime` TEXT NOT NULL COLLATE 'utf8mb4_general_ci',
+ `fine` INT(4) NULL DEFAULT NULL,
+ `paid` INT(4) NULL DEFAULT '0',
+ `timestamp` DATETIME NOT NULL,
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `idx_constraints` (`round_id`, `server_ip`, `server_port`, `citation`(100)) USING BTREE
+)
+COLLATE='utf8mb4_general_ci'
+ENGINE=InnoDB
+AUTO_INCREMENT=1
+;
+```
+>>>>>>> e3b1e3c8c50 (Security citations are now logged to the DB (#58827))
-----------------------------------------------------
diff --git a/SQL/tgstation_schema.sql b/SQL/tgstation_schema.sql
index b7596e7d2af..a218bcbc5a0 100644
--- a/SQL/tgstation_schema.sql
+++ b/SQL/tgstation_schema.sql
@@ -100,6 +100,31 @@ CREATE TABLE `ban` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
+--
+-- Table structure for table `citation`
+--
+DROP TABLE IF EXISTS `citation`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE IF NOT EXISTS `citation` (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `round_id` int(11) unsigned NOT NULL,
+ `server_ip` int(11) unsigned NOT NULL,
+ `server_port` int(11) unsigned NOT NULL,
+ `citation` text NOT NULL,
+ `action` varchar(20) NOT NULL DEFAULT '',
+ `sender` varchar(32) NOT NULL DEFAULT '',
+ `sender_ic` varchar(64) NOT NULL DEFAULT '' COMMENT 'Longer because this is the character name, not the ckey',
+ `recipient` varchar(64) NOT NULL DEFAULT '' COMMENT 'Longer because this is the character name, not the ckey',
+ `crime` text NOT NULL,
+ `fine` int(4) DEFAULT NULL,
+ `paid` int(4) DEFAULT 0,
+ `timestamp` datetime NOT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `idx_constraints` (`round_id`,`server_ip`,`server_port`,`citation`(100)) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
--
-- Table structure for table `connection_log`
--
diff --git a/SQL/tgstation_schema_prefixed.sql b/SQL/tgstation_schema_prefixed.sql
index 0e47e27ed1c..bf84b06d86d 100644
--- a/SQL/tgstation_schema_prefixed.sql
+++ b/SQL/tgstation_schema_prefixed.sql
@@ -100,6 +100,31 @@ CREATE TABLE `SS13_ban` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
+--
+-- Table structure for table `citation`
+--
+DROP TABLE IF EXISTS `SS13_citation`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE IF NOT EXISTS `SS13_citation` (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `round_id` int(11) unsigned NOT NULL,
+ `server_ip` int(11) unsigned NOT NULL,
+ `server_port` int(11) unsigned NOT NULL,
+ `citation` text NOT NULL,
+ `action` varchar(20) NOT NULL DEFAULT '',
+ `sender` varchar(32) NOT NULL DEFAULT '',
+ `sender_ic` varchar(64) NOT NULL DEFAULT '' COMMENT 'Longer because this is the character name, not the ckey',
+ `recipient` varchar(64) NOT NULL DEFAULT '' COMMENT 'Longer because this is the character name, not the ckey',
+ `crime` text NOT NULL,
+ `fine` int(4) DEFAULT NULL,
+ `paid` int(4) DEFAULT 0,
+ `timestamp` datetime NOT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `idx_constraints` (`round_id`,`server_ip`,`server_port`,`citation`(100)) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
--
-- Table structure for table `SS13_connection_log`
--
diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm
index 84a2acfda15..a45b34fde50 100644
--- a/code/controllers/subsystem/blackbox.dm
+++ b/code/controllers/subsystem/blackbox.dm
@@ -352,3 +352,48 @@ Versioning
if(query_report_death)
query_report_death.Execute(async = TRUE)
qdel(query_report_death)
+
+/datum/controller/subsystem/blackbox/proc/ReportCitation(citation, sender, sender_ic, recipient, message, fine = 0, paid = 0)
+ var/datum/db_query/query_report_citation = SSdbcore.NewQuery({"INSERT INTO [format_table_name("citation")]
+ (server_ip,
+ server_port,
+ round_id,
+ citation,
+ action,
+ sender,
+ sender_ic,
+ recipient,
+ crime,
+ fine,
+ paid,
+ timestamp) VALUES (
+ INET_ATON(:server_ip),
+ :port,
+ :round_id,
+ :citation,
+ :action,
+ :sender,
+ :sender_ic,
+ :recipient,
+ :message,
+ :fine,
+ :paid,
+ :timestamp
+ ) ON DUPLICATE KEY UPDATE
+ paid = paid + VALUES(paid)"}, list(
+ "server_ip" = world.internet_address || "0",
+ "port" = "[world.port]",
+ "round_id" = GLOB.round_id,
+ "citation" = citation,
+ "action" = "Citation Created",
+ "sender" = sender,
+ "sender_ic" = sender_ic,
+ "recipient" = recipient,
+ "message" = message,
+ "fine" = fine,
+ "paid" = paid,
+ "timestamp" = SQLtime()
+ ))
+ if(query_report_citation)
+ query_report_citation.Execute(async = TRUE)
+ qdel(query_report_citation)
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index 5b36346a870..cbc3ab560e0 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -366,6 +366,7 @@ What a mess.*/
if (pay == diff || pay > diff || pay >= diff)
investigate_log("Citation Paid off: [p.crimeName] Fine: [p.fine] | Paid off by [key_name(usr)]", INVESTIGATE_RECORDS)
to_chat(usr, "The fine has been paid in full.")
+ SSblackbox.ReportCitation(text2num(href_list["cdataid"]),"","","","", 0, pay)
qdel(C)
playsound(src, "terminal_type", 25, FALSE)
else
@@ -698,7 +699,7 @@ What a mess.*/
if(!canUseSecurityRecordsConsole(usr, t1, null, a2))
return
- var/crime = GLOB.data_core.createCrimeEntry(t1, "", authenticated, station_time_timestamp(), fine)
+ var/datum/data/crime/crime = GLOB.data_core.createCrimeEntry(t1, "", authenticated, station_time_timestamp(), fine)
for (var/obj/item/pda/P in GLOB.PDAs)
if(P.owner == active1.fields["name"])
var/message = "You have been fined [fine] credits for '[t1]'. Fines may be paid at security."
@@ -713,6 +714,7 @@ What a mess.*/
usr.log_message("(PDA: Citation Server) sent \"[message]\" to [signal.format_target()]", LOG_PDA)
GLOB.data_core.addCitation(active1.fields["id"], crime)
investigate_log("New Citation: [t1] Fine: [fine] | Added to [active1.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS)
+ SSblackbox.ReportCitation(crime.dataId, usr.ckey, usr.real_name, active1.fields["name"], t1, fine)
if("citation_delete")
if(istype(active1, /datum/data/record))
if(href_list["cdataid"])
diff --git a/code/game/machinery/computer/warrant.dm b/code/game/machinery/computer/warrant.dm
index 539fef4cefa..10be4eb7d7a 100644
--- a/code/game/machinery/computer/warrant.dm
+++ b/code/game/machinery/computer/warrant.dm
@@ -125,6 +125,7 @@
if (pay == diff || pay > diff || pay >= diff)
investigate_log("Citation Paid off: [p.crimeName] Fine: [p.fine] | Paid off by [key_name(usr)]", INVESTIGATE_RECORDS)
to_chat(M, "The fine has been paid in full.")
+ SSblackbox.ReportCitation(text2num(href_list["cdataid"]),"","","","", 0, pay)
qdel(C)
playsound(src, "terminal_type", 25, FALSE)
else
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index b73ea9c06c2..dfc5e245587 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -288,7 +288,7 @@
return
fine = min(fine, maxFine)
- var/crime = GLOB.data_core.createCrimeEntry(t1, "", allowed_access, station_time_timestamp(), fine)
+ var/datum/data/crime/crime = GLOB.data_core.createCrimeEntry(t1, "", allowed_access, station_time_timestamp(), fine)
for (var/obj/item/pda/P in GLOB.PDAs)
if(P.owner == R.fields["name"])
var/message = "You have been fined [fine] credits for '[t1]'. Fines may be paid at security."
@@ -303,6 +303,7 @@
usr.log_message("(PDA: Citation Server) sent \"[message]\" to [signal.format_target()]", LOG_PDA)
GLOB.data_core.addCitation(R.fields["id"], crime)
investigate_log("New Citation: [t1] Fine: [fine] | Added to [R.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS)
+ SSblackbox.ReportCitation(crime.dataId, usr.ckey, usr.real_name, R.fields["name"], t1, fine)
return
if(href_list["add_crime"])