Files
Yogstation/code/game/atoms.dm
TheGamerdk e056d9a1f1 Ports Runescape Chat bubbles from TG-station (#8293)
* Working

* 512

* Hacky AF 512 workaround, revert if 513 update

* 512 fix

* Update layers.dm

* PLANE GO CRASH

* Revert "512"

This reverts commit 024f7adfe3.

* Revert "512 fix"

This reverts commit 0efdc42688.

* Revert "Hacky AF 512 workaround, revert if 513 update"

This reverts commit 569987d66f.

* f

* -f

* Revert "-f"

This reverts commit aadad7b75d.

* Revert "f"

This reverts commit 0e4368ecee.

* reverts darkness

Co-authored-by: Bobbahbrown <bobbahbrown@gmail.com>
2020-05-02 09:38:36 -04:00

751 lines
22 KiB
Plaintext

/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
var/datum/proximity_monitor/proximity_monitor
var/buckle_message_cooldown = 0
var/fingerprintslast
var/list/filter_data //For handling persistent filters
var/custom_price
var/custom_premium_price
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/chat_color_name // Last name used to calculate a color for the chatmessage overlays
var/chat_color // Last color calculated for the the chatmessage overlays
var/chat_color_darkened // A luminescence-shifted value of the last color calculated for chatmessage overlays
/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
SSdemo.mark_new(src)
//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)
orbiters = null // The component is attached to us normaly and will be deleted elsewhere
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 = 0)
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(ismovable(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(mob/user, allowmobs = TRUE)
return reagents && (reagents.flags & (INJECTABLE | REFILLABLE))
/atom/proc/is_drawable(mob/user, allowmobs = TRUE)
return reagents && (reagents.flags & (DRAWABLE | DRAINABLE))
/atom/proc/is_refillable()
return reagents && (reagents.flags & REFILLABLE)
/atom/proc/is_drainable()
return reagents && (reagents.flags & DRAINABLE)
/atom/proc/AllowDrop()
return FALSE
/atom/proc/CheckExit()
return 1
/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)
/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
if(SEND_SIGNAL(src, COMSIG_ATOM_GET_EXAMINE_NAME, user, override) & COMPONENT_EXNAME_CHANGED)
. = override.Join("")
/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.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.flags & AMOUNT_VISIBLE)
if(reagents.total_volume)
. += "<span class='notice'>It has [reagents.total_volume] unit\s left.</span>"
else
. += "<span class='danger'>It's empty.</span>"
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .)
/atom/proc/relaymove(mob/user)
if(buckle_message_cooldown <= world.time)
buckle_message_cooldown = world.time + 50
to_chat(user, "<span class='warning'>You can't move while buckled to [src]!</span>")
return
/atom/proc/prevent_content_explosion()
return FALSE
/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, paralyze, force_drop)
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()
if(get_blood_id() != /datum/reagent/blood)
return
return list("ANIMAL DNA" = "Y-")
/mob/living/carbon/get_blood_dna_list()
if(get_blood_id() != /datum/reagent/blood)
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*")
/mob/living/silicon/get_blood_dna_list()
return list("MOTOR OIL" = "SAE 5W-30") //just a little flavor text.
//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
var/old_length = blood_DNA_length()
add_blood_DNA(new_blood_dna)
if(blood_DNA_length() == old_length)
return FALSE
return TRUE
//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)
/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()
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)
//yogs start -- stops things from dumping into themselves
if(STR == src_object)
to_chat(user,"<span class='warning'>You can't dump the contents of [src_object.parent] into itself!</span>")
return
//yogs end
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, "<span class='notice'>You dump as much of [src_object.parent]'s contents into [STR.insert_preposition]to [src] as you can.</span>")
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)
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, "<span class='warning'>[I] has no data buffer!</span>")
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
/atom/proc/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
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_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_NTSL)
log_ntsl(log_text)
if(LOG_OOC)
log_ooc(log_text)
if(LOG_LOOC) // yogs - LOOC log
log_looc(log_text) // yogs - LOOC log
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)
if(LOG_MECHA)
log_mecha(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 [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)
if(!filter_data)
filter_data = list()
var/list/p = params.Copy()
p["priority"] = priority
filter_data[name] = p
update_filters()
/atom/movable/proc/update_filters()
filters = null
sortTim(filter_data,associative = 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/proc/intercept_zImpact(atom/movable/AM, levels = 1)
return FALSE