diff --git a/code/controllers/master.dm b/code/controllers/master.dm index 5844ee749d1..084bdaa11a6 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -431,6 +431,10 @@ GLOBAL_REAL(Master, /datum/controller/master) = new continue if ((SS_flags & (SS_TICKER|SS_KEEP_TIMING)) == SS_KEEP_TIMING && SS.last_fire + (SS.wait * 0.75) > world.time) continue + if (SS.postponed_fires >= 1) + SS.postponed_fires-- + SS.update_nextfire() + continue SS.enqueue() . = 1 @@ -525,20 +529,8 @@ GLOBAL_REAL(Master, /datum/controller/master) = new queue_node.last_fire = world.time queue_node.times_fired++ - - var/postpone = queue_node.next_fire - queue_node.queued_time - - if (queue_node_flags & SS_TICKER) - queue_node.next_fire = world.time + (world.tick_lag * queue_node.wait) - else if (queue_node_flags & SS_POST_FIRE_TIMING) - queue_node.next_fire = world.time + queue_node.wait + (world.tick_lag * (queue_node.tick_overrun/100)) - else if (queue_node_flags & SS_KEEP_TIMING) - queue_node.next_fire += queue_node.wait - else - queue_node.next_fire = queue_node.queued_time + queue_node.wait + (world.tick_lag * (queue_node.tick_overrun/100)) - if (postpone >= world.tick_lag) - queue_node.next_fire += postpone + queue_node.update_nextfire() queue_node.queued_time = 0 diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm index b9c49dfe8e7..a1315c484bd 100644 --- a/code/controllers/subsystem.dm +++ b/code/controllers/subsystem.dm @@ -69,6 +69,9 @@ /// Tracks the amount of completed runs for the subsystem var/times_fired = 0 + /// How many fires have we been requested to postpone + var/postponed_fires = 0 + /// Time the subsystem entered the queue, (for timing and priority reasons) var/queued_time = 0 @@ -125,6 +128,31 @@ Master.subsystems -= src return ..() + +/** Update next_fire for the next run. + * reset_time (bool) - Ignore things that would normally alter the next fire, like tick_overrun, and last_fire. (also resets postpone) + */ +/datum/controller/subsystem/proc/update_nextfire(reset_time = FALSE) + var/queue_node_flags = flags + + if (reset_time) + postponed_fires = 0 + if (queue_node_flags & SS_TICKER) + next_fire = world.time + (world.tick_lag * wait) + else + next_fire = world.time + wait + return + + if (queue_node_flags & SS_TICKER) + next_fire = world.time + (world.tick_lag * wait) + else if (queue_node_flags & SS_POST_FIRE_TIMING) + next_fire = world.time + wait + (world.tick_lag * (tick_overrun/100)) + else if (queue_node_flags & SS_KEEP_TIMING) + next_fire += wait + else + next_fire = queued_time + wait + (world.tick_lag * (tick_overrun/100)) + + //Queue it to run. // (we loop thru a linked list until we get to the end or find the right point) // (this lets us sort our run order correctly without having to re-sort the entire already sorted list) @@ -241,11 +269,10 @@ if (SS_IDLE) . = " " -//could be used to postpone a costly subsystem for (default one) var/cycles, cycles -//for instance, during cpu intensive operations like explosions +/// Causes the next "cycle" fires to be missed. Effect is accumulative but can reset by calling update_nextfire(reset_time = TRUE) /datum/controller/subsystem/proc/postpone(cycles = 1) - if(next_fire - world.time < wait) - next_fire += (wait*cycles) + if (can_fire && cycles >= 1) + postponed_fires += cycles //usually called via datum/controller/subsystem/New() when replacing a subsystem (i.e. due to a recurring crash) //should attempt to salvage what it can from the old instance of subsystem @@ -256,7 +283,7 @@ if (NAMEOF(src, can_fire)) //this is so the subsystem doesn't rapid fire to make up missed ticks causing more lag if (var_value) - next_fire = world.time + wait + update_nextfire(reset_time = TRUE) if (NAMEOF(src, queued_priority)) //editing this breaks things. return FALSE . = ..() diff --git a/code/modules/admin/view_variables/reference_tracking.dm b/code/modules/admin/view_variables/reference_tracking.dm index 3154f64740a..f8ee92fb67e 100644 --- a/code/modules/admin/view_variables/reference_tracking.dm +++ b/code/modules/admin/view_variables/reference_tracking.dm @@ -9,7 +9,7 @@ running_find_references = null //restart the garbage collector SSgarbage.can_fire = TRUE - SSgarbage.next_fire = world.time + world.tick_lag + SSgarbage.update_nextfire(reset_time = TRUE) return if(!skip_alert && tgui_alert(usr,"Running this will lock everything up for about 5 minutes. Would you like to begin the search?", "Find References", list("Yes", "No")) != "Yes") @@ -51,7 +51,7 @@ //restart the garbage collector SSgarbage.can_fire = TRUE - SSgarbage.next_fire = world.time + world.tick_lag + SSgarbage.update_nextfire(reset_time = TRUE) /datum/proc/DoSearchVar(potential_container, container_name, recursive_limit = 64, search_time = world.time) #ifdef REFERENCE_TRACKING_DEBUG