[done][needs test merge][waiting for test merge since 3 weeks ago] curb your roundend 2: curb harder: return of curb (#20333)

* Working proof of concept

* Seems to be fully functional, yet ugly

* Beats me

* Perfect layout

* Looks great now

* Clear credits correctly

* Actually fix the rejoin situation

* Credits work when rebooting world manually

* Comments the debug out until I make a proper verb for it

* Adds credits panel & slight refactors

* Adds images to credits

* Adds more disclaimers and episode names

* Names

* Fixes prespawned corpses in the credits

Celt is an idiot and this did not actually work
This commit is contained in:
I-VAPE-VOX-CLOACA-EVERY-DAY-OF-MY-LIFE
2018-12-02 21:30:27 -03:00
committed by Intigracy
parent 98eed8c1e3
commit 2edde95469
32 changed files with 533 additions and 31 deletions

View File

@@ -239,6 +239,7 @@ var/list/score=list(
"foodeaten" = 0, //How much food was consumed
"clownabuse" = 0, //How many times a clown was punched, struck or otherwise maligned
"slips" = 0, //How many people have slipped during this round
"gunsspawned" = 0, //Guns spawned by the Summon Guns spell. Only guns, not other artifacts.
"richestname" = null, //This is all stuff to show who was the richest alive on the shuttle
"richestjob" = null, //Kinda pointless if you dont have a money system i guess
"richestcash" = 0,
@@ -248,6 +249,7 @@ var/list/score=list(
"dmgestdamage" = 0,
"dmgestkey" = null,
"explosions" = 0, //How many explosions happened total
"deadpets" = 0, //Only counts 'special' simple_mobs, like Ian, Poly, Runtime, Sasha etc
"arenafights" = 0,
"arenabest" = null,

View File

@@ -166,6 +166,7 @@
var/mommi_static = 0 //Scrambling mobs for mommis or not
var/skip_minimap_generation = 0 //If 1, don't generate minimaps
var/skip_holominimap_generation = 0 //If 1, don't generate holominimaps
var/skip_vault_generation = 0 //If 1, don't generate vaults
var/shut_up_automatic_diagnostic_and_announcement_system = 0 //If 1, don't play the vox sounds at the start of every shift.
@@ -555,6 +556,8 @@
mommi_static = 1
if("skip_minimap_generation")
skip_minimap_generation = 1
if("skip_holominimap_generation")
skip_holominimap_generation = 1
if("skip_vault_generation")
skip_vault_generation = 1
if("shut_up_automatic_diagnostic_and_announcement_system")

View File

@@ -20,10 +20,15 @@ var/datum/subsystem/more_init/SSmore_init
create_global_parallax_icons()
log_startup_progress(" Finished caching space parallax simulation in [stop_watch(watch)]s.")
watch=start_watch()
log_startup_progress("Generating holominimaps...")
generateHoloMinimaps()
log_startup_progress(" Finished holominimaps in [stop_watch(watch)]s.")
if (!config.skip_minimap_generation)
watch=start_watch()
log_startup_progress("Generating holominimaps...")
generateHoloMinimaps()
log_startup_progress(" Finished holominimaps in [stop_watch(watch)]s.")
else
holomaps_initialized = 1 //Assume holominimaps were prerendered, the worst thing that happens if they're missing is that the minimap consoles don't show a minimap
log_startup_progress("Not generating holominimaps - SKIP_HOLOMINIMAP_GENERATION found in config/config.txt")
..()
buildcamlist()

View File

@@ -21,6 +21,7 @@
var/mind=null
var/list/languages = list()
var/times_cloned=0
var/talkcount
/datum/dna2/record/proc/GetData()
var/list/ser=list("data" = null, "owner" = null, "label" = null, "type" = null, "ue" = 0)

View File

@@ -2,7 +2,7 @@ var/datum/controller/gameticker/ticker
/datum/controller/gameticker
var/remaining_time = 0
var/const/restart_timeout = 600
var/const/restart_timeout = 60 SECONDS
var/current_state = GAME_STATE_PREGAME
var/hide_mode = 0
@@ -425,6 +425,7 @@ var/datum/controller/gameticker/ticker
spawn
declare_completion()
end_credits.on_roundend()
if(config.map_voting)
//testing("Vote picked [chosen_map]")
vote.initiate_vote("map","The Server", popup = 1, weighted_vote = config.weighted_votes)
@@ -465,14 +466,14 @@ var/datum/controller/gameticker/ticker
if (watchdog.waiting)
to_chat(world, "<span class='notice'><B>Server will shut down for an automatic update in [config.map_voting ? "[(restart_timeout/10)] seconds." : "a few seconds."]</B></span>")
if(config.map_voting)
sleep(restart_timeout) //waiting for a mapvote to end
sleep(restart_timeout - end_credits.starting_delay) //waiting for a mapvote to end
if(!delay_end)
watchdog.signal_ready()
else
to_chat(world, "<span class='notice'><B>An admin has delayed the round end</B></span>")
delay_end = 2
else if(!delay_end)
sleep(restart_timeout)
sleep(restart_timeout - end_credits.starting_delay)
if(!delay_end)
CallHook("Reboot",list())
world.Reboot()

View File

@@ -221,6 +221,10 @@
continue
score["litter"]++
for(var/mob/living/simple_animal/SA in dead_mob_list)
if(SA.is_pet)
score["deadpets"]++
//Bonus Modifiers
//var/traitorwins = score["traitorswon"]
var/deathpoints = score["deadcrew"] * 250 //Human beans aren't free

View File

@@ -142,6 +142,7 @@
if("bulletstorm")
new /obj/item/weapon/gun/bulletstorm(get_turf(src))
playsound(src,'sound/effects/summon_guns.ogg', 50, 1)
score["gunsspawned"]++
/mob/living/carbon/human/proc/equip_swords()
var/randomizeswords = pick("unlucky", "misc", "throw", "armblade", "pickaxe", "pcutter", "esword", "alt-esword", "machete", "kitchen", "medieval", "katana", "axe", "boot", "saw", "scalpel", "switchtool", "shitcurity")

View File

@@ -1501,3 +1501,52 @@ proc/formatPlayerPanel(var/mob/U,var/text="PP")
tomob.ckey = frommob.ckey
qdel(frommob)
return 1
/datum/admins/proc/CreditsPanel()
if(!check_rights(0))
return
var/dat = "<center><B>Credits Panel</B></center><hr>"
dat += "<center><B>Episode Name:</B></center>"
dat += "Chosen Name: [end_credits.episode_name == "" ? "(Will Generate Automatically)" : end_credits.episode_name] <A href='?src=\ref[src];credits=setname'>(Set) </A>"
if(end_credits.episode_name != "" && !end_credits.generated)
dat += "<A href='?src=\ref[src];credits=resetname'>(Reset)</A>"
else if(end_credits.generated)
dat += "<A href='?src=\ref[src];credits=rerollname'>(Reroll!)</A>"
dat += "<br>"
if(!end_credits.generated)
dat += "<span style='color:red'>The round isn't over, so the name possibilities haven't been drafted yet.<br>You can manually write down a set name now, or come back when the round ends.</span>"
else
dat += "Drafted Name Possibilities: "
dat += "<div id='draftednames'>"
for(var/datum/episode_name/N in end_credits.episode_names)
dat += "[N.make_div(src)]<br>"
dat += "</div>"
dat += "<hr>"
dat += "<center><B>Disclaimers:</B></center>"
if(!end_credits.generated)
dat += "<span style='color:red'>The round isn't over, so the disclaimers haven't been generated yet.<br>You can add some now (they will show up at the top), or come back when the round ends.</span>"
dat += "<br>Generated Disclaimers: "
dat += "<div id='disclaimers'>"
dat += "<a href='?src=\ref[src];credits=newdisclaimer'>(Add New)</a></br>"
for(var/i = 1; i <= end_credits.disclaimers.len; i++)
var/disclaimer = end_credits.disclaimers[i]
if(i > 1)
dat += "<a href='?src=\ref[src];credits=disclaimerup;disclaimerindex=[i]'>&#8743;</a>"
else
dat += "&nbsp"
if(i < end_credits.disclaimers.len)
dat += "<a href='?src=\ref[src];credits=disclaimerdown;disclaimerindex=[i]'>&#8744;</a>"
else
dat += "&nbsp"
dat += "<a href='?src=\ref[src];credits=editdisclaimer;disclaimerindex=[i]'> (Edit) </a>"
if(findtext(disclaimer, "<img"))
dat += "[disclaimer]"
else
dat += "[html_encode(disclaimer)]"
dat += "<br>"
dat += "</div>"
dat += "<hr><br><center>ADVANCED: <a href='?_src_=vars;Vars=\ref[end_credits]'>Debug Credits Datum</A></center>"
usr << browse(dat, "window=creditspanel;size=600x800")

View File

@@ -77,7 +77,8 @@ var/list/admin_verbs_admin = list(
/client/proc/allow_character_respawn, /* Allows a ghost to respawn */
/client/proc/watchdog_force_restart, /*forces restart using watchdog feature*/
/client/proc/manage_religions,
/client/proc/set_veil_thickness
/client/proc/set_veil_thickness,
/client/proc/credits_panel /*allows you to customize the roundend credits before they happen*/
)
var/list/admin_verbs_ban = list(
/client/proc/unban_panel,
@@ -1210,3 +1211,11 @@ var/list/admin_verbs_mod = list(
else
alert(src, "An external server error has occurred. Please report this.")
return 0
/client/proc/credits_panel()
set name = "Credits Panel"
set category = "Admin"
if(holder)
holder.CreditsPanel()
feedback_add_details("admin_verb","CP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return

View File

@@ -4830,6 +4830,68 @@
return
mind.role_panel()
else if(href_list["credits"])
switch(href_list["credits"])
if("resetname")
if(!end_credits.generated) //Just in case the button somehow gets clicked when it shouldn't
end_credits.episode_name = ""
log_admin("[key_name(usr)] reset the current round's episode name. A new one will automatically generate later.")
message_admins("[key_name_admin(usr)] reset the current round's episode name. A new one will automatically generate later.")
if("rerollname")
end_credits.pick_name()
log_admin("[key_name(usr)] re-rolled the current round's episode name. New name: '[end_credits.episode_name]'")
message_admins("[key_name_admin(usr)] re-rolled the current round's episode name. New name: '[end_credits.episode_name]'")
if("setname")
var/newname = input(usr,"Write the name of this latest rerun...","New Episode Name") as text|null
if(newname)
end_credits.episode_name = newname
log_admin("[key_name(usr)] forced the current round's episode name to '[newname]'")
message_admins("[key_name_admin(usr)] forced the current round's episode name to '[newname]'")
if("namedatumedit")
var/datum/episode_name/N = locate(href_list["nameref"])
if(N)
var/newname = input(usr,"Write a new possible episode name. This is NOT guaranteed to be picked as the final name, unless you modified the weight to 99999% or something.","Edit Name",N.thename) as text|null
if(newname)
N.thename = newname
if("namedatumweight")
var/datum/episode_name/N = locate(href_list["nameref"])
if(N)
var/newweight = input(usr,"Write the new possibility that '[N.thename]' will be selected as the final episode name. Default is 100.","Edit Weight",N.weight) as num|null
if(newweight)
N.weight = newweight
if("namedatumremove")
var/datum/episode_name/N = locate(href_list["nameref"])
if(N && alert("Are you sure you want to remove the name '[N.thename]' from the possible episode names to be picked?", "Removing possible name", "Yes", "No") == "Yes")
end_credits.episode_names -= N
qdel(N)
if("newdisclaimer")
var/newdisclaimer = input(usr,"Write a new rolling disclaimer. Probably something stupid like 'Sponsored by Toxins-R-Us'. This will show up at the top, right after the crew names. Add '\<br>' at the end if you want extra spacing.","New Disclaimer") as message|null
if(newdisclaimer)
end_credits.disclaimers.Insert(1,newdisclaimer)
log_admin("[key_name(usr)] added a new disclaimer to the current round's credits: '[newdisclaimer]'")
message_admins("[key_name_admin(usr)] added a new disclaimer to the current round's credits: '[newdisclaimer]'")
if("editdisclaimer")
var/i = text2num(href_list["disclaimerindex"])
var/olddisclaimer = end_credits.disclaimers[i]
var/newdisclaimer = input(usr,"Write a new rolling disclaimer.","Edit Disclaimer",olddisclaimer) as message|null
if(newdisclaimer)
log_admin("[key_name(usr)] edited a rolling credits disclaimer. New disclaimer: '[newdisclaimer]'")
message_admins("[key_name_admin(usr)] edited a rolling credits disclaimer. New disclaimer: '[newdisclaimer]'")
end_credits.disclaimers[i] = newdisclaimer
if("disclaimerup")
var/i = text2num(href_list["disclaimerindex"])
if(i > 1)
end_credits.disclaimers.Swap(i,i-1)
if("disclaimerdown")
var/i = text2num(href_list["disclaimerindex"])
if(i < end_credits.disclaimers.len)
end_credits.disclaimers.Swap(i,i+1)
CreditsPanel() //refresh!
// ----- Religion and stuff
if (href_list["religions"])
#define MAX_MSG_LENGTH 200

View File

@@ -185,6 +185,7 @@
prefs.client = src
prefs.initialize_preferences(client_login = 1)
. = ..() //calls mob.Login()
chatOutput.start()
@@ -215,6 +216,8 @@
//Set map label to correct map name
winset(src, "rpane.map", "text=\"[map.nameLong]\"")
clear_credits() //Otherwise these persist if the client doesn't close the game between rounds
// Notify scanners.
INVOKE_EVENT(on_login,list(
"client"=src,

View File

@@ -0,0 +1,25 @@
/datum/credits/proc/draft_disclaimers()
var/inline_images = ""
for(var/filename in flist("icons/credits/"))
var/icon/I = icon("icons/credits/[filename]")
inline_images += "<span style='display: inline-block, vertical-align: middle, margin: 0px 20px;'><img style='display: inline-block,' src='data:image/png;base64,[icon2base64(I)]'></span>"
disclaimers += "Filmed on Location at [station_name()]."
disclaimers += "Filmed with BYOND&#169; cameras and lenses. Outer space footage provided by NASA."
disclaimers += "Additional special visual effects by LUMMOX&#174; JR. Motion Picture Productions."
disclaimers += "Unofficially Sponsored by The United States Navy."
disclaimers += "All rights reserved."
disclaimers += "<br>"
disclaimers += pick("All stunts were performed by underpaid and expendable interns. Do NOT try at home.", "[director] do not endorse behaviour depicted. Attempt at your own risk.")
if(score["deadpets"] == 0)
disclaimers += "No animals were harmed in the making of this film.[(score["clownabuse"] > 50) ? " However, many clowns were." : ""]"
else if(score["clownabuse"] == 0)
disclaimers += "No clowns were harmed in the making of this film."
else if(score["clownabuse"] > 50)
disclaimers += "All clowns were harmed in the making of this film."
disclaimers += "<br>"
disclaimers += inline_images
disclaimers += "<br>"
disclaimers += "This motion picture is (not) protected under the copyright laws of the United States and all countries throughout the universe. Country of first publication: United States of America. Any unauthorized exhibition, distribution, or copying of this picture or any part thereof (including soundtrack) is an infringement of the relevant copyright and will subject the infringer to civil liability and criminal prosecution."
disclaimers += "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."
disclaimers += "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."

View File

@@ -0,0 +1,147 @@
var/global/datum/credits/end_credits = new
/datum/credits
var/generated = FALSE
var/starting_delay = 8 SECONDS
var/control = "mapwindow.credits"
var/file = 'code/modules/credits/credits.html'
var/director = "Pomf Chicken Productions"
var/list/producers = list()
var/mob/living/carbon/human/star
var/list/disclaimers = list()
var/list/datum/episode_name/episode_names = list()
var/episode_name = ""
var/producers_string = ""
var/episode_string = ""
var/cast_string = ""
var/disclaimers_string = ""
/datum/credits/proc/on_roundend()
generate_caststring() //roundend grief not included in the credits
generate_producerstring() //so that we show admins who have logged out before the credits roll
draft_disclaimers()
draft_episode_names() //only selects the possibilities, doesn't pick one yet
generated = TRUE
/datum/credits/proc/rollem()
world << sound('sound/music/Frolic_Luciano_Michelini.ogg')
finalize_disclaimerstring() //finalize it after the admins have had time to edit them
if(episode_name == "") //admin might've already set one
pick_name()
finalize_episodestring()
var/scrollytext = episode_string + cast_string + disclaimers_string
var/list/js_args = list(scrollytext, producers_string, 25, 2000)
for(var/client/C in clients)
C.show_credits(js_args)
/client/proc/show_credits(var/list/js_args)
set waitfor = FALSE
verbs += /client/proc/clear_credits
src << output(end_credits.file, end_credits.control)
sleep(end_credits.starting_delay)
src << output(list2params(js_args), "[end_credits.control]:makeCredits")
winset(src, end_credits.control, "is-visible=true")
/client/proc/clear_credits()
set name = "Skip Credits"
set category = "OOC"
verbs -= /client/proc/clear_credits
winset(src, end_credits.control, "is-visible=false")
/datum/credits/proc/pick_name()
var/list/drafted_names = list()
for(var/datum/episode_name/N in episode_names)
drafted_names["[N.thename]"] = N.weight
episode_name = pickweight(drafted_names)
/datum/credits/proc/finalize_episodestring(var/thename)
episode_string = "<h1>SEASON [rand(1,22)] EPISODE [rand(1,17)]<br>[uppertext(episode_name)]</h1><br><div style='padding-bottom: 75px;'></div>"
/datum/credits/proc/finalize_disclaimerstring()
disclaimers_string = "<div class='disclaimers'>"
for(var/disclaimer in disclaimers)
disclaimers_string += "[disclaimer]<br>"
disclaimers_string += "</div>"
/datum/credits/proc/generate_producerstring()
var/list/staff = list("<h1>PRODUCTION STAFF</h1><br>")
var/list/staffjobs = list("Coffee Fetcher", "Cameraman", "Angry Yeller", "Chair Operator", "Choreographer", "Historical Consultant", "Costume Designer", "Chief Editor", "Executive Assistant", "Key Grip")
if(!admins.len)
staff += "<h2>PRODUCER - Alan Smithee</h2><br>"
for(var/client/C in admins)
if(!C.holder)
continue
if(C.holder.rights & (R_DEBUG|R_ADMIN))
var/observername = ""
if(C.mob && istype(C.mob,/mob/dead/observer))
var/mob/dead/observer/O = C.mob
if(O.started_as_observer)
observername = "[O.real_name] a.k.a. "
staff += "<h2>[uppertext(pick(staffjobs))] - [observername]'[C.key]'</h2><br>"
producers = list("<h1>Directed by</br>[uppertext(director)]</h1>","[jointext(staff,"")]")
for(var/head in data_core.get_manifest_json()["heads"])
producers += "<h1>[head["rank"]]<br>[uppertext(head["name"])]</h1><br>"
if(star)
producers += "<h1>Starring<br>[thebigstar(star)]</h1><br>"
producers_string = ""
for(var/producer in end_credits.producers)
producers_string += "[producer]%n" //%n being an arbitrary "new producer" char we use to split this string back in the javascript
/datum/credits/proc/generate_caststring()
cast_string = "<h1>CAST:</h1><br><h2>(in order of appearance)</h2><br>"
cast_string += "<table class='crewtable'>"
for(var/mob/living/carbon/human/H in living_mob_list|dead_mob_list)
if(H.iscorpse || (H.timeofdeath && H.timeofdeath < 5 MINUTES)) //don't mention these losers (prespawned corpses mostly)
continue
if(!star || H.talkcount > star.talkcount)
star = H
cast_string += "[gender_credits(H)]"
cast_string += "</table><br>"
cast_string += "<div class='disclaimers'>"
var/list/corpses = list()
for(var/mob/living/carbon/human/H in dead_mob_list)
if(H.iscorpse || (H.timeofdeath && H.timeofdeath < 5 MINUTES)) //no prespawned corpses
continue
else if(H.real_name)
corpses += H.real_name
if(corpses.len)
var/true_story_bro = "<br>[pick("BASED ON","INSPIRED BY","A RE-ENACTMENT OF")] [pick("A TRUE STORY","REAL EVENTS","THE EVENTS ABOARD [uppertext(station_name())]")]"
cast_string += "<h3>[true_story_bro]</h3><br>In memory of those that did not make it.<br>[english_list(corpses)].<br>"
cast_string += "</div><br>"
/proc/gender_credits(var/mob/living/carbon/human/H)
if(H.mind && H.mind.key)
return "<tr><td class='actorname'>[uppertext(H.mind.key)]</td><td class='actorsegue'> as </td><td class='actorrole'>[H.real_name], [H.get_assignment()]</td></tr>"
else
var/t_him = "Them"
if(H.gender == MALE)
t_him = "Him"
else if(H.gender == FEMALE)
t_him = "Her"
return "<tr><td class='actorname'>[uppertext(H.real_name)]</td><td class='actorsegue'> as </td><td class='actorrole'>[t_him]self</td></tr>"
/proc/thebigstar(var/mob/living/carbon/human/H)
if(H.mind && H.mind.key)
return "[uppertext(H.mind.key)] as [H.real_name]"
else
var/t_him = "Them"
if(H.gender == MALE)
t_him = "Him"
else if(H.gender == FEMALE)
t_him = "Her"
return "[uppertext(H.real_name)] as [t_him]self"

View File

@@ -0,0 +1,130 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style>
body {
overflow: hidden;
background-color: black;
color: white;
font-family: Georgia, serif
}
#container {
position: relative;
width: 100vw;
text-align: center;
}
#splash {
display: table-cell;
height: 100vh;
}
.crewtable{
width: 100%;
table-layout: fixed;
white-space: nowrap;
}
.crewtable td{
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 1.17em;
}
.actorname {
text-align: right;
float: right;
}
.actorsegue {
text-align: center;
width: 40px;
}
.actorrole {
float: left;
text-align: left;
}
.letterboxer {
width: 10%;
}
.disclaimers {
font-family: Arial, Helvetica, sans-serif
}
h1, h2, h3 {
display: inline;
font-weight:normal;
}
</style>
</head>
<body>
<table id="container"> <!-- Yes we use a table to center ourselves. StackOverflow says this is not acceptable practice past 2012 but we're operating with 2009 tech so... !-->
<tr>
<td class="letterboxer"></td>
<td id="splash">
IF YOU CAN SEE THIS, TELL A CODER WHAT HAPPENED!
</td>
<td class="letterboxer"></td>
</tr>
<tr>
<td class="letterboxer"></td>
<td id="marquee">
IF YOU CAN SEE THIS, REALLY TELL A CODER WHAT HAPPENED!
</td>
<td class="letterboxer"></td>
</tr>
</table>
<script type="text/javascript">
var producers = [];
var lastinterval;
function setScrollingText(text){
document.getElementById("marquee").innerHTML = text;
}
function setProducers(text){
producers = text.split("%n");
producers = producers.slice(0, -1); //get rid of the last %n
}
function makeCredits(scrollyString, producersString, scrollSpeed, splashTime){
if (splashTime === undefined) {
splashTime = 2000;
}
splashTime = parseInt(splashTime); //Just in case
if (scrollSpeed === undefined) {
scrollSpeed = 25;
}
scrollSpeed = parseInt(scrollSpeed); //Just in case
setScrollingText(scrollyString);
setProducers(producersString);
splashLoop(producers, 0, splashTime);
setTimeout(rollMarquee, producers.length*splashTime, scrollSpeed);
}
function splashLoop(arr, index, time) {
if (index === arr.length){
return;
}
document.getElementById("splash").innerHTML = arr[index];
setTimeout(splashLoop, time, arr, index+1, time)
}
function rollMarquee(speed){
var div = document.getElementById("container");
var bottom = 0;
lastinterval = setInterval(function () {
bottom = bottom + 1;
div.style.bottom = bottom + "px";
if(bottom > 3000){ //RUNAWAY CREDIT ALART - no seriously this will keep going if the player doesn't close the game between rounds
//document.documentElement.innerHTML = "<textarea rows='4' cols='50'>" + document.documentElement.innerHTML + "</textarea>"; clearInterval(lastinterval); return; //debugging
clearInterval(lastinterval);
window.location = 'byond://winset?id=mapwindow.credits;is-visible=false';
return;
}
}, speed);
};
</script>
</body>
</html>

View File

@@ -0,0 +1,45 @@
/datum/episode_name
var/thename = ""
var/reason = "Default episode name." //Explanation on why this episode name fits this round. For the admin panel.
var/weight = 100 //50 will have 50% the chance of being picked. 200 will have 200% the chance of being picked. etc
/datum/episode_name/New(var/thename, var/reason, var/weight)
if(!thename)
return
src.thename = thename
if(reason)
src.reason = reason
if(weight)
src.weight = weight
/datum/episode_name/proc/make_div(var/admindatum) //This is just for the admin panel.
. = "[weight]% <a href='?src=\ref[admindatum];credits=namedatumweight;nameref=\ref[src]'>(Set)</a> - "
. += "[thename] - <a href='?src=\ref[admindatum];credits=namedatumedit;nameref=\ref[src]'>(Edit)</a> "
. += "<a href='?src=\ref[admindatum];credits=namedatumremove;nameref=\ref[src]'>(Remove)</a> "
. += "<span title='[reason]'>(?)</span>"
/datum/credits/proc/draft_episode_names()
episode_names += new /datum/episode_name("THE [pick("DOWNFALL OF", "RISE OF", "TROUBLE WITH", "FINAL STAND OF", "DARK SIDE OF")] [pick("SPACEMEN", "HUMANITY", "DIGNITY", "SANITY", "THE CHIMPANZEES", "THE VENDOMAT PRICES","[uppertext(station_name())]")]")
episode_names += new /datum/episode_name("THE CREW GETS [pick("RACIST", "PICKLED", "AN INCURABLE DISEASE", "PIZZA", "A VALUABLE HISTORY LESSON", "A BREAK", "HIGH", "TO LIVE", "TO RELIVE THEIR CHILDHOOD", "EMBROILED IN CIVIL WAR", "SERIOUS ABOUT [pick("DRUG ABUSE", "CRIME", "PRODUCTIVITY", "ANCIENT AMERICAN CARTOONS", "SPACEBALL")]")]")
episode_names += new /datum/episode_name("THE CREW LEARNS ABOUT [pick("LOVE", "DRUGS", "THE DANGERS OF MONEY LAUNDERING", "SPACE 'NAM", "INVESTMENT FRAUD", "KELOTANE ABUSE", "RADIATION PROTECTION", "SACRED GEOMETRY", "STRING THEORY", "ABSTRACT MATHEMATICS", "[pick("CATBEAST", "DIONAN", "PLASMAMAN", "VOX", "GREY")] MATING RITUALS", "ANCIENT CHINESE MEDICINE","LAWSETS")]")
episode_names += new /datum/episode_name("[pick("MUCH ADO ABOUT NOTHING", "WHAT HAPPENS WHEN YOU MIX MOMMIS AND COMMERCIAL-GRADE PACKING FOAM", "ATTACK! ATTACK! ATTACK!", "SEX BOMB", "THE BALLAD OF [uppertext(station_name())]")]")
episode_names += new /datum/episode_name("[pick("SPACE", "SEXY", "DRAGON", "WARLOCK", "LAUNDRY", "GUN", "ADVERTISING", "DOG", "CARBON MONOXIDE", "NINJA", "WIZARD", "SOCRATIC", "JUVENILE DELIQUENCY", "POLITICALLY MOTIVATED", "RADTACULAR SICKNASTY")] [pick("QUEST", "FORCE", "ADVENTURE")]")
episode_names += new /datum/episode_name("[pick("THE DAY [uppertext(station_name())] STOOD STILL", "HUNT FOR THE GREEN WEENIE", "ALIEN VS VENDOMAT", "SPACE TRACK")]")
if(SNOW_THEME)
episode_names += new /datum/episode_name("A VERY [pick("NANOTRASEN", "EXPEDITIONARY", "SECURE", "PLASMA", "MARTIAN")] CHRISTMAS", "'Tis the season.", 500)
if(score["gunsspawned"] > 0)
episode_names += new /datum/episode_name("GUNS, GUNS EVERYWHERE", "[score["gunsspawned"]] guns were spawned this round.", max(100, score["gunsspawned"]*10))
if(score["richestcash"] > 30000)
episode_names += new /datum/episode_name("THE IRRESISTIBLE RISE OF [uppertext(score["richestname"])]", "Scrooge Mc[score["richestkey"]] racked up [score["richestcash"]] credits this round.", max(100, score["richestcash"]/300))
if(score["deadaipenalty"] > 2)
episode_names += new /datum/episode_name("THE ONE WHERE [score["deadaipenalty"]] AIS DIE", "That's a lot of dead AIs.", max(100, score["deadaipenalty"]*50))
if(score["deadcrew"] == 0)
episode_names += new /datum/episode_name("[pick("EMPLOYEE TRANSFER", "PEACE AND QUIET IN [uppertext(station_name())]", "THE CREW TRIES TO KILL A FLY FOR [round(score["time"]/60)] MINUTES")]", "No-one died this round.", 200)
if(score["escapees"] == 0 && emergency_shuttle.location == CENTCOMM_Z)
episode_names += new /datum/episode_name("[pick("DEAD SPACE", "THE CREW GOES MISSING", "A ONE-WAY TICKET TO FLAVORTOWN")]", "There were no escapees on the shuttle.", 200)
if(score["slips"] > 100)
episode_names += new /datum/episode_name("THE CREW GOES BANANAS", "[score["slips"]] people slipped this round.", min(200, score["slips"]/2))
for(var/mob/living/simple_animal/corgi/C in living_mob_list)
if(C.spell_list.len > 0)
episode_names += new /datum/episode_name("[pick("A VERY MAGICAL DAY", "IAN SAYS", "IAN'S DAY OUT", "CORGI MAGIC")]", "You know what you did.", 300)
break

View File

@@ -227,6 +227,7 @@
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src, R.dna.species, delay_ready_dna = TRUE)
occupant = H
H.times_cloned = R.times_cloned +1
H.talkcount = R.talkcount
if(!connected.emagged)
icon_state = "pod_1"

View File

@@ -495,6 +495,7 @@
R.types=DNA2_BUF_UI|DNA2_BUF_UE|DNA2_BUF_SE
R.languages = subject.languages.Copy()
R.times_cloned = subject.times_cloned
R.talkcount = subject.talkcount
//Add an implant if needed
var/obj/item/weapon/implant/health/imp = locate(/obj/item/weapon/implant/health, subject)

View File

@@ -91,4 +91,5 @@
var/show_client_status_on_examine = TRUE //If false, don't display catatonic/braindead messages to non-admins
var/become_zombie_after_death = FALSE
var/times_cloned = 0 //How many times this person has been cloned
var/times_cloned = 0 //How many times this person has been cloned
var/talkcount = 0 // How many times a person has talked - used for determining who's been the "star" for the purposes of round end credits

View File

@@ -247,6 +247,10 @@ var/list/department_radio_keys = list(
for (var/atom/movable/listener in listening_nonmobs)
listener.Hear(speech, rendered)
/mob/living/carbon/human/send_speech(var/datum/speech/speech, var/message_range=7, var/bubble_type)
talkcount++
. = ..()
/mob/living/proc/say_test(var/text)
var/ending = copytext(text, length(text))
if (ending == "?")

View File

@@ -45,6 +45,7 @@
icon_living = "cat"
icon_dead = "cat_dead"
gender = FEMALE
is_pet = TRUE
/mob/living/simple_animal/cat/Proc
name = "Proc"
@@ -152,4 +153,4 @@ var/list/wizard_snakes = list()
/mob/living/simple_animal/cat/snek/wizard/Destroy()
wizard_snakes[src] = null
wizard_snakes -= src
..()
..()

View File

@@ -472,6 +472,7 @@
response_disarm = "bops"
response_harm = "kicks"
spin_emotes = list("dances around","chases his tail")
is_pet = TRUE
/mob/living/simple_animal/corgi/Ian/santa
name = "Santa's Corgi Helper"
@@ -631,6 +632,7 @@
icon_living = "doby"
icon_dead = "doby_dead"
spin_emotes = list("prances around","chases her nub of a tail")
is_pet = TRUE
species_type = /mob/living/simple_animal/corgi/sasha
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/animal

View File

@@ -859,6 +859,7 @@
name = "Poly"
desc = "Poly the Parrot. An expert on quantum cracker theory."
speak = list("Poly wanna cracker!", ":e Check the singlo, you chucklefucks!",":e Wire the solars, you lazy bums!",":e WHO TOOK THE DAMN HARDSUITS?",":e OH GOD ITS FREE CALL THE SHUTTLE")
is_pet = TRUE
/mob/living/simple_animal/parrot/Poly/New()
ears = new /obj/item/device/radio/headset/headset_eng(src)

View File

@@ -72,7 +72,7 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t
var/melee_damage_type = BRUTE
var/attacktext = "attacks"
var/attack_sound = null
var/friendly = "nuzzles" //If the mob does no damage with it's attack
var/friendly = "nuzzles" //If the mob does no damage with its attack
// var/environment_smash = 0 //Set to 1 to allow breaking of crates,lockers,racks,tables; 2 for walls; 3 for Rwalls
var/environment_smash_flags = 0
@@ -100,6 +100,8 @@ var/global/list/animal_count = list() //Stores types, and amount of animals of t
var/life_tick = 0
var/list/colourmatrix = list()
var/is_pet = FALSE //We're somebody's precious, precious pet.
/mob/living/simple_animal/apply_beam_damage(var/obj/effect/beam/B)
var/lastcheck=last_beamchecks["\ref[B]"]

View File

@@ -269,26 +269,11 @@ var/savefile/panicfile
Master.Shutdown()
paperwork_stop()
spawn()
world << sound(pick(
'sound/AI/newroundsexy.ogg',
'sound/misc/RoundEndSounds/apcdestroyed.ogg',
'sound/misc/RoundEndSounds/bangindonk.ogg',
'sound/misc/RoundEndSounds/slugmissioncomplete.ogg',
'sound/misc/RoundEndSounds/bayojingle.ogg',
'sound/misc/RoundEndSounds/gameoveryeah.ogg',
'sound/misc/RoundEndSounds/rayman.ogg',
'sound/misc/RoundEndSounds/marioworld.ogg',
'sound/misc/RoundEndSounds/soniclevelcomplete.ogg',
'sound/misc/RoundEndSounds/calamitytrigger.ogg',
'sound/misc/RoundEndSounds/duckgame.ogg',
'sound/misc/RoundEndSounds/FTLvictory.ogg',
'sound/misc/RoundEndSounds/tfvictory.ogg',
'sound/misc/RoundEndSounds/megamanX.ogg',
'sound/misc/RoundEndSounds/castlevania.ogg',
)) // random end sounds!! - LastyBatsy
if(!end_credits.generated)
end_credits.on_roundend()
end_credits.rollem()
sleep(5)//should fix the issue of players not hearing the restart sound.
sleep(end_credits.starting_delay + 10)
for(var/client/C in clients)
if(config.server) //if you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite

View File

@@ -296,6 +296,10 @@ RENDERS_URL http://ss13.pomf.se/img/map-renders
## Uncomment to disable generation of minimaps (makes the server start faster!)
SKIP_MINIMAP_GENERATION
## SKIP_HOLOMINIMAP_GENERATION
## Uncomment to disable generation of holominimaps (makes the server start faster!)
SKIP_HOLOMINIMAP_GENERATION
## SKIP_VAULT_GENERATION
## Uncomment to disable generation of vaults (makes the server start faster!)
SKIP_VAULT_GENERATION

BIN
icons/credits/1zas.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
icons/credits/2cluck.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
icons/credits/3MPAOSA.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -816,6 +816,17 @@ window "mapwindow"
text-color = none
is-default = true
saved-params = "icon-size"
elem "credits"
type = BROWSER
pos = 0,0
size = 640x480
anchor1 = 0,0
anchor2 = 100,100
text-color = #ffffff
background-color = #000000
is-visible = false
saved-params = ""
auto-format = false
window "outputwindow"
elem "outputwindow"
@@ -1063,4 +1074,3 @@ window "window1"
background-color = #fffdd0
border = sunken
saved-params = "max-lines"

Binary file not shown.

Binary file not shown.

View File

@@ -1328,6 +1328,9 @@
#include "code\modules\components\ai\target_holders\target_holder.dm"
#include "code\modules\context_click\context_click.dm"
#include "code\modules\context_click\remote.dm"
#include "code\modules\credits\credit_disclaimers.dm"
#include "code\modules\credits\credits.dm"
#include "code\modules\credits\episode_name.dm"
#include "code\modules\customitems\item_spawning.dm"
#include "code\modules\customitems\definitions\base.dm"
#include "code\modules\customitems\definitions\N3X15.dm"