Map voting

This commit is contained in:
Chris
2014-11-13 22:05:30 -06:00
parent ca9f2a3887
commit 9784e29eb9
7 changed files with 529 additions and 447 deletions

View File

@@ -12,6 +12,32 @@
return text
/proc/get_maps(root="maps/voting/")
var/list/maps = list()
var/recursion_limit = 20 //lots of maps waiting to be played, feels like TF2
//Get our potential maps
//testing("starting in [root]")
for(var/potential in flist(root))
if(copytext(potential,-1,0 != "/")) continue // Not a directory, ignore it.
//testing("Inside [root + potential]")
if(!recursion_limit) break
//our current working directory
var/path = root + potential
//The DMB that has the map we want.
var/binary
//Looking for a binary
for(var/binaries in flist(path))
//testing("Checking file [binaries]")
if(copytext(binaries,-4,0) == ".dmb")
binary = binaries
break
if(!binary)
warning("Map folder [path] does not contain a valid byond binary, skipping.")
else
maps[potential] = path + binary
recursion_limit--
return maps
//Sends resource files to client cache
/client/proc/getFiles()
for(var/file in args)

View File

@@ -153,6 +153,8 @@
var/emag_recharge_rate = 0
var/emag_recharge_ticks = 0
var/map_voting = 0
/datum/configuration/New()
. = ..()
var/list/L = typesof(/datum/game_mode) - /datum/game_mode
@@ -504,6 +506,8 @@
media_secret_key = value
if("vgws_base_url")
vgws_base_url = value
if("map_voting")
map_voting = 1
else
diary << "Unknown setting in configuration: '[name]'"

View File

