diff --git a/config/credits/sounds/space_asshole.ogg b/config/credits/sounds/space_asshole.ogg
index 9d3fd15c6dc2..49c665d67a8b 100644
Binary files a/config/credits/sounds/space_asshole.ogg and b/config/credits/sounds/space_asshole.ogg differ
diff --git a/modular_ss220/cinematics/code/cinematics/credits.dm b/modular_ss220/cinematics/code/cinematics/credits.dm
index 2e60dd54d497..742473fefd35 100644
--- a/modular_ss220/cinematics/code/cinematics/credits.dm
+++ b/modular_ss220/cinematics/code/cinematics/credits.dm
@@ -1,5 +1,4 @@
/datum/cinematic/credits
- cleanup_time = 40 SECONDS
is_global = TRUE
backdrop_type = /obj/screen/fullscreen/cinematic_backdrop/credits
@@ -8,23 +7,35 @@
screen = new/obj/screen/cinematic/credits(src)
/datum/cinematic/credits/start_cinematic(list/watchers)
- watching = watchers
- if(SEND_GLOBAL_SIGNAL(COMSIG_GLOB_PLAY_CINEMATIC, src) & COMPONENT_GLOB_BLOCK_CINEMATIC)
- RegisterSignal(SSdcs, COMSIG_GLOB_CINEMATIC_STOPPED_PLAYING, PROC_REF(queue_gone))
- return
- . = ..()
+ if(!(SEND_GLOBAL_SIGNAL(COMSIG_GLOB_PLAY_CINEMATIC, src) & COMPONENT_GLOB_BLOCK_CINEMATIC))
+ . = ..()
+ RegisterSignal(SSdcs, COMSIG_GLOB_CINEMATIC_STOPPED_PLAYING, PROC_REF(queue_gone))
+ for(var/mob/watching_mob in watchers)
+ if(watching_mob.client)
+ watching += watching_mob
/datum/cinematic/credits/proc/queue_gone(datum/source, datum/cinematic/other)
SIGNAL_HANDLER
-
+ UnregisterSignal(SSdcs, COMSIG_GLOB_CINEMATIC_STOPPED_PLAYING)
start_cinematic(src.watching)
/datum/cinematic/credits/play_cinematic()
- play_cinematic_sound(sound(SScredits.title_music))
+ play_cinematic_sound(sound(SScredits.title_music, volume = 20))
+
SScredits.roll_credits_for_clients(watching)
+ cleanup_time = SScredits.end_titles.playing_time + 3 SECONDS
+
special_callback?.Invoke()
+/datum/cinematic/credits/stop_cinematic()
+ for(var/client/client in watching)
+ SScredits.clear_credits(client)
+
+ UnregisterSignal(SSdcs, COMSIG_GLOB_CINEMATIC_STOPPED_PLAYING)
+
+ . = ..()
+
/obj/screen/cinematic/credits
icon_state = "blank"
diff --git a/modular_ss220/credits/code/SScredits.dm b/modular_ss220/credits/code/SScredits.dm
index d2d9a6ce4509..40c92eadc401 100644
--- a/modular_ss220/credits/code/SScredits.dm
+++ b/modular_ss220/credits/code/SScredits.dm
@@ -4,64 +4,122 @@ SUBSYSTEM_DEF(credits)
name = "Credits"
runlevels = RUNLEVEL_POSTGAME
flags = SS_NO_FIRE
- var/list/end_titles = list()
+
+ var/datum/credits/end_titles
var/title_music = ""
- var/credit_roll_speed = 185
- var/credit_spawn_speed = 20
+ var/credit_roll_speed = 22 SECONDS
+ var/credit_spawn_speed = 2 SECONDS
var/credit_animate_height
- var/credit_ease_duration = 22
/datum/controller/subsystem/credits/Initialize()
- credit_animate_height = 14 * world.icon_size
+ credit_animate_height = 16 * world.icon_size
title_music = pick(file2list("config/credits/sounds/title_music.txt"))
+
/datum/controller/subsystem/credits/proc/roll_credits_for_clients(list/clients)
- if(!length(end_titles))
- end_titles = generate_titles()
+ end_titles = new /datum/credits/default()
for(var/client/client in clients)
SScredits.roll_credits_for_client(client)
+
/datum/controller/subsystem/credits/proc/roll_credits_for_client(client/client)
LAZYINITLIST(client.credits)
- var/list/_credits = client.credits
-
var/obj/screen/credit/logo = new /obj/screen/credit/logo(null, "", client)
- addtimer(CALLBACK(src, PROC_REF(roll_credits), _credits, logo, client), 5 SECONDS, TIMER_CLIENT_TIME)
+ addtimer(CALLBACK(src, PROC_REF(roll_credits), client.credits, logo, client), 5 SECONDS, TIMER_CLIENT_TIME)
/datum/controller/subsystem/credits/proc/roll_credits(list/credits, obj/screen/credit/logo/logo, client/client)
credits += logo
- logo.rollem()
- for(var/item in end_titles)
- if(!client?.credits)
- return
- var/obj/screen/credit/title = new(null, item, client)
- credits += title
- title.rollem()
- sleep(credit_spawn_speed)
+ addtimer(CALLBACK(logo, TYPE_PROC_REF(/obj/screen/credit/logo, rollem)), credit_roll_speed / 2.5, TIMER_CLIENT_TIME)
+
+ for(var/datum/credit/credit in end_titles.credits)
+ for(var/item in credit.content)
+ if(!client?.credits)
+ return
+ var/obj/screen/credit/title = new(null, item, client)
+ credits += title
+ title.rollem()
+ sleep(credit_spawn_speed)
addtimer(CALLBACK(src, PROC_REF(clear_credits), client), (credit_roll_speed), TIMER_CLIENT_TIME)
+
/datum/controller/subsystem/credits/proc/clear_credits(client/client)
if(!client)
return
QDEL_NULL(client.credits)
-/datum/controller/subsystem/credits/proc/generate_titles()
- RETURN_TYPE(/list)
- var/list/titles = list()
- var/list/cast = list()
- var/list/chunk = list()
- var/list/streamers = list()
- var/chunksize = 0
+/datum/credits
+ var/list/credits = list()
+ var/playing_time = 5 SECONDS
+
+/datum/credits/New()
+ . = ..()
+
+ fill_credits()
+
+ count_time()
+
+/datum/credits/proc/fill_credits()
+
+/datum/credits/proc/count_time()
+ for(var/datum/credit/credit in credits)
+ for(var/title in credit.content)
+ playing_time += SScredits.credit_spawn_speed
+
+ playing_time -= SScredits.credit_spawn_speed
+ playing_time += SScredits.credit_roll_speed
+
+/datum/credits/default
+
+/datum/credits/default/fill_credits()
+ credits += new /datum/credit/episode_title()
+ credits += new /datum/credit/streamers()
+ credits += new /datum/credit/crewlist()
+ credits += new /datum/credit/corpses()
+ credits += new /datum/credit/staff()
+ credits += new /datum/credit/disclaimer()
+
+/datum/credits/debug_large_credits
+
+/datum/credits/debug_large_credits/fill_credits()
+ . = ..()
+
+ credits += new /datum/credit/disclaimer()
+ credits += new /datum/credit/disclaimer()
+ credits += new /datum/credit/disclaimer()
+ credits += new /datum/credit/disclaimer()
+ credits += new /datum/credit/disclaimer()
+ credits += new /datum/credit/disclaimer()
+ credits += new /datum/credit/disclaimer()
+ credits += new /datum/credit/disclaimer()
+ credits += new /datum/credit/disclaimer()
+ credits += new /datum/credit/disclaimer()
+ credits += new /datum/credit/disclaimer()
+ credits += new /datum/credit/disclaimer()
+ credits += new /datum/credit/disclaimer()
+ credits += new /datum/credit/disclaimer()
+ credits += new /datum/credit/disclaimer()
+ credits += new /datum/credit/disclaimer()
+ credits += new /datum/credit/disclaimer()
+ credits += new /datum/credit/disclaimer()
+ credits += new /datum/credit/disclaimer()
+ credits += new /datum/credit/disclaimer()
+
+/datum/credit
+ var/list/content = list()
+
+/datum/credit/episode_title
+
+/datum/credit/episode_title/New()
+ . = ..()
var/episode_title = ""
switch(rand(1,100))
-
if(1 to 10)
episode_title += pick(file2list("config/credits/titles/finished_titles.txt"))
if(11 to 30)
@@ -73,7 +131,36 @@ SUBSYSTEM_DEF(credits)
episode_title += pick(file2list("config/credits/titles/random_titles_plural_2_1.txt")) + " "
episode_title += pick(file2list("config/credits/titles/random_titles_plural_2_2.txt"))
- titles += "
EPISODE [GLOB.round_id]
[episode_title]
"
+ content += "EPISODE [GLOB.round_id]
[episode_title]
"
+
+/datum/credit/streamers
+
+/datum/credit/streamers/New()
+ . = ..()
+ var/list/streamers = list()
+
+ for(var/iterator_key in GLOB.configuration.admin.ckey_rank_map)
+ if(!(GLOB.configuration.admin.ckey_rank_map[iterator_key] == "Банда"))
+ continue
+
+ var/ckey = ckey(iterator_key)
+ var/client/client = get_client_by_ckey(ckey)
+ if(!client)
+ continue
+ streamers += "[client.mob.name] a.k.a. ([ckey])"
+
+ if(length(streamers))
+ content += "
"
+ content += "
Приглашенные звезды:
[jointext(streamers, "
")]"
+
+/datum/credit/enormeus_crewlist_debug
+
+/datum/credit/enormeus_crewlist_debug/New()
+ . = ..()
+
+ var/list/cast = list()
+ var/list/chunk = list()
+ var/chunksize = 0
for(var/mob/living/carbon/human/human in GLOB.alive_mob_list | GLOB.dead_mob_list)
if(findtext(human.real_name,"(mannequin)"))
@@ -82,25 +169,63 @@ SUBSYSTEM_DEF(credits)
continue
if(!human.last_known_ckey)
continue
- if(human.client?.holder?.rank == "Банда")
- streamers += "[human.real_name]([human.ckey]) в роли [human.job]
"
+
+ for(var/i = 0, i < 100, i++)
+ if(!length(cast) && !chunksize)
+ cast += "
"
+ chunk += "
В съемках участвовали:"
+ chunk += "[human.real_name] в роли [uppertext(human.job)]"
+ chunksize++
+ if(chunksize > 2)
+ cast += "[jointext(chunk,"
")]"
+ chunk.Cut()
+ chunksize = 0
+
+ if(length(chunk))
+ cast += "[jointext(chunk,"
")]"
+
+
+ content += cast
+
+
+/datum/credit/crewlist
+
+/datum/credit/crewlist/New()
+ . = ..()
+
+ var/list/cast = list()
+ var/list/chunk = list()
+ var/chunksize = 0
+
+ for(var/mob/living/carbon/human/human in GLOB.alive_mob_list | GLOB.dead_mob_list)
+ if(findtext(human.real_name,"(mannequin)"))
+ continue
+ if(ismonkeybasic(human))
+ continue
+ if(!human.last_known_ckey)
continue
+
if(!length(cast) && !chunksize)
- chunk += "В съемках участвовали:"
+ cast += "
"
+ chunk += "
В съемках участвовали:"
chunk += "[human.real_name] в роли [uppertext(human.job)]"
chunksize++
if(chunksize > 2)
cast += "[jointext(chunk,"
")]"
chunk.Cut()
chunksize = 0
+
if(length(chunk))
cast += "[jointext(chunk,"
")]"
- if(length(streamers))
- titles += "Приглашенные звезды:
"
- titles += streamers
- titles += cast
+ content += cast
+
+
+/datum/credit/corpses
+
+/datum/credit/corpses/New()
+ . = ..()
var/list/corpses = list()
@@ -109,11 +234,15 @@ SUBSYSTEM_DEF(credits)
continue
else if(human.real_name)
corpses += human.real_name
-
if(length(corpses))
- titles += "Основано на реальных событиях:
В память о [english_list(corpses)].
"
+ content += "Основано на реальных событиях:
В память о [english_list(corpses)].
"
+
+/datum/credit/staff
- var/list/staff = list("Съемочная группа:")
+/datum/credit/staff/New()
+ . = ..()
+
+ var/list/staff = list()
var/list/staffjobs = file2list("config/credits/jobs/staffjobs.txt")
var/list/goodboys = list()
for(var/client/client in GLOB.clients)
@@ -125,9 +254,17 @@ SUBSYSTEM_DEF(credits)
else if(check_rights_client(R_MENTOR, FALSE, client))
goodboys += "[client.key]"
- titles += "[jointext(staff,"
")]"
+ if(length(staff))
+ content += "Съемочная группа:
"
+ content += "[jointext(staff,"
")]
"
+
if(length(goodboys))
- titles += "Мальчики на побегушках:
[english_list(goodboys)]
"
+ content += "Мальчики на побегушках:
[english_list(goodboys)]
"
+
+/datum/credit/disclaimer
+
+/datum/credit/disclaimer/New()
+ . = ..()
var/disclaimer = "
Sponsored by WYCCSTATION.
All rights reserved.
\
This motion picture is protected under the copyright laws of the Sol Central Government
and other nations throughout the galaxy.
\
@@ -136,28 +273,17 @@ SUBSYSTEM_DEF(credits)
disclaimer += pick("Use for parody prohibited. PROHIBITED.",
"All stunts were performed by underpaid interns. Do NOT try at home.",
"WYCCSTATION does not endorse behaviour depicted. Attempt at your own risk.",
- "Any unauthorized exhibition, distribution, or copying of this film or any part thereof (including soundtrack)
\
- may result in an ERT being called to storm your home and take it back by force.",
- "The story, all names, characters, and incidents portrayed in this production are fictitious. No identification with actual
\
- persons (living or deceased), places, buildings, and products is intended or should be inferred.
\
- This film is based on a true story and all individuals depicted are based on real people, despite what we just said.",
- "No person or entity associated with this film received payment or anything of value, or entered into any agreement, in connection
\
- with the depiction of tobacco products, despite the copious amounts of smoking depicted within.
\
- (This disclaimer sponsored by Carcinoma - Carcinogens are our Business!(TM)).",
"No animals were harmed in the making of this motion picture except for those listed previously as dead. Do not try this at home.")
- titles += "
"
- titles += "[jointext(disclaimer, null)]"
-
- return titles
+ content += "
"
+ content += "[jointext(disclaimer, null)]
"
/obj/screen/credit
icon_state = "blank"
mouse_opacity = 0
- alpha = 0
+ alpha = 255
screen_loc = "CENTER-7,CENTER-7"
plane = CREDITS_PLANE
- var/matrix/target
var/client/parent
/obj/screen/credit/Initialize(mapload, credited, client/client)
@@ -169,18 +295,16 @@ SUBSYSTEM_DEF(credits)
maptext_width = world.icon_size * 14
/obj/screen/credit/proc/rollem()
- var/matrix/M = matrix(transform)
- M.Translate(0, SScredits.credit_animate_height)
- animate(src, transform = M, time = SScredits.credit_roll_speed)
- target = M
- animate(src, alpha = 255, time = SScredits.credit_ease_duration, flags = ANIMATION_PARALLEL)
- addtimer(CALLBACK(src, PROC_REF(delete_credit)), SScredits.credit_roll_speed - SScredits.credit_ease_duration, TIMER_CLIENT_TIME)
+ var/matrix/matrix = matrix(transform)
+ transform = matrix.Translate(0, -world.icon_size)
+
+ matrix.Translate(0, SScredits.credit_animate_height)
+ animate(src, transform = matrix, time = SScredits.credit_roll_speed)
+ addtimer(CALLBACK(src, PROC_REF(delete_credit)), SScredits.credit_roll_speed, TIMER_CLIENT_TIME)
parent.screen += src
/obj/screen/credit/proc/delete_credit()
if(!QDELETED(src))
- animate(src, alpha = 0, transform = target, time = SScredits.credit_ease_duration)
- sleep(SScredits.credit_ease_duration)
qdel(src)
/obj/screen/credit/Destroy()
@@ -193,7 +317,7 @@ SUBSYSTEM_DEF(credits)
/obj/screen/credit/logo
icon = 'modular_ss220/credits/icons/logo.dmi'
icon_state = "ss220"
- screen_loc = "CENTER - 2,CENTER - 3"
+ screen_loc = "CENTER - 2,CENTER"
alpha = 100
@@ -203,18 +327,14 @@ SUBSYSTEM_DEF(credits)
parent.screen += src
/obj/screen/credit/logo/rollem()
- var/matrix/M = matrix(transform)
- M.Translate(0, SScredits.credit_animate_height / 2)
- animate(src, transform = M, time = SScredits.credit_roll_speed / 2)
- target = M
- animate(src, alpha = 255, time = SScredits.credit_ease_duration / 2, flags = ANIMATION_PARALLEL)
- addtimer(CALLBACK(src, PROC_REF(delete_credit)),(SScredits.credit_roll_speed - SScredits.credit_ease_duration) / 2, TIMER_CLIENT_TIME)
+ var/matrix/matrix = matrix(transform)
+ matrix.Translate(0, SScredits.credit_animate_height)
+ animate(src, transform = matrix, time = SScredits.credit_roll_speed)
+ addtimer(CALLBACK(src, PROC_REF(delete_credit)), SScredits.credit_roll_speed, TIMER_CLIENT_TIME)
/obj/screen/credit/logo/delete_credit()
if(!QDELETED(src))
- animate(src, alpha = 0, transform = target, time = SScredits.credit_ease_duration / 2)
- sleep(SScredits.credit_ease_duration / 2)
qdel(src)
/client/var/list/credits