July 5th TG sync (#1883)

July 5th TG sync
This commit is contained in:
Poojawa
2017-07-05 22:14:19 -05:00
committed by GitHub
parent 454b9c3d68
commit b1b4826c0c
1264 changed files with 149689 additions and 570309 deletions
+5 -4
View File
@@ -265,6 +265,8 @@
var/irc_announce_new_game = FALSE
var/list/policies = list()
/datum/configuration/New()
gamemode_cache = typecacheof(/datum/game_mode,TRUE)
for(var/T in gamemode_cache)
@@ -288,6 +290,7 @@
/datum/configuration/proc/Reload()
load("config/config.txt")
load("config/game_options.txt","game_options")
load("config/policies.txt", "policies")
loadsql("config/dbconfig.txt")
if (maprotation)
loadmaplist("config/maps.txt")
@@ -777,12 +780,10 @@
arrivals_shuttle_require_safe_latejoin = TRUE
if("mice_roundstart")
mice_roundstart = text2num(value)
if ("mentor_mobname_only")
mentors_mobname_only = 1
if ("mentor_legacy_system")
mentor_legacy_system = 1
else
GLOB.config_error_log << "Unknown setting in configuration: '[name]'"
else if(type == "policies")
policies[name] = value
fps = round(fps)
if(fps <= 0)
+56 -56
View File
@@ -1,66 +1,66 @@
GLOBAL_REAL(GLOB, /datum/controller/global_vars)
/datum/controller/global_vars
name = "Global Variables"
var/list/gvars_datum_protected_varlist
var/list/gvars_datum_in_built_vars
var/list/gvars_datum_init_order
/datum/controller/global_vars/New()
if(GLOB)
CRASH("Multiple instances of global variable controller created")
GLOB = src
var/datum/controller/exclude_these = new
gvars_datum_in_built_vars = exclude_these.vars + list("gvars_datum_protected_varlist", "gvars_datum_in_built_vars", "gvars_datum_init_order")
qdel(exclude_these)
GLOBAL_REAL(GLOB, /datum/controller/global_vars)
/datum/controller/global_vars
name = "Global Variables"
var/list/gvars_datum_protected_varlist
var/list/gvars_datum_in_built_vars
var/list/gvars_datum_init_order
/datum/controller/global_vars/New()
if(GLOB)
CRASH("Multiple instances of global variable controller created")
GLOB = src
var/datum/controller/exclude_these = new
gvars_datum_in_built_vars = exclude_these.vars + list("gvars_datum_protected_varlist", "gvars_datum_in_built_vars", "gvars_datum_init_order")
qdel(exclude_these)
log_world("[vars.len - gvars_datum_in_built_vars.len] global variables")
Initialize()
/datum/controller/global_vars/Destroy(force)
Initialize()
/datum/controller/global_vars/Destroy(force)
stack_trace("Some fucker qdel'd the global holder!")
if(!force)
return QDEL_HINT_LETMELIVE
QDEL_NULL(statclick)
gvars_datum_protected_varlist.Cut()
gvars_datum_in_built_vars.Cut()
GLOB = null
return ..()
/datum/controller/global_vars/stat_entry()
if(!statclick)
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
if(!force)
return QDEL_HINT_LETMELIVE
QDEL_NULL(statclick)
gvars_datum_protected_varlist.Cut()
gvars_datum_in_built_vars.Cut()
GLOB = null
return ..()
/datum/controller/global_vars/stat_entry()
if(!statclick)
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
stat("Globals:", statclick.update("Edit"))
/datum/controller/global_vars/can_vv_get(var_name)
if(var_name in gvars_datum_protected_varlist)
return FALSE
return ..()
/datum/controller/global_vars/vv_edit_var(var_name, var_value)
if((var_name in gvars_datum_protected_varlist))
return FALSE
return ..()
/datum/controller/global_vars/Initialize()
gvars_datum_init_order = list()
gvars_datum_protected_varlist = list("gvars_datum_protected_varlist")
/datum/controller/global_vars/can_vv_get(var_name)
if(var_name in gvars_datum_protected_varlist)
return FALSE
return ..()
/datum/controller/global_vars/vv_edit_var(var_name, var_value)
if((var_name in gvars_datum_protected_varlist))
return FALSE
return ..()
/datum/controller/global_vars/Initialize()
gvars_datum_init_order = list()
gvars_datum_protected_varlist = list("gvars_datum_protected_varlist")
//See https://github.com/tgstation/tgstation/issues/26954
for(var/I in typesof(/datum/controller/global_vars/proc))
var/CLEANBOT_RETURNS = "[I]"
pass(CLEANBOT_RETURNS)
for(var/I in vars - gvars_datum_in_built_vars)
var/start_tick = world.time
call(src, "InitGlobal[I]")()
var/end_tick = world.time
if(end_tick - start_tick)
warning("Global [I] slept during initialization!")
for(var/I in vars - gvars_datum_in_built_vars)
var/start_tick = world.time
call(src, "InitGlobal[I]")()
var/end_tick = world.time
if(end_tick - start_tick)
warning("Global [I] slept during initialization!")
+6 -6
View File
@@ -30,7 +30,7 @@ SUBSYSTEM_DEF(atoms)
initialized = INITIALIZATION_INNEW_MAPLOAD
LAZYINITLIST(late_loaders)
var/count
var/list/mapload_arg = list(TRUE)
if(atoms)
@@ -60,10 +60,10 @@ SUBSYSTEM_DEF(atoms)
A.LateInitialize()
testing("Late initialized [late_loaders.len] atoms")
late_loaders.Cut()
if(atoms)
. = created_atoms + atoms
created_atoms = null
created_atoms = null
/datum/controller/subsystem/atoms/proc/InitAtom(atom/A, list/arguments)
var/the_type = A.type
@@ -77,7 +77,7 @@ SUBSYSTEM_DEF(atoms)
if(start_tick != world.time)
BadInitializeCalls[the_type] |= BAD_INIT_SLEPT
var/qdeleted = FALSE
if(result != INITIALIZE_HINT_NORMAL)
@@ -92,12 +92,12 @@ SUBSYSTEM_DEF(atoms)
qdeleted = TRUE
else
BadInitializeCalls[the_type] |= BAD_INIT_NO_HINT
if(!A) //possible harddel
qdeleted = TRUE
else if(!A.initialized)
BadInitializeCalls[the_type] |= BAD_INIT_DIDNT_INIT
return qdeleted || QDELING(A)
/datum/controller/subsystem/atoms/proc/map_loader_begin()
+3 -2
View File
@@ -95,11 +95,13 @@ SUBSYSTEM_DEF(blackbox)
for (var/datum/feedback_variable/FV in feedback)
sqlrowlist += list(list("time" = "Now()", "round_id" = GLOB.round_id, "var_name" = "'[sanitizeSQL(FV.get_variable())]'", "var_value" = FV.get_value(), "details" = "'[sanitizeSQL(FV.get_details())]'"))
if (!length(sqlrowlist))
return
SSdbcore.MassInsert(format_table_name("feedback"), sqlrowlist, ignore_errors = TRUE, delayed = TRUE)
/datum/controller/subsystem/blackbox/proc/LogBroadcast(blackbox_msg, freq)
if(sealed)
return
@@ -209,7 +211,6 @@ SUBSYSTEM_DEF(blackbox)
log_game("Blackbox sealed[IsAdminAdvancedProcCall() ? " by [key_name(usr)]" : ""].")
sealed = TRUE
//feedback variable datum, for storing all kinds of data
/datum/feedback_variable
var/variable
@@ -268,4 +269,4 @@ SUBSYSTEM_DEF(blackbox)
return details
/datum/feedback_variable/proc/get_parsed()
return list(variable,value,details)
return list(variable,value,details)
+8 -3
View File
@@ -70,7 +70,10 @@ SUBSYSTEM_DEF(events)
if(!E.canSpawnEvent(players_amt, gamemode))
continue
if(E.weight < 0) //for round-start events etc.
if(TriggerEvent(E))
var/res = TriggerEvent(E)
if(res == EVENT_INTERRUPTED)
continue //like it never happened
if(res == EVENT_CANT_RUN)
return
sum_of_weights += E.weight
@@ -89,7 +92,7 @@ SUBSYSTEM_DEF(events)
. = E.preRunEvent()
if(. == EVENT_CANT_RUN)//we couldn't run this event for some reason, set its max_occurrences to 0
E.max_occurrences = 0
else if(. != EVENT_CANCELLED)
else if(. == EVENT_READY)
E.runEvent(TRUE)
/datum/round_event/proc/findEventArea() //Here's a nice proc to use to find an area for your event to land in!
@@ -172,10 +175,12 @@ SUBSYSTEM_DEF(events)
var/YY = text2num(time2text(world.timeofday, "YY")) // get the current year
var/MM = text2num(time2text(world.timeofday, "MM")) // get the current month
var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day
var/DDD = text2num(time2text(world.timeofday, "DDD")) // get the current weekday
var/W = weekdayofthemonth() // is this the first monday? second? etc.
for(var/H in subtypesof(/datum/holiday))
var/datum/holiday/holiday = new H()
if(holiday.shouldCelebrate(DD, MM, YY))
if(holiday.shouldCelebrate(DD, MM, YY, W, DDD))
holiday.celebrate()
if(!holidays)
holidays = list()
+3 -4
View File
@@ -182,14 +182,13 @@ SUBSYSTEM_DEF(garbage)
// Should be treated as a replacement for the 'del' keyword.
// Datums passed to this will be given a chance to clean up references to allow the GC to collect them.
/proc/qdel(datum/D, force=FALSE)
if(!D)
if(!istype(D))
del(D)
return
#ifdef TESTING
SSgarbage.qdel_list += "[D.type]"
#endif
if(!istype(D))
del(D)
else if(isnull(D.gc_destroyed))
if(isnull(D.gc_destroyed))
D.gc_destroyed = GC_CURRENTLY_BEING_QDELETED
var/start_time = world.time
var/hint = D.Destroy(force) // Let our friend know they're about to get fucked up.
+1
View File
@@ -385,6 +385,7 @@ SUBSYSTEM_DEF(job)
log_world("Couldn't find a round start spawn point for [rank]")
SendToLateJoin(H)
if(H.mind)
H.mind.assigned_role = rank
+1 -1
View File
@@ -210,7 +210,7 @@ SUBSYSTEM_DEF(mapping)
var/list/banned = generateMapList("config/lavaruinblacklist.txt")
banned += generateMapList("config/spaceruinblacklist.txt")
for(var/item in subtypesof(/datum/map_template/ruin))
for(var/item in sortList(subtypesof(/datum/map_template/ruin), /proc/cmp_ruincost_priority))
var/datum/map_template/ruin/ruin_type = item
// screen out the abstract subtypes
if(!initial(ruin_type.id))
+120 -120
View File
@@ -2,45 +2,45 @@
#define PROCESSING_NPCS 1
#define PROCESSING_DELEGATES 2
#define PROCESSING_ASSISTANTS 3
SUBSYSTEM_DEF(npcpool)
name = "NPC Pool"
flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND
priority = 20
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
var/list/canBeUsed = list()
var/list/needsDelegate = list()
var/list/needsAssistant = list()
var/list/processing = list()
var/list/currentrun = list()
var/stage
/datum/controller/subsystem/npcpool/stat_entry()
..("NPCS:[processing.len]|D:[needsDelegate.len]|A:[needsAssistant.len]|U:[canBeUsed.len]")
SUBSYSTEM_DEF(npcpool)
name = "NPC Pool"
flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND
priority = 20
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
var/list/canBeUsed = list()
var/list/needsDelegate = list()
var/list/needsAssistant = list()
var/list/processing = list()
var/list/currentrun = list()
var/stage
/datum/controller/subsystem/npcpool/stat_entry()
..("NPCS:[processing.len]|D:[needsDelegate.len]|A:[needsAssistant.len]|U:[canBeUsed.len]")
/datum/controller/subsystem/npcpool/proc/stop_processing(mob/living/I)
processing -= I
currentrun -= I
needsDelegate -= I
canBeUsed -= I
needsAssistant -= I
/datum/controller/subsystem/npcpool/fire(resumed = FALSE)
//bot delegation and coordination systems
//General checklist/Tasks for delegating a task or coordinating it (for SNPCs)
// 1. Bot proximity to task target: if too far, delegate, if close, coordinate
// 2. Bot Health/status: check health with bots in local area, if their health is higher, delegate task to them, else coordinate
// 3. Process delegation: if a bot (or bots) has been delegated, assign them to the task.
// 4. Process coordination: if a bot(or bots) has been asked to coordinate, assign them to help.
// 5. Do all assignments: goes through the delegated/coordianted bots and assigns the right variables/tasks to them.
if (!resumed)
processing -= I
currentrun -= I
needsDelegate -= I
canBeUsed -= I
needsAssistant -= I
/datum/controller/subsystem/npcpool/fire(resumed = FALSE)
//bot delegation and coordination systems
//General checklist/Tasks for delegating a task or coordinating it (for SNPCs)
// 1. Bot proximity to task target: if too far, delegate, if close, coordinate
// 2. Bot Health/status: check health with bots in local area, if their health is higher, delegate task to them, else coordinate
// 3. Process delegation: if a bot (or bots) has been delegated, assign them to the task.
// 4. Process coordination: if a bot(or bots) has been asked to coordinate, assign them to help.
// 5. Do all assignments: goes through the delegated/coordianted bots and assigns the right variables/tasks to them.
if (!resumed)
src.currentrun = GLOB.simple_animals.Copy()
stage = PROCESSING_SIMPLES
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
if(stage == PROCESSING_SIMPLES)
while(currentrun.len)
@@ -60,88 +60,88 @@ SUBSYSTEM_DEF(npcpool)
stage = PROCESSING_NPCS
currentrun = processing.Copy()
src.currentrun = currentrun
var/list/canBeUsed = src.canBeUsed
if(stage == PROCESSING_NPCS)
while(currentrun.len)
var/mob/living/carbon/human/interactive/thing = currentrun[currentrun.len]
--currentrun.len
thing.InteractiveProcess()
var/checkInRange = view(MAX_RANGE_FIND,thing)
if(thing.IsDeadOrIncap(FALSE) || !(locate(thing.TARGET) in checkInRange))
needsDelegate += thing
else if(thing.doing & FIGHTING)
needsAssistant += thing
else
canBeUsed += thing
if (MC_TICK_CHECK)
return
stage = PROCESSING_DELEGATES
currentrun = needsDelegate //localcache
src.currentrun = currentrun
if(stage == PROCESSING_DELEGATES)
while(currentrun.len && canBeUsed.len)
var/mob/living/carbon/human/interactive/check = currentrun[currentrun.len]
var/mob/living/carbon/human/interactive/candidate = canBeUsed[canBeUsed.len]
--currentrun.len
var/helpProb = 0
var/list/chfac = check.faction
var/list/canfac = candidate.faction
var/facCount = LAZYLEN(chfac) * LAZYLEN(canfac)
for(var/C in chfac)
if(C in canfac)
helpProb = min(100,helpProb + 25)
if(helpProb >= 100)
break
if(facCount == 1 && helpProb)
helpProb = 100
if(prob(helpProb) && candidate.takeDelegate(check))
--canBeUsed.len
candidate.eye_color = "red"
candidate.update_icons()
if(MC_TICK_CHECK)
return
stage = PROCESSING_ASSISTANTS
currentrun = needsAssistant //localcache
src.currentrun = currentrun
//no need for the stage check
while(currentrun.len && canBeUsed.len)
var/mob/living/carbon/human/interactive/check = currentrun[currentrun.len]
var/mob/living/carbon/human/interactive/candidate = canBeUsed[canBeUsed.len]
--currentrun.len
var/helpProb = 0
var/list/chfac = check.faction
var/list/canfac = candidate.faction
var/facCount = LAZYLEN(chfac) * LAZYLEN(canfac)
for(var/C in chfac)
if(C in canfac)
helpProb = min(100,helpProb + 25)
if(helpProb >= 100)
break
if(facCount == 1 && helpProb)
helpProb = 100
if(prob(helpProb) && candidate.takeDelegate(check,FALSE))
--canBeUsed.len
candidate.eye_color = "yellow"
candidate.update_icons()
if(!currentrun.len || MC_TICK_CHECK) //don't change SS state if it isn't necessary
return
/datum/controller/subsystem/npcpool/Recover()
processing = SSnpcpool.processing
var/list/canBeUsed = src.canBeUsed
if(stage == PROCESSING_NPCS)
while(currentrun.len)
var/mob/living/carbon/human/interactive/thing = currentrun[currentrun.len]
--currentrun.len
thing.InteractiveProcess()
var/checkInRange = view(MAX_RANGE_FIND,thing)
if(thing.IsDeadOrIncap(FALSE) || !(locate(thing.TARGET) in checkInRange))
needsDelegate += thing
else if(thing.doing & FIGHTING)
needsAssistant += thing
else
canBeUsed += thing
if (MC_TICK_CHECK)
return
stage = PROCESSING_DELEGATES
currentrun = needsDelegate //localcache
src.currentrun = currentrun
if(stage == PROCESSING_DELEGATES)
while(currentrun.len && canBeUsed.len)
var/mob/living/carbon/human/interactive/check = currentrun[currentrun.len]
var/mob/living/carbon/human/interactive/candidate = canBeUsed[canBeUsed.len]
--currentrun.len
var/helpProb = 0
var/list/chfac = check.faction
var/list/canfac = candidate.faction
var/facCount = LAZYLEN(chfac) * LAZYLEN(canfac)
for(var/C in chfac)
if(C in canfac)
helpProb = min(100,helpProb + 25)
if(helpProb >= 100)
break
if(facCount == 1 && helpProb)
helpProb = 100
if(prob(helpProb) && candidate.takeDelegate(check))
--canBeUsed.len
candidate.eye_color = "red"
candidate.update_icons()
if(MC_TICK_CHECK)
return
stage = PROCESSING_ASSISTANTS
currentrun = needsAssistant //localcache
src.currentrun = currentrun
//no need for the stage check
while(currentrun.len && canBeUsed.len)
var/mob/living/carbon/human/interactive/check = currentrun[currentrun.len]
var/mob/living/carbon/human/interactive/candidate = canBeUsed[canBeUsed.len]
--currentrun.len
var/helpProb = 0
var/list/chfac = check.faction
var/list/canfac = candidate.faction
var/facCount = LAZYLEN(chfac) * LAZYLEN(canfac)
for(var/C in chfac)
if(C in canfac)
helpProb = min(100,helpProb + 25)
if(helpProb >= 100)
break
if(facCount == 1 && helpProb)
helpProb = 100
if(prob(helpProb) && candidate.takeDelegate(check,FALSE))
--canBeUsed.len
candidate.eye_color = "yellow"
candidate.update_icons()
if(!currentrun.len || MC_TICK_CHECK) //don't change SS state if it isn't necessary
return
/datum/controller/subsystem/npcpool/Recover()
processing = SSnpcpool.processing
@@ -5,7 +5,7 @@ PROCESSING_SUBSYSTEM_DEF(flightpacks)
stat_tag = "FM"
flags = SS_NO_INIT|SS_TICKER|SS_KEEP_TIMING
var/flightsuit_processing = FLIGHTSUIT_PROCESSING_NONE
var/flightsuit_processing = FLIGHTSUIT_PROCESSING_FULL
/datum/controller/subsystem/processing/flightpacks/Initialize()
sync_flightsuit_processing()
+3 -3
View File
@@ -17,7 +17,7 @@ SUBSYSTEM_DEF(server_maint)
/datum/controller/subsystem/server_maint/fire(resumed = FALSE)
if(!resumed)
src.currentrun = GLOB.clients.Copy()
var/list/currentrun = src.currentrun
var/round_started = SSticker.HasRoundStarted()
@@ -27,7 +27,7 @@ SUBSYSTEM_DEF(server_maint)
if(round_started && config.kick_inactive)
if(C.is_afk(config.afk_period))
var/cmob = C.mob
if(!(istype(cmob, /mob/dead/observer) || (istype(cmob, /mob/dead) && C.holder)))
if(!(isobserver(cmob) || (isdead(cmob) && C.holder)))
log_access("AFK: [key_name(C)]")
to_chat(C, "<span class='danger'>You have been inactive for more than [config.afk_period / 600] minutes and have been disconnected.</span>")
qdel(C)
@@ -45,4 +45,4 @@ SUBSYSTEM_DEF(server_maint)
if(C && config.server) //if you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite
C << link("byond://[config.server]")
#undef PING_BUFFER_TIME
#undef PING_BUFFER_TIME
+58 -58
View File
@@ -1,59 +1,59 @@
SUBSYSTEM_DEF(spacedrift)
name = "Space Drift"
priority = 30
wait = 5
flags = SS_NO_INIT|SS_KEEP_TIMING
SUBSYSTEM_DEF(spacedrift)
name = "Space Drift"
priority = 30
wait = 5
flags = SS_NO_INIT|SS_KEEP_TIMING
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
var/list/currentrun = list()
var/list/processing = list()
/datum/controller/subsystem/spacedrift/stat_entry()
..("P:[processing.len]")
/datum/controller/subsystem/spacedrift/fire(resumed = 0)
if (!resumed)
src.currentrun = processing.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while (currentrun.len)
var/atom/movable/AM = currentrun[currentrun.len]
currentrun.len--
if (!AM)
processing -= AM
if (MC_TICK_CHECK)
return
continue
if (AM.inertia_next_move > world.time)
if (MC_TICK_CHECK)
return
continue
if (!AM.loc || AM.loc != AM.inertia_last_loc || AM.Process_Spacemove(0))
AM.inertia_dir = 0
if (!AM.inertia_dir)
AM.inertia_last_loc = null
processing -= AM
if (MC_TICK_CHECK)
return
continue
var/old_dir = AM.dir
var/old_loc = AM.loc
AM.inertia_moving = TRUE
step(AM, AM.inertia_dir)
AM.inertia_moving = FALSE
AM.inertia_next_move = world.time + AM.inertia_move_delay
if (AM.loc == old_loc)
AM.inertia_dir = 0
AM.setDir(old_dir)
AM.inertia_last_loc = AM.loc
if (MC_TICK_CHECK)
return
var/list/currentrun = list()
var/list/processing = list()
/datum/controller/subsystem/spacedrift/stat_entry()
..("P:[processing.len]")
/datum/controller/subsystem/spacedrift/fire(resumed = 0)
if (!resumed)
src.currentrun = processing.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while (currentrun.len)
var/atom/movable/AM = currentrun[currentrun.len]
currentrun.len--
if (!AM)
processing -= AM
if (MC_TICK_CHECK)
return
continue
if (AM.inertia_next_move > world.time)
if (MC_TICK_CHECK)
return
continue
if (!AM.loc || AM.loc != AM.inertia_last_loc || AM.Process_Spacemove(0))
AM.inertia_dir = 0
if (!AM.inertia_dir)
AM.inertia_last_loc = null
processing -= AM
if (MC_TICK_CHECK)
return
continue
var/old_dir = AM.dir
var/old_loc = AM.loc
AM.inertia_moving = TRUE
step(AM, AM.inertia_dir)
AM.inertia_moving = FALSE
AM.inertia_next_move = world.time + AM.inertia_move_delay
if (AM.loc == old_loc)
AM.inertia_dir = 0
AM.setDir(old_dir)
AM.inertia_last_loc = AM.loc
if (MC_TICK_CHECK)
return
+3 -1
View File
@@ -10,9 +10,11 @@ SUBSYSTEM_DEF(squeak)
var/list/exposed_wires = list()
/datum/controller/subsystem/squeak/Initialize(timeofday)
trigger_migration()
trigger_migration(config.mice_roundstart)
/datum/controller/subsystem/squeak/proc/trigger_migration(num_mice=10)
if(!num_mice)
return
find_exposed_wires()
var/mob/living/simple_animal/mouse/M
+9 -28
View File
@@ -30,7 +30,6 @@ SUBSYSTEM_DEF(ticker)
var/list/scripture_states = list(SCRIPTURE_DRIVER = TRUE, \
SCRIPTURE_SCRIPT = FALSE, \
SCRIPTURE_APPLICATION = FALSE, \
SCRIPTURE_REVENANT = FALSE, \
SCRIPTURE_JUDGEMENT = FALSE) //list of clockcult scripture states for announcements
var/delay_end = 0 //if set true, the round will not restart on it's own
@@ -62,7 +61,7 @@ SUBSYSTEM_DEF(ticker)
var/list/round_start_events
var/mode_result = "undefined"
var/end_state = "undefined"
var/modevoted = FALSE //Have we sent a vote for the gamemode?
/datum/controller/subsystem/ticker/Initialize(timeofday)
@@ -139,6 +138,7 @@ SUBSYSTEM_DEF(ticker)
declare_completion(force_ending)
Master.SetRunLevel(RUNLEVEL_POSTGAME)
/datum/controller/subsystem/ticker/proc/setup()
to_chat(world, "<span class='boldannounce'>Starting game...</span>")
var/init_start = world.timeofday
@@ -223,7 +223,7 @@ SUBSYSTEM_DEF(ticker)
round_start_time = world.time
to_chat(world, "<FONT color='blue'><B>Welcome to [station_name()], enjoy your stay!</B></FONT>")
world << sound('sound/AI/welcome.ogg')
world << sound('sound/ai/welcome.ogg')
current_state = GAME_STATE_PLAYING
Master.SetRunLevel(RUNLEVEL_GAME)
@@ -585,6 +585,7 @@ SUBSYSTEM_DEF(ticker)
mode.declare_station_goal_completion()
CHECK_TICK
//medals, placed far down so that people can actually see the commendations.
if(GLOB.commendations.len)
to_chat(world, "<b><font size=3>Medal Commendations:</font></b>")
@@ -593,26 +594,9 @@ SUBSYSTEM_DEF(ticker)
CHECK_TICK
CHECK_TICK
//Adds the del() log to world.log in a format condensable by the runtime condenser found in tools
if(SSgarbage.didntgc.len || SSgarbage.sleptDestroy.len)
var/dellog = ""
for(var/path in SSgarbage.didntgc)
dellog += "Path : [path] \n"
dellog += "Failures : [SSgarbage.didntgc[path]] \n"
if(path in SSgarbage.sleptDestroy)
dellog += "Sleeps : [SSgarbage.sleptDestroy[path]] \n"
SSgarbage.sleptDestroy -= path
for(var/path in SSgarbage.sleptDestroy)
dellog += "Path : [path] \n"
dellog += "Sleeps : [SSgarbage.sleptDestroy[path]] \n"
log_world(dellog)
CHECK_TICK
//Collects persistence features
SSpersistence.CollectData()
if(mode.allow_persistence_save)
SSpersistence.CollectData()
//stop collecting feedback during grifftime
SSblackbox.Seal()
@@ -680,7 +664,7 @@ SUBSYSTEM_DEF(ticker)
/datum/controller/subsystem/ticker/proc/IsRoundInProgress()
return current_state == GAME_STATE_PLAYING
/proc/send_gamemode_vote()
SSticker.modevoted = TRUE
SSvote.initiate_vote("roundtype","server")
@@ -723,6 +707,8 @@ SUBSYSTEM_DEF(ticker)
queued_players = SSticker.queued_players
cinematic = SSticker.cinematic
maprotatechecked = SSticker.maprotatechecked
modevoted = SSticker.modevoted
switch (current_state)
if(GAME_STATE_SETTING_UP)
@@ -732,9 +718,6 @@ SUBSYSTEM_DEF(ticker)
if(GAME_STATE_FINISHED)
Master.SetRunLevel(RUNLEVEL_POSTGAME)
modevoted = SSticker.modevoted
/datum/controller/subsystem/ticker/proc/send_news_report()
var/news_message
var/news_source = "Nanotrasen News Network"
@@ -851,11 +834,9 @@ SUBSYSTEM_DEF(ticker)
if(delay_end && !skip_delay)
to_chat(world, "<span class='boldannounce'>Reboot was cancelled by an admin.</span>")
return
if(end_string)
end_state = end_string
log_game("<span class='boldannounce'>Rebooting World. [reason]</span>")
world.Reboot()
+1 -1
View File
@@ -43,7 +43,7 @@ SUBSYSTEM_DEF(timer)
WARNING(msg)
if(bucket_auto_reset)
bucket_resolution = 0
log_world("Active timers at tick [world.time]:")
for(var/I in processing)
var/datum/timedevent/TE = I
+313 -320
View File
@@ -1,321 +1,314 @@
SUBSYSTEM_DEF(vote)
name = "Vote"
wait = 10
flags = SS_KEEP_TIMING|SS_NO_INIT
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
var/initiator = null
var/started_time = null
var/time_remaining = 0
var/mode = null
var/question = null
var/list/choices = list()
var/list/voted = list()
var/list/voting = list()
var/list/generated_actions = list()
/datum/controller/subsystem/vote/fire() //called by master_controller
if(mode)
time_remaining = round((started_time + config.vote_period - world.time)/10)
if(time_remaining < 0)
result()
for(var/client/C in voting)
C << browse(null, "window=vote;can_close=0")
reset()
else
var/datum/browser/client_popup
for(var/client/C in voting)
client_popup = new(C, "vote", "Voting Panel")
client_popup.set_window_options("can_close=0")
client_popup.set_content(interface(C))
client_popup.open(0)
/datum/controller/subsystem/vote/proc/reset()
initiator = null
time_remaining = 0
mode = null
question = null
choices.Cut()
voted.Cut()
voting.Cut()
remove_action_buttons()
/datum/controller/subsystem/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/list/non_voters = GLOB.directory.Copy()
non_voters -= voted
for (var/non_voter_ckey in non_voters)
var/client/C = non_voters[non_voter_ckey]
if (!C || C.is_afk())
non_voters -= non_voter_ckey
if(non_voters.len > 0)
if(mode == "restart")
choices["Continue Playing"] += non_voters.len
if(choices["Continue Playing"] >= greatest_votes)
greatest_votes = choices["Continue Playing"]
else if(mode == "gamemode")
if(GLOB.master_mode in choices)
choices[GLOB.master_mode] += non_voters.len
if(choices[GLOB.master_mode] >= greatest_votes)
greatest_votes = choices[GLOB.master_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/subsystem/vote/proc/announce_result()
var/list/winners = get_result()
var/text
if(winners.len > 0)
if(question)
text += "<b>[question]</b>"
else
text += "<b>[capitalize(mode)] Vote</b>"
for(var/i=1,i<=choices.len,i++)
var/votes = choices[choices[i]]
if(!votes)
votes = 0
text += "\n<b>[choices[i]]:</b> [votes]"
if(mode != "custom")
if(winners.len > 1)
text = "\n<b>Vote Tied Between:</b>"
for(var/option in winners)
text += "\n\t[option]"
. = pick(winners)
text += "\n<b>Vote Result: [.]</b>"
else
text += "\n<b>Did not vote:</b> [GLOB.clients.len-voted.len]"
else
text += "<b>Vote Result: Inconclusive - No Votes!</b>"
log_vote(text)
remove_action_buttons()
to_chat(world, "\n<font color='purple'>[text]</font>")
return .
/datum/controller/subsystem/vote/proc/result()
. = announce_result()
var/restart = 0
if(.)
switch(mode)
if("restart")
if(. == "Restart Round")
restart = 1
if("roundtype")
if(SSticker && SSticker.mode)//Don't change the mode if the round already started.
return message_admins("A vote has tried to change the gamemode, but the game has already started. Aborting.")
GLOB.master_mode = .
SSticker.save_mode(.)
to_chat(world, "<span class='adminnotice'><b>The mode is now: [GLOB.master_mode]</b></span>")
log_admin("Gamemode has been voted for and switched to: [GLOB.master_mode].")
if("gamemode")
if(GLOB.master_mode != .)
SSticker.save_mode(.)
if(SSticker.HasRoundStarted())
restart = 1
else
GLOB.master_mode = .
if(restart)
var/active_admins = 0
for(var/client/C in GLOB.admins)
if(!C.is_afk() && check_rights_for(C, R_SERVER))
active_admins = 1
break
if(!active_admins)
SUBSYSTEM_DEF(vote)
name = "Vote"
wait = 10
flags = SS_KEEP_TIMING|SS_NO_INIT
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
var/initiator = null
var/started_time = null
var/time_remaining = 0
var/mode = null
var/question = null
var/list/choices = list()
var/list/voted = list()
var/list/voting = list()
var/list/generated_actions = list()
/datum/controller/subsystem/vote/fire() //called by master_controller
if(mode)
time_remaining = round((started_time + config.vote_period - world.time)/10)
if(time_remaining < 0)
result()
for(var/client/C in voting)
C << browse(null, "window=vote;can_close=0")
reset()
else
var/datum/browser/client_popup
for(var/client/C in voting)
client_popup = new(C, "vote", "Voting Panel")
client_popup.set_window_options("can_close=0")
client_popup.set_content(interface(C))
client_popup.open(0)
/datum/controller/subsystem/vote/proc/reset()
initiator = null
time_remaining = 0
mode = null
question = null
choices.Cut()
voted.Cut()
voting.Cut()
remove_action_buttons()
/datum/controller/subsystem/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/list/non_voters = GLOB.directory.Copy()
non_voters -= voted
for (var/non_voter_ckey in non_voters)
var/client/C = non_voters[non_voter_ckey]
if (!C || C.is_afk())
non_voters -= non_voter_ckey
if(non_voters.len > 0)
if(mode == "restart")
choices["Continue Playing"] += non_voters.len
if(choices["Continue Playing"] >= greatest_votes)
greatest_votes = choices["Continue Playing"]
else if(mode == "gamemode")
if(GLOB.master_mode in choices)
choices[GLOB.master_mode] += non_voters.len
if(choices[GLOB.master_mode] >= greatest_votes)
greatest_votes = choices[GLOB.master_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/subsystem/vote/proc/announce_result()
var/list/winners = get_result()
var/text
if(winners.len > 0)
if(question)
text += "<b>[question]</b>"
else
text += "<b>[capitalize(mode)] Vote</b>"
for(var/i=1,i<=choices.len,i++)
var/votes = choices[choices[i]]
if(!votes)
votes = 0
text += "\n<b>[choices[i]]:</b> [votes]"
if(mode != "custom")
if(winners.len > 1)
text = "\n<b>Vote Tied Between:</b>"
for(var/option in winners)
text += "\n\t[option]"
. = pick(winners)
text += "\n<b>Vote Result: [.]</b>"
else
text += "\n<b>Did not vote:</b> [GLOB.clients.len-voted.len]"
else
text += "<b>Vote Result: Inconclusive - No Votes!</b>"
log_vote(text)
remove_action_buttons()
to_chat(world, "\n<font color='purple'>[text]</font>")
return .
/datum/controller/subsystem/vote/proc/result()
. = announce_result()
var/restart = 0
if(.)
switch(mode)
if("restart")
if(. == "Restart Round")
restart = 1
if("gamemode")
if(GLOB.master_mode != .)
SSticker.save_mode(.)
if(SSticker.HasRoundStarted())
restart = 1
else
GLOB.master_mode = .
if(restart)
var/active_admins = 0
for(var/client/C in GLOB.admins)
if(!C.is_afk() && check_rights_for(C, R_SERVER))
active_admins = 1
break
if(!active_admins)
SSticker.Reboot("Restart vote successful.", "restart vote")
else
to_chat(world, "<span style='boldannounce'>Notice:Restart vote will not restart the server automatically because there are active admins on.</span>")
message_admins("A restart vote has passed, but there are active admins on with +server, so it has been canceled. If you wish, you may restart the server.")
return .
/datum/controller/subsystem/vote/proc/submit_vote(vote)
if(mode)
if(config.vote_no_dead && usr.stat == DEAD && !usr.client.holder)
return 0
if(!(usr.ckey in voted))
if(vote && 1<=vote && vote<=choices.len)
voted += usr.ckey
choices[choices[vote]]++ //check this
return vote
return 0
/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key)
if(!mode)
if(started_time)
var/next_allowed_time = (started_time + config.vote_delay)
if(mode)
to_chat(usr, "<span class='warning'>There is already a vote in progress! please wait for it to finish.</span>")
return 0
var/admin = FALSE
var/ckey = ckey(initiator_key)
if((GLOB.admin_datums[ckey]) || (ckey in GLOB.deadmins))
admin = TRUE
if(next_allowed_time > world.time && !admin)
to_chat(usr, "<span class='warning'>A vote was initiated recently, you must wait roughly [(next_allowed_time-world.time)/10] seconds before a new vote can be started!</span>")
return 0
reset()
switch(vote_type)
if("restart")
choices.Add("Restart Round","Continue Playing")
if("gamemode")
choices.Add(config.votable_modes)
if("roundtype")
choices.Add("secret", "extended")
if("custom")
question = stripped_input(usr,"What is the vote for?")
if(!question)
return 0
for(var/i=1,i<=10,i++)
var/option = capitalize(stripped_input(usr,"Please enter an option or hit cancel to finish"))
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, "\n<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>")
time_remaining = round(config.vote_period/10)
for(var/c in GLOB.clients)
var/client/C = c
var/datum/action/vote/V = new
if(question)
V.name = "Vote: [question]"
V.Grant(C.mob)
generated_actions += V
return 1
return 0
/datum/controller/subsystem/vote/proc/interface(client/C)
if(!C)
return
var/admin = 0
var/trialmin = 0
if(C.holder)
admin = 1
if(check_rights_for(C, R_ADMIN))
trialmin = 1
voting |= C
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
. += "<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>"
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>"
return .
/datum/controller/subsystem/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("custom")
if(usr.client.holder)
initiate_vote("custom",usr.key)
else
submit_vote(round(text2num(href_list["vote"])))
usr.vote()
/datum/controller/subsystem/vote/proc/remove_action_buttons()
for(var/v in generated_actions)
var/datum/action/vote/V = v
if(!QDELETED(V))
V.Remove(V.owner)
generated_actions = list()
/mob/verb/vote()
set category = "OOC"
set name = "Vote"
var/datum/browser/popup = new(src, "vote", "Voting Panel")
popup.set_window_options("can_close=0")
popup.set_content(SSvote.interface(client))
popup.open(0)
/datum/action/vote
name = "Vote!"
button_icon_state = "vote"
/datum/action/vote/Trigger()
if(owner)
owner.vote()
Remove(owner)
/datum/action/vote/IsAvailable()
return 1
else
to_chat(world, "<span style='boldannounce'>Notice:Restart vote will not restart the server automatically because there are active admins on.</span>")
message_admins("A restart vote has passed, but there are active admins on with +server, so it has been canceled. If you wish, you may restart the server.")
return .
/datum/controller/subsystem/vote/proc/submit_vote(vote)
if(mode)
if(config.vote_no_dead && usr.stat == DEAD && !usr.client.holder)
return 0
if(!(usr.ckey in voted))
if(vote && 1<=vote && vote<=choices.len)
voted += usr.ckey
choices[choices[vote]]++ //check this
return vote
return 0
/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key)
if(!mode)
if(started_time)
var/next_allowed_time = (started_time + config.vote_delay)
if(mode)
to_chat(usr, "<span class='warning'>There is already a vote in progress! please wait for it to finish.</span>")
return 0
var/admin = FALSE
var/ckey = ckey(initiator_key)
if((GLOB.admin_datums[ckey]) || (ckey in GLOB.deadmins))
admin = TRUE
if(next_allowed_time > world.time && !admin)
to_chat(usr, "<span class='warning'>A vote was initiated recently, you must wait roughly [(next_allowed_time-world.time)/10] seconds before a new vote can be started!</span>")
return 0
reset()
switch(vote_type)
if("restart")
choices.Add("Restart Round","Continue Playing")
if("gamemode")
choices.Add(config.votable_modes)
if("roundtype")
choices.Add("secret", "extended")
if("custom")
question = stripped_input(usr,"What is the vote for?")
if(!question)
return 0
for(var/i=1,i<=10,i++)
var/option = capitalize(stripped_input(usr,"Please enter an option or hit cancel to finish"))
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, "\n<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>")
time_remaining = round(config.vote_period/10)
for(var/c in GLOB.clients)
var/client/C = c
var/datum/action/vote/V = new
if(question)
V.name = "Vote: [question]"
V.Grant(C.mob)
generated_actions += V
return 1
return 0
/datum/controller/subsystem/vote/proc/interface(client/C)
if(!C)
return
var/admin = 0
var/trialmin = 0
if(C.holder)
admin = 1
if(check_rights_for(C, R_ADMIN))
trialmin = 1
voting |= C
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
. += "<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>"
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>"
return .
/datum/controller/subsystem/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("custom")
if(usr.client.holder)
initiate_vote("custom",usr.key)
else
submit_vote(round(text2num(href_list["vote"])))
usr.vote()
/datum/controller/subsystem/vote/proc/remove_action_buttons()
for(var/v in generated_actions)
var/datum/action/vote/V = v
if(!QDELETED(V))
V.Remove(V.owner)
generated_actions = list()
/mob/verb/vote()
set category = "OOC"
set name = "Vote"
var/datum/browser/popup = new(src, "vote", "Voting Panel")
popup.set_window_options("can_close=0")
popup.set_content(SSvote.interface(client))
popup.open(0)
/datum/action/vote
name = "Vote!"
button_icon_state = "vote"
/datum/action/vote/Trigger()
if(owner)
owner.vote()
Remove(owner)
/datum/action/vote/IsAvailable()
return 1