mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-01-09 08:51:57 +00:00
Refactored Life() to receive seconds per tick and times fired as parameters. Life() now cannot be slept in, turned various sleepings into async calls procs. Optimized mob AI subsystems, gave them new priorities levels and flags. Grab upgrades are now elaborated asynchronously, tweaked them to avoid stacking multiple upgrades. Fixed plains tyrants keeping sending messages about stomping even if dead.
161 lines
5.0 KiB
Plaintext
161 lines
5.0 KiB
Plaintext
SUBSYSTEM_DEF(mobs)
|
|
name = "Mobs - Life"
|
|
priority = FIRE_PRIORITY_MOBS
|
|
flags = SS_KEEP_TIMING
|
|
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
|
|
wait = 2 SECONDS
|
|
|
|
var/list/currentrun = list()
|
|
var/list/processing = list()
|
|
|
|
var/list/all_rats = list() // Contains all *living* rats.
|
|
|
|
///Contains all mannequins used by character preview
|
|
var/list/mob/living/carbon/human/dummy/mannequin/mannequins = list()
|
|
|
|
var/list/greatworms = list()
|
|
var/list/greatasses = list()
|
|
|
|
var/list/ghost_darkness_images = list() //this is a list of images for things ghosts should still be able to see when they toggle darkness
|
|
var/list/ghost_sightless_images = list() //this is a list of images for things ghosts should still be able to see even without ghost sight
|
|
|
|
// Devour types (these are typecaches). Only simple_animals check these, other types are handled specially.
|
|
var/list/mtl_synthetic = list(
|
|
/mob/living/simple_animal/hostile/hivebot
|
|
)
|
|
|
|
var/list/mtl_weird = list(
|
|
/mob/living/simple_animal/construct,
|
|
/mob/living/simple_animal/shade,
|
|
/mob/living/simple_animal/slime,
|
|
/mob/living/simple_animal/hostile/faithless
|
|
)
|
|
|
|
// Actual human mobs are delibrately not in this list as they are handled elsewhere.
|
|
var/list/mtl_humanoid = list(
|
|
/mob/living/simple_animal/hostile/pirate,
|
|
/mob/living/simple_animal/hostile/russian,
|
|
/mob/living/simple_animal/hostile/syndicate
|
|
)
|
|
|
|
var/list/mtl_incorporeal = list(
|
|
/mob/living/simple_animal/hostile/carp/holodeck,
|
|
/mob/living/simple_animal/penguin/holodeck,
|
|
/mob/living/simple_animal/corgi/puppy/holodeck,
|
|
/mob/living/simple_animal/cat/kitten/holodeck
|
|
)
|
|
|
|
/**
|
|
* An associative list containing timer IDs associated with a mannequin that they're supposed to delete
|
|
*/
|
|
var/list/mannequins_del_timers = list()
|
|
|
|
/datum/controller/subsystem/mobs/Initialize()
|
|
// Some setup work for the eat-types lists.
|
|
mtl_synthetic = typecacheof(mtl_synthetic) + list(
|
|
/mob/living/simple_animal/hostile/icarus_drone = TRUE,
|
|
/mob/living/simple_animal/hostile/viscerator = TRUE,
|
|
/mob/living/simple_animal/spiderbot = TRUE
|
|
)
|
|
|
|
mtl_weird = typecacheof(mtl_weird) + list(
|
|
/mob/living/simple_animal/adultslime = TRUE
|
|
)
|
|
|
|
mtl_humanoid = typecacheof(mtl_humanoid)
|
|
|
|
mtl_incorporeal = typecacheof(mtl_incorporeal)
|
|
|
|
return SS_INIT_SUCCESS
|
|
|
|
/datum/controller/subsystem/mobs/stat_entry(msg)
|
|
msg = "P:[length(GLOB.mob_list)]"
|
|
return ..()
|
|
|
|
/datum/controller/subsystem/mobs/fire(resumed = 0)
|
|
if (!resumed)
|
|
src.currentrun = GLOB.mob_list.Copy()
|
|
src.currentrun += processing.Copy()
|
|
|
|
//Mobs might have been removed between the previous and a resumed fire, yet we want to maintain the priority to process
|
|
//the mobs that we didn't in the previous run, hence we have to pay the price of a list subtraction
|
|
//with &= we say to remove any item in the first list that is not in the second one
|
|
//of course, if we haven't resumed, this comparison would be useless, hence we skip it
|
|
var/list/currentrun = resumed ? (src.currentrun &= (GLOB.mob_list + processing)) : src.currentrun
|
|
|
|
var/seconds_per_tick = wait / (1 SECONDS)
|
|
|
|
while(length(currentrun))
|
|
var/datum/thing = currentrun[length(currentrun)]
|
|
currentrun.len--
|
|
if(!ismob(thing))
|
|
if(!QDELETED(thing))
|
|
if(thing.process(wait, times_fired) == PROCESS_KILL)
|
|
stop_processing(thing)
|
|
else
|
|
processing -= thing
|
|
if(MC_TICK_CHECK)
|
|
return
|
|
continue
|
|
|
|
var/mob/M = thing
|
|
|
|
if(QDELETED(M))
|
|
LOG_DEBUG("SSmobs: QDELETED mob [DEBUG_REF(M)] left in processing list!")
|
|
// We can just go ahead and remove them from all the mob lists.
|
|
GLOB.mob_list -= M
|
|
GLOB.dead_mob_list -= M
|
|
GLOB.living_mob_list -= M
|
|
|
|
if (MC_TICK_CHECK)
|
|
return
|
|
continue
|
|
|
|
if (!M.frozen)
|
|
M.Life(seconds_per_tick, times_fired)
|
|
|
|
if (MC_TICK_CHECK)
|
|
return
|
|
|
|
/datum/controller/subsystem/mobs/proc/get_mannequin(ckey)
|
|
. = mannequins[ckey]
|
|
if (!.)
|
|
. = new /mob/living/carbon/human/dummy/mannequin
|
|
mannequins[ckey] = .
|
|
|
|
mannequins_del_timers[ckey] = addtimer(CALLBACK(src, PROC_REF(del_mannequin), ckey), 5 MINUTES, TIMER_UNIQUE | TIMER_OVERRIDE | TIMER_STOPPABLE)
|
|
|
|
/datum/controller/subsystem/mobs/proc/del_mannequin(ckey)
|
|
var/mannequin = mannequins[ckey]
|
|
mannequins[ckey] = null
|
|
mannequins -= ckey
|
|
|
|
//Remove the deletion timer, if it exists
|
|
if(mannequins_del_timers[ckey])
|
|
deltimer(mannequins_del_timers[ckey])
|
|
mannequins_del_timers[ckey] = null
|
|
mannequins_del_timers -= ckey
|
|
|
|
qdel(mannequin)
|
|
|
|
/**
|
|
* Used to dereference a mannequin, does not delete it per-se
|
|
*
|
|
* * the_mannequin - A `/mob/living/carbon/human/dummy/mannequin` to search for, and dereference if found
|
|
*/
|
|
/datum/controller/subsystem/mobs/proc/free_mannequin(mob/living/carbon/human/dummy/mannequin/the_mannequin)
|
|
for(var/ckey in mannequins)
|
|
if(mannequins[ckey] == the_mannequin)
|
|
mannequins[ckey] = null
|
|
mannequins -= ckey
|
|
|
|
//Remove the deletion timer, if it exists
|
|
if(mannequins_del_timers[ckey])
|
|
deltimer(mannequins_del_timers[ckey])
|
|
mannequins_del_timers[ckey] = null
|
|
mannequins_del_timers -= ckey
|
|
|
|
// Helper so PROCESS_KILL works.
|
|
/datum/controller/subsystem/mobs/proc/stop_processing(datum/D)
|
|
STOP_PROCESSING(src, D)
|