Merge master into map-development

This commit is contained in:
Lohikar
2017-03-21 18:28:14 -05:00
312 changed files with 5822 additions and 3118 deletions

View File

@@ -37,7 +37,7 @@ var/datum/controller/process/effects/effect_master
effects_objects += E
if (EFFECT_DESTROY)
qdel(E)
returnToPool(E)
F_SCHECK
@@ -61,7 +61,7 @@ var/datum/controller/process/effects/effect_master
if (EFFECT_DESTROY)
effects_visuals -= V
V.end()
qdel(V)
returnToPool(V)
F_SCHECK

View File

@@ -10,7 +10,7 @@ var/datum/controller/process/night_lighting/nl_ctrl
/datum/controller/process/night_lighting/setup()
name = "night lighting controller"
schedule_interval = 3600 // Every 5 minutes.
schedule_interval = 5 MINUTES
nl_ctrl = src
@@ -18,34 +18,26 @@ var/datum/controller/process/night_lighting/nl_ctrl
// Stop trying to delete processes. Not how it goes.
disabled = 1
/datum/controller/process/night_lighting/preStart()
switch (worldtime2ticks())
if (0 to config.nl_finish)
deactivate()
if (config.nl_start to TICKS_IN_DAY)
activate()
var/time = worldtime2hours()
if (time <= config.nl_finish || time >= config.nl_start)
activate()
else
deactivate()
/datum/controller/process/night_lighting/doWork()
if (manual_override) // don't automatically change lighting if it was manually changed in-game
return
switch (worldtime2ticks())
if (0 to config.nl_finish)
if (isactive)
command_announcement.Announce("Good morning. The time is [worldtime2text()]. \n\nThe automated systems aboard the [station_name()] will now return the public hallway lighting levels to normal.", "Automated Lighting System", new_sound = 'sound/misc/bosuns_whistle.ogg')
deactivate()
if (config.nl_start to TICKS_IN_DAY)
if (!isactive)
command_announcement.Announce("Good evening. The time is [worldtime2text()]. \n\nThe automated systems aboard the [station_name()] will now dim lighting in the public hallways in order to accommodate the circadian rhythm of some species.", "Automated Lighting System", new_sound = 'sound/misc/bosuns_whistle.ogg')
activate()
else
if (isactive)
deactivate()
var/time = worldtime2hours()
if (time <= config.nl_finish || time >= config.nl_start)
if (!isactive)
command_announcement.Announce("Good evening. The time is [worldtime2text()]. \n\nThe automated systems aboard the [station_name()] will now dim lighting in the public hallways in order to accommodate the circadian rhythm of some species.", "Automated Lighting System", new_sound = 'sound/misc/bosuns_whistle.ogg')
activate()
else
if (isactive)
command_announcement.Announce("Good morning. The time is [worldtime2text()]. \n\nThe automated systems aboard the [station_name()] will now return the public hallway lighting levels to normal.", "Automated Lighting System", new_sound = 'sound/misc/bosuns_whistle.ogg')
deactivate()
// 'whitelisted' areas are areas that have nightmode explicitly enabled

View File

