/atom layer = 2 var/level = 2 var/flags = 0 var/list/fingerprints var/list/fingerprintshidden var/fingerprintslast = null var/list/blood_DNA var/was_bloodied var/blood_color var/last_bumped = 0 var/pass_flags = 0 var/throwpass = 0 var/germ_level = GERM_LEVEL_AMBIENT // The higher the germ level, the more germ on the atom. var/simulated = 1 //filter for actions - used by lighting overlays var/fluorescent // Shows up under a UV light. ///Chemistry. var/datum/reagents/reagents = null //var/chem_is_open_container = 0 // replaced by OPENCONTAINER flags and atom/proc/is_open_container() ///Chemistry. // Overlays var/list/our_overlays //our local copy of (non-priority) overlays without byond magic. Use procs in SSoverlays to manipulate var/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4. //Detective Work, used for the duplicate data points kept in the scanners var/list/original_atom // Track if we are already had initialize() called to prevent double-initialization. var/initialized = FALSE /atom/New(loc, ...) // Don't call ..() unless /datum/New() ever exists // During dynamic mapload (reader.dm) this assigns the var overrides from the .dmm file // Native BYOND maploading sets those vars before invoking New(), by doing this FIRST we come as close to that behavior as we can. if(use_preloader && (src.type == _preloader.target_path))//in case the instanciated atom is creating other atoms in New() _preloader.load(src) // Pass our arguments to InitAtom so they can be passed to initialize(), but replace 1st with if-we're-during-mapload. var/do_initialize = SSatoms && SSatoms.initialized // Workaround our non-ideal initialization order: SSatoms may not exist yet. //var/do_initialize = SSatoms.initialized if(do_initialize > INITIALIZATION_INSSATOMS) args[1] = (do_initialize == INITIALIZATION_INNEW_MAPLOAD) if(SSatoms.InitAtom(src, args)) // We were deleted. No sense continuing return // Uncomment if anything ever uses the return value of SSatoms.InitializeAtoms ~Leshana // If a map is being loaded, it might want to know about newly created objects so they can be handled. // var/list/created = SSatoms.created_atoms // if(created) // created += src // Note: I removed "auto_init" feature (letting types disable auto-init) since it shouldn't be needed anymore. // You can replicate the same by checking the value of the first parameter to initialize() ~Leshana // Called after New if the map is being loaded, with mapload = TRUE // Called from base of New if the map is not being loaded, with mapload = FALSE // This base must be called or derivatives must set initialized to TRUE // Must not sleep! // Other parameters are passed from New (excluding loc), this does not happen if mapload is TRUE // Must return an Initialize hint. Defined in code/__defines/subsystems.dm /atom/proc/initialize(mapload, ...) if(QDELETED(src)) crash_with("GC: -- [type] had initialize() called after qdel() --") if(initialized) crash_with("Warning: [src]([type]) initialized multiple times!") initialized = TRUE return INITIALIZE_HINT_NORMAL // Called after all object's normal initialize() if initialize() returns INITIALIZE_HINT_LATELOAD /atom/proc/LateInitialize() return /atom/proc/reveal_blood() return /atom/proc/assume_air(datum/gas_mixture/giver) return null /atom/proc/remove_air(amount) return null /atom/proc/return_air() if(loc) return loc.return_air() else return null //return flags that should be added to the viewer's sight var. //Otherwise return a negative number to indicate that the view should be cancelled. /atom/proc/check_eye(user as mob) if (istype(user, /mob/living/silicon/ai)) // WHYYYY return 0 return -1 /atom/proc/on_reagent_change() return /atom/proc/Bumped(AM as mob|obj) return // Convenience proc to see if a container is open for chemistry handling // returns true if open // false if closed /atom/proc/is_open_container() return flags & OPENCONTAINER /*//Convenience proc to see whether a container can be accessed in a certain way. proc/can_subract_container() return flags & EXTRACT_CONTAINER proc/can_add_container() return flags & INSERT_CONTAINER */ /atom/proc/CheckExit() return 1 // If you want to use this, the atom must have the PROXMOVE flag, and the moving // atom must also have the PROXMOVE flag currently to help with lag. ~ ComicIronic /atom/proc/HasProximity(atom/movable/AM as mob|obj) return /atom/proc/emp_act(var/severity) return /atom/proc/bullet_act(obj/item/projectile/P, def_zone) P.on_hit(src, 0, def_zone) . = 0 // Called when a blob expands onto the tile the atom occupies. /atom/proc/blob_act() return /atom/proc/in_contents_of(container)//can take class or object instance as argument if(ispath(container)) if(istype(src.loc, container)) return 1 else if(src in container) return 1 return /* * atom/proc/search_contents_for(path,list/filter_path=null) * Recursevly searches all atom contens (including contents contents and so on). * * ARGS: path - search atom contents for atoms of this type * list/filter_path - if set, contents of atoms not of types in this list are excluded from search. * * RETURNS: list of found atoms */ /atom/proc/search_contents_for(path,list/filter_path=null) var/list/found = list() for(var/atom/A in src) if(istype(A, path)) found += A if(filter_path) var/pass = 0 for(var/type in filter_path) pass |= istype(A, type) if(!pass) continue if(A.contents.len) found += A.search_contents_for(path,filter_path) return found //All atoms /atom/proc/examine(mob/user, var/distance = -1, var/infix = "", var/suffix = "") //This reformat names to get a/an properly working on item descriptions when they are bloody var/f_name = "\a [src][infix]." if(src.blood_DNA && !istype(src, /obj/effect/decal)) if(gender == PLURAL) f_name = "some " else f_name = "a " if(blood_color != SYNTH_BLOOD_COLOUR) f_name += "blood-stained [name][infix]!" else f_name += "oil-stained [name][infix]." user << "\icon[src] That's [f_name] [suffix]" user << desc return distance == -1 || (get_dist(src, user) <= distance) // called by mobs when e.g. having the atom as their machine, pulledby, loc (AKA mob being inside the atom) or buckled var set. // see code/modules/mob/mob_movement.dm for more. /atom/proc/relaymove() return //called to set the atom's dir and used to add behaviour to dir-changes /atom/proc/set_dir(new_dir) . = new_dir != dir dir = new_dir /atom/proc/ex_act() return /atom/proc/emag_act(var/remaining_charges, var/mob/user, var/emag_source) return -1 /atom/proc/fire_act() return /atom/proc/melt() return // Previously this was defined both on /obj/ and /turf/ seperately. And that's bad. /atom/proc/update_icon() return /atom/proc/hitby(atom/movable/AM as mob|obj) if (density) AM.throwing = 0 return /atom/proc/add_hiddenprint(mob/living/M as mob) if(isnull(M)) return if(isnull(M.key)) return if (ishuman(M)) var/mob/living/carbon/human/H = M if (!istype(H.dna, /datum/dna)) return 0 if (H.gloves) if(src.fingerprintslast != H.key) src.fingerprintshidden += text("\[[time_stamp()]\] (Wearing gloves). Real name: [], Key: []",H.real_name, H.key) src.fingerprintslast = H.key return 0 if (!( src.fingerprints )) if(src.fingerprintslast != H.key) src.fingerprintshidden += text("\[[time_stamp()]\] Real name: [], Key: []",H.real_name, H.key) src.fingerprintslast = H.key return 1 else if(src.fingerprintslast != M.key) src.fingerprintshidden += text("\[[time_stamp()]\] Real name: [], Key: []",M.real_name, M.key) src.fingerprintslast = M.key return /atom/proc/add_fingerprint(mob/living/M as mob, ignoregloves = 0) if(isnull(M)) return if(isAI(M)) return if(isnull(M.key)) return if (ishuman(M)) //Add the list if it does not exist. if(!fingerprintshidden) fingerprintshidden = list() //Fibers~ add_fibers(M) //He has no prints! if (mFingerprints in M.mutations) if(fingerprintslast != M.key) fingerprintshidden += "(Has no fingerprints) Real name: [M.real_name], Key: [M.key]" fingerprintslast = M.key return 0 //Now, lets get to the dirty work. //First, make sure their DNA makes sense. var/mob/living/carbon/human/H = M if (!istype(H.dna, /datum/dna) || !H.dna.uni_identity || (length(H.dna.uni_identity) != 32)) if(!istype(H.dna, /datum/dna)) H.dna = new /datum/dna(null) H.dna.real_name = H.real_name H.check_dna() //Now, deal with gloves. if (H.gloves && H.gloves != src) if(fingerprintslast != H.key) fingerprintshidden += text("\[[]\](Wearing gloves). Real name: [], Key: []",time_stamp(), H.real_name, H.key) fingerprintslast = H.key H.gloves.add_fingerprint(M) //Deal with gloves the pass finger/palm prints. if(!ignoregloves) if(H.gloves && H.gloves != src) if(istype(H.gloves, /obj/item/clothing/gloves)) var/obj/item/clothing/gloves/G = H.gloves if(!prob(G.fingerprint_chance)) return 0 //More adminstuffz if(fingerprintslast != H.key) fingerprintshidden += text("\[[]\]Real name: [], Key: []",time_stamp(), H.real_name, H.key) fingerprintslast = H.key //Make the list if it does not exist. if(!fingerprints) fingerprints = list() //Hash this shit. var/full_print = H.get_full_print() // Add the fingerprints // if(fingerprints[full_print]) switch(stringpercent(fingerprints[full_print])) //tells us how many stars are in the current prints. if(28 to 32) if(prob(1)) fingerprints[full_print] = full_print // You rolled a one buddy. else fingerprints[full_print] = stars(full_print, rand(0,40)) // 24 to 32 if(24 to 27) if(prob(3)) fingerprints[full_print] = full_print //Sucks to be you. else fingerprints[full_print] = stars(full_print, rand(15, 55)) // 20 to 29 if(20 to 23) if(prob(5)) fingerprints[full_print] = full_print //Had a good run didn't ya. else fingerprints[full_print] = stars(full_print, rand(30, 70)) // 15 to 25 if(16 to 19) if(prob(5)) fingerprints[full_print] = full_print //Welp. else fingerprints[full_print] = stars(full_print, rand(40, 100)) // 0 to 21 if(0 to 15) if(prob(5)) fingerprints[full_print] = stars(full_print, rand(0,50)) // small chance you can smudge. else fingerprints[full_print] = full_print else fingerprints[full_print] = stars(full_print, rand(0, 20)) //Initial touch, not leaving much evidence the first time. return 1 else //Smudge up dem prints some if(fingerprintslast != M.key) fingerprintshidden += text("\[[]\]Real name: [], Key: []",time_stamp(), M.real_name, M.key) fingerprintslast = M.key //Cleaning up shit. if(fingerprints && !fingerprints.len) qdel(fingerprints) return /atom/proc/transfer_fingerprints_to(var/atom/A) if(!istype(A.fingerprints,/list)) A.fingerprints = list() if(!istype(A.fingerprintshidden,/list)) A.fingerprintshidden = list() if(!istype(fingerprintshidden, /list)) fingerprintshidden = list() //skytodo //A.fingerprints |= fingerprints //detective //A.fingerprintshidden |= fingerprintshidden //admin if(A.fingerprints && fingerprints) A.fingerprints |= fingerprints.Copy() //detective if(A.fingerprintshidden && fingerprintshidden) A.fingerprintshidden |= fingerprintshidden.Copy() //admin A.fingerprintslast = fingerprintslast //returns 1 if made bloody, returns 0 otherwise /atom/proc/add_blood(mob/living/carbon/human/M as mob) if(flags & NOBLOODY) return 0 if(!blood_DNA || !istype(blood_DNA, /list)) //if our list of DNA doesn't exist yet (or isn't a list) initialise it. blood_DNA = list() was_bloodied = 1 blood_color = "#A10808" if(istype(M)) if (!istype(M.dna, /datum/dna)) M.dna = new /datum/dna(null) M.dna.real_name = M.real_name M.check_dna() blood_color = M.species.get_blood_colour(M) . = 1 return 1 /atom/proc/add_vomit_floor(mob/living/carbon/M as mob, var/toxvomit = 0) if( istype(src, /turf/simulated) ) var/obj/effect/decal/cleanable/vomit/this = new /obj/effect/decal/cleanable/vomit(src) this.virus2 = virus_copylist(M.virus2) // Make toxins vomit look different if(toxvomit) this.icon_state = "vomittox_[pick(1,4)]" /atom/proc/clean_blood() if(!simulated) return fluorescent = 0 src.germ_level = 0 if(istype(blood_DNA, /list)) blood_DNA = null return 1 /atom/proc/get_global_map_pos() if(!islist(global_map) || isemptylist(global_map)) return var/cur_x = null var/cur_y = null var/list/y_arr = null for(cur_x=1,cur_x<=global_map.len,cur_x++) y_arr = global_map[cur_x] cur_y = y_arr.Find(src.z) if(cur_y) break // world << "X = [cur_x]; Y = [cur_y]" if(cur_x && cur_y) return list("x"=cur_x,"y"=cur_y) else return 0 /atom/proc/checkpass(passflag) return (pass_flags&passflag) /atom/proc/isinspace() if(istype(get_turf(src), /turf/space)) return 1 else return 0 // Show a message to all mobs and objects in sight of this atom // Use for objects performing visible actions // message is output to anyone who can see, e.g. "The [src] does something!" // blind_message (optional) is what blind people will hear e.g. "You hear something!" /atom/proc/visible_message(var/message, var/blind_message) var/list/see = get_mobs_and_objs_in_view_fast(get_turf(src),world.view,remote_ghosts = FALSE) var/list/seeing_mobs = see["mobs"] var/list/seeing_objs = see["objs"] for(var/obj in seeing_objs) var/obj/O = obj O.show_message(message, 1, blind_message, 2) for(var/mob in seeing_mobs) var/mob/M = mob if(M.see_invisible >= invisibility && MOB_CAN_SEE_PLANE(M, plane)) M.show_message(message, 1, blind_message, 2) else if(blind_message) M.show_message(blind_message, 2) // Show a message to all mobs and objects in earshot of this atom // Use for objects performing audible actions // message is the message output to anyone who can hear. // deaf_message (optional) is what deaf people will see. // hearing_distance (optional) is the range, how many tiles away the message can be heard. /atom/proc/audible_message(var/message, var/deaf_message, var/hearing_distance) var/range = hearing_distance || world.view var/list/hear = get_mobs_and_objs_in_view_fast(get_turf(src),range,remote_ghosts = FALSE) var/list/hearing_mobs = hear["mobs"] var/list/hearing_objs = hear["objs"] for(var/obj in hearing_objs) var/obj/O = obj O.show_message(message, 2, deaf_message, 1) for(var/mob in hearing_mobs) var/mob/M = mob var/msg = message M.show_message(msg, 2, deaf_message, 1) /atom/movable/proc/dropInto(var/atom/destination) while(istype(destination)) var/atom/drop_destination = destination.onDropInto(src) if(!istype(drop_destination) || drop_destination == destination) return forceMove(destination) destination = drop_destination return forceMove(null) /atom/proc/onDropInto(var/atom/movable/AM) return // If onDropInto returns null, then dropInto will forceMove AM into us. /atom/movable/onDropInto(var/atom/movable/AM) return loc // If onDropInto returns something, then dropInto will attempt to drop AM there. /atom/proc/InsertedContents() return contents /atom/proc/has_gravity(turf/T) if(!T || !isturf(T)) T = get_turf(src) if(istype(T, /turf/space)) // Turf never has gravity return FALSE var/area/A = get_area(T) if(A && A.has_gravity()) return TRUE return FALSE /atom/proc/drop_location() var/atom/L = loc if(!L) return null return L.AllowDrop() ? L : get_turf(L) /atom/proc/AllowDrop() return FALSE /atom/proc/get_nametag_name(mob/user) return name /atom/proc/get_nametag_desc(mob/user) return "" //Desc itself is often too long to use