/// Init this specific atom /datum/controller/subsystem/atoms/proc/InitAtom(atom/A, from_template = FALSE, list/arguments) var/the_type = A.type if(QDELING(A)) // Check init_start_time to not worry about atoms created before the atoms SS that are cleaned up before this if (A.gc_destroyed > init_start_time) BadInitializeCalls[the_type] |= BAD_INIT_QDEL_BEFORE return TRUE // This is handled and battle tested by dreamchecker. Limit to UNIT_TEST just in case that ever fails. #ifdef UNIT_TEST var/start_tick = world.time #endif var/result = A.Initialize(arglist(arguments)) #ifdef UNIT_TEST if(start_tick != world.time) BadInitializeCalls[the_type] |= BAD_INIT_SLEPT #endif var/qdeleted = FALSE if(result != INITIALIZE_HINT_NORMAL) switch(result) if(INITIALIZE_HINT_LATELOAD) if(arguments[1]) //mapload late_loaders += A else A.LateInitialize() if(INITIALIZE_HINT_QDEL) qdel(A) qdeleted = TRUE else BadInitializeCalls[the_type] |= BAD_INIT_NO_HINT if(!A) //possible harddel qdeleted = TRUE else if(!(A.flags_1 & INITIALIZED_1)) BadInitializeCalls[the_type] |= BAD_INIT_DIDNT_INIT else SEND_SIGNAL(A, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE) SEND_GLOBAL_SIGNAL(COMSIG_GLOB_ATOM_AFTER_POST_INIT, A) var/atom/location = A.loc if(location) /// Sends a signal that the new atom `src`, has been created at `loc` SEND_SIGNAL(location, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON, A, arguments[1]) if(created_atoms && from_template && ispath(the_type, /atom/movable))//we only want to populate the list with movables created_atoms += A.get_all_contents() return qdeleted || QDELING(A) /** * Called when an atom is created in byond (built in engine proc) * * Not a lot happens here in SS13 code, as we offload most of the work to the * [Intialization][/atom/proc/Initialize] proc, mostly we run the preloader * if the preloader is being used and then call [InitAtom][/datum/controller/subsystem/atoms/proc/InitAtom] of which the ultimate * result is that the Intialize proc is called. * */ /atom/New(loc, ...) // For the DMM Suite. if(GLOB.use_preloader && (src.type == GLOB._preloader_path))//in case the instanciated atom is creating other atoms in New() GLOB._preloader.load(src) //. = ..() //uncomment if you are dumb enough to add a /datum/New() proc var/do_initialize = SSatoms.initialized if(do_initialize != INITIALIZATION_INSSATOMS) args[1] = do_initialize == INITIALIZATION_INNEW_MAPLOAD if(SSatoms.InitAtom(src, FALSE, args)) //we were deleted return /** * The primary method that objects are setup in SS13 with * * we don't use New as we have better control over when this is called and we can choose * to delay calls or hook other logic in and so forth * * During roundstart map parsing, atoms are queued for intialization in the base atom/New(), * After the map has loaded, then Initalize is called on all atoms one by one. NB: this * is also true for loading map templates as well, so they don't Initalize until all objects * in the map file are parsed and present in the world * * If you're creating an object at any point after SSInit has run then this proc will be * immediately be called from New. * * mapload: This parameter is true if the atom being loaded is either being intialized during * the Atom subsystem intialization, or if the atom is being loaded from the map template. * If the item is being created at runtime any time after the Atom subsystem is intialized then * it's false. * * The mapload argument occupies the same position as loc when Initialize() is called by New(). * loc will no longer be needed after it passed New(), and thus it is being overwritten * with mapload at the end of atom/New() before this proc (atom/Initialize()) is called. * * You must always call the parent of this proc, otherwise failures will occur as the item * will not be seen as initalized (this can lead to all sorts of strange behaviour, like * the item being completely unclickable) * * You must not sleep in this proc, or any subprocs * * Any parameters from new are passed through (excluding loc), naturally if you're loading from a map * there are no other arguments * * Must return an [initialization hint][INITIALIZE_HINT_NORMAL] or a runtime will occur. * * Note: the following functions don't call the base for optimization and must copypasta handling: * * [/turf/proc/Initialize] * * [/turf/open/space/proc/Initialize] * * NOTE: This desc is of TG's implementation, it might not be reflective of the current one we have here */ /atom/proc/Initialize(mapload, ...) SHOULD_CALL_PARENT(TRUE) SHOULD_NOT_SLEEP(TRUE) if(flags_1 & INITIALIZED_1) stack_trace("Warning: [src]([type]) initialized multiple times!") flags_1 |= INITIALIZED_1 if(LAZYLEN(reagents_to_add)) if(!reagents) create_reagents(0) for(var/v in reagents_to_add) reagents.maximum_volume += max(LAZYACCESS(reagents_to_add, v) - REAGENTS_FREE_SPACE(reagents), 0) reagents.add_reagent(v, LAZYACCESS(reagents_to_add, v), LAZYACCESS(reagent_data, v)) if(light_system != MOVABLE_LIGHT && light_system != DIRECTIONAL_LIGHT && light_power && light_range) update_light() if(loc) SEND_SIGNAL(loc, COMSIG_ATOM_INITIALIZED_ON, src) // used for large_object_transparency component if(isturf(loc) && opacity) var/turf/opaque_turf = loc opaque_turf.directional_opacity = ALL_CARDINALS // No need to recalculate it in this case, it's guaranteed to be on afterwards anyways. if(update_icon_on_init) SSicon_update.add_to_queue(src) //Finally an aurora snowflake code that matters, //this try to ensure noone is stupid enough to instantiate an abstract type if(is_abstract(src)) var/datum/space_level/L = SSmapping.get_level(z) stack_trace("Atom [src] ([type]) \[ X:[x] Y:[y] Z:[z] (Space level: [L ? L.name : "NOT FOUND"]) \] is abstract, but is trying to initialize!") return INITIALIZE_HINT_QDEL return INITIALIZE_HINT_NORMAL /** * Late Intialization, for code that should run after all atoms have run Intialization * * To have your LateIntialize proc be called, your atoms [Initalization][/atom/proc/Initialize] * proc must return the hint * [INITIALIZE_HINT_LATELOAD] otherwise it will never be called. * * useful for doing things like finding other machines on GLOB.machines because you can guarantee * that all atoms will actually exist in the "WORLD" at this time and that all their Intialization * code has been run */ /atom/proc/LateInitialize() set waitfor = FALSE //You can override this in your inheritance if you *really* need to, but probably shouldn't SHOULD_NOT_SLEEP(TRUE)