@@ -10,304 +10,321 @@ var/global/datum/controller/vote/vote = new()
var/list/voted = list()
var/list/voting = list()
var/list/current_votes = list()
var/list/ismapvote
var/chosen_map
New()
. = ..()
/datum/controller/vote/New()
. = ..()
if (vote != src)
if (istype(vote))
qdel(vote)
if (vote != src)
if (istype(vote))
qdel(vote)
vote = src
vote = src
proc/process() //called by master_controller
if(mode)
// No more change mode votes after the game has started.
// 3 is GAME_STATE_PLAYING, but that #define is undefined for some reason
if(mode == "gamemode" && ticker.current_state >= 2)
world << "<b>Voting aborted due to game start.</b>"
src.reset()
return
/datum/controller/vote/proc/process() //called by master_controller
if(mode)
// No more change mode votes after the game has started.
// 3 is GAME_STATE_PLAYING, but that #define is undefined for some reason
if(mode == "gamemode" && ticker.current_state >= 2)
world << "<b>Voting aborted due to game start.</b>"
src.reset()
return
// Calculate how much time is remaining by comparing current time, to time of vote start,
// plus vote duration
time_remaining = round((started_time + config.vote_period - world.time)/10)
if(time_remaining < 0)
result()
for(var/client/C in voting)
if(C)
C << browse(null,"window=vote;can_close=0")
reset()
else
for(var/client/C in voting)
if(C)
C << browse(vote.interface(C),"window=vote;can_close=0")
voting.Cut()
proc/reset()
initiator = null
time_remaining = 0
mode = null
question = null
choices.Cut()
voted.Cut()
voting.Cut()
current_votes.Cut()
proc/get_result()
//get the highest number of votes
var/greatest_votes = 0
var/total_votes = 0
for(var/option in choices)
var/votes = choices[option]
total_votes += votes
if(votes > greatest_votes)
greatest_votes = votes
//default-vote for everyone who didn't vote
if(!config.vote_no_default && choices.len)
var/non_voters = (clients.len - total_votes)
if(non_voters > 0)
if(mode == "restart")
choices["Continue Playing"] += non_voters
if(choices["Continue Playing"] >= greatest_votes)
greatest_votes = choices["Continue Playing"]
else if(mode == "gamemode")
if(master_mode in choices)
choices[master_mode] += non_voters
if(choices[master_mode] >= greatest_votes)
greatest_votes = choices[master_mode]
else if(mode == "crew_transfer")
var/factor = 0.5
switch(world.time / (10 * 60)) // minutes
if(0 to 60)
factor = 0.5
if(61 to 120)
factor = 0.8
if(121 to 240)
factor = 1
if(241 to 300)
factor = 1.2
else
factor = 1.4
choices["Initiate Crew Transfer"] = round(choices["Initiate Crew Transfer"] * factor)
world << "<font color='purple'>Crew Transfer Factor: [factor]</font>"
greatest_votes = max(choices["Initiate Crew Transfer"], choices["Continue The Round"])
//get all options with that many votes and return them in a list
. = list()
if(greatest_votes)
for(var/option in choices)
if(choices[option] == greatest_votes)
. += option
return .
proc/announce_result()
var/list/winners = get_result()
var/text
if(winners.len > 0)
if(winners.len > 1)
text = "<b>Vote Tied Between:</b>\n"
for(var/option in winners)
text += "\t[option]\n"
. = pick(winners)
text += "<b>Vote Result: [.]</b>"
else
text += "<b>Vote Result: Inconclusive - No Votes!</b>"
log_vote(text)
world << "<font color='purple'>[text]</font>"
return .
proc/result()
. = announce_result()
var/restart = 0
if(.)
switch(mode)
if("restart")
if(. == "Restart Round")
restart = 1
if("gamemode")
if(master_mode != .)
world.save_mode(.)
if(ticker && ticker.mode)
restart = 1
else
master_mode = .
if(!going)
going = 1
world << "<font color='red'><b>The round will start soon.</b></font>"
if("crew_transfer")
if(. == "Initiate Crew Transfer")
init_shift_change(null, 1)
if(restart)
world << "World restarting due to vote..."
feedback_set_details("end_error","restart vote")
if(blackbox) blackbox.save_all_data_to_sql()
CallHook("Reboot",list())
sleep(50)
log_game("Rebooting due to restart vote")
world.Reboot()
return .
proc/submit_vote(var/ckey, var/vote)
if(mode)
if(config.vote_no_dead && usr.stat == DEAD && !usr.client.holder)
return 0
if(current_votes[ckey])
choices[choices[current_votes[ckey]]]--
if(vote && 1<=vote && vote<=choices.len)
voted += usr.ckey
choices[choices[vote]]++ //check this
current_votes[ckey] = vote
return vote
return 0
proc/initiate_vote(var/vote_type, var/initiator_key)
if(!mode)
if(started_time != null && !check_rights(R_ADMIN))
var/next_allowed_time = (started_time + config.vote_delay)
if(next_allowed_time > world.time)
return 0
// Calculate how much time is remaining by comparing current time, to time of vote start,
// plus vote duration
time_remaining = (ismapvote && ismapvote.len) ? (round((started_time + 600 - world.time)/10)) : (round((started_time + config.vote_period - world.time)/10))
if(time_remaining < 0)
result()
for(var/client/C in voting)
if(C)
C << browse(null,"window=vote;can_close=0")
reset()
switch(vote_type)
if("restart")
choices.Add("Restart Round","Continue Playing")
if("gamemode")
if(ticker.current_state >= 2)
return 0
choices.Add(config.votable_modes)
if("crew_transfer")
if(ticker.current_state <= 2)
return 0
question = "End the shift?"
choices.Add("Initiate Crew Transfer", "Continue The Round")
if("custom")
question = html_encode(input(usr,"What is the vote for?") as text|null)
if(!question) return 0
for(var/i=1,i<=10,i++)
var/option = capitalize(html_encode(input(usr,"Please enter an option or hit cancel to finish") as text|null))
if(!option || mode || !usr.client) break
choices.Add(option)
else return 0
mode = vote_type
initiator = initiator_key
started_time = world.time
var/text = "[capitalize(mode)] vote started by [initiator]."
if(mode == "custom")
text += "\n[question]"
log_vote(text)
world << "<font color='purple'><b>[text]</b>\nType vote to place your votes.\nYou have [config.vote_period/10] seconds to vote.</font>"
switch(vote_type)
if("crew_transfer")
world << sound('sound/voice/Serithi/Shuttlehere.ogg')
if("gamemode")
world << sound('sound/voice/Serithi/pretenddemoc.ogg')
if("custom")
world << sound('sound/voice/Serithi/weneedvote.ogg')
if(mode == "gamemode" && going)
going = 0
world << "<font color='red'><b>Round start has been delayed.</b></font>"
time_remaining = round(config.vote_period/10)
return 1
return 0
proc/interface(var/client/C)
if(!C) return
var/admin = 0
var/trialmin = 0
if(C.holder)
admin = 1
if(C.holder.rights & R_ADMIN)
trialmin = 1
voting |= C
. = "<html><head><title>Voting Panel</title></head><body>"
if(mode)
if(question) . += "<h2>Vote: '[question]'</h2>"
else . += "<h2>Vote: [capitalize(mode)]</h2>"
. += "Time Left: [time_remaining] s<hr><ul>"
for(var/i = 1, i <= choices.len, i++)
var/votes = choices[choices[i]]
if(!votes) votes = 0
if(current_votes[C.ckey] == i)
. += "<li><b><a href='?src=\ref[src];vote=[i]'>[choices[i]]</a> ([votes] votes)</b></li>"
else
. += "<li><a href='?src=\ref[src];vote=[i]'>[choices[i]]</a> ([votes] votes)</li>"
. += "</ul><hr>"
if(admin)
. += "(<a href='?src=\ref[src];vote=cancel'>Cancel Vote</a>) "
else
. += "<h2>Start a vote:</h2><hr><ul><li>"
//restart
if(trialmin || config.allow_vote_restart)
. += "<a href='?src=\ref[src];vote=restart'>Restart</a>"
else
. += "<font color='grey'>Restart (Disallowed)</font>"
. += "</li><li>"
if(trialmin || config.allow_vote_restart)
. += "<a href='?src=\ref[src];vote=crew_transfer'>Crew Transfer</a>"
else
. += "<font color='grey'>Crew Transfer (Disallowed)</font>"
if(trialmin)
. += "\t(<a href='?src=\ref[src];vote=toggle_restart'>[config.allow_vote_restart?"Allowed":"Disallowed"]</a>)"
. += "</li><li>"
//gamemode
if(trialmin || config.allow_vote_mode)
. += "<a href='?src=\ref[src];vote=gamemode'>GameMode</a>"
else
. += "<font color='grey'>GameMode (Disallowed)</font>"
if(trialmin)
. += "\t(<a href='?src=\ref[src];vote=toggle_gamemode'>[config.allow_vote_mode?"Allowed":"Disallowed"]</a>)"
for(var/client/C in voting)
if(C)
C << browse(vote.interface(C),"window=vote;can_close=0")
. += "</li>"
//custom
if(trialmin)
. += "<li><a href='?src=\ref[src];vote=custom'>Custom</a></li>"
. += "</ul><hr>"
. += "<a href='?src=\ref[src];vote=close' style='position:absolute;right:50px'>Close</a></body></html>"
return .
//voting.Cut()
/datum/controller/vote/proc/reset()
initiator = null
time_remaining = 0
mode = null
question = null
choices.Cut()
voted.Cut()
voting.Cut()
current_votes.Cut()
/datum/controller/vote/proc/get_result()
//get the highest number of votes
var/greatest_votes = 0
var/total_votes = 0
for(var/option in choices)
var/votes = choices[option]
total_votes += votes
if(votes > greatest_votes)
greatest_votes = votes
//default-vote for everyone who didn't vote
if(!config.vote_no_default && choices.len)
var/non_voters = (clients.len - total_votes)
if(non_voters > 0)
if(mode == "restart")
choices["Continue Playing"] += non_voters
if(choices["Continue Playing"] >= greatest_votes)
greatest_votes = choices["Continue Playing"]
else if(mode == "gamemode")
if(master_mode in choices)
choices[master_mode] += non_voters
if(choices[master_mode] >= greatest_votes)
greatest_votes = choices[master_mode]
else if(mode == "crew_transfer")
var/factor = 0.5
switch(world.time / (10 * 60)) // minutes
if(0 to 60)
factor = 0.5
if(61 to 120)
factor = 0.8
if(121 to 240)
factor = 1
if(241 to 300)
factor = 1.2
else
factor = 1.4
choices["Initiate Crew Transfer"] = round(choices["Initiate Crew Transfer"] * factor)
world << "<font color='purple'>Crew Transfer Factor: [factor]</font>"
greatest_votes = max(choices["Initiate Crew Transfer"], choices["Continue The Round"])
Topic(href,href_list[],hsrc)
if(!usr || !usr.client) return //not necessary but meh...just in-case somebody does something stupid
switch(href_list["vote"])
if("close")
voting -= usr.client
usr << browse(null, "window=vote")
return
if("cancel")
if(usr.client.holder)
reset()
if("toggle_restart")
if(usr.client.holder)
config.allow_vote_restart = !config.allow_vote_restart
if("toggle_gamemode")
if(usr.client.holder)
config.allow_vote_mode = !config.allow_vote_mode
//get all options with that many votes and return them in a list
. = list()
if(greatest_votes)
for(var/option in choices)
if(choices[option] == greatest_votes)
. += option
return .
/datum/controller/vote/proc/announce_result()
var/list/winners = get_result()
var/text
if(winners.len > 0)
if(winners.len > 1)
text = "<b>Vote Tied Between:</b><br>"
for(var/option in winners)
text += "\t[option]<br>"
. = pick(winners)
text += "<b>Vote Result: [.]</b>"
else
text += "<b>Vote Result: Inconclusive - No Votes!</b>"
log_vote(text)
world << "<font color='purple'>[text]</font>"
return .
/datum/controller/vote/proc/result()
. = announce_result()
var/restart = 0
if(.)
switch(mode)
if("restart")
if(config.allow_vote_restart || usr.client.holder)
initiate_vote("restart",usr.key)
if(. == "Restart Round")
restart = 1
if("gamemode")
if(config.allow_vote_mode || usr.client.holder)
initiate_vote("gamemode",usr.key)
if(master_mode != .)
world.save_mode(.)
if(ticker && ticker.mode)
restart = 1
else
master_mode = .
if(!going)
going = 1
world << "<font color='red'><b>The round will start soon.</b></font>"
if("crew_transfer")
if(config.allow_vote_restart || usr.client.holder)
initiate_vote("crew_transfer",usr.key)
if(. == "Initiate Crew Transfer")
init_shift_change(null, 1)
if("map")
if(.)
chosen_map = ismapvote[.]
//testing("Vote picked [chosen_map]")
if(restart)
world << "World restarting due to vote..."
feedback_set_details("end_error","restart vote")
if(blackbox) blackbox.save_all_data_to_sql()
CallHook("Reboot",list())
sleep(50)
log_game("Rebooting due to restart vote")
world.Reboot()
return .
/datum/controller/vote/proc/submit_vote(var/ckey, var/vote)
if(mode)
if(config.vote_no_dead && usr.stat == DEAD && !usr.client.holder)
return 0
if(current_votes[ckey])
choices[choices[current_votes[ckey]]]--
if(vote && 1<=vote && vote<=choices.len)
voted += usr.ckey
choices[choices[vote]]++ //check this
current_votes[ckey] = vote
return vote
return 0
/datum/controller/vote/proc/initiate_vote(var/vote_type, var/initiator_key)
if(!mode)
if(started_time != null && !check_rights(R_ADMIN))
var/next_allowed_time = (started_time + config.vote_delay)
if(next_allowed_time > world.time)
return 0
reset()
switch(vote_type)
if("restart")
choices.Add("Restart Round","Continue Playing")
if("gamemode")
if(ticker.current_state >= 2)
return 0
choices.Add(config.votable_modes)
if("crew_transfer")
if(ticker.current_state <= 2)
return 0
question = "End the shift?"
choices.Add("Initiate Crew Transfer", "Continue The Round")
if("custom")
if(usr.client.holder)
initiate_vote("custom",usr.key)
question = html_encode(input(usr,"What is the vote for?") as text|null)
if(!question) return 0
for(var/i=1,i<=10,i++)
var/option = capitalize(html_encode(input(usr,"Please enter an option or hit cancel to finish") as text|null))
if(!option || mode || !usr.client) break
choices.Add(option)
if("map")
question = "Rock The Vote Next Map!"
var/list/maps = get_maps()
for(var/key in maps)
choices.Add(key)
if(!choices.len)
world << "<span class='danger'>Failed to initiate map vote, no maps found.</span>"
return 0
ismapvote = maps
else return 0
mode = vote_type
initiator = initiator_key
started_time = world.time
var/text = "[capitalize(mode)] vote started by [initiator]."
if(mode == "custom")
text += "<br>[question]"
log_vote(text)
world << "<font color='purple'><b>[text]</b><br>Type vote to place your votes.<br>You have [ismapvote && ismapvote.len ? "60" : config.vote_period/10] seconds to vote.</font>"
switch(vote_type)
if("crew_transfer")
world << sound('sound/voice/Serithi/Shuttlehere.ogg')
if("gamemode")
world << sound('sound/voice/Serithi/pretenddemoc.ogg')
if("custom")
world << sound('sound/voice/Serithi/weneedvote.ogg')
if("map")
world << sound('sound/misc/rockthevote.ogg')
if(mode == "gamemode" && going)
going = 0
world << "<font color='red'><b>Round start has been delayed.</b></font>"
time_remaining = (ismapvote && ismapvote.len ? 60 : round(config.vote_period/10))
return 1
return 0
/datum/controller/vote/proc/interface(var/client/C)
if(!C) return
var/admin = 0
var/trialmin = 0
if(C.holder)
admin = 1
if(C.holder.rights & R_ADMIN)
trialmin = 1
voting |= C
. = "<html><head><title>Voting Panel</title></head><body>"
if(mode)
if(question) . += "<h2>Vote: '[question]'</h2>"
else . += "<h2>Vote: [capitalize(mode)]</h2>"
. += "Time Left: [time_remaining] s<hr><ul>"
for(var/i = 1, i <= choices.len, i++)
var/votes = choices[choices[i]]
if(!votes) votes = 0
if(current_votes[C.ckey] == i)
. += "<li><b><a href='?src=\ref[src];vote=[i]'>[choices[i]]</a> ([votes] votes)</b></li>"
else
submit_vote(usr.ckey, round(text2num(href_list["vote"])))
usr.vote()
. += "<li><a href='?src=\ref[src];vote=[i]'>[choices[i]]</a> ([votes] votes)</li>"
. += "</ul><hr>"
if(admin)
. += "(<a href='?src=\ref[src];vote=cancel'>Cancel Vote</a>) "
else
. += "<h2>Start a vote:</h2><hr><ul><li>"
//restart
if(trialmin || config.allow_vote_restart)
. += "<a href='?src=\ref[src];vote=restart'>Restart</a>"
else
. += "<font color='grey'>Restart (Disallowed)</font>"
. += "</li><li>"
if(trialmin || config.allow_vote_restart)
. += "<a href='?src=\ref[src];vote=crew_transfer'>Crew Transfer</a>"
else
. += "<font color='grey'>Crew Transfer (Disallowed)</font>"
if(trialmin)
. += "\t(<a href='?src=\ref[src];vote=toggle_restart'>[config.allow_vote_restart?"Allowed":"Disallowed"]</a>)"
. += "</li><li>"
//gamemode
if(trialmin || config.allow_vote_mode)
. += "<a href='?src=\ref[src];vote=gamemode'>GameMode</a>"
else
. += "<font color='grey'>GameMode (Disallowed)</font>"
if(trialmin)
. += "\t(<a href='?src=\ref[src];vote=toggle_gamemode'>[config.allow_vote_mode?"Allowed":"Disallowed"]</a>)"
. += "</li>"
//custom
if(trialmin)
. += "<li><a href='?src=\ref[src];vote=custom'>Custom</a></li>"
. += "</ul><hr>"
. += "<a href='?src=\ref[src];vote=close' style='position:absolute;right:50px'>Close</a></body></html>"
return .
/datum/controller/vote/Topic(href,href_list[],hsrc)
if(!usr || !usr.client) return //not necessary but meh...just in-case somebody does something stupid
switch(href_list["vote"])
if("close")
voting -= usr.client
usr << browse(null, "window=vote")
return
if("cancel")
if(usr.client.holder)
reset()
if("toggle_restart")
if(usr.client.holder)
config.allow_vote_restart = !config.allow_vote_restart
if("toggle_gamemode")
if(usr.client.holder)
config.allow_vote_mode = !config.allow_vote_mode
if("restart")
if(config.allow_vote_restart || usr.client.holder)
initiate_vote("restart",usr.key)
if("gamemode")
if(config.allow_vote_mode || usr.client.holder)
initiate_vote("gamemode",usr.key)
if("crew_transfer")
if(config.allow_vote_restart || usr.client.holder)
initiate_vote("crew_transfer",usr.key)
if("custom")
if(usr.client.holder)
initiate_vote("custom",usr.key)
else
submit_vote(usr.ckey, round(text2num(href_list["vote"])))
usr.vote()
/mob/verb/vote()

