Resolves conflicts.

This commit is contained in:
Desolate
2018-10-11 05:36:22 -05:00
486 changed files with 16260 additions and 10647 deletions
-20
View File
@@ -2,7 +2,6 @@ var/global/datum/controller/process/npcai/npcai_master
/datum/controller/process/npcai
var/current_cycle
var/saved_voice = 0
/datum/controller/process/npcai/setup()
name = "npc ai"
@@ -36,25 +35,6 @@ var/global/datum/controller/process/npcai/npcai_master
catchBadType(M)
GLOB.simple_animal_list -= M
if(ticker.current_state == GAME_STATE_FINISHED && !saved_voice)
var/mob/living/carbon/human/interactive/M = safepick(GLOB.snpc_list)
if(M)
M.saveVoice()
saved_voice = 1
for(last_object in GLOB.snpc_list)
var/mob/living/carbon/human/interactive/M = last_object
if(istype(M) && !QDELETED(M))
try
if(!M.alternateProcessing || M.forceProcess)
M.doProcess()
catch(var/exception/e)
catchException(e, M)
SCHECK
else
catchBadType(M)
GLOB.snpc_list -= M
current_cycle++
-119
View File
@@ -1,119 +0,0 @@
var/global/datum/controller/process/npcpool/npc_master
/datum/controller/process/npcpool
var/list/canBeUsed = list()
var/list/canBeUsed_non = list()
var/list/needsDelegate = list()
var/list/needsAssistant = list()
var/list/needsHelp_non = list()
var/list/botPool_l = list() //list of all npcs using the pool
var/list/botPool_l_non = list() //list of all non SNPC mobs using the pool
/datum/controller/process/npcpool/setup()
name = "npc pool"
schedule_interval = 100
start_delay = 17
log_startup_progress("NPC pool ticker starting up.")
/datum/controller/process/npcpool/copyStateFrom(var/datum/controller/process/npcpool/target)
canBeUsed = target.canBeUsed
canBeUsed_non = target.canBeUsed_non
needsDelegate = target.needsDelegate
needsAssistant = target.needsAssistant
needsHelp_non = target.needsHelp_non
botPool_l = target.botPool_l
botPool_l_non = target.botPool_l_non
DECLARE_GLOBAL_CONTROLLER(npcpool, npc_master)
/datum/controller/process/npcpool/proc/insertBot(toInsert)
if(istype(toInsert, /mob/living/carbon/human/interactive))
botPool_l |= toInsert
/datum/controller/process/npcpool/proc/removeBot(toRemove)
botPool_l -= toRemove
/datum/controller/process/npcpool/statProcess()
..()
stat(null, "T [botPool_l.len + botPool_l_non.len] | D [needsDelegate.len] | A [needsAssistant.len + needsHelp_non.len] | U [canBeUsed.len + canBeUsed_non.len]")
/datum/controller/process/npcpool/doWork()
//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.
listclearnulls(canBeUsed)
//SNPC handling
for(var/mob/living/carbon/human/interactive/check in botPool_l)
if(!check)
botPool_l -= check
continue
var/checkInRange = view(SNPC_MAX_RANGE_FIND, check)
if(!(locate(check.TARGET) in checkInRange))
needsDelegate |= check
else if(check.IsDeadOrIncap(0))
needsDelegate |= check
else if(check.doing & SNPC_FIGHTING)
needsAssistant |= check
else
canBeUsed |= check
SCHECK
if(needsDelegate.len)
needsDelegate -= pick(needsDelegate) // cheapo way to make sure stuff doesn't pingpong around in the pool forever. delegation runs seperately to each loop so it will work much smoother
for(var/mob/living/carbon/human/interactive/check in needsDelegate)
if(!check)
needsDelegate -= check
continue
if(canBeUsed.len)
var/mob/living/carbon/human/interactive/candidate = pick(canBeUsed)
var/facCount = 0
var/helpProb = 0
for(var/C in check.faction)
for(var/D in candidate.faction)
if(D == C)
helpProb = min(100, helpProb + 25)
facCount++
if(facCount == 1 && helpProb > 0)
helpProb = 100
if(prob(helpProb))
if(candidate.takeDelegate(check))
needsDelegate -= check
canBeUsed -= candidate
candidate.change_eye_color(255, 0, 0)
SCHECK
if(needsAssistant.len)
needsAssistant -= pick(needsAssistant)
for(var/mob/living/carbon/human/interactive/check in needsAssistant)
if(!check)
needsAssistant -= check
continue
if(canBeUsed.len)
var/mob/living/carbon/human/interactive/candidate = pick(canBeUsed)
var/facCount = 0
var/helpProb = 0
for(var/C in check.faction)
for(var/D in candidate.faction)
if(D == C)
helpProb = min(100, helpProb + 25)
facCount++
if(facCount == 1 && helpProb > 0)
helpProb = 100
if(prob(helpProb))
if(candidate.takeDelegate(check, 0))
needsAssistant -= check
canBeUsed -= candidate
candidate.change_eye_color(255, 255, 0)
SCHECK
+3 -3
View File
@@ -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
+24
View File
@@ -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
+127
View File
@@ -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
+212
View File
@@ -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()
+1 -1
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -85,7 +85,7 @@
debug_variables(SSmobs)
feedback_add_details("admin_verb","DMob")
if("NPC AI")
debug_variables(npcai_master)
debug_variables(SSnpcai)
feedback_add_details("admin_verb","DNPCAI")
if("Shuttle")
debug_variables(SSshuttle)