mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-23 21:18:37 +01:00
[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:
co-authored by
Iamgoofball
Waterpig
parent
89677f37ba
commit
2429a2821a
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user