Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MIRROR] ai controllers use cell trackers to know when to idle #2938

Merged
merged 1 commit into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion code/__DEFINES/ai/ai.dm
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#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
#define AI_DEFAULT_INTERESTING_DIST 10

///Cooldown on planning if planning failed last time

Expand Down
14 changes: 1 addition & 13 deletions code/controllers/subsystem/ai_controllers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@ SUBSYSTEM_DEF(ai_controllers)

/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
Expand All @@ -53,14 +48,7 @@ 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.
Expand Down
59 changes: 59 additions & 0 deletions code/datums/ai/_ai_controller.dm
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ multiple modular subtrees with behaviors

///The idle behavior this AI performs when it has no actions.
var/datum/idle_behavior/idle_behavior = null
///our current cell grid
var/datum/cell_tracker/our_cells

// Movement related things here
///Reference to the movement datum we use. Is a type on initialize but becomes a ref afterwards.
Expand Down Expand Up @@ -73,6 +75,7 @@ multiple modular subtrees with behaviors

/datum/ai_controller/Destroy(force)
UnpossessPawn(FALSE)
our_cells = null
set_movement_target(type, null)
if(ai_movement.moving_controllers[src])
ai_movement.stop_moving_towards(src)
Expand Down Expand Up @@ -131,6 +134,59 @@ multiple modular subtrees with behaviors
RegisterSignal(pawn, COMSIG_MOB_LOGIN, PROC_REF(on_sentience_gained))
RegisterSignal(pawn, COMSIG_QDELETING, PROC_REF(on_pawn_qdeleted))

our_cells = new(interesting_dist, interesting_dist, 1)
set_new_cells()

RegisterSignal(pawn, COMSIG_MOVABLE_MOVED, PROC_REF(update_grid))

/datum/ai_controller/proc/update_grid(datum/source, datum/spatial_grid_cell/new_cell)
SIGNAL_HANDLER

set_new_cells()

/datum/ai_controller/proc/set_new_cells()

var/turf/our_turf = get_turf(pawn)

if(isnull(our_turf))
return

var/list/cell_collections = our_cells.recalculate_cells(our_turf)

for(var/datum/old_grid as anything in cell_collections[2])
UnregisterSignal(old_grid, list(SPATIAL_GRID_CELL_ENTERED(SPATIAL_GRID_CONTENTS_TYPE_CLIENTS), SPATIAL_GRID_CELL_EXITED(SPATIAL_GRID_CONTENTS_TYPE_CLIENTS)))

for(var/datum/spatial_grid_cell/new_grid as anything in cell_collections[1])
RegisterSignal(new_grid, SPATIAL_GRID_CELL_ENTERED(SPATIAL_GRID_CONTENTS_TYPE_CLIENTS), PROC_REF(on_client_enter))
RegisterSignal(new_grid, SPATIAL_GRID_CELL_EXITED(SPATIAL_GRID_CONTENTS_TYPE_CLIENTS), PROC_REF(on_client_exit))

recalculate_idle()

/datum/ai_controller/proc/should_idle()
if(!can_idle)
return FALSE
for(var/datum/spatial_grid_cell/grid as anything in our_cells.member_cells)
if(length(grid.client_contents))
return FALSE
return TRUE

/datum/ai_controller/proc/recalculate_idle()
if(ai_status == AI_STATUS_OFF)
return
if(should_idle())
set_ai_status(AI_STATUS_IDLE)

/datum/ai_controller/proc/on_client_enter(datum/source, atom/target)
SIGNAL_HANDLER

if(ai_status == AI_STATUS_IDLE)
set_ai_status(AI_STATUS_ON)

/datum/ai_controller/proc/on_client_exit(datum/source, datum/exited)
SIGNAL_HANDLER

recalculate_idle()

/// Sets the AI on or off based on current conditions, call to reset after you've manually disabled it somewhere
/datum/ai_controller/proc/reset_ai_status()
set_ai_status(get_expected_ai_status())
Expand All @@ -141,6 +197,7 @@ multiple modular subtrees with behaviors
* Returns AI_STATUS_ON otherwise.
*/
/datum/ai_controller/proc/get_expected_ai_status()

if (!ismob(pawn))
return AI_STATUS_ON

Expand All @@ -160,6 +217,8 @@ multiple modular subtrees with behaviors
#endif
if(!length(SSmobs.clients_by_zlevel[pawn_turf.z]))
return AI_STATUS_OFF
if(should_idle())
return AI_STATUS_IDLE
return AI_STATUS_ON

/datum/ai_controller/proc/get_current_turf()
Expand Down
Loading