mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-16 17:38:37 +01:00
So after a long time spent digging really deep into the code, and going over numbers passing into this with a fine comb, I discovered that this entire time, Mobs were being affected by a bug that was largely unnoticed for over a year due to mobs not doing anything that would directly interact with said bug. Right up until I started refactoring organs. Seconds_per_tick that was being passed to mobs was actually ticks_per_second, it was inverted for mobs and only for mobs, everything else worked just fine with time deltas. But when I started making organs use time deltas, I got blindsided by organs doing nonsensical things that seemingly did not match up with what my models were predicting. Case in point, livers. So you can now get drunk again with this PR. I've actually gone around and tested this PR too. <img width="527" height="114" alt="image" src="https://github.com/user-attachments/assets/a9f92233-fe2a-406d-9ddd-104c069bbc3d" /> <img width="601" height="165" alt="image" src="https://github.com/user-attachments/assets/6f6877f3-edd2-441b-9ea2-a29d816558ee" /> And verifying in a dev environment that brain math is now sensible again: <img width="1474" height="814" alt="image" src="https://github.com/user-attachments/assets/07634d23-bfaa-477e-a64f-322bb0a3f3ec" />
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 = (1 SECONDS) / wait
|
|
|
|
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)
|