mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 18:32:03 +00:00
Map voting
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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]'"
|
||||
|
||||
|
||||
@@ -10,8 +10,10 @@ 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)
|
||||
@@ -20,7 +22,7 @@ var/global/datum/controller/vote/vote = new()
|
||||
|
||||
vote = src
|
||||
|
||||
proc/process() //called by master_controller
|
||||
/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
|
||||
@@ -31,7 +33,7 @@ var/global/datum/controller/vote/vote = new()
|
||||
|
||||
// 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)
|
||||
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()
|
||||
@@ -44,9 +46,9 @@ var/global/datum/controller/vote/vote = new()
|
||||
if(C)
|
||||
C << browse(vote.interface(C),"window=vote;can_close=0")
|
||||
|
||||
voting.Cut()
|
||||
//voting.Cut()
|
||||
|
||||
proc/reset()
|
||||
/datum/controller/vote/proc/reset()
|
||||
initiator = null
|
||||
time_remaining = 0
|
||||
mode = null
|
||||
@@ -56,7 +58,7 @@ var/global/datum/controller/vote/vote = new()
|
||||
voting.Cut()
|
||||
current_votes.Cut()
|
||||
|
||||
proc/get_result()
|
||||
/datum/controller/vote/proc/get_result()
|
||||
//get the highest number of votes
|
||||
var/greatest_votes = 0
|
||||
var/total_votes = 0
|
||||
@@ -104,14 +106,14 @@ var/global/datum/controller/vote/vote = new()
|
||||
. += option
|
||||
return .
|
||||
|
||||
proc/announce_result()
|
||||
/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>\n"
|
||||
text = "<b>Vote Tied Between:</b><br>"
|
||||
for(var/option in winners)
|
||||
text += "\t[option]\n"
|
||||
text += "\t[option]<br>"
|
||||
. = pick(winners)
|
||||
text += "<b>Vote Result: [.]</b>"
|
||||
else
|
||||
@@ -120,7 +122,7 @@ var/global/datum/controller/vote/vote = new()
|
||||
world << "<font color='purple'>[text]</font>"
|
||||
return .
|
||||
|
||||
proc/result()
|
||||
/datum/controller/vote/proc/result()
|
||||
. = announce_result()
|
||||
var/restart = 0
|
||||
if(.)
|
||||
@@ -141,6 +143,10 @@ var/global/datum/controller/vote/vote = new()
|
||||
if("crew_transfer")
|
||||
if(. == "Initiate Crew Transfer")
|
||||
init_shift_change(null, 1)
|
||||
if("map")
|
||||
if(.)
|
||||
chosen_map = ismapvote[.]
|
||||
//testing("Vote picked [chosen_map]")
|
||||
|
||||
|
||||
if(restart)
|
||||
@@ -154,7 +160,7 @@ var/global/datum/controller/vote/vote = new()
|
||||
|
||||
return .
|
||||
|
||||
proc/submit_vote(var/ckey, var/vote)
|
||||
/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
|
||||
@@ -167,7 +173,7 @@ var/global/datum/controller/vote/vote = new()
|
||||
return vote
|
||||
return 0
|
||||
|
||||
proc/initiate_vote(var/vote_type, var/initiator_key)
|
||||
/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)
|
||||
@@ -194,16 +200,25 @@ var/global/datum/controller/vote/vote = new()
|
||||
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 += "\n[question]"
|
||||
text += "<br>[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>"
|
||||
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')
|
||||
@@ -211,15 +226,17 @@ var/global/datum/controller/vote/vote = new()
|
||||
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 = round(config.vote_period/10)
|
||||
time_remaining = (ismapvote && ismapvote.len ? 60 : round(config.vote_period/10))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
proc/interface(var/client/C)
|
||||
/datum/controller/vote/proc/interface(var/client/C)
|
||||
if(!C) return
|
||||
var/admin = 0
|
||||
var/trialmin = 0
|
||||
@@ -277,7 +294,7 @@ var/global/datum/controller/vote/vote = new()
|
||||
return .
|
||||
|
||||
|
||||
Topic(href,href_list[],hsrc)
|
||||
/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")
|
||||
|
||||
@@ -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,7 +209,7 @@ 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)
|
||||
/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
|
||||
@@ -307,7 +307,7 @@ var/global/datum/controller/gameticker/ticker
|
||||
return
|
||||
|
||||
|
||||
proc/create_characters()
|
||||
/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")
|
||||
@@ -320,13 +320,13 @@ var/global/datum/controller/gameticker/ticker
|
||||
del(player)
|
||||
|
||||
|
||||
proc/collect_minds()
|
||||
/datum/controller/gameticker/proc/collect_minds()
|
||||
for(var/mob/living/player in player_list)
|
||||
if(player.mind)
|
||||
ticker.minds += player.mind
|
||||
|
||||
|
||||
proc/equip_characters()
|
||||
/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)
|
||||
@@ -341,7 +341,7 @@ var/global/datum/controller/gameticker/ticker
|
||||
M << "Captainship not forced on anyone."
|
||||
|
||||
|
||||
proc/process()
|
||||
/datum/controller/gameticker/proc/process()
|
||||
if(current_state != GAME_STATE_PLAYING)
|
||||
return 0
|
||||
|
||||
@@ -362,22 +362,24 @@ var/global/datum/controller/gameticker/ticker
|
||||
|
||||
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 << "\blue <B>Rebooting due to destruction of station in [restart_timeout/10] seconds</B>"
|
||||
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 << "\blue <B>Restarting in [restart_timeout/10] seconds</B>"
|
||||
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 << "\blue <B>Server will shut down for an automatic update in a few seconds.</B>"
|
||||
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)
|
||||
@@ -385,13 +387,13 @@ var/global/datum/controller/gameticker/ticker
|
||||
CallHook("Reboot",list())
|
||||
world.Reboot()
|
||||
else
|
||||
world << "\blue <B>An admin has delayed the round end</B>"
|
||||
world << "<span class='notice'><B>An admin has delayed the round end</B></span>"
|
||||
else
|
||||
world << "\blue <B>An admin has delayed the round end</B>"
|
||||
world << "<span class='notice'><B>An admin has delayed the round end</B></span>"
|
||||
|
||||
return 1
|
||||
|
||||
proc/getfactionbyname(var/name)
|
||||
/datum/controller/gameticker/proc/getfactionbyname(var/name)
|
||||
for(var/datum/faction/F in factions)
|
||||
if(F.name == name)
|
||||
return F
|
||||
|
||||
@@ -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
11
maps/voting/Readme.txt
Normal 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
BIN
sound/misc/rockthevote.ogg
Normal file
Binary file not shown.
Reference in New Issue
Block a user