mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-11 10:11:09 +00:00
## About The Pull Request AI controllers do not respect their tick limits, behaving as if they need to process all controllers in one tick. This means every time the idle subsystem runs we process 500 controllers at once. This is bad, and induces overtime for free, which sucks. I can't think of a reason we would need to do all this work at once.
61 lines
2.3 KiB
Plaintext
61 lines
2.3 KiB
Plaintext
/// The subsystem used to tick [/datum/ai_controllers] instances. Handling the re-checking of plans.
|
|
SUBSYSTEM_DEF(ai_controllers)
|
|
name = "AI Controller Ticker"
|
|
flags = SS_POST_FIRE_TIMING|SS_BACKGROUND
|
|
priority = FIRE_PRIORITY_NPC
|
|
init_order = INIT_ORDER_AI_CONTROLLERS
|
|
wait = 0.5 SECONDS //Plan every half second if required, not great not terrible.
|
|
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
|
|
///type of status we are interested in running
|
|
var/planning_status = AI_STATUS_ON
|
|
/// The average tick cost of all active AI, calculated on fire.
|
|
var/our_cost
|
|
/// The tick cost of all currently processed AI, being summed together
|
|
var/summing_cost
|
|
|
|
/datum/controller/subsystem/ai_controllers/Initialize()
|
|
setup_subtrees()
|
|
return SS_INIT_SUCCESS
|
|
|
|
/datum/controller/subsystem/ai_controllers/stat_entry(msg)
|
|
var/list/planning_list = GLOB.ai_controllers_by_status[planning_status]
|
|
msg = "Planning AIs:[length(planning_list)]/[round(our_cost,1)]%"
|
|
return ..()
|
|
|
|
/datum/controller/subsystem/ai_controllers/fire(resumed)
|
|
if(!resumed)
|
|
summing_cost = 0
|
|
var/timer = TICK_USAGE_REAL
|
|
for(var/datum/ai_controller/ai_controller as anything in GLOB.ai_controllers_by_status[planning_status])
|
|
if(!ai_controller.able_to_plan)
|
|
continue
|
|
ai_controller.SelectBehaviors(wait * 0.1)
|
|
|
|
if(!length(ai_controller.current_behaviors)) //Still no plan
|
|
ai_controller.planning_failed()
|
|
|
|
if(MC_TICK_CHECK)
|
|
break
|
|
|
|
summing_cost += TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer)
|
|
if(MC_TICK_CHECK)
|
|
return
|
|
|
|
our_cost = MC_AVERAGE(our_cost, summing_cost)
|
|
|
|
///Creates all instances of ai_subtrees and assigns them to the ai_subtrees list.
|
|
/datum/controller/subsystem/ai_controllers/proc/setup_subtrees()
|
|
if(length(GLOB.ai_subtrees))
|
|
return
|
|
for(var/subtree_type in subtypesof(/datum/ai_planning_subtree))
|
|
var/datum/ai_planning_subtree/subtree = new subtree_type
|
|
GLOB.ai_subtrees[subtree_type] = subtree
|
|
|
|
///Called when the max Z level was changed, updating our coverage.
|
|
/datum/controller/subsystem/ai_controllers/proc/on_max_z_changed()
|
|
if(!length(GLOB.ai_controllers_by_zlevel))
|
|
GLOB.ai_controllers_by_zlevel = new /list(world.maxz,0)
|
|
while (GLOB.ai_controllers_by_zlevel.len < world.maxz)
|
|
GLOB.ai_controllers_by_zlevel.len++
|
|
GLOB.ai_controllers_by_zlevel[GLOB.ai_controllers_by_zlevel.len] = list()
|