View File

@@ -63,7 +63,7 @@ var/global/datum/controller/gameticker/ticker
vote.process()
watchdog.check_for_update()
if(watchdog.waiting)
world << "\blue Server update detected, restarting momentarily."
world << "<span class='notice'>Server update detected, restarting momentarily.</span>"
watchdog.signal_ready()
return
if(going)
@@ -209,192 +209,194 @@ var/global/datum/controller/gameticker/ticker
var/obj/screen/cinematic = null
//Plus it provides an easy way to make cinematics for other events. Just use this as a template :)
proc/station_explosion_cinematic(var/station_missed=0, var/override = null)
if( cinematic ) return //already a cinematic in progress!
/datum/controller/gameticker/proc/station_explosion_cinematic(var/station_missed=0, var/override = null)
if( cinematic ) return //already a cinematic in progress!
//initialise our cinematic screen object
cinematic = new(src)
cinematic.icon = 'icons/effects/station_explosion.dmi'
cinematic.icon_state = "station_intact"
cinematic.layer = 20
cinematic.mouse_opacity = 0
cinematic.screen_loc = "1,0"
//initialise our cinematic screen object
cinematic = new(src)
cinematic.icon = 'icons/effects/station_explosion.dmi'
cinematic.icon_state = "station_intact"
cinematic.layer = 20
cinematic.mouse_opacity = 0
cinematic.screen_loc = "1,0"
var/obj/structure/stool/bed/temp_buckle = new(src)
//Incredibly hackish. It creates a bed within the gameticker (lol) to stop mobs running around
if(station_missed)
for(var/mob/living/M in living_mob_list)
M.buckled = temp_buckle //buckles the mob so it can't do anything
if(M.client)
M.client.screen += cinematic //show every client the cinematic
else //nuke kills everyone on z-level 1 to prevent "hurr-durr I survived"
for(var/mob/living/M in living_mob_list)
M.buckled = temp_buckle
if(M.client)
M.client.screen += cinematic
var/obj/structure/stool/bed/temp_buckle = new(src)
//Incredibly hackish. It creates a bed within the gameticker (lol) to stop mobs running around
if(station_missed)
for(var/mob/living/M in living_mob_list)
M.buckled = temp_buckle //buckles the mob so it can't do anything
if(M.client)
M.client.screen += cinematic //show every client the cinematic
else //nuke kills everyone on z-level 1 to prevent "hurr-durr I survived"
for(var/mob/living/M in living_mob_list)
M.buckled = temp_buckle
if(M.client)
M.client.screen += cinematic
switch(M.z)
if(0) //inside a crate or something
var/turf/T = get_turf(M)
if(T && T.z==1) //we don't use M.death(0) because it calls a for(/mob) loop and
M.health = 0
M.stat = DEAD
if(1) //on a z-level 1 turf.
switch(M.z)
if(0) //inside a crate or something
var/turf/T = get_turf(M)
if(T && T.z==1) //we don't use M.death(0) because it calls a for(/mob) loop and
M.health = 0
M.stat = DEAD
if(1) //on a z-level 1 turf.
M.health = 0
M.stat = DEAD
//Now animate the cinematic
switch(station_missed)
if(1) //nuke was nearby but (mostly) missed
if( mode && !override )
override = mode.name
switch( override )
if("nuclear emergency") //Nuke wasn't on station when it blew up
flick("intro_nuke",cinematic)
sleep(35)
world << sound('sound/effects/explosionfar.ogg')
flick("station_intact_fade_red",cinematic)
cinematic.icon_state = "summary_nukefail"
else
flick("intro_nuke",cinematic)
sleep(35)
world << sound('sound/effects/explosionfar.ogg')
//flick("end",cinematic)
if(2) //nuke was nowhere nearby //TODO: a really distant explosion animation
sleep(50)
world << sound('sound/effects/explosionfar.ogg')
else //station was destroyed
if( mode && !override )
override = mode.name
switch( override )
if("nuclear emergency") //Nuke Ops successfully bombed the station
flick("intro_nuke",cinematic)
sleep(35)
flick("station_explode_fade_red",cinematic)
world << sound('sound/effects/explosionfar.ogg')
cinematic.icon_state = "summary_nukewin"
if("AI malfunction") //Malf (screen,explosion,summary)
flick("intro_malf",cinematic)
sleep(76)
flick("station_explode_fade_red",cinematic)
world << sound('sound/effects/explosionfar.ogg')
cinematic.icon_state = "summary_malf"
if("blob") //Station nuked (nuke,explosion,summary)
flick("intro_nuke",cinematic)
sleep(35)
flick("station_explode_fade_red",cinematic)
world << sound('sound/effects/explosionfar.ogg')
cinematic.icon_state = "summary_selfdes"
else //Station nuked (nuke,explosion,summary)
flick("intro_nuke",cinematic)
sleep(35)
flick("station_explode_fade_red", cinematic)
world << sound('sound/effects/explosionfar.ogg')
cinematic.icon_state = "summary_selfdes"
for(var/mob/living/M in living_mob_list)
if(M.loc.z == 1)
M.death()//No mercy
//If its actually the end of the round, wait for it to end.
//Otherwise if its a verb it will continue on afterwards.
sleep(300)
if(cinematic) del(cinematic) //end the cinematic
if(temp_buckle) del(temp_buckle) //release everybody
return
proc/create_characters()
for(var/mob/new_player/player in player_list)
if(player.ready && player.mind)
if(player.mind.assigned_role=="AI")
player.close_spawn_windows()
player.AIize()
else if(!player.mind.assigned_role)
continue
//Now animate the cinematic
switch(station_missed)
if(1) //nuke was nearby but (mostly) missed
if( mode && !override )
override = mode.name
switch( override )
if("nuclear emergency") //Nuke wasn't on station when it blew up
flick("intro_nuke",cinematic)
sleep(35)
world << sound('sound/effects/explosionfar.ogg')
flick("station_intact_fade_red",cinematic)
cinematic.icon_state = "summary_nukefail"
else
player.FuckUpGenes(player.create_character())
del(player)
flick("intro_nuke",cinematic)
sleep(35)
world << sound('sound/effects/explosionfar.ogg')
//flick("end",cinematic)
proc/collect_minds()
for(var/mob/living/player in player_list)
if(player.mind)
ticker.minds += player.mind
if(2) //nuke was nowhere nearby //TODO: a really distant explosion animation
sleep(50)
world << sound('sound/effects/explosionfar.ogg')
proc/equip_characters()
var/captainless=1
for(var/mob/living/carbon/human/player in player_list)
if(player && player.mind && player.mind.assigned_role)
if(player.mind.assigned_role == "Captain")
captainless=0
if(player.mind.assigned_role != "MODE")
job_master.EquipRank(player, player.mind.assigned_role, 0)
EquipCustomItems(player)
if(captainless)
for(var/mob/M in player_list)
if(!istype(M,/mob/new_player))
M << "Captainship not forced on anyone."
else //station was destroyed
if( mode && !override )
override = mode.name
switch( override )
if("nuclear emergency") //Nuke Ops successfully bombed the station
flick("intro_nuke",cinematic)
sleep(35)
flick("station_explode_fade_red",cinematic)
world << sound('sound/effects/explosionfar.ogg')
cinematic.icon_state = "summary_nukewin"
if("AI malfunction") //Malf (screen,explosion,summary)
flick("intro_malf",cinematic)
sleep(76)
flick("station_explode_fade_red",cinematic)
world << sound('sound/effects/explosionfar.ogg')
cinematic.icon_state = "summary_malf"
if("blob") //Station nuked (nuke,explosion,summary)
flick("intro_nuke",cinematic)
sleep(35)
flick("station_explode_fade_red",cinematic)
world << sound('sound/effects/explosionfar.ogg')
cinematic.icon_state = "summary_selfdes"
else //Station nuked (nuke,explosion,summary)
flick("intro_nuke",cinematic)
sleep(35)
flick("station_explode_fade_red", cinematic)
world << sound('sound/effects/explosionfar.ogg')
cinematic.icon_state = "summary_selfdes"
for(var/mob/living/M in living_mob_list)
if(M.loc.z == 1)
M.death()//No mercy
//If its actually the end of the round, wait for it to end.
//Otherwise if its a verb it will continue on afterwards.
sleep(300)
if(cinematic) del(cinematic) //end the cinematic
if(temp_buckle) del(temp_buckle) //release everybody
return
proc/process()
if(current_state != GAME_STATE_PLAYING)
return 0
/datum/controller/gameticker/proc/create_characters()
for(var/mob/new_player/player in player_list)
if(player.ready && player.mind)
if(player.mind.assigned_role=="AI")
player.close_spawn_windows()
player.AIize()
else if(!player.mind.assigned_role)
continue
else
player.FuckUpGenes(player.create_character())
del(player)
mode.process()
emergency_shuttle.process()
watchdog.check_for_update()
/datum/controller/gameticker/proc/collect_minds()
for(var/mob/living/player in player_list)
if(player.mind)
ticker.minds += player.mind
var/force_round_end=0
// If server's empty, force round end.
if(watchdog.waiting && player_list.len == 0)
force_round_end=1
/datum/controller/gameticker/proc/equip_characters()
var/captainless=1
for(var/mob/living/carbon/human/player in player_list)
if(player && player.mind && player.mind.assigned_role)
if(player.mind.assigned_role == "Captain")
captainless=0
if(player.mind.assigned_role != "MODE")
job_master.EquipRank(player, player.mind.assigned_role, 0)
EquipCustomItems(player)
if(captainless)
for(var/mob/M in player_list)
if(!istype(M,/mob/new_player))
M << "Captainship not forced on anyone."
var/mode_finished = mode.check_finished() || (emergency_shuttle.location == 2 && emergency_shuttle.alert == 1) || force_round_end
if(!mode.explosion_in_progress && mode_finished)
current_state = GAME_STATE_FINISHED
spawn
declare_completion()
/datum/controller/gameticker/proc/process()
if(current_state != GAME_STATE_PLAYING)
return 0
spawn(50)
if (mode.station_was_nuked)
feedback_set_details("end_proper","nuke")
if(!delay_end && !watchdog.waiting)
world << "\blue <B>Rebooting due to destruction of station in [restart_timeout/10] seconds</B>"
mode.process()
emergency_shuttle.process()
watchdog.check_for_update()
var/force_round_end=0
// If server's empty, force round end.
if(watchdog.waiting && player_list.len == 0)
force_round_end=1
var/mode_finished = mode.check_finished() || (emergency_shuttle.location == 2 && emergency_shuttle.alert == 1) || force_round_end
if(!mode.explosion_in_progress && mode_finished)
current_state = GAME_STATE_FINISHED
spawn
declare_completion()
if(config.map_voting)
vote.initiate_vote("map","The Server")
spawn(50)
if (mode.station_was_nuked)
feedback_set_details("end_proper","nuke")
if(!delay_end && !watchdog.waiting)
world << "<span class='notice'><B>Rebooting due to destruction of station in [restart_timeout/10] seconds</B></span>"
else
feedback_set_details("end_proper","proper completion")
if(!delay_end && !watchdog.waiting)
world << "<span class='notice'><B>Restarting in [restart_timeout/10] seconds</B></span>"
if(blackbox)
blackbox.save_all_data_to_sql()
if (watchdog.waiting)
world << "<span class='notice'><B>Server will shut down for an automatic update in a few seconds.</B></span>"
watchdog.signal_ready()
else if(!delay_end)
sleep(restart_timeout)
if(!delay_end)
CallHook("Reboot",list())
world.Reboot()
else
feedback_set_details("end_proper","proper completion")
if(!delay_end && !watchdog.waiting)
world << "\blue <B>Restarting in [restart_timeout/10] seconds</B>"
world << "<span class='notice'><B>An admin has delayed the round end</B></span>"
else
world << "<span class='notice'><B>An admin has delayed the round end</B></span>"
if(blackbox)
blackbox.save_all_data_to_sql()
return 1
if (watchdog.waiting)
world << "\blue <B>Server will shut down for an automatic update in a few seconds.</B>"
watchdog.signal_ready()
else if(!delay_end)
sleep(restart_timeout)
if(!delay_end)
CallHook("Reboot",list())
world.Reboot()
else
world << "\blue <B>An admin has delayed the round end</B>"
else
world << "\blue <B>An admin has delayed the round end</B>"
return 1
proc/getfactionbyname(var/name)
for(var/datum/faction/F in factions)
if(F.name == name)
return F
/datum/controller/gameticker/proc/getfactionbyname(var/name)
for(var/datum/faction/F in factions)
if(F.name == name)
return F
/datum/controller/gameticker/proc/declare_completion()