@@ -4,54 +4,141 @@
* Scheduler *
************/
/datum/controller/process/scheduler
var/list/scheduled_tasks
var/tick_completed = TRUE
var/list/queued_tasks
var/list/datum/scheduled_task/tasks = list()
var/datum/scheduled_task/head
/datum/controller/process/scheduler/setup()
name = "scheduler"
schedule_interval = 2 SECONDS
scheduled_tasks = list()
schedule_interval = 2
scheduler = src
/datum/controller/process/scheduler/doWork()
if (tick_completed)
queued_tasks = scheduled_tasks.Copy()
tick_completed = FALSE
while (head && !PSCHED_CHECK_TICK)
if (head.destroyed)
head.kill()
head = head.next
tasks -= head
continue
if (head.trigger_time >= world.time)
return // Nothing after this will be ready to fire.
while (queued_tasks.len)
var/datum/scheduled_task/task = queued_tasks[queued_tasks.len]
queued_tasks.len--
// This one's ready to fire, process it.
var/datum/scheduled_task/task = head
head = task.next
task.pre_process()
task.process()
task.post_process()
if (task.destroyed) // post_process probably destroyed it.
tasks -= task
task.kill()
/datum/controller/process/scheduler/proc/queue(datum/scheduled_task/task)
if (!task || !task.trigger_time)
warning("scheduler: Invalid task queued! Ignoring.")
return
// Reset this in-case we're doing a rebuild.
task.next = null
if (!head && !tasks.len)
head = task
tasks += task
return
if (!head) // Head's missing but we still have tasks, rebuild.
tasks += task
rebuild_queue()
return
var/datum/scheduled_task/curr = head
while (curr.next && curr.trigger_time < task.trigger_time)
curr = curr.next
if (!curr.next)
// We're at the end of the queue, just append.
curr.next = task
tasks += task
return
// Inserting midway into the list.
var/old_next = curr.next
curr.next = task
task.next = old_next
tasks += task
// Rebuilds the queue linked-list, removing invalid or destroyed entries.
/datum/controller/process/scheduler/proc/rebuild_queue()
log_debug("scheduler: Rebuilding queue.")
var/list/old_tasks = tasks
tasks = list()
if (!old_tasks.len)
log_debug("scheduler: rebuild was called on empty queue! Aborting.")
return
// Find the head.
for (var/thing in old_tasks)
var/datum/scheduled_task/task = thing
if (QDELETED(task))
scheduled_tasks -= task
old_tasks -= task
continue
if (world.time > task.trigger_time)
unschedule(task)
task.pre_process()
task.process()
task.post_process()
F_SCHECK
if (task.destroyed)
old_tasks -= task
task.kill()
continue
tick_completed = TRUE
if (!head || task.trigger_time < head.trigger_time)
head = task
if (!head)
log_debug("scheduler: unable to find head! Purging task queue.")
for (var/thing in old_tasks)
var/datum/scheduled_task/task = thing
if (QDELETED(task))
continue
task.kill()
head = null
return
// Don't queue the head.
tasks += head
old_tasks -= head
// Now rebuild the queue.
for (var/thing in old_tasks)
var/datum/scheduled_task/task = thing
queue(task)
log_debug("scheduler: Queue diff is [old_tasks.len - tasks.len].")
/datum/controller/process/scheduler/statProcess()
..()
stat(null, "[scheduled_tasks.len] tasks, [queued_tasks.len] queued")
stat(null, "[tasks.len] task\s")
/datum/controller/process/scheduler/proc/schedule(var/datum/scheduled_task/st)
scheduled_tasks += st
destroyed_event.register(st, src, /datum/controller/process/scheduler/proc/unschedule)
queue(st)
/datum/controller/process/scheduler/proc/unschedule(var/datum/scheduled_task/st)
if(st in scheduled_tasks)
scheduled_tasks -= st
destroyed_event.unregister(st, src)
st.destroyed = TRUE
/**********
* Helpers *
**********/
/proc/schedule(source, the_proc, time, ...)
if (time < 0)
return
time += world.time
var/list/the_args
if (length(args) > 3)
the_args = args.Copy(4)
else
the_args = list()
if (source)
return schedule_task_with_source(time, the_proc, the_args)
else
return schedule_task(time, the_proc, the_args)
/proc/schedule_task_in(var/in_time, var/procedure, var/list/arguments = list())
return schedule_task(world.time + in_time, procedure, arguments)
@@ -77,68 +164,3 @@
var/datum/scheduled_task/st = new/datum/scheduled_task/source(trigger_time, source, procedure, arguments, /proc/repeat_scheduled_task, list(repeat_interval))
scheduler.schedule(st)
return st
/*************
* Task Datum *
*************/
/datum/scheduled_task
var/trigger_time
var/procedure
var/list/arguments
var/task_after_process
var/list/task_after_process_args
/datum/scheduled_task/New(var/trigger_time, var/procedure, var/list/arguments, var/proc/task_after_process, var/list/task_after_process_args)
..()
src.trigger_time = trigger_time
src.procedure = procedure
src.arguments = arguments ? arguments : list()
src.task_after_process = task_after_process ? task_after_process : /proc/destroy_scheduled_task
src.task_after_process_args = istype(task_after_process_args) ? task_after_process_args : list()
task_after_process_args += src
/datum/scheduled_task/Destroy()
procedure = null
arguments.Cut()
task_after_process = null
task_after_process_args.Cut()
return ..()
/datum/scheduled_task/proc/pre_process()
task_triggered_event.raise_event(list(src))
/datum/scheduled_task/proc/process()
if(procedure)
call(procedure)(arglist(arguments))
/datum/scheduled_task/proc/post_process()
call(task_after_process)(arglist(task_after_process_args))
// Resets the trigger time, has no effect if the task has already triggered
/datum/scheduled_task/proc/trigger_task_in(var/trigger_in)
src.trigger_time = world.time + trigger_in
/datum/scheduled_task/source
var/datum/source
/datum/scheduled_task/source/New(var/trigger_time, var/datum/source, var/procedure, var/list/arguments, var/proc/task_after_process, var/list/task_after_process_args)
src.source = source
destroyed_event.register(src.source, src, /datum/scheduled_task/source/proc/source_destroyed)
..(trigger_time, procedure, arguments, task_after_process, task_after_process_args)
/datum/scheduled_task/source/Destroy()
source = null
return ..()
/datum/scheduled_task/source/process()
call(source, procedure)(arglist(arguments))
/datum/scheduled_task/source/proc/source_destroyed()
qdel(src)
/proc/destroy_scheduled_task(var/datum/scheduled_task/st)
qdel(st)
/proc/repeat_scheduled_task(var/trigger_delay, var/datum/scheduled_task/st)
st.trigger_time = world.time + trigger_delay
scheduler.schedule(st)

