/atom layer = TURF_LAYER plane = GAME_PLANE var/level = 2 var/article // If non-null, overrides a/an/some in all cases var/flags_1 = NONE var/interaction_flags_atom = NONE var/datum/reagents/reagents = null //This atom's HUD (med/sec, etc) images. Associative list. var/list/image/hud_list = null //HUD images that this atom can provide. var/list/hud_possible //Value used to increment ex_act() if reactionary_explosions is on var/explosion_block = 0 var/list/atom_colours //used to store the different colors on an atom //its inherent color, the colored paint applied on it, special color effect etc... var/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4. var/list/remove_overlays // a very temporary list of overlays to remove var/list/add_overlays // a very temporary list of overlays to add var/list/managed_vis_overlays //vis overlays managed by SSvis_overlays to automaticaly turn them like other overlays ///overlays managed by update_overlays() to prevent removing overlays that weren't added by the same proc var/list/managed_overlays var/datum/proximity_monitor/proximity_monitor var/buckle_message_cooldown = 0 var/fingerprintslast var/list/filter_data //For handling persistent filters var/datum/component/orbiter/orbiters var/rad_flags = NONE // Will move to flags_1 when i can be arsed to var/rad_insulation = RAD_NO_INSULATION var/icon/blood_splatter_icon var/list/fingerprints var/list/fingerprintshidden var/list/blood_DNA var/list/suit_fibers /atom/New(loc, ...) //atom creation method that preloads variables at creation if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New() world.preloader_load(src) if(datum_flags & DF_USE_TAG) GenerateTag() 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 return //Called after New if the map is being loaded. mapload = TRUE //Called from base of New if the map is not being loaded. 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 __DEFINES/subsystems.dm //Note: the following functions don't call the base for optimization and must copypasta: // /turf/Initialize // /turf/open/space/Initialize /atom/proc/Initialize(mapload, ...) if(flags_1 & INITIALIZED_1) stack_trace("Warning: [src]([type]) initialized multiple times!") flags_1 |= INITIALIZED_1 //atom color stuff if(color) add_atom_colour(color, FIXED_COLOUR_PRIORITY) if (light_power && light_range) update_light() if (opacity && isturf(loc)) var/turf/T = loc T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guaranteed to be on afterwards anyways. if (canSmoothWith) canSmoothWith = typelist("canSmoothWith", canSmoothWith) ComponentInitialize() return INITIALIZE_HINT_NORMAL //called if Initialize returns INITIALIZE_HINT_LATELOAD /atom/proc/LateInitialize() return // Put your AddComponent() calls here /atom/proc/ComponentInitialize() return /atom/Destroy() if(alternate_appearances) for(var/K in alternate_appearances) var/datum/atom_hud/alternate_appearance/AA = alternate_appearances[K] AA.remove_from_hud(src) if(reagents) qdel(reagents) LAZYCLEARLIST(overlays) LAZYCLEARLIST(priority_overlays) QDEL_NULL(light) return ..() /atom/proc/handle_ricochet(obj/item/projectile/P) return /atom/proc/CanPass(atom/movable/mover, turf/target) return !density /atom/proc/onCentCom() var/turf/T = get_turf(src) if(!T) return FALSE if(is_reserved_level(T.z)) for(var/A in SSshuttle.mobile) var/obj/docking_port/mobile/M = A if(M.launch_status == ENDGAME_TRANSIT) for(var/place in M.shuttle_areas) var/area/shuttle/shuttle_area = place if(T in shuttle_area) return TRUE if(!is_centcom_level(T.z))//if not, don't bother return FALSE //Check for centcom itself if(istype(T.loc, /area/centcom)) return TRUE //Check for centcom shuttles for(var/A in SSshuttle.mobile) var/obj/docking_port/mobile/M = A if(M.launch_status == ENDGAME_LAUNCHED) for(var/place in M.shuttle_areas) var/area/shuttle/shuttle_area = place if(T in shuttle_area) return TRUE /atom/proc/onSyndieBase() var/turf/T = get_turf(src) if(!T) return FALSE if(!is_centcom_level(T.z))//if not, don't bother return FALSE if(istype(T.loc, /area/shuttle/syndicate) || istype(T.loc, /area/syndicate_mothership) || istype(T.loc, /area/shuttle/assault_pod)) return TRUE return FALSE /atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) SEND_SIGNAL(src, COMSIG_ATOM_HULK_ATTACK, user) if(does_attack_animation) user.changeNext_move(CLICK_CD_MELEE) log_combat(user, src, "punched", "hulk powers") user.do_attack_animation(src, ATTACK_EFFECT_SMASH) /atom/proc/CheckParts(list/parts_list) for(var/A in parts_list) if(istype(A, /datum/reagent)) if(!reagents) reagents = new() reagents.reagent_list.Add(A) reagents.conditional_update() else if(ismovableatom(A)) var/atom/movable/M = A if(isliving(M.loc)) var/mob/living/L = M.loc L.transferItemToLoc(M, src) else M.forceMove(src) //common name /atom/proc/update_multiz(prune_on_fail = FALSE) return FALSE /atom/proc/assume_air(datum/gas_mixture/giver) qdel(giver) return null /atom/proc/remove_air(amount) return null /atom/proc/return_air() if(loc) return loc.return_air() else return null /atom/proc/check_eye(mob/user) return /atom/proc/Bumped(atom/movable/AM) set waitfor = FALSE // Convenience procs to see if a container is open for chemistry handling /atom/proc/is_open_container() return is_refillable() && is_drainable() /atom/proc/is_injectable(allowmobs = TRUE) return reagents && (reagents.reagents_holder_flags & (INJECTABLE | REFILLABLE)) /atom/proc/is_drawable(allowmobs = TRUE) return reagents && (reagents.reagents_holder_flags & (DRAWABLE | DRAINABLE)) /atom/proc/is_refillable() return reagents && (reagents.reagents_holder_flags & REFILLABLE) /atom/proc/is_drainable() return reagents && (reagents.reagents_holder_flags & DRAINABLE) /atom/proc/AllowDrop() return FALSE /atom/proc/CheckExit() return TRUE /atom/proc/HasProximity(atom/movable/AM as mob|obj) return /atom/proc/emp_act(severity) var/protection = SEND_SIGNAL(src, COMSIG_ATOM_EMP_ACT, severity) if(!(protection & EMP_PROTECT_WIRES) && istype(wires)) wires.emp_pulse() return protection // Pass the protection value collected here upwards /atom/proc/bullet_act(obj/item/projectile/P, def_zone) SEND_SIGNAL(src, COMSIG_ATOM_BULLET_ACT, P, def_zone) . = P.on_hit(src, 0, def_zone) //used on altdisarm() for special interactions between the shoved victim (target) and the src, with user being the one shoving the target on it. // IMPORTANT: if you wish to add a new own shove_act() to a certain object, remember to add SHOVABLE_ONTO to its obj_flags bitfied var first. /atom/proc/shove_act(mob/living/target, mob/living/user) return FALSE /atom/proc/in_contents_of(container)//can take class or object instance as argument if(ispath(container)) if(istype(src.loc, container)) return TRUE else if(src in container) return TRUE return FALSE /atom/proc/get_examine_name(mob/user) . = "\a [src]" var/list/override = list(gender == PLURAL ? "some" : "a", " ", "[name]") if(article) . = "[article] [src]" override[EXAMINE_POSITION_ARTICLE] = article var/should_override = FALSE if(SEND_SIGNAL(src, COMSIG_ATOM_GET_EXAMINE_NAME, user, override) & COMPONENT_EXNAME_CHANGED) should_override = TRUE if(blood_DNA && !istype(src, /obj/effect/decal)) override[EXAMINE_POSITION_BEFORE] = " blood-stained " should_override = TRUE if(should_override) . = override.Join("") ///Generate the full examine string of this atom (including icon for goonchat) /atom/proc/get_examine_string(mob/user, thats = FALSE) return "[icon2html(src, user)] [thats? "That's ":""][get_examine_name(user)]" /atom/proc/examine(mob/user) . = list("[get_examine_string(user, TRUE)].") if(desc) . += desc if(reagents) if(reagents.reagents_holder_flags & TRANSPARENT) . += "It contains:" if(length(reagents.reagent_list)) if(user.can_see_reagents()) //Show each individual reagent for(var/datum/reagent/R in reagents.reagent_list) . += "[R.volume] units of [R.name]" else //Otherwise, just show the total volume var/total_volume = 0 for(var/datum/reagent/R in reagents.reagent_list) total_volume += R.volume . += "[total_volume] units of various reagents" else . += "Nothing." else if(reagents.reagents_holder_flags & AMOUNT_VISIBLE) if(reagents.total_volume) . += "It has [reagents.total_volume] unit\s left." else . += "It's empty." SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .) /// Updates the icon of the atom /atom/proc/update_icon() // I expect we're going to need more return flags and options in this proc var/signalOut = SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_ICON) if(!(signalOut & COMSIG_ATOM_NO_UPDATE_ICON_STATE)) update_icon_state() if(!(signalOut & COMSIG_ATOM_NO_UPDATE_OVERLAYS)) var/list/new_overlays = update_overlays() if(managed_overlays) cut_overlay(managed_overlays) managed_overlays = null if(length(new_overlays)) managed_overlays = new_overlays add_overlay(new_overlays) /// Updates the icon state of the atom /atom/proc/update_icon_state() /// Updates the overlays of the atom /atom/proc/update_overlays() SHOULD_CALL_PARENT(1) . = list() SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_OVERLAYS, .) /atom/proc/relaymove(mob/user) if(buckle_message_cooldown <= world.time) buckle_message_cooldown = world.time + 50 to_chat(user, "You can't move while buckled to [src]!") return /atom/proc/contents_explosion(severity, target) return //For handling the effects of explosions on contents that would not normally be effected /atom/proc/ex_act(severity, target) set waitfor = FALSE contents_explosion(severity, target) SEND_SIGNAL(src, COMSIG_ATOM_EX_ACT, severity, target) /atom/proc/blob_act(obj/structure/blob/B) SEND_SIGNAL(src, COMSIG_ATOM_BLOB_ACT, B) return /atom/proc/fire_act(exposed_temperature, exposed_volume) SEND_SIGNAL(src, COMSIG_ATOM_FIRE_ACT, exposed_temperature, exposed_volume) return /atom/proc/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) if(density && !has_gravity(AM)) //thrown stuff bounces off dense stuff in no grav, unless the thrown stuff ends up inside what it hit(embedding, bola, etc...). addtimer(CALLBACK(src, .proc/hitby_react, AM), 2) /atom/proc/hitby_react(atom/movable/AM) if(AM && isturf(AM.loc)) step(AM, turn(AM.dir, 180)) /atom/proc/handle_slip(mob/living/carbon/C, knockdown_amount, obj/O, lube) return //returns the mob's dna info as a list, to be inserted in an object's blood_DNA list /mob/living/proc/get_blood_dna_list() var/blood_id = get_blood_id() if(!(blood_id =="blood" || blood_id == "jellyblood")) return return list("ANIMAL DNA" = "Y-") /mob/living/carbon/get_blood_dna_list() var/blood_id = get_blood_id() if(!(blood_id =="blood" || blood_id == "jellyblood")) return var/list/blood_dna = list() if(dna) blood_dna[dna.unique_enzymes] = dna.blood_type else blood_dna["UNKNOWN DNA"] = "X*" return blood_dna /mob/living/carbon/alien/get_blood_dna_list() return list("UNKNOWN DNA" = "X*") //to add a mob's dna info into an object's blood_DNA list. /atom/proc/transfer_mob_blood_dna(mob/living/L) // Returns 0 if we have that blood already var/new_blood_dna = L.get_blood_dna_list() if(!new_blood_dna) return FALSE LAZYINITLIST(blood_DNA) //if our list of DNA doesn't exist yet, initialise it. var/old_length = blood_DNA.len blood_DNA |= new_blood_dna if(blood_DNA.len == old_length) return FALSE return TRUE //to add blood dna info to the object's blood_DNA list /atom/proc/transfer_blood_dna(list/blood_dna, list/datum/disease/diseases) LAZYINITLIST(blood_DNA) var/old_length = blood_DNA.len blood_DNA |= blood_dna if(blood_DNA.len > old_length) return TRUE //some new blood DNA was added //to add blood from a mob onto something, and transfer their dna info /atom/proc/add_mob_blood(mob/living/M) var/list/blood_dna = M.get_blood_dna_list() if(!blood_dna) return FALSE return add_blood_DNA(blood_dna, M.diseases) //to add blood onto something, with blood dna info to include. /atom/proc/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) return FALSE /obj/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) return transfer_blood_dna(blood_dna, diseases) /obj/item/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) . = ..() if(!.) return add_blood_overlay() /obj/item/proc/add_blood_overlay() if(!blood_DNA.len) return if(initial(icon) && initial(icon_state)) blood_splatter_icon = icon(initial(icon), initial(icon_state), , 1) //we only want to apply blood-splatters to the initial icon_state for each object blood_splatter_icon.Blend("#fff", ICON_ADD) //fills the icon_state with white (except where it's transparent) blood_splatter_icon.Blend(icon('icons/effects/blood.dmi', "itemblood"), ICON_MULTIPLY) //adds blood and the remaining white areas become transparant blood_splatter_icon.Blend(blood_DNA_to_color(), ICON_MULTIPLY) add_overlay(blood_splatter_icon) /obj/item/clothing/gloves/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) . = ..() transfer_blood = rand(2, 4) /turf/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) var/obj/effect/decal/cleanable/blood/splatter/B = locate() in src if(!B) B = new /obj/effect/decal/cleanable/blood/splatter(src, diseases) B.transfer_blood_dna(blood_dna, diseases) //give blood info to the blood decal. return TRUE //we bloodied the floor /mob/living/carbon/human/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) if(head) head.add_blood_DNA(blood_dna, diseases) update_inv_head() else if(wear_mask) wear_mask.add_blood_DNA(blood_dna, diseases) update_inv_wear_mask() if(wear_neck) wear_neck.add_blood_DNA(blood_dna, diseases) update_inv_neck() if(wear_suit) wear_suit.add_blood_DNA(blood_dna, diseases) update_inv_wear_suit() else if(w_uniform) w_uniform.add_blood_DNA(blood_dna, diseases) update_inv_w_uniform() if(gloves) var/obj/item/clothing/gloves/G = gloves G.add_blood_DNA(blood_dna, diseases) else transfer_blood_dna(blood_dna, diseases) bloody_hands = rand(2, 4) update_inv_gloves() //handles bloody hands overlays and updating return TRUE /atom/proc/blood_DNA_to_color() var/list/colors = list()//first we make a list of all bloodtypes present for(var/bloop in blood_DNA) if(colors[blood_DNA[bloop]]) colors[blood_DNA[bloop]]++ else colors[blood_DNA[bloop]] = 1 var/final_rgb = BLOOD_COLOR_HUMAN //a default so we don't have white blood graphics if something messed up if(colors.len) var/sum = 0 //this is all shitcode, but it works; trust me final_rgb = bloodtype_to_color(colors[1]) sum = colors[colors[1]] if(colors.len > 1) var/i = 2 while(i <= colors.len) var/tmp = colors[colors[i]] final_rgb = BlendRGB(final_rgb, bloodtype_to_color(colors[i]), tmp/(tmp+sum)) sum += tmp i++ return final_rgb /atom/proc/clean_blood() . = blood_DNA? TRUE : FALSE blood_DNA = null /atom/proc/wash_cream() return TRUE /atom/proc/isinspace() if(isspaceturf(get_turf(src))) return TRUE else return FALSE /atom/proc/handle_fall() return /atom/proc/singularity_act() return /atom/proc/singularity_pull(obj/singularity/S, current_size) SEND_SIGNAL(src, COMSIG_ATOM_SING_PULL, S, current_size) /atom/proc/acid_act(acidpwr, acid_volume) SEND_SIGNAL(src, COMSIG_ATOM_ACID_ACT, acidpwr, acid_volume) /atom/proc/emag_act() return SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT) /atom/proc/rad_act(strength) SEND_SIGNAL(src, COMSIG_ATOM_RAD_ACT, strength) /atom/proc/narsie_act() SEND_SIGNAL(src, COMSIG_ATOM_NARSIE_ACT) /atom/proc/ratvar_act() SEND_SIGNAL(src, COMSIG_ATOM_RATVAR_ACT) /atom/proc/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) return FALSE /atom/proc/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) SEND_SIGNAL(src, COMSIG_ATOM_RCD_ACT, user, the_rcd, passed_mode) return FALSE /atom/proc/storage_contents_dump_act(obj/item/storage/src_object, mob/user) if(GetComponent(/datum/component/storage)) return component_storage_contents_dump_act(src_object, user) return FALSE /atom/proc/component_storage_contents_dump_act(datum/component/storage/src_object, mob/user) var/list/things = src_object.contents() var/datum/progressbar/progress = new(user, things.len, src) var/datum/component/storage/STR = GetComponent(/datum/component/storage) while (do_after(user, 10, TRUE, src, FALSE, CALLBACK(STR, /datum/component/storage.proc/handle_mass_item_insertion, things, src_object, user, progress))) stoplag(1) qdel(progress) to_chat(user, "You dump as much of [src_object.parent]'s contents into [STR.insert_preposition]to [src] as you can.") STR.orient2hud(user) src_object.orient2hud(user) if(user.active_storage) //refresh the HUD to show the transfered contents user.active_storage.close(user) user.active_storage.show_to(user) return TRUE /atom/proc/get_dumping_location(obj/item/storage/source,mob/user) return null //This proc is called on the location of an atom when the atom is Destroy()'d /atom/proc/handle_atom_del(atom/A) SEND_SIGNAL(src, COMSIG_ATOM_CONTENTS_DEL, A) //called when the turf the atom resides on is ChangeTurfed /atom/proc/HandleTurfChange(turf/T) for(var/a in src) var/atom/A = a A.HandleTurfChange(T) //the vision impairment to give to the mob whose perspective is set to that atom (e.g. an unfocused camera giving you an impaired vision when looking through it) /atom/proc/get_remote_view_fullscreens(mob/user) return //the sight changes to give to the mob whose perspective is set to that atom (e.g. A mob with nightvision loses its nightvision while looking through a normal camera) /atom/proc/update_remote_sight(mob/living/user) return //Hook for running code when a dir change occurs /atom/proc/setDir(newdir, ismousemovement=FALSE) SEND_SIGNAL(src, COMSIG_ATOM_DIR_CHANGE, dir, newdir) dir = newdir /atom/proc/mech_melee_attack(obj/mecha/M) return //If a mob logouts/logins in side of an object you can use this proc /atom/proc/on_log(login) if(loc) loc.on_log(login) /* Atom Colour Priority System A System that gives finer control over which atom colour to colour the atom with. The "highest priority" one is always displayed as opposed to the default of "whichever was set last is displayed" */ /* Adds an instance of colour_type to the atom's atom_colours list */ /atom/proc/add_atom_colour(coloration, colour_priority) if(!atom_colours || !atom_colours.len) atom_colours = list() atom_colours.len = COLOUR_PRIORITY_AMOUNT //four priority levels currently. if(!coloration) return if(colour_priority > atom_colours.len) return atom_colours[colour_priority] = coloration update_atom_colour() /* Removes an instance of colour_type from the atom's atom_colours list */ /atom/proc/remove_atom_colour(colour_priority, coloration) if(!atom_colours) atom_colours = list() atom_colours.len = COLOUR_PRIORITY_AMOUNT //four priority levels currently. if(colour_priority > atom_colours.len) return if(coloration && atom_colours[colour_priority] != coloration) return //if we don't have the expected color (for a specific priority) to remove, do nothing atom_colours[colour_priority] = null update_atom_colour() /* Resets the atom's color to null, and then sets it to the highest priority colour available */ /atom/proc/update_atom_colour() if(!atom_colours) atom_colours = list() atom_colours.len = COLOUR_PRIORITY_AMOUNT //four priority levels currently. color = null for(var/C in atom_colours) if(islist(C)) var/list/L = C if(L.len) color = L return else if(C) color = C return /atom/vv_edit_var(var_name, var_value) if(!GLOB.Debug2) flags_1 |= ADMIN_SPAWNED_1 . = ..() switch(var_name) if("color") add_atom_colour(color, ADMIN_COLOUR_PRIORITY) /atom/vv_get_dropdown() . = ..() . += "---" var/turf/curturf = get_turf(src) if (curturf) .["Jump to"] = "?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[curturf.x];Y=[curturf.y];Z=[curturf.z]" .["Modify Transform"] = "?_src_=vars;[HrefToken()];modtransform=[REF(src)]" .["Add reagent"] = "?_src_=vars;[HrefToken()];addreagent=[REF(src)]" .["Trigger EM pulse"] = "?_src_=vars;[HrefToken()];emp=[REF(src)]" .["Trigger explosion"] = "?_src_=vars;[HrefToken()];explode=[REF(src)]" /atom/proc/drop_location() var/atom/L = loc if(!L) return null return L.AllowDrop() ? L : L.drop_location() /atom/Entered(atom/movable/AM, atom/oldLoc) SEND_SIGNAL(src, COMSIG_ATOM_ENTERED, AM, oldLoc) /atom/Exit(atom/movable/AM, atom/newLoc) . = ..() if(SEND_SIGNAL(src, COMSIG_ATOM_EXIT, AM, newLoc) & COMPONENT_ATOM_BLOCK_EXIT) return FALSE /atom/Exited(atom/movable/AM, atom/newLoc) SEND_SIGNAL(src, COMSIG_ATOM_EXITED, AM, newLoc) /atom/proc/return_temperature() return // Tool behavior procedure. Redirects to tool-specific procs by default. // You can override it to catch all tool interactions, for use in complex deconstruction procs. // Just don't forget to return ..() in the end. /atom/proc/tool_act(mob/living/user, obj/item/I, tool_type) switch(tool_type) if(TOOL_CROWBAR) return crowbar_act(user, I) if(TOOL_MULTITOOL) return multitool_act(user, I) if(TOOL_SCREWDRIVER) return screwdriver_act(user, I) if(TOOL_WRENCH) return wrench_act(user, I) if(TOOL_WIRECUTTER) return wirecutter_act(user, I) if(TOOL_WELDER) return welder_act(user, I) if(TOOL_ANALYZER) return analyzer_act(user, I) // Tool-specific behavior procs. To be overridden in subtypes. /atom/proc/crowbar_act(mob/living/user, obj/item/I) return /atom/proc/multitool_act(mob/living/user, obj/item/I) return /atom/proc/multitool_check_buffer(user, obj/item/I, silent = FALSE) if(!istype(I, /obj/item/multitool)) if(user && !silent) to_chat(user, "[I] has no data buffer!") return FALSE return TRUE /atom/proc/screwdriver_act(mob/living/user, obj/item/I) SEND_SIGNAL(src, COMSIG_ATOM_SCREWDRIVER_ACT, user, I) /atom/proc/wrench_act(mob/living/user, obj/item/I) return /atom/proc/wirecutter_act(mob/living/user, obj/item/I) return /atom/proc/welder_act(mob/living/user, obj/item/I) return /atom/proc/analyzer_act(mob/living/user, obj/item/I) return /atom/proc/GenerateTag() return // Generic logging helper /atom/proc/log_message(message, message_type, color=null, log_globally=TRUE) if(!log_globally) return var/log_text = "[key_name(src)] [message] [loc_name(src)]" switch(message_type) if(LOG_ATTACK) log_attack(log_text) if(LOG_SAY) log_say(log_text) if(LOG_WHISPER) log_whisper(log_text) if(LOG_EMOTE) log_emote(log_text) if(LOG_SUBTLER) log_subtler(log_text) if(LOG_DSAY) log_dsay(log_text) if(LOG_PDA) log_pda(log_text) if(LOG_CHAT) log_chat(log_text) if(LOG_COMMENT) log_comment(log_text) if(LOG_TELECOMMS) log_telecomms(log_text) if(LOG_OOC) log_ooc(log_text) if(LOG_ADMIN) log_admin(log_text) if(LOG_ADMIN_PRIVATE) log_admin_private(log_text) if(LOG_ASAY) log_adminsay(log_text) if(LOG_OWNERSHIP) log_game(log_text) if(LOG_GAME) log_game(log_text) else stack_trace("Invalid individual logging type: [message_type]. Defaulting to [LOG_GAME] (LOG_GAME).") log_game(log_text) // Helper for logging chat messages or other logs with arbitrary inputs (e.g. announcements) /atom/proc/log_talk(message, message_type, tag=null, log_globally=TRUE, forced_by=null) var/prefix = tag ? "([tag]) " : "" var/suffix = forced_by ? " FORCED by [forced_by]" : "" log_message("[prefix]\"[message]\"[suffix]", message_type, log_globally=log_globally) // Helper for logging of messages with only one sender and receiver /proc/log_directed_talk(atom/source, atom/target, message, message_type, tag) if(!tag) stack_trace("Unspecified tag for private message") tag = "UNKNOWN" source.log_talk(message, message_type, tag="[tag] to [key_name(target)]") if(source != target) target.log_talk(message, message_type, tag="[tag] from [key_name(source)]", log_globally=FALSE) /* Proc for attack log creation, because really why not 1 argument is the actor performing the action 2 argument is the target of the action 3 is a verb describing the action (e.g. punched, throwed, kicked, etc.) 4 is a tool with which the action was made (usually an item) 5 is any additional text, which will be appended to the rest of the log line */ /proc/log_combat(atom/user, atom/target, what_done, atom/object=null, addition=null) var/ssource = key_name(user) var/starget = key_name(target) var/mob/living/living_target = target var/hp = istype(living_target) ? " (NEWHP: [living_target.health]) " : "" var/sobject = "" if(object) sobject = " with [key_name(object)]" var/saddition = "" if(addition) saddition = " [addition]" var/postfix = "[sobject][saddition][hp]" var/message = "has [what_done] [starget][postfix]" user.log_message(message, LOG_ATTACK, color="red") if(user != target) var/reverse_message = "has been [what_done] by [ssource][postfix]" target.log_message(reverse_message, LOG_ATTACK, color="orange", log_globally=FALSE) // Filter stuff /atom/movable/proc/add_filter(name,priority,list/params) LAZYINITLIST(filter_data) var/list/p = params.Copy() p["priority"] = priority filter_data[name] = p update_filters() /atom/movable/proc/update_filters() filters = null filter_data = sortTim(filter_data, /proc/cmp_filter_data_priority, TRUE) for(var/f in filter_data) var/list/data = filter_data[f] var/list/arguments = data.Copy() arguments -= "priority" filters += filter(arglist(arguments)) /atom/movable/proc/get_filter(name) if(filter_data && filter_data[name]) return filters[filter_data.Find(name)] /atom/movable/proc/remove_filter(name) if(filter_data && filter_data[name]) filter_data -= name update_filters() return TRUE /atom/proc/intercept_zImpact(atom/movable/AM, levels = 1) . |= SEND_SIGNAL(src, COMSIG_ATOM_INTERCEPT_Z_FALL, AM, levels)