diff --git a/modular_skyrat/modules/opposing_force/code/roundend.dm b/modular_skyrat/modules/opposing_force/code/roundend.dm
deleted file mode 100644
index 1725eeaf363..00000000000
--- a/modular_skyrat/modules/opposing_force/code/roundend.dm
+++ /dev/null
@@ -1,12 +0,0 @@
-/datum/controller/subsystem/ticker/proc/opfor_report()
- var/list/result = list()
-
- result += "
"
-
- if(!SSopposing_force.approved_applications.len)
- result += span_red("No applications were approved.")
- else
- for(var/datum/opposing_force/opfor in SSopposing_force.approved_applications)
- result += opfor.roundend_report()
-
- return "
[result.Join()]
"
diff --git a/modular_zubbers/code/controllers/subsystem/ticker.dm b/modular_zubbers/code/controllers/subsystem/ticker.dm
index 7a2548b213e..a6f21ef8bf3 100644
--- a/modular_zubbers/code/controllers/subsystem/ticker.dm
+++ b/modular_zubbers/code/controllers/subsystem/ticker.dm
@@ -1,6 +1,27 @@
/datum/controller/subsystem/ticker
var/list/job_estimation_list = list()
+ // QOTR stuff
+ var/quote_of_the_round_record_start
+ var/quote_of_the_round_text
+ var/quote_of_the_round_attribution
+ var/quote_of_the_round_ckey
+
+/datum/controller/subsystem/ticker/Initialize()
+ . = ..()
+ quote_of_the_round_record_start = rand(CONFIG_GET(number/quote_of_the_round_time_random_start), CONFIG_GET(number/quote_of_the_round_time_random_end))
+ message_admins(
+ span_notice("Notice: The quote of the round will be chosen in [DisplayTimeText(quote_of_the_round_record_start,1)].")
+ )
+ log_runtime("The quote of the round will be chosen in [DisplayTimeText(quote_of_the_round_record_start,1)].")
+
+/datum/controller/subsystem/ticker/declare_completion(was_forced = END_ROUND_AS_NORMAL)
+ handle_antag_tickets()
+ handle_quote_of_the_round()
+ handle_credits()
+
+ . = ..()
+
/datum/controller/subsystem/ticker/proc/get_job_estimation(list/players)
var/list/player_ready_data = list()
sortTim(players, GLOBAL_PROC_REF(cmp_text_asc))
@@ -39,3 +60,56 @@
player_ready_data.Insert(1, "Job Estimation:")
player_ready_data.Insert(1, "")
return player_ready_data
+
+/datum/controller/subsystem/ticker/proc/handle_antag_tickets()
+ set waitfor = FALSE
+
+ for(var/ckey in GLOB.preferences_datums)
+ var/datum/preferences/prefs = GLOB.preferences_datums[ckey]
+ if(prefs.antag_tickets == prefs.antag_tickets_old)
+ continue //Only save if there has been a change.
+ prefs.save_preferences()
+
+/datum/controller/subsystem/ticker/proc/handle_credits()
+ if(!GLOB.end_titles)
+ GLOB.end_titles = generate_titles()
+
+ for(var/client/C)
+ if(!C?.credits)
+ C?.RollCredits()
+
+/datum/controller/subsystem/ticker/proc/handle_quote_of_the_round()
+ if(quote_of_the_round_text)
+ for(var/channel_tag in CONFIG_GET(str_list/channel_announce_new_game))
+ send2chat(
+ new /datum/tgs_message_content(generate_quote_of_the_round()),
+ channel_tag
+ )
+ to_chat(world, span_notice("A quote of the round was found, and should have been sent to discord."))
+ log_runtime("A quote of the round was found, and should have been sent to discord.")
+
+ else
+ if(world.time <= quote_of_the_round_record_start)
+ to_chat(world, span_notice("A quote of the round could not be found due to the round being too short."))
+ log_runtime("A quote of the round could not be found. The round ended too early.")
+ else
+ to_chat(world, span_notice("A quote of the round could not be found. Perhaps the crew should be more memorable."))
+ log_runtime("A quote of the round could not be found. Perhaps the filters are too strict?")
+
+/datum/controller/subsystem/ticker/proc/generate_quote_of_the_round()
+ return "The shift has ended. Get ready, a new round on **[SSmap_vote.next_map_config.map_name]** starts soon! <@&[CONFIG_GET(string/game_alert_role_id)]>\n\
+ [pick(strings("quote_of_the_round.json", "workers"))] [pick(strings("quote_of_the_round.json", "action"))] [pick(strings("quote_of_the_round.json", "message"))] that occured during said shift:\n\
+ > *[quote_of_the_round_text]*\n \\- *[quote_of_the_round_attribution]*"
+
+/datum/controller/subsystem/ticker/proc/opfor_report()
+ var/list/result = list()
+
+ result += "
"
+
+ if(!SSopposing_force.approved_applications.len)
+ result += span_red("No applications were approved.")
+ else
+ for(var/datum/opposing_force/opfor in SSopposing_force.approved_applications)
+ result += opfor.roundend_report()
+
+ return "[result.Join()]
"
diff --git a/modular_zubbers/code/modules/quote_of_the_round/ticker.dm b/modular_zubbers/code/modules/quote_of_the_round/ticker.dm
deleted file mode 100644
index e9ebc365b7f..00000000000
--- a/modular_zubbers/code/modules/quote_of_the_round/ticker.dm
+++ /dev/null
@@ -1,39 +0,0 @@
-/datum/controller/subsystem/ticker
- var/quote_of_the_round_record_start
- var/quote_of_the_round_text
- var/quote_of_the_round_attribution
- var/quote_of_the_round_ckey
-
-/datum/controller/subsystem/ticker/Initialize()
- . = ..()
- quote_of_the_round_record_start = rand(CONFIG_GET(number/quote_of_the_round_time_random_start), CONFIG_GET(number/quote_of_the_round_time_random_end))
- message_admins(
- span_notice("Notice: The quote of the round will be chosen in [DisplayTimeText(quote_of_the_round_record_start,1)].")
- )
- log_runtime("The quote of the round will be chosen in [DisplayTimeText(quote_of_the_round_record_start,1)].")
-
-/datum/controller/subsystem/ticker/declare_completion(force_ending)
-
- if(quote_of_the_round_text)
- for(var/channel_tag in CONFIG_GET(str_list/channel_announce_new_game))
- send2chat(
- new /datum/tgs_message_content(generate_quote_of_the_round()),
- channel_tag
- )
- to_chat(world, span_notice("A quote of the round was found, and should have been sent to discord."))
- log_runtime("A quote of the round was found, and should have been sent to discord.")
-
- else
- if(world.time <= quote_of_the_round_record_start)
- to_chat(world, span_notice("A quote of the round could not be found due to the round being too short."))
- log_runtime("A quote of the round could not be found. The round ended too early.")
- else
- to_chat(world, span_notice("A quote of the round could not be found. Perhaps the crew should be more memorable."))
- log_runtime("A quote of the round could not be found. Perhaps the filters are too strict?")
-
- . = ..()
-
-/datum/controller/subsystem/ticker/proc/generate_quote_of_the_round()
- return "The shift has ended. Get ready, a new round on **[SSmap_vote.next_map_config.map_name]** starts soon! <@&[CONFIG_GET(string/game_alert_role_id)]>\n\
- [pick(strings("quote_of_the_round.json", "workers"))] [pick(strings("quote_of_the_round.json", "action"))] [pick(strings("quote_of_the_round.json", "message"))] that occured during said shift:\n\
- > *[quote_of_the_round_text]*\n \\- *[quote_of_the_round_attribution]*"
diff --git a/modular_zubbers/code/modules/zantag_tickets/preferences.dm b/modular_zubbers/code/modules/zantag_tickets/preferences.dm
index 097cfc9ffce..4b83d14729c 100644
--- a/modular_zubbers/code/modules/zantag_tickets/preferences.dm
+++ b/modular_zubbers/code/modules/zantag_tickets/preferences.dm
@@ -25,15 +25,3 @@
savefile.set_entry("antag_tickets", antag_tickets)
antag_tickets_old = antag_tickets
. = ..()
-
-/datum/controller/subsystem/ticker/declare_completion(was_forced = END_ROUND_AS_NORMAL)
-
- set waitfor = FALSE
-
- for(var/ckey in GLOB.preferences_datums)
- var/datum/preferences/prefs = GLOB.preferences_datums[ckey]
- if(prefs.antag_tickets == prefs.antag_tickets_old)
- continue //Only save if there has been a change.
- prefs.save_preferences()
-
- . = ..()
diff --git a/tgstation.dme b/tgstation.dme
index ce57c1feff2..7442c083215 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -8789,7 +8789,6 @@
#include "modular_skyrat\modules\opposing_force\code\mind.dm"
#include "modular_skyrat\modules\opposing_force\code\opposing_force_datum.dm"
#include "modular_skyrat\modules\opposing_force\code\opposing_force_subsystem.dm"
-#include "modular_skyrat\modules\opposing_force\code\roundend.dm"
#include "modular_skyrat\modules\opposing_force\code\equipment\ammo.dm"
#include "modular_skyrat\modules\opposing_force\code\equipment\biology.dm"
#include "modular_skyrat\modules\opposing_force\code\equipment\bombs.dm"
@@ -10181,7 +10180,6 @@
#include "modular_zubbers\code\modules\quote_of_the_round\config.dm"
#include "modular_zubbers\code\modules\quote_of_the_round\debug_verbs.dm"
#include "modular_zubbers\code\modules\quote_of_the_round\telecomms.dm"
-#include "modular_zubbers\code\modules\quote_of_the_round\ticker.dm"
#include "modular_zubbers\code\modules\ratqueen\regalrat.dm"
#include "modular_zubbers\code\modules\reagents\drink_reagents.dm"
#include "modular_zubbers\code\modules\reagents\reagent_dispenser.dm"