View File

@@ -177,8 +177,8 @@ var/list/gamemode_cache = list()
var/ghost_interaction = 0
var/night_lighting = 0
var/nl_start = 19 * TICKS_IN_HOUR
var/nl_finish = 8 * TICKS_IN_HOUR
var/nl_start = 19
var/nl_finish = 8
var/comms_password = ""
@@ -187,6 +187,7 @@ var/list/gamemode_cache = list()
var/use_discord_bot = 0
var/discord_bot_host = "localhost"
var/discord_bot_port = 0
var/use_discord_pins = 0
var/python_path = "python" //Path to the python executable. Defaults to "python" on windows and "/usr/bin/env python2" on unix
var/use_lib_nudge = 0 //Use the C library nudge instead of the python nudge.
var/use_overmap = 0
@@ -629,10 +630,10 @@ var/list/gamemode_cache = list()
config.night_lighting = 1
if("nl_start_hour")
config.nl_start = text2num(value) * TICKS_IN_HOUR
config.nl_start = text2num(value)
if("nl_finish_hour")
config.nl_finish = text2num(value) * TICKS_IN_HOUR
config.nl_finish = text2num(value)
if("disable_player_mice")
config.disable_player_mice = 1
@@ -652,6 +653,9 @@ var/list/gamemode_cache = list()
if("discord_bot_port")
config.discord_bot_port = value
if("use_discord_pins")
config.use_discord_pins = 1
if("python_path")
if(value)
config.python_path = value
@@ -878,6 +882,8 @@ var/list/gamemode_cache = list()
discord_bot.active = 1
if ("robust_debug")
discord_bot.robust_debug = 1
if ("subscriber")
discord_bot.subscriber_role = value
else
log_misc("Unknown setting in discord configuration: '[name]'")

View File

@@ -194,8 +194,16 @@ 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 (mode == "crew_transfer")
if(config.vote_no_dead && usr && !usr.client.holder)
if (isnewplayer(usr))
usr << "<span class='warning'>You must be playing or have been playing to start a vote.</span>"
return 0
else if (isobserver(usr))
var/mob/dead/observer/O = usr
if (O.started_as_observer)
usr << "<span class='warning'>You must be playing or have been playing to start a vote.</span>"
return 0
if(vote && vote >= 1 && vote <= choices.len)
if(current_votes[ckey])
choices[choices[current_votes[ckey]]]--
@@ -211,6 +219,16 @@ datum/controller/vote
// Transfer votes are their own little special snowflake
var/next_allowed_time = 0
if (vote_type == "crew_transfer")
if (config.vote_no_dead && !usr.client.holder)
if (isnewplayer(usr))
usr << "<span class='warning'>You must be playing or have been playing to start a vote.</span>"
return 0
else if (isobserver(usr))
var/mob/dead/observer/O = usr
if (O.started_as_observer)
usr << "<span class='warning'>You must be playing or have been playing to start a vote.</span>"
return 0
if (last_transfer_vote)
next_allowed_time = (last_transfer_vote + config.vote_delay)
else
@@ -275,16 +293,16 @@ datum/controller/vote
log_vote(text)
world << "<font color='purple'><b>[text]</b>\nType <b>vote</b> or click <a href='?src=\ref[src]'>here</a> to place your votes.\nYou have [config.vote_period/10] seconds to vote.</font>"
for(var/client/C in clients)
for(var/cc in clients)
var/client/C = cc
if(C.prefs.asfx_togs & ASFX_VOTE) //Personal mute
C << sound('sound/effects/vote.ogg')
switch(vote_type)
if("crew_transfer")
world << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
if("gamemode")
world << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
if("custom")
world << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
switch(vote_type)
if("crew_transfer")
C << sound('sound/effects/vote.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
if("gamemode")
C << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
if("custom")
C << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
if(mode == "gamemode" && round_progressing)
round_progressing = 0
world << "<font color='red'><b>Round start has been delayed.</b></font>"