From a79f3ea49fa3a7f5e0bcd59eb664f509308bd254 Mon Sep 17 00:00:00 2001 From: warriorstar-orion Date: Tue, 8 Apr 2025 09:33:08 -0400 Subject: [PATCH] fix ai controllers ignoring client presence on z-level (#28917) --- code/modules/mob/living/living.dm | 36 +++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 31a3d23af02..fdf3aee0c27 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1017,18 +1017,42 @@ if(registered_z != new_z) if(registered_z) SSmobs.clients_by_zlevel[registered_z] -= src - if(client) - if(new_z) - SSmobs.clients_by_zlevel[new_z] += src + + if(isnull(client)) + registered_z = null + return + + // Check the amount of clients exists on the Z level we're leaving from, + // this excludes us because at this point we are not registered to any z level. + var/old_level_new_clients = (registered_z ? length(SSmobs.clients_by_zlevel[registered_z]) : null) + // No one is left after we're gone, shut off inactive ones + if(registered_z && old_level_new_clients == 0) + for(var/datum/ai_controller/controller as anything in SSai_controllers.ai_controllers_by_zlevel[registered_z]) + controller.set_ai_status(AI_STATUS_OFF) + + + if(new_z) + // Check the amount of clients exists on the Z level we're moving towards, excluding ourselves. + var/new_level_old_clients = length(SSmobs.clients_by_zlevel[new_z]) + + //We'll add ourselves to the list now so get_expected_ai_status() will know we're on the z level. + SSmobs.clients_by_zlevel[new_z] += src + + if(new_level_old_clients == 0) // No one was here before, wake up all the AIs. + // Basic mob AI + for(var/datum/ai_controller/controller as anything in SSai_controllers.ai_controllers_by_zlevel[new_z]) + // We don't set them directly on, for instances like AIs acting while dead and other cases that may exist in the future. + // This isn't a problem for AIs with a client since the client will prevent this from being called anyway. + controller.set_ai_status(controller.get_expected_ai_status()) + + // Simple mob AI for(var/I in length(SSidlenpcpool.idle_mobs_by_zlevel[new_z]) to 1 step -1) //Backwards loop because we're removing (guarantees optimal rather than worst-case performance) var/mob/living/simple_animal/SA = SSidlenpcpool.idle_mobs_by_zlevel[new_z][I] if(SA) SA.toggle_ai(AI_ON) // Guarantees responsiveness for when appearing right next to mobs else SSidlenpcpool.idle_mobs_by_zlevel[new_z] -= SA - registered_z = new_z - else - registered_z = null + registered_z = new_z /mob/living/on_changed_z_level(turf/old_turf, turf/new_turf) ..()