From 360d8838794ab2f1c7397a13278e594b03314f3f Mon Sep 17 00:00:00 2001 From: vuonojenmustaturska Date: Thu, 19 Oct 2017 12:57:10 +0300 Subject: [PATCH] expand simple_animals/hostile/aistatus into a simple_animals-wide system for putting mobs into idling mode (#31778) * Initial commit * Time is a circus * Send in the clowns * i broke something * Revert "i broke something" This reverts commit 5a29c40d131b39effe9ebcb6c8c1883693baf07f. * I think it works? * cleanup * define reminders * Fixes tendrils and such * sentience_act now moves the mob to AI_OFF state --- code/__DEFINES/mobs.dm | 1 + code/_globalvars/lists/mobs.dm | 2 +- code/controllers/subsystem/idlenpcpool.dm | 34 +++++++++++++++++++ code/controllers/subsystem/npcpool.dm | 3 +- code/modules/fields/timestop.dm | 4 +-- code/modules/mining/minebot.dm | 2 +- .../mob/living/simple_animal/hostile/bees.dm | 20 ++++++++--- .../living/simple_animal/hostile/hostile.dm | 13 ++++--- .../mob/living/simple_animal/simple_animal.dm | 30 ++++++++++++++-- .../mob/living/simple_animal/spawner.dm | 2 +- .../ruins/objects_and_mobs/ash_walker_den.dm | 2 +- tgstation.dme | 1 + 12 files changed, 96 insertions(+), 18 deletions(-) create mode 100644 code/controllers/subsystem/idlenpcpool.dm diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 8017cde520..69596e7a0f 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -93,6 +93,7 @@ //Mob AI Status //Hostile simple animals +//If you add a new status, be sure to add a list for it to the simple_animals global in _globalvars/lists/mobs.dm #define AI_ON 1 #define AI_IDLE 2 #define AI_OFF 3 diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index 62a5b8c80e..4368757352 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -19,7 +19,7 @@ GLOBAL_LIST_EMPTY(silicon_mobs) //all silicon mobs GLOBAL_LIST_EMPTY(ai_list) GLOBAL_LIST_EMPTY(pai_list) GLOBAL_LIST_EMPTY(available_ai_shells) -GLOBAL_LIST_EMPTY(simple_animals) +GLOBAL_LIST_INIT(simple_animals, list(list(),list(),list())) // One for each AI_* status define GLOBAL_LIST_EMPTY(spidermobs) //all sentient spider mobs GLOBAL_LIST_EMPTY(language_datum_instances) diff --git a/code/controllers/subsystem/idlenpcpool.dm b/code/controllers/subsystem/idlenpcpool.dm new file mode 100644 index 0000000000..49846e6c9d --- /dev/null +++ b/code/controllers/subsystem/idlenpcpool.dm @@ -0,0 +1,34 @@ +SUBSYSTEM_DEF(idlenpcpool) + name = "Idling NPC Pool" + flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND + priority = 10 + wait = 60 + runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME + + var/list/currentrun = list() + +/datum/controller/subsystem/idlenpcpool/stat_entry() + var/list/idlelist = GLOB.simple_animals[AI_IDLE] + ..("IdleNPCS:[idlelist.len]") + +/datum/controller/subsystem/idlenpcpool/fire(resumed = FALSE) + + if (!resumed) + var/list/idlelist = GLOB.simple_animals[AI_IDLE] + src.currentrun = idlelist.Copy() + + //cache for sanic speed (lists are references anyways) + var/list/currentrun = src.currentrun + + + while(currentrun.len) + var/mob/living/simple_animal/SA = currentrun[currentrun.len] + --currentrun.len + + if(!SA.ckey) + if(SA.stat != DEAD) + SA.handle_automated_movement() + if(SA.stat != DEAD) + SA.consider_wakeup() + if (MC_TICK_CHECK) + return diff --git a/code/controllers/subsystem/npcpool.dm b/code/controllers/subsystem/npcpool.dm index 4f875721e8..6ee4626f25 100644 --- a/code/controllers/subsystem/npcpool.dm +++ b/code/controllers/subsystem/npcpool.dm @@ -37,7 +37,8 @@ SUBSYSTEM_DEF(npcpool) // 5. Do all assignments: goes through the delegated/coordianted bots and assigns the right variables/tasks to them. if (!resumed) - src.currentrun = GLOB.simple_animals.Copy() + var/list/activelist = GLOB.simple_animals[AI_ON] + src.currentrun = activelist.Copy() stage = PROCESSING_SIMPLES //cache for sanic speed (lists are references anyways) var/list/currentrun = src.currentrun diff --git a/code/modules/fields/timestop.dm b/code/modules/fields/timestop.dm index 2fe1f775b4..e5d7b6b4fe 100644 --- a/code/modules/fields/timestop.dm +++ b/code/modules/fields/timestop.dm @@ -119,7 +119,7 @@ L.anchored = TRUE if(ishostile(L)) var/mob/living/simple_animal/hostile/H = L - H.AIStatus = AI_OFF + H.toggle_ai(AI_OFF) H.LoseTarget() /datum/proximity_monitor/advanced/timestop/proc/unfreeze_mob(mob/living/L) @@ -128,4 +128,4 @@ frozen_mobs -= L if(ishostile(L)) var/mob/living/simple_animal/hostile/H = L - H.AIStatus = initial(H.AIStatus) + H.toggle_ai(initial(H.AIStatus)) diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm index 58f091fd4c..1fcb03e2b6 100644 --- a/code/modules/mining/minebot.dm +++ b/code/modules/mining/minebot.dm @@ -59,7 +59,7 @@ SetCollectBehavior() /mob/living/simple_animal/hostile/mining_drone/sentience_act() - AIStatus = AI_OFF + ..() check_friendly_fire = 0 /mob/living/simple_animal/hostile/mining_drone/attackby(obj/item/I, mob/user, params) diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm index 9f7a7d1bbf..0213a79e4a 100644 --- a/code/modules/mob/living/simple_animal/hostile/bees.dm +++ b/code/modules/mob/living/simple_animal/hostile/bees.dm @@ -49,6 +49,8 @@ var/idle = 0 var/isqueen = FALSE var/icon_base = "bee" + var/static/beehometypecache = typecacheof(/obj/structure/beebox) + var/static/hydroponicstypecache = typecacheof(/obj/machinery/hydroponics) /mob/living/simple_animal/hostile/poison/bees/Process_Spacemove(movement_dir = 0) @@ -118,7 +120,7 @@ if(istype(A, /obj/machinery/hydroponics)) var/obj/machinery/hydroponics/Hydro = A if(Hydro.myseed && !Hydro.dead && !Hydro.recent_bee_visit) - wanted_objects |= typecacheof(/obj/machinery/hydroponics) //so we only hunt them while they're alive/seeded/not visisted + wanted_objects |= hydroponicstypecache //so we only hunt them while they're alive/seeded/not visisted return TRUE return FALSE @@ -132,8 +134,9 @@ if(target == beehome) var/obj/structure/beebox/BB = target forceMove(BB) + toggle_ai(AI_IDLE) target = null - wanted_objects -= typecacheof(/obj/structure/beebox) //so we don't attack beeboxes when not going home + wanted_objects -= beehometypecache //so we don't attack beeboxes when not going home return //no don't attack the goddamm box else . = ..() @@ -157,7 +160,7 @@ return target = null //so we pick a new hydro tray next FindTarget(), instead of loving the same plant for eternity - wanted_objects -= typecacheof(/obj/machinery/hydroponics) //so we only hunt them while they're alive/seeded/not visisted + wanted_objects -= hydroponicstypecache //so we only hunt them while they're alive/seeded/not visisted Hydro.recent_bee_visit = TRUE spawn(BEE_TRAY_RECENT_VISIT) if(Hydro) @@ -187,12 +190,13 @@ if(loc == beehome) idle = min(100, ++idle) if(idle >= BEE_IDLE_ROAMING && prob(BEE_PROB_GOROAM)) + toggle_ai(AI_ON) forceMove(beehome.drop_location()) else idle = max(0, --idle) if(idle <= BEE_IDLE_GOHOME && prob(BEE_PROB_GOHOME)) if(!FindTarget()) - wanted_objects |= typecacheof(/obj/structure/beebox) //so we don't attack beeboxes when not going home + wanted_objects |= beehometypecache //so we don't attack beeboxes when not going home target = beehome if(!beehome) //add outselves to a beebox (of the same reagent) if we have no home for(var/obj/structure/beebox/BB in view(vision_range, src)) @@ -285,3 +289,11 @@ QDEL_NULL(queen) return ..() +/mob/living/simple_animal/hostile/poison/bees/consider_wakeup() + if (beehome && loc == beehome) // If bees are chilling in their nest, they're not actively looking for targets + idle = min(100, ++idle) + if(idle >= BEE_IDLE_ROAMING && prob(BEE_PROB_GOROAM)) + toggle_ai(AI_ON) + forceMove(beehome.drop_location()) + else + ..() diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 6f3b526a03..f1b3043447 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -49,7 +49,6 @@ var/stat_attack = CONSCIOUS //Mobs with stat_attack to UNCONSCIOUS will attempt to attack things that are unconscious, Mobs with stat_attack set to DEAD will attempt to attack the dead. var/stat_exclusive = FALSE //Mobs with this set to TRUE will exclusively attack things defined by stat_attack, stat_attack DEAD means they will only attack corpses var/attack_same = 0 //Set us to 1 to allow us to attack our own faction - var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever) var/atom/targets_from = null //all range/attack/etc. calculations should be done from this atom, defaults to the mob itself, useful for Vehicles and such var/attack_all_objects = FALSE //if true, equivalent to having a wanted_objects list containing ALL objects. @@ -88,7 +87,7 @@ DestroySurroundings() if(!MoveToTarget(possible_targets)) //if we lose our target if(AIShouldSleep(possible_targets)) // we try to acquire a new one - AIStatus = AI_IDLE // otherwise we go idle + toggle_ai(AI_IDLE) // otherwise we go idle return 1 /mob/living/simple_animal/hostile/attacked_by(obj/item/I, mob/living/user) @@ -289,7 +288,7 @@ target = null LoseSearchObjects() if(AIStatus == AI_IDLE) - AIStatus = AI_ON + toggle_ai(AI_ON) FindTarget() else if(target != null && prob(40))//No more pulling a mob forever and having a second player attack it, it can switch targets now if it finds a more suitable one FindTarget() @@ -424,7 +423,7 @@ if(AI_IDLE) if(FindTarget(possible_targets, 1)) . = 1 - AIStatus = AI_ON //Wake up for more than one Life() cycle. + toggle_ai(AI_ON) //Wake up for more than one Life() cycle. else . = 0 @@ -455,3 +454,9 @@ if(!value) value = initial(search_objects) search_objects = value + +/mob/living/simple_animal/hostile/consider_wakeup() + ..() + if(AIStatus == AI_IDLE && FindTarget(ListTargets(), 1)) + toggle_ai(AI_ON) + diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index c9b858f76c..a9ed6a4120 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -82,6 +82,10 @@ var/dextrous_hud_type = /datum/hud/dextrous var/datum/personal_crafting/handcrafting + var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever) + + var/shouldwakeup = FALSE //convenience var for forcibly waking up an idling AI on next check. + //domestication var/tame = 0 @@ -89,7 +93,7 @@ /mob/living/simple_animal/Initialize() . = ..() - GLOB.simple_animals += src + GLOB.simple_animals[AIStatus] += src handcrafting = new() if(gender == PLURAL) gender = pick(MALE,FEMALE) @@ -102,7 +106,7 @@ verbs |= /mob/living/proc/animal_nom /mob/living/simple_animal/Destroy() - GLOB.simple_animals -= src + GLOB.simple_animals[AIStatus] -= src return ..() /mob/living/simple_animal/updatehealth() @@ -422,7 +426,7 @@ /mob/living/simple_animal/proc/sentience_act() //Called when a simple animal gains sentience via gold slime potion - return + toggle_ai(AI_OFF) // To prevent any weirdness. /mob/living/simple_animal/update_sight() if(!client) @@ -545,3 +549,23 @@ /mob/living/simple_animal/buckle_mob(mob/living/buckled_mob, force = 0, check_loc = 1) . = ..() riding_datum = new/datum/riding/animal + + +/mob/living/simple_animal/proc/toggle_ai(togglestatus) + if (AIStatus != togglestatus) + if (togglestatus > 0 && togglestatus < 4) + GLOB.simple_animals[AIStatus] -= src + GLOB.simple_animals[togglestatus] += src + AIStatus = togglestatus + else + stack_trace("Something attempted to set simple animals AI to an invalid state: [togglestatus]") + +/mob/living/simple_animal/proc/consider_wakeup() + if (pulledby || shouldwakeup) + toggle_ai(AI_ON) + +/mob/living/simple_animal/adjustHealth(amount, updating_health = TRUE, forced = FALSE) + . = ..() + if(!ckey && !stat)//Not unconscious + if(AIStatus == AI_IDLE) + toggle_ai(AI_ON) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/spawner.dm b/code/modules/mob/living/simple_animal/spawner.dm index a8ff6be4ba..33eade6014 100644 --- a/code/modules/mob/living/simple_animal/spawner.dm +++ b/code/modules/mob/living/simple_animal/spawner.dm @@ -30,7 +30,7 @@ spawned_mobs = null return ..() -/mob/living/simple_animal/hostile/spawner/handle_automated_action() +/mob/living/simple_animal/hostile/spawner/Life() . = ..() spawn_mob() diff --git a/code/modules/ruins/objects_and_mobs/ash_walker_den.dm b/code/modules/ruins/objects_and_mobs/ash_walker_den.dm index 1cc5b482f0..7f301bf8b9 100644 --- a/code/modules/ruins/objects_and_mobs/ash_walker_den.dm +++ b/code/modules/ruins/objects_and_mobs/ash_walker_den.dm @@ -16,7 +16,7 @@ new /obj/item/device/assembly/signaler/anomaly (get_step(loc, pick(GLOB.alldirs))) return ..() -/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker/handle_automated_action() +/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker/Life() consume() return ..() diff --git a/tgstation.dme b/tgstation.dme index 903f4878c8..07025a8b70 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -226,6 +226,7 @@ #include "code\controllers\subsystem\fire_burning.dm" #include "code\controllers\subsystem\garbage.dm" #include "code\controllers\subsystem\icon_smooth.dm" +#include "code\controllers\subsystem\idlenpcpool.dm" #include "code\controllers\subsystem\inbounds.dm" #include "code\controllers\subsystem\ipintel.dm" #include "code\controllers\subsystem\job.dm"