mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-17 10:03:50 +01:00
Merge remote-tracking branch 'refs/remotes/origin/master' into smoothing-improvements
This commit is contained in:
@@ -66,8 +66,8 @@ SUBSYSTEM_DEF(air)
|
||||
/datum/controller/subsystem/air/Initialize(timeofday)
|
||||
setup_overlays() // Assign icons and such for gas-turf-overlays
|
||||
setup_allturfs()
|
||||
setup_atmos_machinery(machines)
|
||||
setup_pipenets(machines)
|
||||
setup_atmos_machinery(GLOB.machines)
|
||||
setup_pipenets(GLOB.machines)
|
||||
..()
|
||||
|
||||
|
||||
@@ -363,19 +363,19 @@ SUBSYSTEM_DEF(air)
|
||||
plmaster.icon = 'icons/effects/tile_effects.dmi'
|
||||
plmaster.icon_state = "plasma"
|
||||
plmaster.layer = FLY_LAYER
|
||||
plmaster.mouse_opacity = 0
|
||||
plmaster.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
|
||||
slmaster = new /obj/effect/overlay()
|
||||
slmaster.icon = 'icons/effects/tile_effects.dmi'
|
||||
slmaster.icon_state = "sleeping_agent"
|
||||
slmaster.layer = FLY_LAYER
|
||||
slmaster.mouse_opacity = 0
|
||||
slmaster.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
|
||||
icemaster = new /obj/effect/overlay()
|
||||
icemaster.icon = 'icons/turf/overlays.dmi'
|
||||
icemaster.icon_state = "snowfloor"
|
||||
icemaster.layer = TURF_LAYER + 0.1
|
||||
icemaster.mouse_opacity = 0
|
||||
icemaster.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
|
||||
#undef SSAIR_PIPENETS
|
||||
#undef SSAIR_ATMOSMACHINERY
|
||||
|
||||
@@ -67,7 +67,7 @@ SUBSYSTEM_DEF(machines)
|
||||
/datum/controller/subsystem/machines/proc/process_premachines(resumed = 0)
|
||||
/* Literally exists as snowflake for fucking powersinks goddamnit */
|
||||
if(!resumed)
|
||||
src.currentrun = processing_power_items.Copy()
|
||||
src.currentrun = GLOB.processing_power_items.Copy()
|
||||
//cache for sanid speed (lists are references anyways)
|
||||
var/list/currentrun = src.currentrun
|
||||
while(currentrun.len)
|
||||
@@ -75,9 +75,9 @@ SUBSYSTEM_DEF(machines)
|
||||
currentrun.len--
|
||||
if(!QDELETED(I))
|
||||
if(!I.pwr_drain())
|
||||
processing_power_items.Remove(I)
|
||||
GLOB.processing_power_items.Remove(I)
|
||||
else
|
||||
processing_power_items.Remove(I)
|
||||
GLOB.processing_power_items.Remove(I)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
|
||||
@@ -7,12 +7,12 @@ SUBSYSTEM_DEF(mobs)
|
||||
var/list/currentrun = list()
|
||||
|
||||
/datum/controller/subsystem/mobs/stat_entry()
|
||||
..("P:[mob_list.len]")
|
||||
..("P:[GLOB.mob_list.len]")
|
||||
|
||||
/datum/controller/subsystem/mobs/fire(resumed = 0)
|
||||
var/seconds = wait * 0.1
|
||||
if(!resumed)
|
||||
src.currentrun = mob_list.Copy()
|
||||
src.currentrun = GLOB.mob_list.Copy()
|
||||
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/currentrun = src.currentrun
|
||||
@@ -23,6 +23,6 @@ SUBSYSTEM_DEF(mobs)
|
||||
if(M)
|
||||
M.Life(seconds, times_fired)
|
||||
else
|
||||
mob_list.Remove(M)
|
||||
GLOB.mob_list.Remove(M)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
@@ -54,7 +54,7 @@ SUBSYSTEM_DEF(nightshift)
|
||||
announce("Good evening, crew. To reduce power consumption and stimulate the circadian rhythms of some species, all of the lights aboard the station have been dimmed for the night.")
|
||||
else
|
||||
announce("Good morning, crew. As it is now day time, all of the lights aboard the station have been restored to their former brightness.")
|
||||
for(var/A in apcs)
|
||||
for(var/A in GLOB.apcs)
|
||||
var/obj/machinery/power/apc/APC = A
|
||||
if(is_station_level(APC.z))
|
||||
APC.set_nightshift(active)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
SUBSYSTEM_DEF(npcai)
|
||||
name = "NPC AI" // Simple AI controller, isolated from the SNPC one (NPCPool).
|
||||
flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND
|
||||
priority = FIRE_PRIORITY_NPC
|
||||
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
|
||||
var/list/simple_animal_list = list()
|
||||
|
||||
/datum/controller/subsystem/npcai/stat_entry()
|
||||
..("SimAnimals:[simple_animal_list.len]")
|
||||
|
||||
/datum/controller/subsystem/npcai/fire(resumed = FALSE)
|
||||
if(!resumed)
|
||||
src.simple_animal_list = simple_animal_list.Copy()
|
||||
for(var/mob/living/simple_animal/M in simple_animal_list)
|
||||
if(istype(M) && !QDELETED(M))
|
||||
if(!M.client && M.stat == CONSCIOUS)
|
||||
M.process_ai()
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
else
|
||||
simple_animal_list -= M
|
||||
|
||||
/datum/controller/subsystem/npcai/Recover()
|
||||
simple_animal_list = SSnpcai.simple_animal_list
|
||||
@@ -0,0 +1,127 @@
|
||||
#define PROCESSING_NPCS 0
|
||||
#define PROCESSING_DELEGATES 1
|
||||
#define PROCESSING_ASSISTANTS 2
|
||||
|
||||
SUBSYSTEM_DEF(npcpool)
|
||||
name = "NPC Pool"
|
||||
flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND
|
||||
priority = FIRE_PRIORITY_NPC
|
||||
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/carbon/human/interactive/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)
|
||||
currentrun = processing.Copy()
|
||||
stage = PROCESSING_NPCS
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/cachecurrentrun = currentrun
|
||||
var/list/cachecanBeUsed = canBeUsed
|
||||
|
||||
if(stage == PROCESSING_NPCS)
|
||||
while(cachecurrentrun.len)
|
||||
var/mob/living/carbon/human/interactive/thing = cachecurrentrun[cachecurrentrun.len]
|
||||
--cachecurrentrun.len
|
||||
|
||||
thing.InteractiveProcess()
|
||||
|
||||
var/checkInRange = view(SNPC_MAX_RANGE_FIND,thing)
|
||||
if(thing.IsDeadOrIncap(FALSE) || !(locate(thing.TARGET) in checkInRange))
|
||||
needsDelegate += thing
|
||||
else if(thing.doing & SNPC_FIGHTING)
|
||||
needsAssistant += thing
|
||||
else
|
||||
cachecanBeUsed += thing
|
||||
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
stage = PROCESSING_DELEGATES
|
||||
cachecurrentrun = needsDelegate //localcache
|
||||
currentrun = cachecurrentrun
|
||||
|
||||
if(stage == PROCESSING_DELEGATES)
|
||||
while(cachecurrentrun.len && cachecanBeUsed.len)
|
||||
var/mob/living/carbon/human/interactive/check = cachecurrentrun[cachecurrentrun.len]
|
||||
var/mob/living/carbon/human/interactive/candidate = cachecanBeUsed[cachecanBeUsed.len]
|
||||
--cachecurrentrun.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))
|
||||
--cachecanBeUsed.len
|
||||
candidate.change_eye_color(255, 0, 0)
|
||||
candidate.update_icons()
|
||||
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
stage = PROCESSING_ASSISTANTS
|
||||
cachecurrentrun = needsAssistant //localcache
|
||||
currentrun = cachecurrentrun
|
||||
|
||||
//no need for the stage check
|
||||
|
||||
while(cachecurrentrun.len && cachecanBeUsed.len)
|
||||
var/mob/living/carbon/human/interactive/check = cachecurrentrun[cachecurrentrun.len]
|
||||
var/mob/living/carbon/human/interactive/candidate = cachecanBeUsed[cachecanBeUsed.len]
|
||||
--cachecurrentrun.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))
|
||||
--cachecanBeUsed.len
|
||||
candidate.change_eye_color(255, 255, 0)
|
||||
candidate.update_icons()
|
||||
|
||||
if(!cachecurrentrun.len || MC_TICK_CHECK) //don't change SS state if it isn't necessary
|
||||
return
|
||||
|
||||
/datum/controller/subsystem/npcpool/Recover()
|
||||
processing = SSnpcpool.processing
|
||||
@@ -0,0 +1,212 @@
|
||||
SUBSYSTEM_DEF(overlays)
|
||||
name = "Overlay"
|
||||
flags = SS_TICKER
|
||||
wait = 1
|
||||
priority = FIRE_PRIORITY_OVERLAYS
|
||||
init_order = INIT_ORDER_OVERLAY
|
||||
|
||||
var/list/queue
|
||||
var/list/stats
|
||||
var/list/overlay_icon_state_caches
|
||||
var/list/overlay_icon_cache
|
||||
|
||||
/datum/controller/subsystem/overlays/PreInit()
|
||||
overlay_icon_state_caches = list()
|
||||
overlay_icon_cache = list()
|
||||
queue = list()
|
||||
stats = list()
|
||||
|
||||
/datum/controller/subsystem/overlays/Initialize()
|
||||
initialized = TRUE
|
||||
fire(mc_check = FALSE)
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/controller/subsystem/overlays/stat_entry()
|
||||
..("Ov:[length(queue)]")
|
||||
|
||||
/datum/controller/subsystem/overlays/Recover()
|
||||
overlay_icon_state_caches = SSoverlays.overlay_icon_state_caches
|
||||
overlay_icon_cache = SSoverlays.overlay_icon_cache
|
||||
queue = SSoverlays.queue
|
||||
|
||||
|
||||
/datum/controller/subsystem/overlays/fire(resumed = FALSE, mc_check = TRUE)
|
||||
var/list/queue = src.queue
|
||||
var/static/count = 0
|
||||
if(count)
|
||||
var/c = count
|
||||
count = 0 //so if we runtime on the Cut, we don't try again.
|
||||
queue.Cut(1, c + 1)
|
||||
|
||||
for(var/thing in queue)
|
||||
count++
|
||||
if(thing)
|
||||
var/atom/A = thing
|
||||
COMPILE_OVERLAYS(A)
|
||||
if(mc_check)
|
||||
if(MC_TICK_CHECK)
|
||||
break
|
||||
else
|
||||
CHECK_TICK
|
||||
|
||||
if(count)
|
||||
queue.Cut(1, count + 1)
|
||||
count = 0
|
||||
|
||||
/proc/iconstate2appearance(icon, iconstate)
|
||||
var/static/image/stringbro = new()
|
||||
var/list/icon_states_cache = SSoverlays.overlay_icon_state_caches
|
||||
var/list/cached_icon = icon_states_cache[icon]
|
||||
if(cached_icon)
|
||||
var/cached_appearance = cached_icon["[iconstate]"]
|
||||
if(cached_appearance)
|
||||
return cached_appearance
|
||||
stringbro.icon = icon
|
||||
stringbro.icon_state = iconstate
|
||||
if(!cached_icon) //not using the macro to save an associated lookup
|
||||
cached_icon = list()
|
||||
icon_states_cache[icon] = cached_icon
|
||||
var/cached_appearance = stringbro.appearance
|
||||
cached_icon["[iconstate]"] = cached_appearance
|
||||
return cached_appearance
|
||||
|
||||
/proc/icon2appearance(icon)
|
||||
var/static/image/iconbro = new()
|
||||
var/list/icon_cache = SSoverlays.overlay_icon_cache
|
||||
. = icon_cache[icon]
|
||||
if(!.)
|
||||
iconbro.icon = icon
|
||||
. = iconbro.appearance
|
||||
icon_cache[icon] = .
|
||||
|
||||
/atom/proc/build_appearance_list(old_overlays)
|
||||
var/static/image/appearance_bro = new()
|
||||
var/list/new_overlays = list()
|
||||
if(!islist(old_overlays))
|
||||
old_overlays = list(old_overlays)
|
||||
for(var/overlay in old_overlays)
|
||||
if(!overlay)
|
||||
continue
|
||||
if(istext(overlay))
|
||||
new_overlays += iconstate2appearance(icon, overlay)
|
||||
else if(isicon(overlay))
|
||||
new_overlays += icon2appearance(overlay)
|
||||
else
|
||||
if(isloc(overlay))
|
||||
var/atom/A = overlay
|
||||
if(A.flags_2 & OVERLAY_QUEUED_2)
|
||||
COMPILE_OVERLAYS(A)
|
||||
appearance_bro.appearance = overlay //this works for images and atoms too!
|
||||
if(!ispath(overlay))
|
||||
var/image/I = overlay
|
||||
appearance_bro.dir = I.dir
|
||||
new_overlays += appearance_bro.appearance
|
||||
return new_overlays
|
||||
|
||||
#define NOT_QUEUED_ALREADY (!(flags_2 & OVERLAY_QUEUED_2))
|
||||
#define QUEUE_FOR_COMPILE flags_2 |= OVERLAY_QUEUED_2; SSoverlays.queue += src;
|
||||
/atom/proc/cut_overlays(priority = FALSE)
|
||||
LAZYINITLIST(priority_overlays)
|
||||
LAZYINITLIST(remove_overlays)
|
||||
LAZYINITLIST(add_overlays)
|
||||
remove_overlays = overlays.Copy()
|
||||
add_overlays.Cut()
|
||||
|
||||
if(priority)
|
||||
priority_overlays.Cut()
|
||||
|
||||
//If not already queued for work and there are overlays to remove
|
||||
if(NOT_QUEUED_ALREADY && remove_overlays.len)
|
||||
QUEUE_FOR_COMPILE
|
||||
|
||||
/atom/proc/cut_overlay(list/overlays, priority)
|
||||
if(!overlays)
|
||||
return
|
||||
overlays = build_appearance_list(overlays)
|
||||
LAZYINITLIST(add_overlays) //always initialized after this point
|
||||
LAZYINITLIST(priority_overlays)
|
||||
LAZYINITLIST(remove_overlays)
|
||||
var/a_len = add_overlays.len
|
||||
var/r_len = remove_overlays.len
|
||||
var/p_len = priority_overlays.len
|
||||
remove_overlays += overlays
|
||||
add_overlays -= overlays
|
||||
|
||||
if(priority)
|
||||
var/list/cached_priority = priority_overlays
|
||||
LAZYREMOVE(cached_priority, overlays)
|
||||
|
||||
var/fa_len = add_overlays.len
|
||||
var/fr_len = remove_overlays.len
|
||||
var/fp_len = priority_overlays.len
|
||||
|
||||
//If not already queued and there is work to be done
|
||||
if(NOT_QUEUED_ALREADY && (fa_len != a_len || fr_len != r_len || fp_len != p_len))
|
||||
QUEUE_FOR_COMPILE
|
||||
|
||||
/atom/proc/add_overlay(list/overlays, priority = FALSE)
|
||||
if(!overlays)
|
||||
return
|
||||
|
||||
overlays = build_appearance_list(overlays)
|
||||
|
||||
LAZYINITLIST(add_overlays) //always initialized after this point
|
||||
LAZYINITLIST(priority_overlays)
|
||||
var/a_len = add_overlays.len
|
||||
var/p_len = priority_overlays.len
|
||||
|
||||
if(priority)
|
||||
priority_overlays += overlays //or in the image. Can we use [image] = image?
|
||||
var/fp_len = priority_overlays.len
|
||||
if(NOT_QUEUED_ALREADY && fp_len != p_len)
|
||||
QUEUE_FOR_COMPILE
|
||||
else
|
||||
add_overlays += overlays
|
||||
var/fa_len = add_overlays.len
|
||||
if(NOT_QUEUED_ALREADY && fa_len != a_len)
|
||||
QUEUE_FOR_COMPILE
|
||||
|
||||
/atom/proc/copy_overlays(atom/other, cut_old) //copys our_overlays from another atom
|
||||
if(!other)
|
||||
if(cut_old)
|
||||
cut_overlays()
|
||||
return
|
||||
|
||||
var/list/cached_other = other.overlays.Copy()
|
||||
if(cached_other)
|
||||
if(cut_old || !LAZYLEN(overlays))
|
||||
remove_overlays = overlays
|
||||
add_overlays = cached_other
|
||||
if(NOT_QUEUED_ALREADY)
|
||||
QUEUE_FOR_COMPILE
|
||||
else if(cut_old)
|
||||
cut_overlays()
|
||||
|
||||
#undef NOT_QUEUED_ALREADY
|
||||
#undef QUEUE_FOR_COMPILE
|
||||
|
||||
//TODO: Better solution for these?
|
||||
/image/proc/add_overlay(x)
|
||||
overlays |= x
|
||||
|
||||
/image/proc/cut_overlay(x)
|
||||
overlays -= x
|
||||
|
||||
/image/proc/cut_overlays(x)
|
||||
overlays.Cut()
|
||||
|
||||
/image/proc/copy_overlays(atom/other, cut_old)
|
||||
if(!other)
|
||||
if(cut_old)
|
||||
cut_overlays()
|
||||
return
|
||||
|
||||
var/list/cached_other = other.overlays.Copy()
|
||||
if(cached_other)
|
||||
if(cut_old || !overlays.len)
|
||||
overlays = cached_other
|
||||
else
|
||||
overlays |= cached_other
|
||||
else if(cut_old)
|
||||
cut_overlays()
|
||||
@@ -180,7 +180,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
/datum/controller/subsystem/shuttle/proc/autoEvac()
|
||||
var/callShuttle = 1
|
||||
|
||||
for(var/thing in shuttle_caller_list)
|
||||
for(var/thing in GLOB.shuttle_caller_list)
|
||||
if(istype(thing, /mob/living/silicon/ai))
|
||||
var/mob/living/silicon/ai/AI = thing
|
||||
if(AI.stat || !AI.client)
|
||||
|
||||
@@ -35,7 +35,7 @@ SUBSYSTEM_DEF(tickets)
|
||||
message_adminTicket("<span class='adminticket'>Tickets [report] have been open for over [ADMIN_TICKET_TIMEOUT / 600] minutes. Changing status to stale.</span>")
|
||||
|
||||
/datum/controller/subsystem/tickets/stat_entry()
|
||||
..("Tickets: [allTickets.len]")
|
||||
..("Tickets: [LAZYLEN(allTickets)]")
|
||||
|
||||
/datum/controller/subsystem/tickets/proc/checkStaleness()
|
||||
var/stales = list()
|
||||
|
||||
+108
-102
@@ -1,5 +1,5 @@
|
||||
#define BUCKET_LEN (world.fps*1*60) //how many ticks should we keep in the bucket. (1 minutes worth)
|
||||
#define BUCKET_POS(timer) ((round((timer.timeToRun - SStimer.head_offset) / world.tick_lag) % BUCKET_LEN) + 1)
|
||||
#define BUCKET_POS(timer) ((round((timer.timeToRun - SStimer.head_offset) / world.tick_lag) % BUCKET_LEN)||BUCKET_LEN)
|
||||
#define TIMER_MAX (world.time + TICKS2DS(min(BUCKET_LEN-(SStimer.practical_offset-DS2TICKS(world.time - SStimer.head_offset))-1, BUCKET_LEN-1)))
|
||||
#define TIMER_ID_MAX (2**24) //max float with integer precision
|
||||
|
||||
@@ -71,6 +71,7 @@ SUBSYSTEM_DEF(timer)
|
||||
for(var/I in second_queue)
|
||||
log_world(get_timer_debug_string(I))
|
||||
|
||||
var/cut_start_index = 1
|
||||
var/next_clienttime_timer_index = 0
|
||||
var/len = length(clienttime_timers)
|
||||
|
||||
@@ -90,11 +91,17 @@ SUBSYSTEM_DEF(timer)
|
||||
|
||||
ctime_timer.spent = REALTIMEOFDAY
|
||||
callBack.InvokeAsync()
|
||||
qdel(ctime_timer)
|
||||
|
||||
if(ctime_timer.flags & TIMER_LOOP)
|
||||
ctime_timer.spent = 0
|
||||
clienttime_timers.Insert(ctime_timer, 1)
|
||||
cut_start_index++
|
||||
else
|
||||
qdel(ctime_timer)
|
||||
|
||||
|
||||
if(next_clienttime_timer_index)
|
||||
clienttime_timers.Cut(1,next_clienttime_timer_index+1)
|
||||
clienttime_timers.Cut(cut_start_index,next_clienttime_timer_index+1)
|
||||
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
@@ -197,8 +204,22 @@ SUBSYSTEM_DEF(timer)
|
||||
|
||||
bucket_count -= length(spent)
|
||||
|
||||
for(var/spent_timer in spent)
|
||||
qdel(spent_timer)
|
||||
for(var/i in spent)
|
||||
var/datum/timedevent/qtimer = i
|
||||
if(QDELETED(qtimer))
|
||||
bucket_count++
|
||||
continue
|
||||
if(!(qtimer.flags & TIMER_LOOP))
|
||||
qdel(qtimer)
|
||||
else
|
||||
bucket_count++
|
||||
qtimer.spent = 0
|
||||
qtimer.bucketEject()
|
||||
if(qtimer.flags & TIMER_CLIENT_TIME)
|
||||
qtimer.timeToRun = REALTIMEOFDAY + qtimer.wait
|
||||
else
|
||||
qtimer.timeToRun = world.time + qtimer.wait
|
||||
qtimer.bucketJoin()
|
||||
|
||||
spent.len = 0
|
||||
|
||||
@@ -294,6 +315,7 @@ SUBSYSTEM_DEF(timer)
|
||||
var/id
|
||||
var/datum/callback/callBack
|
||||
var/timeToRun
|
||||
var/wait
|
||||
var/hash
|
||||
var/list/flags
|
||||
var/spent = 0 //time we ran the timer.
|
||||
@@ -302,14 +324,19 @@ SUBSYSTEM_DEF(timer)
|
||||
var/datum/timedevent/next
|
||||
var/datum/timedevent/prev
|
||||
|
||||
/datum/timedevent/New(datum/callback/callBack, timeToRun, flags, hash)
|
||||
/datum/timedevent/New(datum/callback/callBack, wait, flags, hash)
|
||||
var/static/nextid = 1
|
||||
id = TIMER_ID_NULL
|
||||
src.callBack = callBack
|
||||
src.timeToRun = timeToRun
|
||||
src.wait = wait
|
||||
src.flags = flags
|
||||
src.hash = hash
|
||||
|
||||
if(flags & TIMER_CLIENT_TIME)
|
||||
timeToRun = REALTIMEOFDAY + wait
|
||||
else
|
||||
timeToRun = world.time + wait
|
||||
|
||||
if(flags & TIMER_UNIQUE)
|
||||
SStimer.hashes[hash] = src
|
||||
|
||||
@@ -321,68 +348,15 @@ SUBSYSTEM_DEF(timer)
|
||||
nextid++
|
||||
SStimer.timer_id_dict[id] = src
|
||||
|
||||
name = "Timer: [id] (\ref[src]), TTR: [timeToRun], Flags: [jointext(bitfield2list(flags, list("TIMER_UNIQUE", "TIMER_OVERRIDE", "TIMER_CLIENT_TIME", "TIMER_STOPPABLE", "TIMER_NO_HASH_WAIT")), ", ")], callBack: \ref[callBack], callBack.object: [callBack.object]\ref[callBack.object]([getcallingtype()]), callBack.delegate:[callBack.delegate]([callBack.arguments ? callBack.arguments.Join(", ") : ""])"
|
||||
name = "Timer: [id] (\ref[src]), TTR: [timeToRun], Flags: [jointext(bitfield2list(flags, list("TIMER_UNIQUE", "TIMER_OVERRIDE", "TIMER_CLIENT_TIME", "TIMER_STOPPABLE", "TIMER_NO_HASH_WAIT", "TIMER_LOOP")), ", ")], callBack: \ref[callBack], callBack.object: [callBack.object]\ref[callBack.object]([getcallingtype()]), callBack.delegate:[callBack.delegate]([callBack.arguments ? callBack.arguments.Join(", ") : ""])"
|
||||
|
||||
if((timeToRun < world.time || timeToRun < SStimer.head_offset) && !(flags & TIMER_CLIENT_TIME))
|
||||
CRASH("Invalid timer state: Timer created that would require a backtrack to run (addtimer would never let this happen): [SStimer.get_timer_debug_string(src)]")
|
||||
|
||||
if(callBack.object != GLOBAL_PROC)
|
||||
if(callBack.object != GLOBAL_PROC && !QDESTROYING(callBack.object))
|
||||
LAZYADD(callBack.object.active_timers, src)
|
||||
|
||||
|
||||
var/list/L
|
||||
|
||||
if(flags & TIMER_CLIENT_TIME)
|
||||
L = SStimer.clienttime_timers
|
||||
else if(timeToRun >= TIMER_MAX)
|
||||
L = SStimer.second_queue
|
||||
|
||||
|
||||
if(L)
|
||||
//binary search sorted insert
|
||||
var/cttl = length(L)
|
||||
if(cttl)
|
||||
var/left = 1
|
||||
var/right = cttl
|
||||
var/mid = (left+right) >> 1 //rounded divide by two for hedgehogs
|
||||
|
||||
var/datum/timedevent/item
|
||||
while(left < right)
|
||||
item = L[mid]
|
||||
if(item.timeToRun <= timeToRun)
|
||||
left = mid+1
|
||||
else
|
||||
right = mid
|
||||
mid = (left+right) >> 1
|
||||
|
||||
item = L[mid]
|
||||
mid = item.timeToRun > timeToRun ? mid : mid+1
|
||||
L.Insert(mid, src)
|
||||
|
||||
else
|
||||
L += src
|
||||
return
|
||||
|
||||
//get the list of buckets
|
||||
var/list/bucket_list = SStimer.bucket_list
|
||||
|
||||
//calculate our place in the bucket list
|
||||
var/bucket_pos = BUCKET_POS(src)
|
||||
|
||||
//get the bucket for our tick
|
||||
var/datum/timedevent/bucket_head = bucket_list[bucket_pos]
|
||||
SStimer.bucket_count++
|
||||
//empty bucket, we will just add ourselves
|
||||
if(!bucket_head)
|
||||
bucket_list[bucket_pos] = src
|
||||
return
|
||||
//other wise, lets do a simplified linked list add.
|
||||
if(!bucket_head.prev)
|
||||
bucket_head.prev = bucket_head
|
||||
next = bucket_head
|
||||
prev = bucket_head.prev
|
||||
next.prev = src
|
||||
prev.next = src
|
||||
bucketJoin()
|
||||
|
||||
/datum/timedevent/Destroy()
|
||||
..()
|
||||
@@ -406,31 +380,7 @@ SUBSYSTEM_DEF(timer)
|
||||
|
||||
if(!spent)
|
||||
spent = world.time
|
||||
var/bucketpos = BUCKET_POS(src)
|
||||
var/datum/timedevent/buckethead
|
||||
var/list/bucket_list = SStimer.bucket_list
|
||||
if(bucketpos > 0)
|
||||
buckethead = bucket_list[bucketpos]
|
||||
|
||||
if(buckethead == src)
|
||||
bucket_list[bucketpos] = next
|
||||
SStimer.bucket_count--
|
||||
else if(timeToRun < TIMER_MAX || next || prev)
|
||||
SStimer.bucket_count--
|
||||
else
|
||||
var/l = length(SStimer.second_queue)
|
||||
SStimer.second_queue -= src
|
||||
if(l == length(SStimer.second_queue))
|
||||
SStimer.bucket_count--
|
||||
|
||||
if(prev == next && next)
|
||||
next.prev = null
|
||||
prev.next = null
|
||||
else
|
||||
if(prev)
|
||||
prev.next = next
|
||||
if(next)
|
||||
next.prev = prev
|
||||
bucketEject()
|
||||
else
|
||||
if(prev && prev.next == src)
|
||||
prev.next = next
|
||||
@@ -440,6 +390,66 @@ SUBSYSTEM_DEF(timer)
|
||||
prev = null
|
||||
return QDEL_HINT_IWILLGC
|
||||
|
||||
/datum/timedevent/proc/bucketEject()
|
||||
var/bucketpos = BUCKET_POS(src)
|
||||
var/list/bucket_list = SStimer.bucket_list
|
||||
var/list/second_queue = SStimer.second_queue
|
||||
var/datum/timedevent/buckethead
|
||||
if(bucketpos > 0)
|
||||
buckethead = bucket_list[bucketpos]
|
||||
if(buckethead == src)
|
||||
bucket_list[bucketpos] = next
|
||||
SStimer.bucket_count--
|
||||
else if(timeToRun < TIMER_MAX || next || prev)
|
||||
SStimer.bucket_count--
|
||||
else
|
||||
var/l = length(second_queue)
|
||||
second_queue -= src
|
||||
if(l == length(second_queue))
|
||||
SStimer.bucket_count--
|
||||
if(prev != next)
|
||||
prev.next = next
|
||||
next.prev = prev
|
||||
else
|
||||
if(prev)
|
||||
prev.next = null
|
||||
if(next)
|
||||
next.prev = null
|
||||
prev = next = null
|
||||
|
||||
/datum/timedevent/proc/bucketJoin()
|
||||
var/list/L
|
||||
|
||||
if(flags & TIMER_CLIENT_TIME)
|
||||
L = SStimer.clienttime_timers
|
||||
else if(timeToRun >= TIMER_MAX)
|
||||
L = SStimer.second_queue
|
||||
|
||||
if(L)
|
||||
BINARY_INSERT(src, L, datum/timedevent, timeToRun)
|
||||
return
|
||||
|
||||
//get the list of buckets
|
||||
var/list/bucket_list = SStimer.bucket_list
|
||||
|
||||
//calculate our place in the bucket list
|
||||
var/bucket_pos = BUCKET_POS(src)
|
||||
|
||||
//get the bucket for our tick
|
||||
var/datum/timedevent/bucket_head = bucket_list[bucket_pos]
|
||||
SStimer.bucket_count++
|
||||
//empty bucket, we will just add ourselves
|
||||
if(!bucket_head)
|
||||
bucket_list[bucket_pos] = src
|
||||
return
|
||||
//other wise, lets do a simplified linked list add.
|
||||
if(!bucket_head.prev)
|
||||
bucket_head.prev = bucket_head
|
||||
next = bucket_head
|
||||
prev = bucket_head.prev
|
||||
next.prev = src
|
||||
prev.next = src
|
||||
|
||||
/datum/timedevent/proc/getcallingtype()
|
||||
. = "ERROR"
|
||||
if(callBack.object == GLOBAL_PROC)
|
||||
@@ -452,13 +462,12 @@ SUBSYSTEM_DEF(timer)
|
||||
CRASH("addtimer called without a callback")
|
||||
|
||||
if(wait < 0)
|
||||
stack_trace("addtimer called with a negative wait. Converting to 0")
|
||||
stack_trace("addtimer called with a negative wait. Converting to [world.tick_lag]")
|
||||
|
||||
//alot of things add short timers on themselves in their destroy, we ignore those cases
|
||||
if(wait >= 1 && callback && callback.object && callback.object != GLOBAL_PROC && QDELETED(callback.object))
|
||||
stack_trace("addtimer called with a callback assigned to a qdeleted object")
|
||||
if(callback.object != GLOBAL_PROC && QDELETED(callback.object) && !QDESTROYING(callback.object))
|
||||
stack_trace("addtimer called with a callback assigned to a qdeleted object. In the future such timers will not be supported and may refuse to run or run with a 0 wait")
|
||||
|
||||
wait = max(wait, 0)
|
||||
wait = max(CEILING(wait, world.tick_lag), world.tick_lag)
|
||||
|
||||
if(wait >= INFINITY)
|
||||
CRASH("Attempted to create timer with INFINITY delay")
|
||||
@@ -468,9 +477,9 @@ SUBSYSTEM_DEF(timer)
|
||||
if(flags & TIMER_UNIQUE)
|
||||
var/list/hashlist
|
||||
if(flags & TIMER_NO_HASH_WAIT)
|
||||
hashlist = list(callback.object, "([callback.object.UID()])", callback.delegate, flags & TIMER_CLIENT_TIME)
|
||||
hashlist = list(callback.object, "(\ref[callback.object])", callback.delegate, flags & TIMER_CLIENT_TIME)
|
||||
else
|
||||
hashlist = list(callback.object, "([callback.object.UID()])", callback.delegate, wait, flags & TIMER_CLIENT_TIME)
|
||||
hashlist = list(callback.object, "(\ref[callback.object])", callback.delegate, wait, flags & TIMER_CLIENT_TIME)
|
||||
hashlist += callback.arguments
|
||||
hash = hashlist.Join("|||||||")
|
||||
|
||||
@@ -486,13 +495,10 @@ SUBSYSTEM_DEF(timer)
|
||||
if(hash_timer.flags & TIMER_STOPPABLE)
|
||||
. = hash_timer.id
|
||||
return
|
||||
else if(flags & TIMER_OVERRIDE)
|
||||
stack_trace("TIMER_OVERRIDE used without TIMER_UNIQUE")
|
||||
|
||||
|
||||
var/timeToRun = world.time + wait
|
||||
if(flags & TIMER_CLIENT_TIME)
|
||||
timeToRun = REALTIMEOFDAY + wait
|
||||
|
||||
var/datum/timedevent/timer = new(callback, timeToRun, flags, hash)
|
||||
var/datum/timedevent/timer = new(callback, wait, flags, hash)
|
||||
return timer.id
|
||||
|
||||
/proc/deltimer(id)
|
||||
@@ -515,4 +521,4 @@ SUBSYSTEM_DEF(timer)
|
||||
#undef BUCKET_LEN
|
||||
#undef BUCKET_POS
|
||||
#undef TIMER_MAX
|
||||
#undef TIMER_ID_MAX
|
||||
#undef TIMER_ID_MAX
|
||||
@@ -19,7 +19,7 @@ SUBSYSTEM_DEF(weather)
|
||||
var/datum/weather/W = V
|
||||
if(W.aesthetic || W.stage != MAIN_STAGE)
|
||||
continue
|
||||
for(var/i in living_mob_list)
|
||||
for(var/i in GLOB.living_mob_list)
|
||||
var/mob/living/L = i
|
||||
if(W.can_weather_act(L))
|
||||
W.weather_act(L)
|
||||
|
||||
Reference in New Issue
Block a user