mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2025-12-26 10:03:45 +00:00
Removes a very large amount of world loops. Adds a macro to painlessly generate a global list, and the needed code to modify the list when an object is made or deleted automatically. Cleans up some commented out code.
522 lines
16 KiB
Plaintext
522 lines
16 KiB
Plaintext
GLOBAL_LIST_BOILERPLATE(all_atoms, /atom) // Use with care, its likely barely better than using world.
|
|
|
|
/atom
|
|
layer = TURF_LAYER //This was here when I got here. Why though?
|
|
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 += "<span class='danger'>blood-stained</span> [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
|