[MIRROR] Fixes AI lag by re-adding idle mode to all AI that was lost with the simple mob to basic mob conversion. (#27296)

Fixes AI lag by re-adding idle mode to all AI that was lost with the simple mob to basic mob conversion.

Co-authored-by: Iamgoofball <iamgoofball@gmail.com>
Co-authored-by: Waterpig <wtryoutube@seznam.cz>
This commit is contained in:
SkyratBot
2024-04-25 16:39:06 +02:00
committed by GitHub
co-authored by Iamgoofball Waterpig
parent 89677f37ba
commit 2429a2821a
8 changed files with 47 additions and 8 deletions
+6
View File
@@ -2,17 +2,23 @@
#define GET_TARGETING_STRATEGY(targeting_type) SSai_behaviors.targeting_strategies[targeting_type]
#define HAS_AI_CONTROLLER_TYPE(thing, type) istype(thing?.ai_controller, type)
//AI controller flags
//If you add a new status, be sure to add it to the ai_controllers subsystem's ai_controllers_by_status list.
///The AI is currently active.
#define AI_STATUS_ON "ai_on"
///The AI is currently offline for any reason.
#define AI_STATUS_OFF "ai_off"
///The AI is currently in idle mode.
#define AI_STATUS_IDLE "ai_idle"
///For JPS pathing, the maximum length of a path we'll try to generate. Should be modularized depending on what we're doing later on
#define AI_MAX_PATH_LENGTH 30 // 30 is possibly overkill since by default we lose interest after 14 tiles of distance, but this gives wiggle room for weaving around obstacles
#define AI_BOT_PATH_LENGTH 150
// How far should we, by default, be looking for interesting things to de-idle?
#define AI_DEFAULT_INTERESTING_DIST 14
///Cooldown on planning if planning failed last time
#define AI_FAILED_PLANNING_COOLDOWN (1.5 SECONDS)
+25 -1
View File
@@ -13,9 +13,14 @@ SUBSYSTEM_DEF(ai_controllers)
var/list/ai_controllers_by_status = list(
AI_STATUS_ON = list(),
AI_STATUS_OFF = list(),
AI_STATUS_IDLE = list(),
)
///Assoc List of all AI controllers and the Z level they are on, which we check when someone enters/leaves a Z level to turn them on/off.
var/list/ai_controllers_by_zlevel = list()
/// The tick cost of all active AI, calculated on fire.
var/cost_on
/// The tick cost of all idle AI, calculated on fire.
var/cost_idle
/datum/controller/subsystem/ai_controllers/Initialize()
setup_subtrees()
@@ -24,10 +29,20 @@ SUBSYSTEM_DEF(ai_controllers)
/datum/controller/subsystem/ai_controllers/stat_entry(msg)
var/list/active_list = ai_controllers_by_status[AI_STATUS_ON]
var/list/inactive_list = ai_controllers_by_status[AI_STATUS_OFF]
msg = "Active AIs:[length(active_list)]|Inactive:[length(inactive_list)]"
var/list/idle_list = ai_controllers_by_status[AI_STATUS_IDLE]
msg = "Active AIs:[length(active_list)]/[round(cost_on,1)]%|Inactive:[length(inactive_list)]|Idle:[length(idle_list)]/[round(cost_idle,1)]%"
return ..()
/datum/controller/subsystem/ai_controllers/fire(resumed)
var/timer = TICK_USAGE_REAL
for(var/datum/ai_controller/ai_controller as anything in ai_controllers_by_status[AI_STATUS_IDLE])
for(var/client/client_found in GLOB.clients)
if(get_dist(get_turf(client_found.mob), get_turf(ai_controller.pawn)) <= ai_controller.interesting_dist)
ai_controller.set_ai_status(AI_STATUS_ON)
break
cost_idle = MC_AVERAGE(cost_idle, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
timer = TICK_USAGE_REAL
for(var/datum/ai_controller/ai_controller as anything in ai_controllers_by_status[AI_STATUS_ON])
if(!COOLDOWN_FINISHED(ai_controller, failed_planning_cooldown))
continue
@@ -37,6 +52,15 @@ SUBSYSTEM_DEF(ai_controllers)
ai_controller.SelectBehaviors(wait * 0.1)
if(!LAZYLEN(ai_controller.current_behaviors)) //Still no plan
COOLDOWN_START(ai_controller, failed_planning_cooldown, AI_FAILED_PLANNING_COOLDOWN)
if(ai_controller.can_idle)
var/found_interesting = FALSE
for(var/client/client_found in GLOB.clients)
if(get_dist(get_turf(client_found.mob), get_turf(ai_controller.pawn)) <= ai_controller.interesting_dist)
found_interesting = TRUE
break
if(!found_interesting)
ai_controller.set_ai_status(AI_STATUS_IDLE)
cost_on = MC_AVERAGE(cost_on, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
///Creates all instances of ai_subtrees and assigns them to the ai_subtrees list.
/datum/controller/subsystem/ai_controllers/proc/setup_subtrees()
+11 -4
View File
@@ -56,6 +56,10 @@ multiple modular subtrees with behaviors
// The variables below are fucking stupid and should be put into the blackboard at some point.
///AI paused time
var/paused_until = 0
///Can this AI idle?
var/can_idle = TRUE
///What distance should we be checking for interesting things when considering idling/deidling? Defaults to AI_DEFAULT_INTERESTING_DIST
var/interesting_dist = AI_DEFAULT_INTERESTING_DIST
/datum/ai_controller/New(atom/new_pawn)
change_ai_movement_type(ai_movement)
@@ -148,7 +152,7 @@ multiple modular subtrees with behaviors
if(ai_traits & CAN_ACT_WHILE_DEAD)
return AI_STATUS_ON
return AI_STATUS_OFF
var/turf/pawn_turf = get_turf(mob_pawn)
#ifdef TESTING
if(!pawn_turf)
@@ -175,7 +179,7 @@ multiple modular subtrees with behaviors
SSai_controllers.ai_controllers_by_zlevel[new_turf.z] += src
var/new_level_clients = SSmobs.clients_by_zlevel[new_turf.z].len
if(new_level_clients)
set_ai_status(AI_STATUS_ON)
set_ai_status(AI_STATUS_IDLE)
else
set_ai_status(AI_STATUS_OFF)
@@ -307,7 +311,7 @@ multiple modular subtrees with behaviors
/datum/ai_controller/proc/set_ai_status(new_ai_status)
if(ai_status == new_ai_status)
return FALSE //no change
//remove old status, if we've got one
if(ai_status)
SSai_controllers.ai_controllers_by_status[ai_status] -= src
@@ -319,6 +323,9 @@ multiple modular subtrees with behaviors
if(AI_STATUS_OFF)
STOP_PROCESSING(SSai_behaviors, src)
CancelActions()
if(AI_STATUS_IDLE)
STOP_PROCESSING(SSai_behaviors, src)
CancelActions()
/datum/ai_controller/proc/PauseAi(time)
paused_until = world.time + time
@@ -378,7 +385,7 @@ multiple modular subtrees with behaviors
/datum/ai_controller/proc/on_sentience_lost()
SIGNAL_HANDLER
UnregisterSignal(pawn, COMSIG_MOB_LOGOUT)
set_ai_status(AI_STATUS_ON) //Can't do anything while player is connected
set_ai_status(AI_STATUS_IDLE) //Can't do anything while player is connected
RegisterSignal(pawn, COMSIG_MOB_LOGIN, PROC_REF(on_sentience_gained))
// Turn the controller off if the pawn has been qdeleted
+1 -1
View File
@@ -514,7 +514,7 @@
owner.grant_language(/datum/language/monkey, UNDERSTOOD_LANGUAGE, TRAUMA_TRAIT)
owner.ai_controller.set_blackboard_key(BB_MONKEY_AGGRESSIVE, prob(75))
if(owner.ai_controller.ai_status == AI_STATUS_OFF)
owner.ai_controller.set_ai_status(AI_STATUS_ON)
owner.ai_controller.set_ai_status(AI_STATUS_IDLE)
owner.log_message("became controlled by monkey instincts ([owner.ai_controller.blackboard[BB_MONKEY_AGGRESSIVE] ? "aggressive" : "docile"])", LOG_ATTACK, color = "orange")
to_chat(owner, span_warning("You feel the urge to act on your primal instincts..."))
// extend original timer if we roll the effect while it's already ongoing
@@ -27,6 +27,7 @@
var/current_pathing_attempts = 0
///if we cant reach it after this many attempts, add it to our ignore list
var/max_pathing_attempts = 25
can_idle = FALSE // we want these to be running always
/datum/ai_controller/basic_controller/bot/TryPossessPawn(atom/new_pawn)
. = ..()
@@ -26,6 +26,7 @@ GLOBAL_LIST_INIT(mook_commands, list(
/datum/ai_planning_subtree/mine_walls/mook,
/datum/ai_planning_subtree/wander_away_from_village,
)
can_idle = FALSE // these guys are intended to operate even if nobody's around
///check for faction if not a ash walker, otherwise just attack
/datum/targeting_strategy/basic/mook/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target)
@@ -173,7 +173,6 @@
/mob/living/basic/living_limb_flesh/proc/wake_up(atom/limb)
visible_message(span_warning("[src] begins flailing around!"))
Shake(6, 6, 0.5 SECONDS)
ai_controller.set_ai_status(AI_STATUS_ON)
ai_controller.set_ai_status(AI_STATUS_IDLE)
forceMove(limb.drop_location())
qdel(limb)
@@ -21,6 +21,7 @@
var/fake_dt = SSai_controllers.wait * 0.1
// Set AI - AIs by default are off in z-levels with no client, we have to force it on.
biter.ai_controller.set_ai_status(AI_STATUS_ON)
biter.ai_controller.can_idle = FALSE
// Select behavior - this will queue finding the cable
biter.ai_controller.SelectBehaviors(fake_dt)
// Process behavior - this will execute the "locate the cable" behavior