Merge branch 'master' into vg-parallax

This commit is contained in:
monster860
2016-07-28 16:45:10 -04:00
1423 changed files with 32699 additions and 29022 deletions
@@ -171,7 +171,7 @@
main.restartProcess(src.name)
/datum/controller/process/proc/kill()
if (!killed)
if(!killed)
var/msg = "[name] process was killed at tick #[ticks]."
log_debug(msg)
message_admins(msg)
@@ -186,22 +186,22 @@
// Do not call this directly - use SHECK or SCHECK_EVERY
/datum/controller/process/proc/sleepCheck(var/tickId = 0)
calls_since_last_scheck = 0
if (killed)
if(killed)
// The kill proc is the only place where killed is set.
// The kill proc should have deleted this datum, and all sleeping procs that are
// owned by it.
CRASH("A killed process is still running somehow...")
if (hung)
if(hung)
// This will only really help if the doWork proc ends up in an infinite loop.
handleHung()
CRASH("Process [name] hung and was restarted.")
if (main.getCurrentTickElapsedTime() > main.timeAllowance)
if(main.getCurrentTickElapsedTime() > main.timeAllowance)
sleep(world.tick_lag)
cpu_defer_count++
last_slept = 0
else
if (TimeOfTick > last_slept + sleep_interval)
if(TimeOfTick > last_slept + sleep_interval)
// If we haven't slept in sleep_interval deciseconds, sleep to allow other work to proceed.
sleep(0)
last_slept = TimeOfTick
@@ -213,14 +213,14 @@
var/elapsedTime = getElapsedTime()
if (hung)
if(hung)
handleHung()
return
else if (elapsedTime > hang_restart_time)
else if(elapsedTime > hang_restart_time)
hung()
else if (elapsedTime > hang_alert_time)
else if(elapsedTime > hang_alert_time)
setStatus(PROCESS_STATUS_PROBABLY_HUNG)
else if (elapsedTime > hang_warning_time)
else if(elapsedTime > hang_warning_time)
setStatus(PROCESS_STATUS_MAYBE_HUNG)
@@ -327,9 +327,7 @@
/datum/controller/process/proc/catchException(var/exception/e, var/thrower)
if(istype(e)) // Real runtimes go to the real error handler
// There are two newlines here, because handling desc sucks
e.desc = " Caught by process: [name]\n\n" + e.desc
world.Error(e, e_src = thrower)
log_runtime(e, thrower, "Caught by process: [name]")
return
var/etext = "[e]"
var/eid = "[e]" // Exception ID, for tracking repeated exceptions
@@ -66,7 +66,7 @@ var/global/datum/controller/processScheduler/processScheduler
* this treatment.
*/
/datum/controller/processScheduler/proc/deferSetupFor(var/processPath)
if (!(processPath in deferredSetupList))
if(!(processPath in deferredSetupList))
deferredSetupList += processPath
/datum/controller/processScheduler/proc/setup()
@@ -77,11 +77,11 @@ var/global/datum/controller/processScheduler/processScheduler
var/process
// Add all the processes we can find, except for the ticker
for (process in subtypesof(/datum/controller/process))
if (!(process in deferredSetupList))
for(process in subtypesof(/datum/controller/process))
if(!(process in deferredSetupList))
addProcess(new process(src))
for (process in deferredSetupList)
for(process in deferredSetupList)
addProcess(new process(src))
/datum/controller/processScheduler/proc/start()
@@ -114,7 +114,7 @@ var/global/datum/controller/processScheduler/processScheduler
for(var/datum/controller/process/p in running)
p.update()
if (isnull(p)) // Process was killed
if(isnull(p)) // Process was killed
continue
var/status = p.getStatus()
@@ -132,11 +132,11 @@ var/global/datum/controller/processScheduler/processScheduler
/datum/controller/processScheduler/proc/queueProcesses()
for(var/datum/controller/process/p in processes)
// Don't double-queue, don't queue running processes
if (p.disabled || p.running || p.queued || !p.idle)
if(p.disabled || p.running || p.queued || !p.idle)
continue
// If the process should be running by now, go ahead and queue it
if (world.time >= last_queued[p] + p.schedule_interval)
if(world.time >= last_queued[p] + p.schedule_interval)
setQueuedProcessState(p)
/datum/controller/processScheduler/proc/runQueuedProcesses()
@@ -217,34 +217,34 @@ var/global/datum/controller/processScheduler/processScheduler
recordEnd(process)
/datum/controller/processScheduler/proc/setIdleProcessState(var/datum/controller/process/process)
if (process in running)
if(process in running)
running -= process
if (process in queued)
if(process in queued)
queued -= process
if (!(process in idle))
if(!(process in idle))
idle += process
/datum/controller/processScheduler/proc/setQueuedProcessState(var/datum/controller/process/process)
if (process in running)
if(process in running)
running -= process
if (process in idle)
if(process in idle)
idle -= process
if (!(process in queued))
if(!(process in queued))
queued += process
// The other state transitions are handled internally by the process.
process.queued()
/datum/controller/processScheduler/proc/setRunningProcessState(var/datum/controller/process/process)
if (process in queued)
if(process in queued)
queued -= process
if (process in idle)
if(process in idle)
idle -= process
if (!(process in running))
if(!(process in running))
running += process
/datum/controller/processScheduler/proc/recordStart(var/datum/controller/process/process, var/time = null)
if (isnull(time))
if(isnull(time))
time = TimeOfGame
last_queued[process] = world.time
last_start[process] = time
@@ -253,7 +253,7 @@ var/global/datum/controller/processScheduler/processScheduler
last_start[process] = time
/datum/controller/processScheduler/proc/recordEnd(var/datum/controller/process/process, var/time = null)
if (isnull(time))
if(isnull(time))
time = TimeOfGame
var/lastRunTime = time - last_start[process]
@@ -273,7 +273,7 @@ var/global/datum/controller/processScheduler/processScheduler
highest_run_time[process] = time
var/list/lastTwenty = last_twenty_run_times[process]
if (lastTwenty.len == 20)
if(lastTwenty.len == 20)
lastTwenty.Cut(1, 2)
lastTwenty.len++
lastTwenty[lastTwenty.len] = time
@@ -304,7 +304,7 @@ var/global/datum/controller/processScheduler/processScheduler
/datum/controller/processScheduler/proc/getStatusData()
var/list/data = new
for (var/datum/controller/process/p in processes)
for(var/datum/controller/process/p in processes)
data.len++
data[data.len] = p.getContextData()
@@ -314,14 +314,14 @@ var/global/datum/controller/processScheduler/processScheduler
return processes.len
/datum/controller/processScheduler/proc/hasProcess(var/processName as text)
if (nameToProcessMap[processName])
if(nameToProcessMap[processName])
return 1
/datum/controller/processScheduler/proc/killProcess(var/processName as text)
restartProcess(processName)
/datum/controller/processScheduler/proc/restartProcess(var/processName as text)
if (hasProcess(processName))
if(hasProcess(processName))
var/datum/controller/process/oldInstance = nameToProcessMap[processName]
var/datum/controller/process/newInstance = new oldInstance.type(src)
newInstance._copyStateFrom(oldInstance)
@@ -329,24 +329,24 @@ var/global/datum/controller/processScheduler/processScheduler
oldInstance.kill()
/datum/controller/processScheduler/proc/enableProcess(var/processName as text)
if (hasProcess(processName))
if(hasProcess(processName))
var/datum/controller/process/process = nameToProcessMap[processName]
process.enable()
/datum/controller/processScheduler/proc/disableProcess(var/processName as text)
if (hasProcess(processName))
if(hasProcess(processName))
var/datum/controller/process/process = nameToProcessMap[processName]
process.disable()
/datum/controller/processScheduler/proc/getCurrentTickElapsedTime()
if (world.time > currentTick)
if(world.time > currentTick)
updateCurrentTickData()
return 0
else
return TimeOfTick
/datum/controller/processScheduler/proc/updateCurrentTickData()
if (world.time > currentTick)
if(world.time > currentTick)
// New tick!
currentTick = world.time
updateTimeAllowance()
+1 -1
View File
@@ -146,4 +146,4 @@ var/global/datum/controller/process/air_system/air_master
icemaster.icon = 'icons/turf/overlays.dmi'
icemaster.icon_state = "snowfloor"
icemaster.layer = TURF_LAYER+0.1
icemaster.mouse_opacity = 0
icemaster.mouse_opacity = 0
+1
View File
@@ -11,6 +11,7 @@ var/global/datum/controller/process/sun/sun
name = "sun"
schedule_interval = 600 // every 60 seconds
sun = src
log_startup_progress("Sun ticker starting up.")
angle = rand (0,360) // the station position to the sun is randomised at round start
rate = rand(50,200)/100 // 50% - 200% of standard rotation
+1
View File
@@ -9,6 +9,7 @@ var/global/datum/controller/process/ticker/tickerProcess
schedule_interval = 20 // every 2 seconds
lastTickerTime = world.timeofday
log_startup_progress("Time ticker starting up.")
if(!ticker)
ticker = new
+2 -1
View File
@@ -8,6 +8,7 @@ var/global/datum/controller/process/timer/timer_master
name = "timer"
schedule_interval = 5 //every 0.5 seconds
timer_master = src
log_startup_progress("Timer process starting up.")
/datum/controller/process/timer/statProcess()
..()
@@ -79,4 +80,4 @@ var/global/datum/controller/process/timer/timer_master
if(event.id == id)
qdel(event)
return 1
return 0
return 0
-6
View File
@@ -1,6 +0,0 @@
/datum/controller/process/vote/setup()
name = "vote"
schedule_interval = 10 // every second
/datum/controller/process/vote/doWork()
vote.process()
+52
View File
@@ -0,0 +1,52 @@
//Used for all kinds of weather, ex. lavaland ash storms.
var/global/datum/controller/process/weather/weather_master
/datum/controller/process/weather
var/list/processing_weather = list()
var/list/existing_weather = list()
var/list/eligible_zlevels = list()
/datum/controller/process/weather/setup()
name = "weather"
schedule_interval = 10
weather_master = src
for(var/V in subtypesof(/datum/weather))
var/datum/weather/W = V
existing_weather |= new W
/datum/controller/process/weather/statProcess()
..()
stat(null, "[processing_weather.len] weather")
/datum/controller/process/weather/doWork()
for(var/V in processing_weather)
var/datum/weather/W = V
if(W.aesthetic)
continue
for(var/mob/living/L in mob_list)
if(W.can_impact(L))
W.impact(L)
SCHECK
for(var/Z in eligible_zlevels)
var/list/possible_weather_for_this_z = list()
for(var/V in existing_weather)
var/datum/weather/WE = V
if(WE.target_z == Z && WE.probability) //Another check so that it doesn't run extra weather
possible_weather_for_this_z[WE] = WE.probability
var/datum/weather/W = pickweight(possible_weather_for_this_z)
run_weather(W.name)
eligible_zlevels -= Z
addtimer(src, "make_z_eligible", rand(3000, 6000) + W.weather_duration_upper, TRUE, Z) //Around 5-10 minutes between weathers
/datum/controller/process/weather/proc/run_weather(weather_name)
if(!weather_name)
return
for(var/V in existing_weather)
var/datum/weather/W = V
if(W.name == weather_name)
W.telegraph()
SCHECK
/datum/controller/process/weather/proc/make_z_eligible(zlevel)
eligible_zlevels |= zlevel
+12 -12
View File
@@ -153,7 +153,7 @@ var/list/DEPT_FREQS = list(AI_FREQ, COMM_FREQ, ENG_FREQ, MED_FREQ, SEC_FREQ, SCI
/proc/frequency_span_class(var/frequency)
// Antags!
if (frequency in ANTAG_FREQS)
if(frequency in ANTAG_FREQS)
return "syndradio"
// centcomm channels (deathsquid and ert)
if(frequency in CENT_FREQS)
@@ -167,7 +167,7 @@ var/list/DEPT_FREQS = list(AI_FREQ, COMM_FREQ, ENG_FREQ, MED_FREQ, SEC_FREQ, SCI
// department radio formatting (poorly optimized, ugh)
if(frequency == SEC_FREQ)
return "secradio"
if (frequency == ENG_FREQ)
if(frequency == ENG_FREQ)
return "engradio"
if(frequency == SCI_FREQ)
return "sciradio"
@@ -265,17 +265,17 @@ var/global/datum/controller/radio/radio_controller
if(!start_point)
qdel(signal)
return 0
if (filter)
if(filter)
send_to_filter(source, signal, filter, start_point, range)
send_to_filter(source, signal, RADIO_DEFAULT, start_point, range)
else
//Broadcast the signal to everyone!
for (var/next_filter in devices)
for(var/next_filter in devices)
send_to_filter(source, signal, next_filter, start_point, range)
//Sends a signal to all machines belonging to a given filter. Should be called by post_signal()
/datum/radio_frequency/proc/send_to_filter(obj/source, datum/signal/signal, var/filter, var/turf/start_point = null, var/range = null)
if (range && !start_point)
if(range && !start_point)
return
for(var/obj/device in devices[filter])
@@ -291,11 +291,11 @@ var/global/datum/controller/radio/radio_controller
device.receive_signal(signal, TRANSMISSION_RADIO, frequency)
/datum/radio_frequency/proc/add_listener(obj/device as obj, var/filter as text|null)
if (!filter)
if(!filter)
filter = RADIO_DEFAULT
//log_admin("add_listener(device=[device],filter=[filter]) frequency=[frequency]")
var/list/obj/devices_line = devices[filter]
if (!devices_line)
if(!devices_line)
devices_line = new
devices[filter] = devices_line
devices_line+=device
@@ -305,12 +305,12 @@ var/global/datum/controller/radio/radio_controller
//log_admin("DEBUG: devices(filter_str).len=[l]")
/datum/radio_frequency/proc/remove_listener(obj/device)
for (var/devices_filter in devices)
for(var/devices_filter in devices)
var/list/devices_line = devices[devices_filter]
devices_line-=device
while (null in devices_line)
while(null in devices_line)
devices_line -= null
if (devices_line.len==0)
if(devices_line.len==0)
devices -= devices_filter
qdel(devices_line)
@@ -335,11 +335,11 @@ var/global/datum/controller/radio/radio_controller
frequency = model.frequency
/datum/signal/proc/debug_print()
if (source)
if(source)
. = "signal = {source = '[source]' ([source:x],[source:y],[source:z])\n"
else
. = "signal = {source = '[source]' ()\n"
for (var/i in data)
for(var/i in data)
. += "data\[\"[i]\"\] = \"[data[i]]\"\n"
if(islist(data[i]))
var/list/L = data[i]
+86 -83
View File
@@ -18,9 +18,8 @@
var/log_adminwarn = 0 // log warnings admins get about bomb construction and such
var/log_pda = 0 // log pda messages
var/log_world_output = 0 // log world.log << messages
var/log_runtimes = 0 // Logs all runtimes.
var/log_runtimes = 0 // logs world.log to a file
var/log_hrefs = 0 // logs all links clicked in-game. Could be used for debugging and tracking down exploits
var/log_runtime = 0 // logs world.log to a file
var/sql_enabled = 0 // for sql switching
var/allow_admin_ooccolor = 0 // Allows admins with relevant permissions to have their own ooc colour
var/allow_vote_restart = 0 // allow votes to restart
@@ -168,6 +167,7 @@
var/list/overflow_whitelist = list() //whitelist for overflow
var/disable_away_missions = 0 // disable away missions
var/disable_space_ruins = 0 //disable space ruins
var/ooc_allowed = 1
var/looc_allowed = 1
@@ -181,18 +181,18 @@
/datum/configuration/New()
var/list/L = subtypesof(/datum/game_mode)
for (var/T in L)
for(var/T in L)
// I wish I didn't have to instance the game modes in order to look up
// their information, but it is the only way (at least that I know of).
var/datum/game_mode/M = new T()
if (M.config_tag)
if(M.config_tag)
if(!(M.config_tag in modes)) // ensure each mode is added only once
diary << "Adding game mode [M.name] ([M.config_tag]) to configuration."
src.modes += M.config_tag
src.mode_names[M.config_tag] = M.name
src.probabilities[M.config_tag] = M.probability
if (M.votable)
if(M.votable)
src.votable_modes += M.config_tag
qdel(M)
src.votable_modes += "secret"
@@ -204,188 +204,188 @@
if(!t) continue
t = trim(t)
if (length(t) == 0)
if(length(t) == 0)
continue
else if (copytext(t, 1, 2) == "#")
else if(copytext(t, 1, 2) == "#")
continue
var/pos = findtext(t, " ")
var/name = null
var/value = null
if (pos)
if(pos)
name = lowertext(copytext(t, 1, pos))
value = copytext(t, pos + 1)
else
name = lowertext(t)
if (!name)
if(!name)
continue
if(type == "config")
switch (name)
if ("resource_urls")
switch(name)
if("resource_urls")
config.resource_urls = splittext(value, " ")
if ("admin_legacy_system")
if("admin_legacy_system")
config.admin_legacy_system = 1
if ("ban_legacy_system")
if("ban_legacy_system")
config.ban_legacy_system = 1
if ("use_age_restriction_for_jobs")
if("use_age_restriction_for_jobs")
config.use_age_restriction_for_jobs = 1
if ("use_age_restriction_for_antags")
if("use_age_restriction_for_antags")
config.use_age_restriction_for_antags = 1
if ("jobs_have_minimal_access")
if("jobs_have_minimal_access")
config.jobs_have_minimal_access = 1
if ("log_ooc")
if("log_ooc")
config.log_ooc = 1
if ("log_access")
if("log_access")
config.log_access = 1
if ("log_say")
if("log_say")
config.log_say = 1
if ("log_admin")
if("log_admin")
config.log_admin = 1
if ("log_debug")
if("log_debug")
config.log_debug = text2num(value)
if ("log_game")
if("log_game")
config.log_game = 1
if ("log_vote")
if("log_vote")
config.log_vote = 1
if ("log_whisper")
if("log_whisper")
config.log_whisper = 1
if ("log_attack")
if("log_attack")
config.log_attack = 1
if ("log_emote")
if("log_emote")
config.log_emote = 1
if ("log_adminchat")
if("log_adminchat")
config.log_adminchat = 1
if ("log_adminwarn")
if("log_adminwarn")
config.log_adminwarn = 1
if ("log_pda")
if("log_pda")
config.log_pda = 1
if ("log_world_output")
if("log_world_output")
config.log_world_output = 1
if ("log_hrefs")
if("log_hrefs")
config.log_hrefs = 1
if ("log_runtime")
config.log_runtime = 1
if("log_runtime")
config.log_runtimes = 1
if ("mentors")
if("mentors")
config.mods_are_mentors = 1
if("allow_admin_ooccolor")
config.allow_admin_ooccolor = 1
if ("allow_vote_restart")
if("allow_vote_restart")
config.allow_vote_restart = 1
if ("allow_vote_mode")
if("allow_vote_mode")
config.allow_vote_mode = 1
if("no_dead_vote")
config.vote_no_dead = 1
if ("default_no_vote")
if("default_no_vote")
config.vote_no_default = 1
if ("vote_delay")
if("vote_delay")
config.vote_delay = text2num(value)
if ("vote_period")
if("vote_period")
config.vote_period = text2num(value)
if ("allow_ai")
if("allow_ai")
config.allow_ai = 1
// if ("authentication")
// if("authentication")
// config.enable_authentication = 1
if ("norespawn")
if("norespawn")
config.respawn = 0
if ("servername")
if("servername")
config.server_name = value
if ("serversuffix")
if("serversuffix")
config.server_suffix = 1
if ("nudge_script_path")
if("nudge_script_path")
config.nudge_script_path = value
if ("hostedby")
if("hostedby")
config.hostedby = value
if ("server")
if("server")
config.server = value
if ("banappeals")
if("banappeals")
config.banappeals = value
if ("wikiurl")
if("wikiurl")
config.wikiurl = value
if ("forumurl")
if("forumurl")
config.forumurl = value
if ("rulesurl")
if("rulesurl")
config.rulesurl = value
if ("donationsurl")
if("donationsurl")
config.donationsurl = value
if ("repositoryurl")
if("repositoryurl")
config.repositoryurl = value
if ("guest_jobban")
if("guest_jobban")
config.guest_jobban = 1
if ("guest_ban")
if("guest_ban")
guests_allowed = 0
if ("usewhitelist")
if("usewhitelist")
config.usewhitelist = 1
if ("feature_object_spell_system")
if("feature_object_spell_system")
config.feature_object_spell_system = 1
if ("allow_metadata")
if("allow_metadata")
config.allow_Metadata = 1
if ("traitor_scaling")
if("traitor_scaling")
config.traitor_scaling = 1
if("protect_roles_from_antagonist")
config.protect_roles_from_antagonist = 1
if ("probability")
if("probability")
var/prob_pos = findtext(value, " ")
var/prob_name = null
var/prob_value = null
if (prob_pos)
if(prob_pos)
prob_name = lowertext(copytext(value, 1, prob_pos))
prob_value = copytext(value, prob_pos + 1)
if (prob_name in config.modes)
if(prob_name in config.modes)
config.probabilities[prob_name] = text2num(prob_value)
else
diary << "Unknown game mode probability configuration definition: [prob_name]."
@@ -548,6 +548,9 @@
if("disable_away_missions")
config.disable_away_missions = 1
if("disable_space_ruins")
config.disable_space_ruins = 1
if("disable_lobby_music")
config.disable_lobby_music = 1
@@ -611,11 +614,11 @@
config.reactionary_explosions = 1
if("bombcap")
var/BombCap = text2num(value)
if (!BombCap)
if(!BombCap)
continue
if (BombCap < 4)
if(BombCap < 4)
BombCap = 4
if (BombCap > 128)
if(BombCap > 128)
BombCap = 128
MAX_EX_DEVESTATION_RANGE = round(BombCap/4)
@@ -634,36 +637,36 @@
if(!t) continue
t = trim(t)
if (length(t) == 0)
if(length(t) == 0)
continue
else if (copytext(t, 1, 2) == "#")
else if(copytext(t, 1, 2) == "#")
continue
var/pos = findtext(t, " ")
var/name = null
var/value = null
if (pos)
if(pos)
name = lowertext(copytext(t, 1, pos))
value = copytext(t, pos + 1)
else
name = lowertext(t)
if (!name)
if(!name)
continue
switch (name)
switch(name)
if("sql_enabled")
config.sql_enabled = 1
if ("address")
if("address")
sqladdress = value
if ("port")
if("port")
sqlport = value
if ("feedback_database")
if("feedback_database")
sqlfdbkdb = value
if ("feedback_login")
if("feedback_login")
sqlfdbklogin = value
if ("feedback_password")
if("feedback_password")
sqlfdbkpass = value
if("feedback_tableprefix")
sqlfdbktableprefix = value
@@ -676,9 +679,9 @@
if(!t) continue
t = trim(t)
if (length(t) == 0)
if(length(t) == 0)
continue
else if (copytext(t, 1, 2) == "#")
else if(copytext(t, 1, 2) == "#")
continue
config.overflow_whitelist += t
@@ -686,25 +689,25 @@
/datum/configuration/proc/pick_mode(mode_name)
// I wish I didn't have to instance the game modes in order to look up
// their information, but it is the only way (at least that I know of).
for (var/T in subtypesof(/datum/game_mode))
for(var/T in subtypesof(/datum/game_mode))
var/datum/game_mode/M = new T()
if (M.config_tag && M.config_tag == mode_name)
if(M.config_tag && M.config_tag == mode_name)
return M
qdel(M)
return new /datum/game_mode/extended()
/datum/configuration/proc/get_runnable_modes()
var/list/datum/game_mode/runnable_modes = new
for (var/T in subtypesof(/datum/game_mode))
for(var/T in subtypesof(/datum/game_mode))
var/datum/game_mode/M = new T()
// to_chat(world, "DEBUG: [T], tag=[M.config_tag], prob=[probabilities[M.config_tag]]")
if (!(M.config_tag in modes))
if(!(M.config_tag in modes))
qdel(M)
continue
if (probabilities[M.config_tag]<=0)
if(probabilities[M.config_tag]<=0)
qdel(M)
continue
if (M.can_start())
if(M.can_start())
runnable_modes[M] = probabilities[M.config_tag]
// to_chat(world, "DEBUG: runnable_mode\[[runnable_modes.len]\] = [M.config_tag]")
return runnable_modes
+2 -2
View File
@@ -18,8 +18,8 @@ var/global/datum/controller/failsafe/failsafe
. = ..()
// There can be only one failsafe. Out with the old in with the new (that way we can restart the Failsafe by spawning a new one).
if (failsafe != src)
if (istype(failsafe))
if(failsafe != src)
if(istype(failsafe))
recover()
qdel(failsafe)
+21
View File
@@ -99,3 +99,24 @@
* Parameters: var/mob/living/carbon/human/captain
*/
/hook/captain_spawned
/**
* Mob login hook.
* Called in login.dm when a player logs in to a mob.
* Parameters: var/client/client, var/mob/mob
*/
/hook/mob_login
/**
* Mob logout hook.
* Called in logout.dm when a player logs out of a mob.
* Parameters: var/client/client, var/mob/mob
*/
/hook/mob_logout
/**
* Mob area change hook.
* Called in area.dm when a mob moves from one area to another.
* Parameters: var/mob/mob, var/area/newarea, var/area/oldarea
*/
/hook/mob_area_change
+16 -12
View File
@@ -11,16 +11,16 @@ var/global/air_processing_killed = 0
var/global/pipe_processing_killed = 0
/datum/controller
var/processing = 0
var/iteration = 0
var/processing_interval = 0
var/processing = 0
var/iteration = 0
var/processing_interval = 0
/datum/controller/proc/recover() // If we are replacing an existing controller (due to a crash) we attempt to preserve as much as we can.
datum/controller/game_controller
var/list/shuttle_list // For debugging and VV
/datum/controller/game_controller
var/list/shuttle_list // For debugging and VV
datum/controller/game_controller/New()
/datum/controller/game_controller/New()
//There can be only one master_controller. Out with the old and in with the new.
if(master_controller != src)
if(istype(master_controller))
@@ -38,12 +38,16 @@ datum/controller/game_controller/New()
if(!syndicate_code_phrase) syndicate_code_phrase = generate_code_phrase()
if(!syndicate_code_response) syndicate_code_response = generate_code_phrase()
datum/controller/game_controller/proc/setup()
/datum/controller/game_controller/proc/setup()
world.tick_lag = config.Ticklag
zlevels.initialize()
preloadTemplates()
if(!config.disable_away_missions)
createRandomZlevel()
if(!config.disable_space_ruins)
seedRuins(7, rand(0, 3), /area/space, space_ruins_templates)
setup_objects()
setupgenetics()
@@ -60,21 +64,21 @@ datum/controller/game_controller/proc/setup()
populate_spawn_points()
datum/controller/game_controller/proc/setup_objects()
/datum/controller/game_controller/proc/setup_objects()
var/watch = start_watch()
var/count = 0
var/overwatch = start_watch() // Overall.
log_startup_progress("Populating asset cache...")
populate_asset_cache()
log_startup_progress(" Populated [asset_cache.len] assets in [stop_watch(watch)]s.")
log_startup_progress(" Populated [asset_cache.len] assets in [stop_watch(watch)]s.")
watch = start_watch()
log_startup_progress("Initializing objects...")
for(var/atom/movable/object in world)
object.initialize()
count++
log_startup_progress(" Initialized [count] objects in [stop_watch(watch)]s.")
log_startup_progress(" Initialized [count] objects in [stop_watch(watch)]s.")
watch = start_watch()
count = 0
@@ -88,7 +92,7 @@ datum/controller/game_controller/proc/setup_objects()
var/obj/machinery/atmospherics/unary/vent_scrubber/T = U
T.broadcast_status()
count++
log_startup_progress(" Initialized [count] atmospherics machines in [stop_watch(watch)]s.")
log_startup_progress(" Initialized [count] atmospherics machines in [stop_watch(watch)]s.")
watch = start_watch()
count = 0
@@ -96,6 +100,6 @@ datum/controller/game_controller/proc/setup_objects()
for(var/obj/machinery/atmospherics/machine in machines)
machine.build_network()
count++
log_startup_progress(" Initialized [count] pipe networks in [stop_watch(watch)]s.")
log_startup_progress(" Initialized [count] pipes in [stop_watch(watch)]s.")
log_startup_progress("Finished object initializations in [stop_watch(overwatch)]s.")
+5 -2
View File
@@ -18,7 +18,7 @@
return
/client/proc/debug_controller(controller in list("Master","failsafe","Ticker","Air","Lighting","Jobs","Sun","Radio","Configuration","pAI", "Cameras","Garbage", "Transfer Controller","Event","Alarm","Scheduler","Nano"))
/client/proc/debug_controller(controller in list("Master","failsafe","Ticker","Air","Lighting","Jobs","Sun","Radio","Configuration","pAI", "Cameras","Garbage", "Transfer Controller","Event","Alarm","Scheduler","Nano","Vote"))
set category = "Debug"
set name = "Debug Controller"
set desc = "Debug the various periodic loop controllers for the game (be careful!)"
@@ -28,7 +28,7 @@
if("Master")
debug_variables(master_controller)
feedback_add_details("admin_verb","DMC")
if ("failsafe")
if("failsafe")
debug_variables(failsafe)
feedback_add_details("admin_verb", "dfailsafe")
if("Ticker")
@@ -73,6 +73,9 @@
if("Nano")
debug_variables(nanomanager)
feedback_add_details("admin_verb","DNano")
if("Vote")
debug_variables(vote)
feedback_add_details("admin_verb","DVote")
message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.")
return
+365 -310
View File
@@ -2,7 +2,7 @@ var/datum/controller/vote/vote = new()
var/global/list/round_voters = list() //Keeps track of the individuals voting for a given round, for use in forcedrafting.
datum/controller/vote
/datum/controller/vote
var/initiator = null
var/started_time = null
var/time_remaining = 0
@@ -14,340 +14,395 @@ datum/controller/vote
var/list/current_votes = list()
var/auto_muted = 0
New()
if(vote != src)
if(istype(vote))
qdel(vote)
vote = src
/datum/controller/vote/New()
if(vote != src)
if(istype(vote))
qdel(vote)
vote = src
spawn(0)
while(!gcDestroyed)
try
while(!gcDestroyed)
sleep(10)
process()
catch(var/exception/e)
log_runtime(e, src, "Caught in vote controller")
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)
to_chat(world, "<b>Voting aborted due to game start.</b>")
src.reset()
return
/datum/controller/vote/proc/process()
if(mode)
// No more change mode votes after the game has started.
if(mode == "gamemode" && ticker.current_state >= GAME_STATE_SETTING_UP)
to_chat(world, "<b>Voting aborted due to game start.</b>")
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)
// 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")
if(time_remaining < 0)
result()
for(var/client/C in voting)
if(C)
C << browse(null,"window=vote")
reset()
else
for(var/client/C in voting)
update_panel(C)
CHECK_TICK
voting.Cut()
/datum/controller/vote/proc/autotransfer()
initiate_vote("crew_transfer","the server")
proc/autotransfer()
initiate_vote("crew_transfer","the server")
/datum/controller/vote/proc/reset()
initiator = null
time_remaining = 0
mode = null
question = null
choices.Cut()
voted.Cut()
voting.Cut()
current_votes.Cut()
proc/reset()
initiator = null
time_remaining = 0
mode = null
question = null
choices.Cut()
voted.Cut()
voting.Cut()
current_votes.Cut()
if(auto_muted && !config.ooc_allowed)
auto_muted = 0
config.ooc_allowed = !( config.ooc_allowed )
to_chat(world, "<b>The OOC channel has been automatically enabled due to vote end.</b>")
log_admin("OOC was toggled automatically due to vote end.")
message_admins("OOC has been toggled on automatically.")
if(auto_muted && !config.ooc_allowed)
auto_muted = 0
config.ooc_allowed = !( config.ooc_allowed )
to_chat(world, "<b>The OOC channel has been automatically enabled due to vote end.</b>")
log_admin("OOC was toggled automatically due to vote end.")
message_admins("OOC has been toggled on automatically.")
proc/get_result()
//get the highest number of votes
var/greatest_votes = 0
var/total_votes = 0
/datum/controller/vote/proc/get_result()
var/greatest_votes = 0
var/total_votes = 0
var/list/sorted_choices = list()
var/sorted_highest
var/sorted_votes = -1
//get the highest number of votes, while also sorting the list
while(choices.len)
// This is a very inefficient sorting method, but that's okay
for(var/option in choices)
var/votes = choices[option]
total_votes += votes
if(sorted_votes < votes)
sorted_highest = option
sorted_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)
to_chat(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)
if(mode != "gamemode" || ticker.hide_mode == 0) // Here we are making sure we don't announce potential game modes
text = "<b>Vote Tied Between:</b>\n"
for(var/option in winners)
text += "\t[option]\n"
. = pick(winners)
for(var/key in current_votes)
if(choices[current_votes[key]] == .)
round_voters += key // Keep track of who voted for the winning round.
if((mode == "gamemode" && . == "extended") || ticker.hide_mode == 0) // Announce Extended gamemode, but not other gamemodes
text += "<b>Vote Result: [.]</b>"
else
if(mode != "gamemode")
text += "<b>Vote Result: [.]</b>"
else
text += "<b>The vote has ended.</b>" // What will be shown if it is a gamemode vote that isn't extended
else
text += "<b>Vote Result: Inconclusive - No Votes!</b>"
log_vote(text)
to_chat(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
to_chat(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.Reboot("Restart vote successful.", "end_error", "restart vote")
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
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 (check_rights(R_ADMIN|R_MOD))
if(ticker.current_state <= 2)
return 0
question = "End the shift?"
choices.Add("Initiate Crew Transfer", "Continue The Round")
sorted_votes = -1
total_votes += choices[sorted_highest]
sorted_choices[sorted_highest] = choices[sorted_highest] || 0
choices -= sorted_highest
choices = sorted_choices
//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
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)
to_chat(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/ambience/alarm4.ogg')
if("gamemode")
world << sound('sound/ambience/alarm4.ogg')
if("custom")
world << sound('sound/ambience/alarm4.ogg')
if(mode == "gamemode" && going)
going = 0
to_chat(world, "<font color='red'><b>Round start has been delayed.</b></font>")
if(mode == "crew_transfer" && config.ooc_allowed)
auto_muted = 1
config.ooc_allowed = !( config.ooc_allowed )
to_chat(world, "<b>The OOC channel has been automatically disabled due to a crew transfer vote.</b>")
log_admin("OOC was toggled automatically due to crew_transfer vote.")
message_admins("OOC has been toggled off automatically.")
if(mode == "gamemode" && config.ooc_allowed)
auto_muted = 1
config.ooc_allowed = !( config.ooc_allowed )
to_chat(world, "<b>The OOC channel has been automatically disabled due to the gamemode vote.</b>")
log_admin("OOC was toggled automatically due to gamemode vote.")
message_admins("OOC has been toggled off automatically.")
if(mode == "custom" && config.ooc_allowed)
auto_muted = 1
config.ooc_allowed = !( config.ooc_allowed )
to_chat(world, "<b>The OOC channel has been automatically disabled due to a custom vote.</b>")
log_admin("OOC was toggled automatically due to custom vote.")
message_admins("OOC has been toggled off automatically.")
factor = 1.4
choices["Initiate Crew Transfer"] = round(choices["Initiate Crew Transfer"] * factor)
to_chat(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 .
/datum/controller/vote/proc/announce_result()
var/list/winners = get_result()
var/text
if(winners.len > 0)
if(winners.len > 1)
if(mode != "gamemode" || ticker.hide_mode == 0) // Here we are making sure we don't announce potential game modes
text = "<b>Vote Tied Between:</b>\n"
for(var/option in winners)
text += "\t[option]\n"
. = pick(winners)
time_remaining = round(config.vote_period/10)
return 1
return 0
proc/interface(var/client/C)
if(!C) return
var/admin = check_rights(R_ADMIN,0)
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]] ([votes] votes)</a></b></li>"
else
. += "<li><a href='?src=\ref[src];vote=[i]'>[choices[i]] ([votes] votes)</a></li>"
. += "</ul><hr>"
if(admin)
. += "(<a href='?src=\ref[src];vote=cancel'>Cancel Vote</a>) "
for(var/key in current_votes)
if(choices[current_votes[key]] == .)
round_voters += key // Keep track of who voted for the winning round.
if(mode == "gamemode" && (. == "extended" || ticker.hide_mode == 0)) // Announce Extended gamemode, but not other gamemodes
text += "<b>Vote Result: [.] ([choices[.]] vote\s)</b>"
else
. += "<h2>Start a vote:</h2><hr><ul><li>"
//restart
if(admin || config.allow_vote_restart)
. += "<a href='?src=\ref[src];vote=restart'>Restart</a>"
if(mode == "custom")
// Completely replace text to show all results in custom votes
text = "<b><span style='text-decoration: underline;'>[question]</span></b>\n"
for(var/option in winners)
text += "\t<b>[option]: [choices[option]] vote\s</b>\n"
for(var/option in (choices-winners))
text += "\t[option]: [choices[option]] vote\s\n"
else if(mode != "gamemode")
text += "<b>Vote Result: [.] ([choices[.]] vote\s)</b>"
else
. += "<font color='grey'>Restart (Disallowed)</font>"
. += "</li><li>"
if(admin || config.allow_vote_restart)
. += "<a href='?src=\ref[src];vote=crew_transfer'>Crew Transfer</a>"
else
. += "<font color='grey'>Crew Transfer (Disallowed)</font>"
if(admin)
. += "\t(<a href='?src=\ref[src];vote=toggle_restart'>[config.allow_vote_restart?"Allowed":"Disallowed"]</a>)"
. += "</li><li>"
//gamemode
if(admin || config.allow_vote_mode)
. += "<a href='?src=\ref[src];vote=gamemode'>GameMode</a>"
else
. += "<font color='grey'>GameMode (Disallowed)</font>"
if(admin)
. += "\t(<a href='?src=\ref[src];vote=toggle_gamemode'>[config.allow_vote_mode?"Allowed":"Disallowed"]</a>)"
text += "<b>The vote has ended.</b>" // What will be shown if it is a gamemode vote that isn't extended
. += "</li>"
//custom
if(admin)
. += "<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 .
else
text += "<b>Vote Result: Inconclusive - No Votes!</b>"
log_vote(text)
to_chat(world, "<font color='purple'>[text]</font>")
return .
Topic(href,href_list[],hsrc)
if(!usr || !usr.client) return //not necessary but meh...just in-case somebody does something stupid
var/admin = check_rights(R_ADMIN,0)
switch(href_list["vote"])
if("close")
voting -= usr.client
usr << browse(null, "window=vote")
return
if("cancel")
if(admin)
reset()
if("toggle_restart")
if(admin)
config.allow_vote_restart = !config.allow_vote_restart
if("toggle_gamemode")
if(admin)
config.allow_vote_mode = !config.allow_vote_mode
/datum/controller/vote/proc/result()
. = announce_result()
var/restart = 0
if(.)
switch(mode)
if("restart")
if(config.allow_vote_restart || admin)
initiate_vote("restart",usr.key)
if(. == "Restart Round")
restart = 1
if("gamemode")
if(config.allow_vote_mode || admin)
initiate_vote("gamemode",usr.key)
if(master_mode != .)
world.save_mode(.)
if(ticker && ticker.mode)
restart = 1
else
master_mode = .
if(!going)
going = 1
to_chat(world, "<font color='red'><b>The round will start soon.</b></font>")
if("crew_transfer")
if(config.allow_vote_restart || admin)
initiate_vote("crew_transfer",usr.key)
if(. == "Initiate Crew Transfer")
init_shift_change(null, 1)
if(restart)
world.Reboot("Restart vote successful.", "end_error", "restart vote")
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(check_rights(R_ADMIN|R_MOD))
if(ticker.current_state <= 2)
return 0
question = "End the shift?"
choices.Add("Initiate Crew Transfer", "Continue The Round")
else
if(ticker.current_state <= 2)
return 0
question = "End the shift?"
choices.Add("Initiate Crew Transfer", "Continue The Round")
if("custom")
if(admin)
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)
else
submit_vote(usr.ckey, round(text2num(href_list["vote"])))
usr.vote()
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]"
if(usr)
log_admin("[capitalize(mode)] ([question]) vote started by [key_name(usr)].")
else if(usr)
log_admin("[capitalize(mode)] vote started by [key_name(usr)].")
log_vote(text)
to_chat(world, {"<font color='purple'><b>[text]</b>
<a href='?src=\ref[src];vote=open'>Click here or type vote to place your vote.</a>
You have [config.vote_period/10] seconds to vote.</font>"})
switch(vote_type)
if("crew_transfer")
world << sound('sound/ambience/alarm4.ogg')
if("gamemode")
world << sound('sound/ambience/alarm4.ogg')
if("custom")
world << sound('sound/ambience/alarm4.ogg')
if(mode == "gamemode" && going)
going = 0
to_chat(world, "<font color='red'><b>Round start has been delayed.</b></font>")
if(mode == "crew_transfer" && config.ooc_allowed)
auto_muted = 1
config.ooc_allowed = !( config.ooc_allowed )
to_chat(world, "<b>The OOC channel has been automatically disabled due to a crew transfer vote.</b>")
log_admin("OOC was toggled automatically due to crew_transfer vote.")
message_admins("OOC has been toggled off automatically.")
if(mode == "gamemode" && config.ooc_allowed)
auto_muted = 1
config.ooc_allowed = !( config.ooc_allowed )
to_chat(world, "<b>The OOC channel has been automatically disabled due to the gamemode vote.</b>")
log_admin("OOC was toggled automatically due to gamemode vote.")
message_admins("OOC has been toggled off automatically.")
if(mode == "custom" && config.ooc_allowed)
auto_muted = 1
config.ooc_allowed = !( config.ooc_allowed )
to_chat(world, "<b>The OOC channel has been automatically disabled due to a custom vote.</b>")
log_admin("OOC was toggled automatically due to custom vote.")
message_admins("OOC has been toggled off automatically.")
time_remaining = round(config.vote_period/10)
return 1
return 0
/datum/controller/vote/proc/browse_to(var/client/C)
if(!C)
return
var/admin = check_rights(R_ADMIN, 0, user = C.mob)
voting |= C
var/dat = {"<script>
function update_vote_div(new_content) {
var votediv = document.getElementById("vote_div");
if(votediv) {
votediv.innerHTML = new_content;
}
}
</script>"}
if(mode)
dat += "<div id='vote_div'>[vote_html(C)]</div><hr>"
if(admin)
dat += "(<a href='?src=\ref[src];vote=cancel'>Cancel Vote</a>) "
else
dat += "<div id='vote_div'><h2>Start a vote:</h2><hr><ul><li>"
//restart
if(admin || config.allow_vote_restart)
dat += "<a href='?src=\ref[src];vote=restart'>Restart</a>"
else
dat += "<font color='grey'>Restart (Disallowed)</font>"
dat += "</li><li>"
if(admin || config.allow_vote_restart)
dat += "<a href='?src=\ref[src];vote=crew_transfer'>Crew Transfer</a>"
else
dat += "<font color='grey'>Crew Transfer (Disallowed)</font>"
if(admin)
dat += "\t(<a href='?src=\ref[src];vote=toggle_restart'>[config.allow_vote_restart?"Allowed":"Disallowed"]</a>)"
dat += "</li><li>"
//gamemode
if(admin || config.allow_vote_mode)
dat += "<a href='?src=\ref[src];vote=gamemode'>GameMode</a>"
else
dat += "<font color='grey'>GameMode (Disallowed)</font>"
if(admin)
dat += "\t(<a href='?src=\ref[src];vote=toggle_gamemode'>[config.allow_vote_mode?"Allowed":"Disallowed"]</a>)"
dat += "</li>"
//custom
if(admin)
dat += "<li><a href='?src=\ref[src];vote=custom'>Custom</a></li>"
dat += "</ul></div><hr>"
var/datum/browser/popup = new(C.mob, "vote", "Voting Panel", nref=src)
popup.set_content(dat)
popup.open()
/datum/controller/vote/proc/update_panel(var/client/C)
C << output(url_encode(vote_html(C)), "vote.browser:update_vote_div")
/datum/controller/vote/proc/vote_html(var/client/C)
. = ""
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]] ([votes] vote\s)</a></b></li>"
else
. += "<li><a href='?src=\ref[src];vote=[i]'>[choices[i]] ([votes] vote\s)</a></li>"
. += "</ul>"
/datum/controller/vote/Topic(href,href_list[],hsrc)
if(!usr || !usr.client)
return //not necessary but meh...just in-case somebody does something stupid
var/admin = check_rights(R_ADMIN,0)
if(href_list["close"])
voting -= usr.client
return
switch(href_list["vote"])
if("open")
// vote proc will automatically get called after this switch ends
if("cancel")
if(admin && mode)
var/votedesc = capitalize(mode)
if(mode == "custom")
votedesc += " ([question])"
admin_log_and_message_admins("cancelled the running [votedesc] vote.")
reset()
if("toggle_restart")
if(admin)
config.allow_vote_restart = !config.allow_vote_restart
if("toggle_gamemode")
if(admin)
config.allow_vote_mode = !config.allow_vote_mode
if("restart")
if(config.allow_vote_restart || admin)
initiate_vote("restart",usr.key)
if("gamemode")
if(config.allow_vote_mode || admin)
initiate_vote("gamemode",usr.key)
if("crew_transfer")
if(config.allow_vote_restart || admin)
initiate_vote("crew_transfer",usr.key)
if("custom")
if(admin)
initiate_vote("custom",usr.key)
else
submit_vote(usr.ckey, round(text2num(href_list["vote"])))
update_panel(usr.client)
return
usr.vote()
/mob/verb/vote()
@@ -355,4 +410,4 @@ datum/controller/vote
set name = "Vote"
if(vote)
src << browse(vote.interface(client),"window=vote;can_close=0")
vote.browse_to(client)