View File

@@ -5,6 +5,8 @@
cache_lifespan = 0 //stops player uploaded stuff from being kept in the rsc past the current session
#define RECOMMENDED_VERSION 501
/world/New()
// Honk honk, fuck you science
populate_seed_list()
@@ -178,6 +180,26 @@
/world/Reboot(reason)
if(config.map_voting)
//testing("we have done a map vote")
if(fexists(vote.chosen_map))
//testing("[vote.chosen_map] exists")
var/start = 1
var/pos = findtext(vote.chosen_map, "/", start)
var/lastpos = pos
//testing("First slash [lastpos]")
while(pos > 0)
lastpos = pos
pos = findtext(vote.chosen_map, "/", start)
start = pos + 1
//testing("Next slash [pos]")
var/filename = copytext(vote.chosen_map, lastpos + 1, 0)
//testing("Found [filename]")
if(!fcopy(vote.chosen_map, filename))
//testing("Fcopy failed, deleting and copying")
fdel(filename)
fcopy(vote.chosen_map, filename)
spawn(0)
world << sound(pick('sound/AI/newroundsexy.ogg','sound/misc/apcdestroyed.ogg','sound/misc/bangindonk.ogg','sound/misc/slugmissioncomplete.ogg')) // random end sounds!! - LastyBatsy
@@ -200,7 +222,7 @@
if(C.is_afk(INACTIVITY_KICK))
if(!istype(C.mob, /mob/dead))
log_access("AFK: [key_name(C)]")
C << "\red You have been inactive for more than 10 minutes and have been disconnected."
C << "<span class='warning'>You have been inactive for more than 10 minutes and have been disconnected.</span>"
del(C)
#undef INACTIVITY_KICK

11
maps/voting/Readme.txt Normal file
View File

@@ -0,0 +1,11 @@
To utilize the map voter:
1. Uncomment or put MAP_VOTING in config.txt
2. Compile the DMB's for each map you want to be voted on(requires a recompile on every update)
3. Put each map's DMB in a folder designated to the map's name in maps/voting/ eg MetaStation for Meta Station and Box for Box Station
4. At the natural end of a round the map will be voted upon.
TODO:
Maybe add a verb for admins to force another map using file browse.
Setup a script to easily mass compile the maps (hint hint nexy)

BIN
sound/misc/rockthevote.ogg Normal file

Binary file not shown.