mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-28 23:58:07 +01:00
[MIRROR] Splits up most of atoms.dm [MDB IGNORE] (#25055)
* Splits up most of atoms.dm * Fix diffs * Update tgstation.dme --------- Co-authored-by: Emmett Gaines <ninjanomnom@gmail.com> Co-authored-by: Giz <13398309+vinylspiders@users.noreply.github.com>
This commit is contained in:
co-authored by
Emmett Gaines
Giz
parent
3238023f73
commit
e5e5130696
@@ -1,67 +0,0 @@
|
||||
/**
|
||||
* Causes the passed atom / image to appear floating,
|
||||
* playing a simple animation where they move up and down by 2 pixels (looping)
|
||||
*
|
||||
* In most cases you should NOT call this manually, instead use [/datum/element/movetype_handler]!
|
||||
* This is just so you can apply the animation to things which can be animated but are not movables (like images)
|
||||
*/
|
||||
#define DO_FLOATING_ANIM(target) \
|
||||
animate(target, pixel_y = 2, time = 1 SECONDS, loop = -1, flags = ANIMATION_RELATIVE); \
|
||||
animate(pixel_y = -2, time = 1 SECONDS, flags = ANIMATION_RELATIVE)
|
||||
|
||||
/**
|
||||
* Stops the passed atom / image from appearing floating
|
||||
* (Living mobs also have a 'body_position_pixel_y_offset' variable that has to be taken into account here)
|
||||
*
|
||||
* In most cases you should NOT call this manually, instead use [/datum/element/movetype_handler]!
|
||||
* This is just so you can apply the animation to things which can be animated but are not movables (like images)
|
||||
*/
|
||||
#define STOP_FLOATING_ANIM(target) \
|
||||
var/final_pixel_y = 0; \
|
||||
if(ismovable(target)) { \
|
||||
var/atom/movable/movable_target = target; \
|
||||
final_pixel_y = movable_target.base_pixel_y; \
|
||||
}; \
|
||||
if(isliving(target)) { \
|
||||
var/mob/living/living_target = target; \
|
||||
final_pixel_y += living_target.body_position_pixel_y_offset; \
|
||||
}; \
|
||||
animate(target, pixel_y = final_pixel_y, time = 1 SECONDS)
|
||||
|
||||
/// The duration of the animate call in mob/living/update_transform
|
||||
#define UPDATE_TRANSFORM_ANIMATION_TIME (0.2 SECONDS)
|
||||
|
||||
///Animates source spinning around itself. For docmentation on the args, check atom/proc/SpinAnimation()
|
||||
/atom/proc/do_spin_animation(speed = 1 SECONDS, loops = -1, segments = 3, angle = 120, parallel = TRUE)
|
||||
var/list/matrices = list()
|
||||
for(var/i in 1 to segments-1)
|
||||
var/matrix/segment_matrix = matrix(transform)
|
||||
segment_matrix.Turn(angle*i)
|
||||
matrices += segment_matrix
|
||||
var/matrix/last = matrix(transform)
|
||||
matrices += last
|
||||
|
||||
speed /= segments
|
||||
|
||||
if(parallel)
|
||||
animate(src, transform = matrices[1], time = speed, loops , flags = ANIMATION_PARALLEL)
|
||||
else
|
||||
animate(src, transform = matrices[1], time = speed, loops)
|
||||
for(var/i in 2 to segments) //2 because 1 is covered above
|
||||
animate(transform = matrices[i], time = speed)
|
||||
//doesn't have an object argument because this is "Stacking" with the animate call above
|
||||
//3 billion% intentional
|
||||
|
||||
/// Similar to shake but more spasm-y and jerk-y
|
||||
/atom/proc/spasm_animation(loops = -1)
|
||||
var/list/transforms = list(
|
||||
matrix(transform).Translate(-1, 0),
|
||||
matrix(transform).Translate(0, 1),
|
||||
matrix(transform).Translate(1, 0),
|
||||
matrix(transform).Translate(0, -1),
|
||||
)
|
||||
|
||||
animate(src, transform = transforms[1], time = 0.2, loop = loops)
|
||||
animate(transform = transforms[2], time = 0.1)
|
||||
animate(transform = transforms[3], time = 0.2)
|
||||
animate(transform = transforms[4], time = 0.3)
|
||||
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* Causes the passed atom / image to appear floating,
|
||||
* playing a simple animation where they move up and down by 2 pixels (looping)
|
||||
*
|
||||
* In most cases you should NOT call this manually, instead use [/datum/element/movetype_handler]!
|
||||
* This is just so you can apply the animation to things which can be animated but are not movables (like images)
|
||||
*/
|
||||
#define DO_FLOATING_ANIM(target) \
|
||||
animate(target, pixel_y = 2, time = 1 SECONDS, loop = -1, flags = ANIMATION_RELATIVE); \
|
||||
animate(pixel_y = -2, time = 1 SECONDS, flags = ANIMATION_RELATIVE)
|
||||
|
||||
/**
|
||||
* Stops the passed atom / image from appearing floating
|
||||
* (Living mobs also have a 'body_position_pixel_y_offset' variable that has to be taken into account here)
|
||||
*
|
||||
* In most cases you should NOT call this manually, instead use [/datum/element/movetype_handler]!
|
||||
* This is just so you can apply the animation to things which can be animated but are not movables (like images)
|
||||
*/
|
||||
#define STOP_FLOATING_ANIM(target) \
|
||||
var/final_pixel_y = 0; \
|
||||
if(ismovable(target)) { \
|
||||
var/atom/movable/movable_target = target; \
|
||||
final_pixel_y = movable_target.base_pixel_y; \
|
||||
}; \
|
||||
if(isliving(target)) { \
|
||||
var/mob/living/living_target = target; \
|
||||
final_pixel_y += living_target.body_position_pixel_y_offset; \
|
||||
}; \
|
||||
animate(target, pixel_y = final_pixel_y, time = 1 SECONDS)
|
||||
|
||||
/// The duration of the animate call in mob/living/update_transform
|
||||
#define UPDATE_TRANSFORM_ANIMATION_TIME (0.2 SECONDS)
|
||||
|
||||
///Animates source spinning around itself. For docmentation on the args, check atom/proc/SpinAnimation()
|
||||
/atom/proc/do_spin_animation(speed = 1 SECONDS, loops = -1, segments = 3, angle = 120, parallel = TRUE)
|
||||
var/list/matrices = list()
|
||||
for(var/i in 1 to segments-1)
|
||||
var/matrix/segment_matrix = matrix(transform)
|
||||
segment_matrix.Turn(angle*i)
|
||||
matrices += segment_matrix
|
||||
var/matrix/last = matrix(transform)
|
||||
matrices += last
|
||||
|
||||
speed /= segments
|
||||
|
||||
if(parallel)
|
||||
animate(src, transform = matrices[1], time = speed, loops , flags = ANIMATION_PARALLEL)
|
||||
else
|
||||
animate(src, transform = matrices[1], time = speed, loops)
|
||||
for(var/i in 2 to segments) //2 because 1 is covered above
|
||||
animate(transform = matrices[i], time = speed)
|
||||
//doesn't have an object argument because this is "Stacking" with the animate call above
|
||||
//3 billion% intentional
|
||||
|
||||
/// Similar to shake but more spasm-y and jerk-y
|
||||
/atom/proc/spasm_animation(loops = -1)
|
||||
var/list/transforms = list(
|
||||
matrix(transform).Translate(-1, 0),
|
||||
matrix(transform).Translate(0, 1),
|
||||
matrix(transform).Translate(1, 0),
|
||||
matrix(transform).Translate(0, -1),
|
||||
)
|
||||
|
||||
animate(src, transform = transforms[1], time = 0.2, loop = loops)
|
||||
animate(transform = transforms[2], time = 0.1)
|
||||
animate(transform = transforms[3], time = 0.2)
|
||||
animate(transform = transforms[4], time = 0.3)
|
||||
|
||||
/**
|
||||
* Proc called when you want the atom to spin around the center of its icon (or where it would be if its transform var is translated)
|
||||
* By default, it makes the atom spin forever and ever at a speed of 60 rpm.
|
||||
*
|
||||
* Arguments:
|
||||
* * speed: how much it takes for the atom to complete one 360° rotation
|
||||
* * loops: how many times do we want the atom to rotate
|
||||
* * clockwise: whether the atom ought to spin clockwise or counter-clockwise
|
||||
* * segments: in how many animate calls the rotation is split. Probably unnecessary, but you shouldn't set it lower than 3 anyway.
|
||||
* * parallel: whether the animation calls have the ANIMATION_PARALLEL flag, necessary for it to run alongside concurrent animations.
|
||||
*/
|
||||
/atom/proc/SpinAnimation(speed = 1 SECONDS, loops = -1, clockwise = TRUE, segments = 3, parallel = TRUE)
|
||||
if(!segments)
|
||||
return
|
||||
var/segment = 360/segments
|
||||
if(!clockwise)
|
||||
segment = -segment
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_SPIN_ANIMATION, speed, loops, segments, segment)
|
||||
do_spin_animation(speed, loops, segments, segment, parallel)
|
||||
|
||||
/// Makes this atom look like a "hologram"
|
||||
/// So transparent, blue, with a scanline and an emissive glow
|
||||
/// This is acomplished using a combination of filters and render steps/overlays
|
||||
/// The degree of the opacity is optional, based off the opacity arg (0 -> 1)
|
||||
/atom/proc/makeHologram(opacity = 0.5)
|
||||
// First, we'll make things blue (roughly) and sorta transparent
|
||||
add_filter("HOLO: Color and Transparent", 1, color_matrix_filter(rgb(125,180,225, opacity * 255)))
|
||||
// Now we're gonna do a scanline effect
|
||||
// Gonna take this atom and give it a render target, then use it as a source for a filter
|
||||
// (We use an atom because it seems as if setting render_target on an MA is just invalid. I hate this engine)
|
||||
var/atom/movable/scanline = new(null)
|
||||
scanline.icon = 'icons/effects/effects.dmi'
|
||||
scanline.icon_state = "scanline"
|
||||
scanline.appearance_flags |= RESET_TRANSFORM
|
||||
// * so it doesn't render
|
||||
var/static/uid_scan = 0
|
||||
scanline.render_target = "*HoloScanline [uid_scan]"
|
||||
uid_scan++
|
||||
// Now we add it as a filter, and overlay the appearance so the render source is always around
|
||||
add_filter("HOLO: Scanline", 2, alpha_mask_filter(render_source = scanline.render_target))
|
||||
add_overlay(scanline)
|
||||
qdel(scanline)
|
||||
// Annd let's make the sucker emissive, so it glows in the dark
|
||||
if(!render_target)
|
||||
var/static/uid = 0
|
||||
render_target = "HOLOGRAM [uid]"
|
||||
uid++
|
||||
// I'm using static here to reduce the overhead, it does mean we need to do plane stuff manually tho
|
||||
var/static/atom/movable/render_step/emissive/glow = new(null)
|
||||
glow.render_source = render_target
|
||||
SET_PLANE_EXPLICIT(glow, initial(glow.plane), src)
|
||||
// We're creating a render step that copies ourselves, and draws it to the emissive plane
|
||||
// Then we overlay it, and release "ownership" back to this proc, since we get to keep the appearance it generates
|
||||
// We can't just use an MA from the start cause render_source setting starts going fuckey REALLY quick
|
||||
var/mutable_appearance/glow_appearance = new(glow)
|
||||
add_overlay(glow_appearance)
|
||||
LAZYADD(update_overlays_on_z, glow_appearance)
|
||||
@@ -0,0 +1,3 @@
|
||||
# Core /atom Systems
|
||||
|
||||
This is a folder of basic systems that apply to all /atom types, split into relevant files. Keep the files named fittingly and don't put anything in `_atom.dm` if you can avoid it.
|
||||
@@ -0,0 +1,959 @@
|
||||
/**
|
||||
* The base type for nearly all physical objects in SS13
|
||||
|
||||
* Lots and lots of functionality lives here, although in general we are striving to move
|
||||
* as much as possible to the components/elements system
|
||||
*/
|
||||
/atom
|
||||
layer = TURF_LAYER
|
||||
plane = GAME_PLANE
|
||||
appearance_flags = TILE_BOUND|LONG_GLIDE
|
||||
|
||||
/// pass_flags that we are. If any of this matches a pass_flag on a moving thing, by default, we let them through.
|
||||
var/pass_flags_self = NONE
|
||||
|
||||
///First atom flags var
|
||||
var/flags_1 = NONE
|
||||
///Intearaction flags
|
||||
var/interaction_flags_atom = NONE
|
||||
|
||||
var/flags_ricochet = NONE
|
||||
|
||||
///When a projectile tries to ricochet off this atom, the projectile ricochet chance is multiplied by this
|
||||
var/receive_ricochet_chance_mod = 1
|
||||
///When a projectile ricochets off this atom, it deals the normal damage * this modifier to this atom
|
||||
var/receive_ricochet_damage_coeff = 0.33
|
||||
|
||||
///Reagents holder
|
||||
var/datum/reagents/reagents = null
|
||||
|
||||
///all of this atom's HUD (med/sec, etc) images. Associative list of the form: list(hud category = hud image or images for that category).
|
||||
///most of the time hud category is associated with a single image, sometimes its associated with a list of images.
|
||||
///not every hud in this list is actually used. for ones available for others to see, look at active_hud_list.
|
||||
var/list/image/hud_list = null
|
||||
///all of this atom's HUD images which can actually be seen by players with that hud
|
||||
var/list/image/active_hud_list = null
|
||||
///HUD images that this atom can provide.
|
||||
var/list/hud_possible
|
||||
|
||||
///How much this atom resists explosions by, in the end
|
||||
var/explosive_resistance = 0
|
||||
|
||||
///vis overlays managed by SSvis_overlays to automaticaly turn them like other overlays.
|
||||
var/list/managed_vis_overlays
|
||||
|
||||
/// Lazylist of all images (or atoms, I'm sorry) (hopefully attached to us) to update when we change z levels
|
||||
/// You will need to manage adding/removing from this yourself, but I'll do the updating for you
|
||||
var/list/image/update_on_z
|
||||
|
||||
/// Lazylist of all overlays attached to us to update when we change z levels
|
||||
/// You will need to manage adding/removing from this yourself, but I'll do the updating for you
|
||||
/// Oh and note, if order of addition is important this WILL break that. so mind yourself
|
||||
var/list/image/update_overlays_on_z
|
||||
|
||||
///Cooldown tick timer for buckle messages
|
||||
var/buckle_message_cooldown = 0
|
||||
///Last fingerprints to touch this atom
|
||||
var/fingerprintslast
|
||||
|
||||
/// Radiation insulation types
|
||||
var/rad_insulation = RAD_NO_INSULATION
|
||||
|
||||
/// The icon state intended to be used for the acid component. Used to override the default acid overlay icon state.
|
||||
var/custom_acid_overlay = null
|
||||
|
||||
var/datum/wires/wires = null
|
||||
|
||||
///Light systems, both shouldn't be active at the same time.
|
||||
var/light_system = STATIC_LIGHT
|
||||
///Range of the light in tiles. Zero means no light.
|
||||
var/light_range = 0
|
||||
///Intensity of the light. The stronger, the less shadows you will see on the lit area.
|
||||
var/light_power = 1
|
||||
///Hexadecimal RGB string representing the colour of the light. White by default.
|
||||
var/light_color = COLOR_WHITE
|
||||
/// Angle of light to show in light_dir
|
||||
/// 360 is a circle, 90 is a cone, etc.
|
||||
var/light_angle = 360
|
||||
/// What angle to project light in
|
||||
var/light_dir = NORTH
|
||||
///Boolean variable for toggleable lights. Has no effect without the proper light_system, light_range and light_power values.
|
||||
var/light_on = TRUE
|
||||
/// How many tiles "up" this light is. 1 is typical, should only really change this if it's a floor light
|
||||
var/light_height = LIGHTING_HEIGHT
|
||||
///Bitflags to determine lighting-related atom properties.
|
||||
var/light_flags = NONE
|
||||
///Our light source. Don't fuck with this directly unless you have a good reason!
|
||||
var/tmp/datum/light_source/light
|
||||
///Any light sources that are "inside" of us, for example, if src here was a mob that's carrying a flashlight, that flashlight's light source would be part of this list.
|
||||
var/tmp/list/light_sources
|
||||
|
||||
/// Last name used to calculate a color for the chatmessage overlays
|
||||
var/chat_color_name
|
||||
/// Last color calculated for the the chatmessage overlays
|
||||
var/chat_color
|
||||
/// A luminescence-shifted value of the last color calculated for chatmessage overlays
|
||||
var/chat_color_darkened
|
||||
|
||||
// Use SET_BASE_PIXEL(x, y) to set these in typepath definitions, it'll handle pixel_x and y for you
|
||||
///Default pixel x shifting for the atom's icon.
|
||||
var/base_pixel_x = 0
|
||||
///Default pixel y shifting for the atom's icon.
|
||||
var/base_pixel_y = 0
|
||||
// Use SET_BASE_VISUAL_PIXEL(x, y) to set these in typepath definitions, it'll handle pixel_w and z for you
|
||||
///Default pixel w shifting for the atom's icon.
|
||||
var/base_pixel_w = 0
|
||||
///Default pixel z shifting for the atom's icon.
|
||||
var/base_pixel_z = 0
|
||||
///Used for changing icon states for different base sprites.
|
||||
var/base_icon_state
|
||||
|
||||
///Icon-smoothing behavior.
|
||||
var/smoothing_flags = NONE
|
||||
///What directions this is currently smoothing with. IMPORTANT: This uses the smoothing direction flags as defined in icon_smoothing.dm, instead of the BYOND flags.
|
||||
var/smoothing_junction = null //This starts as null for us to know when it's first set, but after that it will hold a 8-bit mask ranging from 0 to 255.
|
||||
///Smoothing variable
|
||||
var/top_left_corner
|
||||
///Smoothing variable
|
||||
var/top_right_corner
|
||||
///Smoothing variable
|
||||
var/bottom_left_corner
|
||||
///Smoothing variable
|
||||
var/bottom_right_corner
|
||||
///What smoothing groups does this atom belongs to, to match canSmoothWith. If null, nobody can smooth with it. Must be sorted.
|
||||
var/list/smoothing_groups = null
|
||||
///List of smoothing groups this atom can smooth with. If this is null and atom is smooth, it smooths only with itself. Must be sorted.
|
||||
var/list/canSmoothWith = null
|
||||
|
||||
///AI controller that controls this atom. type on init, then turned into an instance during runtime
|
||||
var/datum/ai_controller/ai_controller
|
||||
|
||||
/// forensics datum, contains fingerprints, fibres, blood_dna and hiddenprints on this atom
|
||||
var/datum/forensics/forensics
|
||||
|
||||
/// How this atom should react to having its astar blocking checked
|
||||
var/can_astar_pass = CANASTARPASS_DENSITY
|
||||
|
||||
/**
|
||||
* Top level of the destroy chain for most atoms
|
||||
*
|
||||
* Cleans up the following:
|
||||
* * Removes alternate apperances from huds that see them
|
||||
* * qdels the reagent holder from atoms if it exists
|
||||
* * clears the orbiters list
|
||||
* * clears overlays and priority overlays
|
||||
* * clears the light object
|
||||
*/
|
||||
/atom/Destroy(force)
|
||||
if(alternate_appearances)
|
||||
for(var/current_alternate_appearance in alternate_appearances)
|
||||
var/datum/atom_hud/alternate_appearance/selected_alternate_appearance = alternate_appearances[current_alternate_appearance]
|
||||
selected_alternate_appearance.remove_atom_from_hud(src)
|
||||
|
||||
if(reagents)
|
||||
QDEL_NULL(reagents)
|
||||
|
||||
if(forensics)
|
||||
QDEL_NULL(forensics)
|
||||
|
||||
if(atom_storage)
|
||||
QDEL_NULL(atom_storage)
|
||||
|
||||
orbiters = null // The component is attached to us normaly and will be deleted elsewhere
|
||||
|
||||
// Checking length(overlays) before cutting has significant speed benefits
|
||||
if (length(overlays))
|
||||
overlays.Cut()
|
||||
|
||||
LAZYNULL(managed_overlays)
|
||||
if(ai_controller)
|
||||
QDEL_NULL(ai_controller)
|
||||
if(light)
|
||||
QDEL_NULL(light)
|
||||
if (length(light_sources))
|
||||
light_sources.Cut()
|
||||
|
||||
if(smoothing_flags & SMOOTH_QUEUED)
|
||||
SSicon_smooth.remove_from_queues(src)
|
||||
|
||||
return ..()
|
||||
|
||||
/atom/proc/handle_ricochet(obj/projectile/ricocheting_projectile)
|
||||
var/turf/p_turf = get_turf(ricocheting_projectile)
|
||||
var/face_direction = get_dir(src, p_turf) || get_dir(src, ricocheting_projectile)
|
||||
var/face_angle = dir2angle(face_direction)
|
||||
var/incidence_s = GET_ANGLE_OF_INCIDENCE(face_angle, (ricocheting_projectile.Angle + 180))
|
||||
var/a_incidence_s = abs(incidence_s)
|
||||
if(a_incidence_s > 90 && a_incidence_s < 270)
|
||||
return FALSE
|
||||
if((ricocheting_projectile.armor_flag in list(BULLET, BOMB)) && ricocheting_projectile.ricochet_incidence_leeway)
|
||||
if((a_incidence_s < 90 && a_incidence_s < 90 - ricocheting_projectile.ricochet_incidence_leeway) || (a_incidence_s > 270 && a_incidence_s -270 > ricocheting_projectile.ricochet_incidence_leeway))
|
||||
return FALSE
|
||||
var/new_angle_s = SIMPLIFY_DEGREES(face_angle + incidence_s)
|
||||
ricocheting_projectile.set_angle(new_angle_s)
|
||||
return TRUE
|
||||
|
||||
/// Whether the mover object can avoid being blocked by this atom, while arriving from (or leaving through) the border_dir.
|
||||
/atom/proc/CanPass(atom/movable/mover, border_dir)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
SHOULD_BE_PURE(TRUE)
|
||||
if(SEND_SIGNAL(src, COMSIG_ATOM_TRIED_PASS, mover, border_dir) & COMSIG_COMPONENT_PERMIT_PASSAGE)
|
||||
return TRUE
|
||||
if(mover.movement_type & PHASING)
|
||||
return TRUE
|
||||
. = CanAllowThrough(mover, border_dir)
|
||||
// This is cheaper than calling the proc every time since most things dont override CanPassThrough
|
||||
if(!mover.generic_canpass)
|
||||
return mover.CanPassThrough(src, REVERSE_DIR(border_dir), .)
|
||||
|
||||
/// Returns true or false to allow the mover to move through src
|
||||
/atom/proc/CanAllowThrough(atom/movable/mover, border_dir)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
//SHOULD_BE_PURE(TRUE)
|
||||
if(mover.pass_flags & pass_flags_self)
|
||||
return TRUE
|
||||
if(mover.throwing && (pass_flags_self & LETPASSTHROW))
|
||||
return TRUE
|
||||
return !density
|
||||
|
||||
/**
|
||||
* Is this atom currently located on centcom (or riding off into the sunset on a shuttle)
|
||||
*
|
||||
* Specifically, is it on the z level and within the centcom areas.
|
||||
* You can also be in a shuttle during endgame transit.
|
||||
*
|
||||
* Used in gamemode to identify mobs who have escaped and for some other areas of the code
|
||||
* who don't want atoms where they shouldn't be
|
||||
*
|
||||
* Returns TRUE if this atom is on centcom or an escape shuttle, or FALSE if not
|
||||
*/
|
||||
/atom/proc/onCentCom()
|
||||
var/turf/current_turf = get_turf(src)
|
||||
if(!current_turf)
|
||||
return FALSE
|
||||
|
||||
// This doesn't necessarily check that we're at central command,
|
||||
// but it checks for any shuttles which have finished are still in hyperspace
|
||||
// (IE, stuff like the whiteship which fly off into the sunset and "escape")
|
||||
if(is_reserved_level(current_turf.z))
|
||||
return on_escaped_shuttle(ENDGAME_TRANSIT)
|
||||
|
||||
// From here on we only concern ourselves with people actually on the centcom Z
|
||||
if(!is_centcom_level(current_turf.z))
|
||||
return FALSE
|
||||
|
||||
if(istype(current_turf.loc, /area/centcom))
|
||||
return TRUE
|
||||
|
||||
// Finally, check if we're on an escaped shuttle
|
||||
return on_escaped_shuttle()
|
||||
|
||||
/**
|
||||
* Is the atom in any of the syndicate areas
|
||||
*
|
||||
* Either in the syndie base, or any of their shuttles
|
||||
*
|
||||
* Also used in gamemode code for win conditions
|
||||
*
|
||||
* Returns TRUE if this atom is on the syndicate recon base, any of its shuttles, or an escape shuttle, or FALSE if not
|
||||
*/
|
||||
/atom/proc/onSyndieBase()
|
||||
var/turf/current_turf = get_turf(src)
|
||||
if(!current_turf)
|
||||
return FALSE
|
||||
|
||||
// Syndicate base is loaded in a reserved level. If not reserved, we don't care.
|
||||
if(!is_reserved_level(current_turf.z))
|
||||
return FALSE
|
||||
|
||||
var/static/list/syndie_typecache = typecacheof(list(
|
||||
/area/centcom/syndicate_mothership, // syndicate base itself
|
||||
/area/shuttle/assault_pod, // steel rain
|
||||
/area/shuttle/syndicate, // infiltrator
|
||||
))
|
||||
|
||||
if(is_type_in_typecache(current_turf.loc, syndie_typecache))
|
||||
return TRUE
|
||||
|
||||
// Finally, check if we're on an escaped shuttle
|
||||
return on_escaped_shuttle()
|
||||
|
||||
/**
|
||||
* Checks that we're on a shuttle that's escaped
|
||||
*
|
||||
* * check_for_launch_status - What launch status do we check for? Generally the two you want to check for are ENDGAME_LAUNCHED or ENDGAME_TRANSIT
|
||||
*
|
||||
* Returns TRUE if this atom is on a shuttle which is escaping or has escaped, or FALSE otherwise
|
||||
*/
|
||||
/atom/proc/on_escaped_shuttle(check_for_launch_status = ENDGAME_LAUNCHED)
|
||||
var/turf/current_turf = get_turf(src)
|
||||
if(!current_turf)
|
||||
return FALSE
|
||||
|
||||
for(var/obj/docking_port/mobile/mobile_docking_port as anything in SSshuttle.mobile_docking_ports)
|
||||
if(mobile_docking_port.launch_status != check_for_launch_status)
|
||||
continue
|
||||
for(var/area/shuttle/shuttle_area as anything in mobile_docking_port.shuttle_areas)
|
||||
if(current_turf in shuttle_area.get_contained_turfs())
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Is the atom in an away mission
|
||||
*
|
||||
* Must be in the away mission z-level to return TRUE
|
||||
*
|
||||
* Also used in gamemode code for win conditions
|
||||
*/
|
||||
/atom/proc/onAwayMission()
|
||||
var/turf/current_turf = get_turf(src)
|
||||
if(!current_turf)
|
||||
return FALSE
|
||||
|
||||
if(is_away_level(current_turf.z))
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Ensure a list of atoms/reagents exists inside this atom
|
||||
*
|
||||
* Goes throught he list of passed in parts, if they're reagents, adds them to our reagent holder
|
||||
* creating the reagent holder if it exists.
|
||||
*
|
||||
* If the part is a moveable atom and the previous location of the item was a mob/living,
|
||||
* it calls the inventory handler transferItemToLoc for that mob/living and transfers the part
|
||||
* to this atom
|
||||
*
|
||||
* Otherwise it simply forceMoves the atom into this atom
|
||||
*/
|
||||
/atom/proc/CheckParts(list/parts_list, datum/crafting_recipe/current_recipe)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_CHECKPARTS, parts_list, current_recipe)
|
||||
if(!parts_list)
|
||||
return
|
||||
for(var/part in parts_list)
|
||||
if(istype(part, /datum/reagent))
|
||||
if(!reagents)
|
||||
reagents = new()
|
||||
reagents.reagent_list.Add(part)
|
||||
reagents.conditional_update()
|
||||
else if(ismovable(part))
|
||||
var/atom/movable/object = part
|
||||
if(isliving(object.loc))
|
||||
var/mob/living/living = object.loc
|
||||
living.transferItemToLoc(object, src)
|
||||
else
|
||||
object.forceMove(src)
|
||||
SEND_SIGNAL(object, COMSIG_ATOM_USED_IN_CRAFT, src)
|
||||
parts_list.Cut()
|
||||
|
||||
///Take air from the passed in gas mixture datum
|
||||
/atom/proc/assume_air(datum/gas_mixture/giver)
|
||||
return null
|
||||
|
||||
///Remove air from this atom
|
||||
/atom/proc/remove_air(amount)
|
||||
return null
|
||||
|
||||
///Return the current air environment in this atom
|
||||
/atom/proc/return_air()
|
||||
if(loc)
|
||||
return loc.return_air()
|
||||
else
|
||||
return null
|
||||
|
||||
///Return the air if we can analyze it
|
||||
/atom/proc/return_analyzable_air()
|
||||
return null
|
||||
|
||||
///Check if this atoms eye is still alive (probably)
|
||||
/atom/proc/check_eye(mob/user)
|
||||
SIGNAL_HANDLER
|
||||
return
|
||||
|
||||
/atom/proc/Bumped(atom/movable/bumped_atom)
|
||||
set waitfor = FALSE
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_BUMPED, bumped_atom)
|
||||
|
||||
/// Convenience proc to see if a container is open for chemistry handling
|
||||
/atom/proc/is_open_container()
|
||||
return is_refillable() && is_drainable()
|
||||
|
||||
/// Is this atom injectable into other atoms
|
||||
/atom/proc/is_injectable(mob/user, allowmobs = TRUE)
|
||||
return reagents && (reagents.flags & (INJECTABLE | REFILLABLE))
|
||||
|
||||
/// Can we draw from this atom with an injectable atom
|
||||
/atom/proc/is_drawable(mob/user, allowmobs = TRUE)
|
||||
return reagents && (reagents.flags & (DRAWABLE | DRAINABLE))
|
||||
|
||||
/// Can this atoms reagents be refilled
|
||||
/atom/proc/is_refillable()
|
||||
return reagents && (reagents.flags & REFILLABLE)
|
||||
|
||||
/// Is this atom drainable of reagents
|
||||
/atom/proc/is_drainable()
|
||||
return reagents && (reagents.flags & DRAINABLE)
|
||||
|
||||
/** Handles exposing this atom to a list of reagents.
|
||||
*
|
||||
* Sends COMSIG_ATOM_EXPOSE_REAGENTS
|
||||
* Calls expose_atom() for every reagent in the reagent list.
|
||||
*
|
||||
* Arguments:
|
||||
* - [reagents][/list]: The list of reagents the atom is being exposed to.
|
||||
* - [source][/datum/reagents]: The reagent holder the reagents are being sourced from.
|
||||
* - methods: How the atom is being exposed to the reagents. Bitflags.
|
||||
* - volume_modifier: Volume multiplier.
|
||||
* - show_message: Whether to display anything to mobs when they are exposed.
|
||||
*/
|
||||
/atom/proc/expose_reagents(list/reagents, datum/reagents/source, methods=TOUCH, volume_modifier=1, show_message=TRUE)
|
||||
. = SEND_SIGNAL(src, COMSIG_ATOM_EXPOSE_REAGENTS, reagents, source, methods, volume_modifier, show_message)
|
||||
if(. & COMPONENT_NO_EXPOSE_REAGENTS)
|
||||
return
|
||||
|
||||
SEND_SIGNAL(source, COMSIG_REAGENTS_EXPOSE_ATOM, src, reagents, methods, volume_modifier, show_message)
|
||||
for(var/datum/reagent/current_reagent as anything in reagents)
|
||||
. |= current_reagent.expose_atom(src, reagents[current_reagent])
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_AFTER_EXPOSE_REAGENTS, reagents, source, methods, volume_modifier, show_message)
|
||||
|
||||
/// Are you allowed to drop this atom
|
||||
/atom/proc/AllowDrop()
|
||||
return FALSE
|
||||
|
||||
///Is this atom within 1 tile of another atom
|
||||
/atom/proc/HasProximity(atom/movable/proximity_check_mob as mob|obj)
|
||||
return
|
||||
|
||||
/// Sets the wire datum of an atom
|
||||
/atom/proc/set_wires(datum/wires/new_wires)
|
||||
wires = new_wires
|
||||
|
||||
///Return true if we're inside the passed in atom
|
||||
/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
|
||||
|
||||
/**
|
||||
* Checks the atom's loc and calls update_held_items on it if it is a mob.
|
||||
*
|
||||
* This should only be used in situations when you are unable to use /datum/element/update_icon_updates_onmob for whatever reason.
|
||||
* Check code/datums/elements/update_icon_updates_onmob.dm before using this. Adding that to the atom and calling update_appearance will work for most cases.
|
||||
*
|
||||
* Arguments:
|
||||
* * mob/target - The mob to update the icons of. Optional argument, use if the atom's loc is not the mob you want to update.
|
||||
*/
|
||||
/atom/proc/update_inhand_icon(mob/target = loc)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(!istype(target))
|
||||
return
|
||||
|
||||
target.update_held_items()
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_INHAND_ICON, target)
|
||||
|
||||
/**
|
||||
* An atom we are buckled or is contained within us has tried to move
|
||||
*
|
||||
* Default behaviour is to send a warning that the user can't move while buckled as long
|
||||
* as the [buckle_message_cooldown][/atom/var/buckle_message_cooldown] has expired (50 ticks)
|
||||
*/
|
||||
/atom/proc/relaymove(mob/living/user, direction)
|
||||
if(SEND_SIGNAL(src, COMSIG_ATOM_RELAYMOVE, user, direction) & COMSIG_BLOCK_RELAYMOVE)
|
||||
return
|
||||
if(buckle_message_cooldown <= world.time)
|
||||
buckle_message_cooldown = world.time + 25
|
||||
balloon_alert(user, "can't move while buckled!")
|
||||
return
|
||||
|
||||
/**
|
||||
* A special case of relaymove() in which the person relaying the move may be "driving" this atom
|
||||
*
|
||||
* This is a special case for vehicles and ridden animals where the relayed movement may be handled
|
||||
* by the riding component attached to this atom. Returns TRUE as long as there's nothing blocking
|
||||
* the movement, or FALSE if the signal gets a reply that specifically blocks the movement
|
||||
*/
|
||||
/atom/proc/relaydrive(mob/living/user, direction)
|
||||
return !(SEND_SIGNAL(src, COMSIG_RIDDEN_DRIVER_MOVE, user, direction) & COMPONENT_DRIVER_BLOCK_MOVE)
|
||||
|
||||
///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-")
|
||||
|
||||
///Get the mobs dna list
|
||||
/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
|
||||
|
||||
///to add a mob's dna info into an object's blood_dna list.
|
||||
/atom/proc/transfer_mob_blood_dna(mob/living/injected_mob)
|
||||
// Returns 0 if we have that blood already
|
||||
var/new_blood_dna = injected_mob.get_blood_dna_list()
|
||||
if(!new_blood_dna)
|
||||
return FALSE
|
||||
var/old_length = GET_ATOM_BLOOD_DNA_LENGTH(src)
|
||||
add_blood_DNA(new_blood_dna)
|
||||
if(GET_ATOM_BLOOD_DNA_LENGTH(src) == 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/injected_mob)
|
||||
var/list/blood_dna = injected_mob.get_blood_dna_list()
|
||||
if(!blood_dna)
|
||||
return FALSE
|
||||
return add_blood_DNA(blood_dna)
|
||||
|
||||
///Is this atom in space
|
||||
/atom/proc/isinspace()
|
||||
if(isspaceturf(get_turf(src)))
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* If someone's trying to dump items onto our atom, where should they be dumped to?
|
||||
*
|
||||
* Return a loc to place objects, or null to stop dumping.
|
||||
*/
|
||||
/atom/proc/get_dumping_location()
|
||||
return null
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Not recommended to use, listen for the [COMSIG_ATOM_DIR_CHANGE] signal instead (sent by this proc)
|
||||
*/
|
||||
/atom/proc/setDir(newdir)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if (SEND_SIGNAL(src, COMSIG_ATOM_PRE_DIR_CHANGE, dir, newdir) & COMPONENT_ATOM_BLOCK_DIR_CHANGE)
|
||||
newdir = dir
|
||||
return
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_DIR_CHANGE, dir, newdir)
|
||||
dir = newdir
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_POST_DIR_CHANGE, dir, newdir)
|
||||
if(smoothing_flags & SMOOTH_BORDER_OBJECT)
|
||||
QUEUE_SMOOTH_NEIGHBORS(src)
|
||||
|
||||
/**
|
||||
* Wash this atom
|
||||
*
|
||||
* This will clean it off any temporary stuff like blood. Override this in your item to add custom cleaning behavior.
|
||||
* Returns true if any washing was necessary and thus performed
|
||||
* Arguments:
|
||||
* * clean_types: any of the CLEAN_ constants
|
||||
*/
|
||||
/atom/proc/wash(clean_types)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, clean_types) & COMPONENT_CLEANED)
|
||||
return TRUE
|
||||
|
||||
// Basically "if has washable coloration"
|
||||
if(length(atom_colours) >= WASHABLE_COLOUR_PRIORITY && atom_colours[WASHABLE_COLOUR_PRIORITY])
|
||||
remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
///Where atoms should drop if taken from this atom
|
||||
/atom/proc/drop_location()
|
||||
var/atom/location = loc
|
||||
if(!location)
|
||||
return null
|
||||
return location.AllowDrop() ? location : location.drop_location()
|
||||
|
||||
/**
|
||||
* An atom has entered this atom's contents
|
||||
*
|
||||
* Default behaviour is to send the [COMSIG_ATOM_ENTERED]
|
||||
*/
|
||||
/atom/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_ENTERED, arrived, old_loc, old_locs)
|
||||
SEND_SIGNAL(arrived, COMSIG_ATOM_ENTERING, src, old_loc, old_locs)
|
||||
|
||||
/**
|
||||
* An atom is attempting to exit this atom's contents
|
||||
*
|
||||
* Default behaviour is to send the [COMSIG_ATOM_EXIT]
|
||||
*/
|
||||
/atom/Exit(atom/movable/leaving, direction)
|
||||
// Don't call `..()` here, otherwise `Uncross()` gets called.
|
||||
// See the doc comment on `Uncross()` to learn why this is bad.
|
||||
|
||||
if(SEND_SIGNAL(src, COMSIG_ATOM_EXIT, leaving, direction) & COMPONENT_ATOM_BLOCK_EXIT)
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* An atom has exited this atom's contents
|
||||
*
|
||||
* Default behaviour is to send the [COMSIG_ATOM_EXITED]
|
||||
*/
|
||||
/atom/Exited(atom/movable/gone, direction)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_EXITED, gone, direction)
|
||||
|
||||
///Return atom temperature
|
||||
/atom/proc/return_temperature()
|
||||
return
|
||||
|
||||
/atom/proc/process_recipes(mob/living/user, obj/item/processed_object, list/processing_recipes)
|
||||
//Only one recipe? use the first
|
||||
if(processing_recipes.len == 1)
|
||||
StartProcessingAtom(user, processed_object, processing_recipes[1])
|
||||
return
|
||||
//Otherwise, select one with a radial
|
||||
ShowProcessingGui(user, processed_object, processing_recipes)
|
||||
|
||||
///Creates the radial and processes the selected option
|
||||
/atom/proc/ShowProcessingGui(mob/living/user, obj/item/processed_object, list/possible_options)
|
||||
var/list/choices_to_options = list() //Dict of object name | dict of object processing settings
|
||||
var/list/choices = list()
|
||||
|
||||
for(var/list/current_option as anything in possible_options)
|
||||
var/atom/current_option_type = current_option[TOOL_PROCESSING_RESULT]
|
||||
choices_to_options[initial(current_option_type.name)] = current_option
|
||||
var/image/option_image = image(icon = initial(current_option_type.icon), icon_state = initial(current_option_type.icon_state))
|
||||
choices += list("[initial(current_option_type.name)]" = option_image)
|
||||
|
||||
var/pick = show_radial_menu(user, src, choices, radius = 36, require_near = TRUE)
|
||||
if(!pick)
|
||||
return
|
||||
|
||||
StartProcessingAtom(user, processed_object, choices_to_options[pick])
|
||||
|
||||
|
||||
/atom/proc/StartProcessingAtom(mob/living/user, obj/item/process_item, list/chosen_option)
|
||||
var/processing_time = chosen_option[TOOL_PROCESSING_TIME]
|
||||
to_chat(user, span_notice("You start working on [src]."))
|
||||
if(process_item.use_tool(src, user, processing_time, volume=50))
|
||||
var/atom/atom_to_create = chosen_option[TOOL_PROCESSING_RESULT]
|
||||
var/list/atom/created_atoms = list()
|
||||
var/amount_to_create = chosen_option[TOOL_PROCESSING_AMOUNT]
|
||||
for(var/i = 1 to amount_to_create)
|
||||
var/atom/created_atom = new atom_to_create(drop_location())
|
||||
if(custom_materials)
|
||||
created_atom.set_custom_materials(custom_materials, 1 / amount_to_create)
|
||||
created_atom.pixel_x = pixel_x
|
||||
created_atom.pixel_y = pixel_y
|
||||
if(i > 1)
|
||||
created_atom.pixel_x += rand(-8,8)
|
||||
created_atom.pixel_y += rand(-8,8)
|
||||
created_atom.OnCreatedFromProcessing(user, process_item, chosen_option, src)
|
||||
created_atoms.Add(created_atom)
|
||||
to_chat(user, span_notice("You manage to create [amount_to_create] [initial(atom_to_create.gender) == PLURAL ? "[initial(atom_to_create.name)]" : "[initial(atom_to_create.name)][plural_s(initial(atom_to_create.name))]"] from [src]."))
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_PROCESSED, user, process_item, created_atoms)
|
||||
UsedforProcessing(user, process_item, chosen_option)
|
||||
return
|
||||
|
||||
/atom/proc/UsedforProcessing(mob/living/user, obj/item/used_item, list/chosen_option)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/atom/proc/OnCreatedFromProcessing(mob/living/user, obj/item/work_tool, list/chosen_option, atom/original_atom)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_CREATEDBY_PROCESSING, original_atom, chosen_option)
|
||||
if(user.mind)
|
||||
ADD_TRAIT(src, TRAIT_FOOD_CHEF_MADE, REF(user.mind))
|
||||
|
||||
///Connect this atom to a shuttle
|
||||
/atom/proc/connect_to_shuttle(mapload, obj/docking_port/mobile/port, obj/docking_port/stationary/dock)
|
||||
return
|
||||
|
||||
/atom/proc/intercept_zImpact(list/falling_movables, levels = 1)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
. |= SEND_SIGNAL(src, COMSIG_ATOM_INTERCEPT_Z_FALL, falling_movables, levels)
|
||||
|
||||
///Setter for the `density` variable to append behavior related to its changing.
|
||||
/atom/proc/set_density(new_value)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(density == new_value)
|
||||
return
|
||||
. = density
|
||||
density = new_value
|
||||
|
||||
|
||||
///Setter for the `base_pixel_x` variable to append behavior related to its changing.
|
||||
/atom/proc/set_base_pixel_x(new_value)
|
||||
if(base_pixel_x == new_value)
|
||||
return
|
||||
. = base_pixel_x
|
||||
base_pixel_x = new_value
|
||||
|
||||
pixel_x = pixel_x + base_pixel_x - .
|
||||
|
||||
|
||||
///Setter for the `base_pixel_y` variable to append behavior related to its changing.
|
||||
/atom/proc/set_base_pixel_y(new_value)
|
||||
if(base_pixel_y == new_value)
|
||||
return
|
||||
. = base_pixel_y
|
||||
base_pixel_y = new_value
|
||||
|
||||
pixel_y = pixel_y + base_pixel_y - .
|
||||
|
||||
// Not a valid operation, turfs and movables handle block differently
|
||||
/atom/proc/set_explosion_block(explosion_block)
|
||||
return
|
||||
|
||||
/**
|
||||
* Returns true if this atom has gravity for the passed in turf
|
||||
*
|
||||
* Sends signals [COMSIG_ATOM_HAS_GRAVITY] and [COMSIG_TURF_HAS_GRAVITY], both can force gravity with
|
||||
* the forced gravity var.
|
||||
*
|
||||
* micro-optimized to hell because this proc is very hot, being called several times per movement every movement.
|
||||
*
|
||||
* HEY JACKASS, LISTEN
|
||||
* IF YOU ADD SOMETHING TO THIS PROC, MAKE SURE /mob/living ACCOUNTS FOR IT
|
||||
* Living mobs treat gravity in an event based manner. We've decomposed this proc into different checks
|
||||
* for them to use. If you add more to it, make sure you do that, or things will behave strangely
|
||||
*
|
||||
* Gravity situations:
|
||||
* * No gravity if you're not in a turf
|
||||
* * No gravity if this atom is in is a space turf
|
||||
* * Gravity if the area it's in always has gravity
|
||||
* * Gravity if there's a gravity generator on the z level
|
||||
* * Gravity if the Z level has an SSMappingTrait for ZTRAIT_GRAVITY
|
||||
* * otherwise no gravity
|
||||
*/
|
||||
/atom/proc/has_gravity(turf/gravity_turf)
|
||||
if(!isturf(gravity_turf))
|
||||
gravity_turf = get_turf(src)
|
||||
|
||||
if(!gravity_turf)//no gravity in nullspace
|
||||
return FALSE
|
||||
|
||||
var/list/forced_gravity = list()
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_HAS_GRAVITY, gravity_turf, forced_gravity)
|
||||
SEND_SIGNAL(gravity_turf, COMSIG_TURF_HAS_GRAVITY, src, forced_gravity)
|
||||
if(length(forced_gravity))
|
||||
var/positive_grav = max(forced_gravity)
|
||||
var/negative_grav = min(min(forced_gravity), 0) //negative grav needs to be below or equal to 0
|
||||
|
||||
//our gravity is sum of the most massive positive and negative numbers returned by the signal
|
||||
//so that adding two forced_gravity elements with an effect size of 1 each doesnt add to 2 gravity
|
||||
//but negative force gravity effects can cancel out positive ones
|
||||
|
||||
return (positive_grav + negative_grav)
|
||||
|
||||
var/area/turf_area = gravity_turf.loc
|
||||
|
||||
return !gravity_turf.force_no_gravity && (SSmapping.gravity_by_z_level[gravity_turf.z] || turf_area.has_gravity)
|
||||
|
||||
/**
|
||||
* Used to set something as 'open' if it's being used as a supplypod
|
||||
*
|
||||
* Override this if you want an atom to be usable as a supplypod.
|
||||
*/
|
||||
/atom/proc/setOpened()
|
||||
return
|
||||
|
||||
/**
|
||||
* Used to set something as 'closed' if it's being used as a supplypod
|
||||
*
|
||||
* Override this if you want an atom to be usable as a supplypod.
|
||||
*/
|
||||
/atom/proc/setClosed()
|
||||
return
|
||||
|
||||
/**
|
||||
* Used to attempt to charge an object with a payment component.
|
||||
*
|
||||
* Use this if an atom needs to attempt to charge another atom.
|
||||
*/
|
||||
/atom/proc/attempt_charge(atom/sender, atom/target, extra_fees = 0)
|
||||
return SEND_SIGNAL(sender, COMSIG_OBJ_ATTEMPT_CHARGE, target, extra_fees)
|
||||
|
||||
///Passes Stat Browser Panel clicks to the game and calls client click on an atom
|
||||
/atom/Topic(href, list/href_list)
|
||||
. = ..()
|
||||
if(!usr?.client)
|
||||
return
|
||||
var/client/usr_client = usr.client
|
||||
var/list/paramslist = list()
|
||||
|
||||
if(href_list["statpanel_item_click"])
|
||||
switch(href_list["statpanel_item_click"])
|
||||
if("left")
|
||||
paramslist[LEFT_CLICK] = "1"
|
||||
if("right")
|
||||
paramslist[RIGHT_CLICK] = "1"
|
||||
if("middle")
|
||||
paramslist[MIDDLE_CLICK] = "1"
|
||||
else
|
||||
return
|
||||
|
||||
if(href_list["statpanel_item_shiftclick"])
|
||||
paramslist[SHIFT_CLICK] = "1"
|
||||
if(href_list["statpanel_item_ctrlclick"])
|
||||
paramslist[CTRL_CLICK] = "1"
|
||||
if(href_list["statpanel_item_altclick"])
|
||||
paramslist[ALT_CLICK] = "1"
|
||||
|
||||
var/mouseparams = list2params(paramslist)
|
||||
usr_client.Click(src, loc, null, mouseparams)
|
||||
return TRUE
|
||||
|
||||
/atom/MouseEntered(location, control, params)
|
||||
SSmouse_entered.hovers[usr.client] = src
|
||||
|
||||
/// Fired whenever this atom is the most recent to be hovered over in the tick.
|
||||
/// Preferred over MouseEntered if you do not need information such as the position of the mouse.
|
||||
/// Especially because this is deferred over a tick, do not trust that `client` is not null.
|
||||
/atom/proc/on_mouse_enter(client/client)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
var/mob/user = client?.mob
|
||||
if (isnull(user))
|
||||
return
|
||||
///SKYRAT EDIT ADDITION BEGIN
|
||||
// Face directions on combat mode. No procs, no typechecks, just a var for speed
|
||||
if(user.face_mouse)
|
||||
user.face_atom(src)
|
||||
///SKYRAT EDIT ADDITION END
|
||||
|
||||
// Screentips
|
||||
var/datum/hud/active_hud = user.hud_used
|
||||
if(!active_hud)
|
||||
return
|
||||
|
||||
var/screentips_enabled = active_hud.screentips_enabled
|
||||
if(screentips_enabled == SCREENTIP_PREFERENCE_DISABLED || flags_1 & NO_SCREENTIPS_1)
|
||||
active_hud.screentip_text.maptext = ""
|
||||
return
|
||||
|
||||
active_hud.screentip_text.maptext_y = 10 // 10px lines us up with the action buttons top left corner
|
||||
var/lmb_rmb_line = ""
|
||||
var/ctrl_lmb_ctrl_rmb_line = ""
|
||||
var/alt_lmb_alt_rmb_line = ""
|
||||
var/shift_lmb_ctrl_shift_lmb_line = ""
|
||||
var/extra_lines = 0
|
||||
var/extra_context = ""
|
||||
|
||||
if (isliving(user) || isovermind(user) || isaicamera(user))
|
||||
var/obj/item/held_item = user.get_active_held_item()
|
||||
|
||||
if (flags_1 & HAS_CONTEXTUAL_SCREENTIPS_1 || held_item?.item_flags & ITEM_HAS_CONTEXTUAL_SCREENTIPS)
|
||||
var/list/context = list()
|
||||
|
||||
var/contextual_screentip_returns = \
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, context, held_item, user) \
|
||||
| (held_item && SEND_SIGNAL(held_item, COMSIG_ITEM_REQUESTING_CONTEXT_FOR_TARGET, context, src, user))
|
||||
|
||||
if (contextual_screentip_returns & CONTEXTUAL_SCREENTIP_SET)
|
||||
var/screentip_images = active_hud.screentip_images
|
||||
// LMB and RMB on one line...
|
||||
var/lmb_text = build_context(context, SCREENTIP_CONTEXT_LMB, screentip_images)
|
||||
var/rmb_text = build_context(context, SCREENTIP_CONTEXT_RMB, screentip_images)
|
||||
|
||||
if (lmb_text != "")
|
||||
lmb_rmb_line = lmb_text
|
||||
if (rmb_text != "")
|
||||
lmb_rmb_line += " | [rmb_text]"
|
||||
else if (rmb_text != "")
|
||||
lmb_rmb_line = rmb_text
|
||||
|
||||
// Ctrl-LMB, Ctrl-RMB on one line...
|
||||
if (lmb_rmb_line != "")
|
||||
lmb_rmb_line += "<br>"
|
||||
extra_lines++
|
||||
if (SCREENTIP_CONTEXT_CTRL_LMB in context)
|
||||
ctrl_lmb_ctrl_rmb_line += build_context(context, SCREENTIP_CONTEXT_CTRL_LMB, screentip_images)
|
||||
|
||||
if (SCREENTIP_CONTEXT_CTRL_RMB in context)
|
||||
if (ctrl_lmb_ctrl_rmb_line != "")
|
||||
ctrl_lmb_ctrl_rmb_line += " | "
|
||||
ctrl_lmb_ctrl_rmb_line += build_context(context, SCREENTIP_CONTEXT_CTRL_RMB, screentip_images)
|
||||
|
||||
// Alt-LMB, Alt-RMB on one line...
|
||||
if (ctrl_lmb_ctrl_rmb_line != "")
|
||||
ctrl_lmb_ctrl_rmb_line += "<br>"
|
||||
extra_lines++
|
||||
if (SCREENTIP_CONTEXT_ALT_LMB in context)
|
||||
alt_lmb_alt_rmb_line += build_context(context, SCREENTIP_CONTEXT_ALT_LMB, screentip_images)
|
||||
if (SCREENTIP_CONTEXT_ALT_RMB in context)
|
||||
if (alt_lmb_alt_rmb_line != "")
|
||||
alt_lmb_alt_rmb_line += " | "
|
||||
alt_lmb_alt_rmb_line += build_context(context, SCREENTIP_CONTEXT_ALT_RMB, screentip_images)
|
||||
|
||||
// Shift-LMB, Ctrl-Shift-LMB on one line...
|
||||
if (alt_lmb_alt_rmb_line != "")
|
||||
alt_lmb_alt_rmb_line += "<br>"
|
||||
extra_lines++
|
||||
if (SCREENTIP_CONTEXT_SHIFT_LMB in context)
|
||||
shift_lmb_ctrl_shift_lmb_line += build_context(context, SCREENTIP_CONTEXT_SHIFT_LMB, screentip_images)
|
||||
if (SCREENTIP_CONTEXT_CTRL_SHIFT_LMB in context)
|
||||
if (shift_lmb_ctrl_shift_lmb_line != "")
|
||||
shift_lmb_ctrl_shift_lmb_line += " | "
|
||||
shift_lmb_ctrl_shift_lmb_line += build_context(context, SCREENTIP_CONTEXT_CTRL_SHIFT_LMB, screentip_images)
|
||||
|
||||
if (shift_lmb_ctrl_shift_lmb_line != "")
|
||||
extra_lines++
|
||||
|
||||
if(extra_lines)
|
||||
extra_context = "<br><span class='subcontext'>[lmb_rmb_line][ctrl_lmb_ctrl_rmb_line][alt_lmb_alt_rmb_line][shift_lmb_ctrl_shift_lmb_line]</span>"
|
||||
//first extra line pushes atom name line up 11px, subsequent lines push it up 9px, this offsets that and keeps the first line in the same place
|
||||
active_hud.screentip_text.maptext_y = -1 + (extra_lines - 1) * -9
|
||||
|
||||
if (screentips_enabled == SCREENTIP_PREFERENCE_CONTEXT_ONLY && extra_context == "")
|
||||
active_hud.screentip_text.maptext = ""
|
||||
else
|
||||
//We inline a MAPTEXT() here, because there's no good way to statically add to a string like this
|
||||
active_hud.screentip_text.maptext = "<span class='context' style='text-align: center; color: [active_hud.screentip_color]'>[name][extra_context]</span>"
|
||||
|
||||
/**
|
||||
* This proc is used for telling whether something can pass by this atom in a given direction, for use by the pathfinding system.
|
||||
*
|
||||
* Trying to generate one long path across the station will call this proc on every single object on every single tile that we're seeing if we can move through, likely
|
||||
* multiple times per tile since we're likely checking if we can access said tile from multiple directions, so keep these as lightweight as possible.
|
||||
*
|
||||
* For turfs this will only be used if pathing_pass_method is TURF_PATHING_PASS_PROC
|
||||
*
|
||||
* Arguments:
|
||||
* * to_dir - What direction we're trying to move in, relevant for things like directional windows that only block movement in certain directions
|
||||
* * pass_info - Datum that stores info about the thing that's trying to pass us
|
||||
*
|
||||
* IMPORTANT NOTE: /turf/proc/LinkBlockedWithAccess assumes that overrides of CanAStarPass will always return true if density is FALSE
|
||||
* If this is NOT you, ensure you edit your can_astar_pass variable. Check __DEFINES/path.dm
|
||||
**/
|
||||
/atom/proc/CanAStarPass(to_dir, datum/can_pass_info/pass_info)
|
||||
if(pass_info.pass_flags & pass_flags_self)
|
||||
return TRUE
|
||||
. = !density
|
||||
@@ -1,5 +1,8 @@
|
||||
GLOBAL_LIST_EMPTY(active_alternate_appearances)
|
||||
|
||||
/atom
|
||||
var/list/alternate_appearances
|
||||
|
||||
/atom/proc/remove_alt_appearance(key)
|
||||
if(alternate_appearances)
|
||||
for(var/K in alternate_appearances)
|
||||
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* +++++++++++++++++++++++++++++++++++++++++ ABOUT THIS FILE +++++++++++++++++++++++++++++++++++++++++++++
|
||||
* Not everything here necessarily has the name pattern of [x]_act()
|
||||
* This is a file for various atom procs that simply get called when something is happening to that atom.
|
||||
* If you're adding something here, you likely want a signal and SHOULD_CALL_PARENT(TRUE)
|
||||
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
*/
|
||||
|
||||
/**
|
||||
* Respond to fire being used on our atom
|
||||
*
|
||||
* Default behaviour is to send [COMSIG_ATOM_FIRE_ACT] and return
|
||||
*/
|
||||
/atom/proc/fire_act(exposed_temperature, exposed_volume)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_FIRE_ACT, exposed_temperature, exposed_volume)
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Sends [COMSIG_ATOM_EXTINGUISH] signal, which properly removes burning component if it is present.
|
||||
*
|
||||
* Default behaviour is to send [COMSIG_ATOM_ACID_ACT] and return
|
||||
*/
|
||||
/atom/proc/extinguish()
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
return SEND_SIGNAL(src, COMSIG_ATOM_EXTINGUISH)
|
||||
|
||||
/**
|
||||
* React to being hit by an explosion
|
||||
*
|
||||
* Should be called through the [EX_ACT] wrapper macro.
|
||||
* The wrapper takes care of the [COMSIG_ATOM_EX_ACT] signal.
|
||||
* as well as calling [/atom/proc/contents_explosion].
|
||||
*
|
||||
* Returns TRUE by default, and behavior should be implemented on children procs on a per-atom basis. Should only return FALSE if we resist the explosion for any reason.
|
||||
* We assume that the default is TRUE because all atoms should be considered destructible in some manner unless they explicitly opt out (in our current framework).
|
||||
* However, the return value itself doesn't have any external consumers, it's only so children procs can listen to the value from their parent procs (due to the nature of the [EX_ACT] macro).
|
||||
* Thus, the return value only matters on overrides of this proc, and the only thing that truly matters is the code that is executed (applying damage, calling damage procs, etc.)
|
||||
*
|
||||
*/
|
||||
/atom/proc/ex_act(severity, target)
|
||||
set waitfor = FALSE
|
||||
return TRUE
|
||||
|
||||
/// Handle what happens when your contents are exploded by a bomb
|
||||
/atom/proc/contents_explosion(severity, target)
|
||||
return //For handling the effects of explosions on contents that would not normally be effected
|
||||
|
||||
/**
|
||||
* React to a hit by a blob objecd
|
||||
*
|
||||
* default behaviour is to send the [COMSIG_ATOM_BLOB_ACT] signal
|
||||
*/
|
||||
/atom/proc/blob_act(obj/structure/blob/attacking_blob)
|
||||
var/blob_act_result = SEND_SIGNAL(src, COMSIG_ATOM_BLOB_ACT, attacking_blob)
|
||||
if (blob_act_result & COMPONENT_CANCEL_BLOB_ACT)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* React to an EMP of the given severity
|
||||
*
|
||||
* Default behaviour is to send the [COMSIG_ATOM_PRE_EMP_ACT] and [COMSIG_ATOM_EMP_ACT] signal
|
||||
*
|
||||
* If the pre-signal does not return protection, and there are attached wires then we call
|
||||
* [emp_pulse][/datum/wires/proc/emp_pulse] on the wires
|
||||
*
|
||||
* We then return the protection value
|
||||
*/
|
||||
/atom/proc/emp_act(severity)
|
||||
var/protection = SEND_SIGNAL(src, COMSIG_ATOM_PRE_EMP_ACT, severity)
|
||||
if(!(protection & EMP_PROTECT_WIRES) && istype(wires))
|
||||
wires.emp_pulse()
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_EMP_ACT, severity, protection)
|
||||
return protection // Pass the protection value collected here upwards
|
||||
|
||||
/**
|
||||
* React to a hit by a projectile object
|
||||
*
|
||||
* @params
|
||||
* * hitting_projectile - projectile
|
||||
* * def_zone - zone hit
|
||||
* * piercing_hit - is this hit piercing or normal?
|
||||
*/
|
||||
/atom/proc/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit = FALSE)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
|
||||
var/sigreturn = SEND_SIGNAL(src, COMSIG_ATOM_PRE_BULLET_ACT, hitting_projectile, def_zone)
|
||||
if(sigreturn & COMPONENT_BULLET_PIERCED)
|
||||
return BULLET_ACT_FORCE_PIERCE
|
||||
if(sigreturn & COMPONENT_BULLET_BLOCKED)
|
||||
return BULLET_ACT_BLOCK
|
||||
if(sigreturn & COMPONENT_BULLET_ACTED)
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_BULLET_ACT, hitting_projectile, def_zone)
|
||||
if(QDELETED(hitting_projectile)) // Signal deleted it?
|
||||
return BULLET_ACT_BLOCK
|
||||
|
||||
return hitting_projectile.on_hit(
|
||||
target = src,
|
||||
// This armor check only matters for the visuals and messages in on_hit(), it's not actually used to reduce damage since
|
||||
// only living mobs use armor to reduce damage, but on_hit() is going to need the value no matter what is shot.
|
||||
blocked = check_projectile_armor(def_zone, hitting_projectile),
|
||||
pierce_hit = piercing_hit,
|
||||
)
|
||||
|
||||
/**
|
||||
* React to being hit by a thrown object
|
||||
*
|
||||
* Default behaviour is to call [hitby_react][/atom/proc/hitby_react] on ourselves after 2 seconds if we are dense
|
||||
* and under normal gravity.
|
||||
*
|
||||
* Im not sure why this the case, maybe to prevent lots of hitby's if the thrown object is
|
||||
* deleted shortly after hitting something (during explosions or other massive events that
|
||||
* throw lots of items around - singularity being a notable example)
|
||||
*/
|
||||
/atom/proc/hitby(atom/movable/hitting_atom, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_HITBY, hitting_atom, skipcatch, hitpush, blocked, throwingdatum)
|
||||
if(density && !has_gravity(hitting_atom)) //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_REF(hitby_react), hitting_atom), 2)
|
||||
|
||||
/**
|
||||
* We have have actually hit the passed in atom
|
||||
*
|
||||
* Default behaviour is to move back from the item that hit us
|
||||
*/
|
||||
/atom/proc/hitby_react(atom/movable/harmed_atom)
|
||||
if(harmed_atom && isturf(harmed_atom.loc))
|
||||
step(harmed_atom, REVERSE_DIR(harmed_atom.dir))
|
||||
|
||||
///Handle the atom being slipped over
|
||||
/atom/proc/handle_slip(mob/living/carbon/slipped_carbon, knockdown_amount, obj/slipping_object, lube, paralyze, force_drop)
|
||||
return
|
||||
|
||||
///Used for making a sound when a mob involuntarily falls into the ground.
|
||||
/atom/proc/handle_fall(mob/faller)
|
||||
return
|
||||
|
||||
///Respond to the singularity eating this atom
|
||||
/atom/proc/singularity_act()
|
||||
return
|
||||
|
||||
/**
|
||||
* Respond to the singularity pulling on us
|
||||
*
|
||||
* Default behaviour is to send [COMSIG_ATOM_SING_PULL] and return
|
||||
*/
|
||||
/atom/proc/singularity_pull(obj/singularity/singularity, current_size)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_SING_PULL, singularity, current_size)
|
||||
|
||||
/**
|
||||
* Respond to acid being used on our atom
|
||||
*
|
||||
* Default behaviour is to send [COMSIG_ATOM_ACID_ACT] and return
|
||||
*/
|
||||
/atom/proc/acid_act(acidpwr, acid_volume)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_ACID_ACT, acidpwr, acid_volume)
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Respond to an emag being used on our atom
|
||||
*
|
||||
* Args:
|
||||
* * mob/user: The mob that used the emag. Nullable.
|
||||
* * obj/item/card/emag/emag_card: The emag that was used. Nullable.
|
||||
*
|
||||
* Returns:
|
||||
* TRUE if the emag had any effect, falsey otherwise.
|
||||
*/
|
||||
/atom/proc/emag_act(mob/user, obj/item/card/emag/emag_card)
|
||||
return (SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT, user, emag_card))
|
||||
|
||||
/**
|
||||
* Respond to narsie eating our atom
|
||||
*
|
||||
* Default behaviour is to send [COMSIG_ATOM_NARSIE_ACT] and return
|
||||
*/
|
||||
/atom/proc/narsie_act()
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_NARSIE_ACT)
|
||||
|
||||
/**
|
||||
* Respond to an electric bolt action on our item
|
||||
*
|
||||
* Default behaviour is to return, we define here to allow for cleaner code later on
|
||||
*/
|
||||
/atom/proc/zap_act(power, zap_flags)
|
||||
return
|
||||
|
||||
/**
|
||||
* Called when the atom log's in or out
|
||||
*
|
||||
* Default behaviour is to call on_log on the location this atom is in
|
||||
*/
|
||||
/atom/proc/on_log(login)
|
||||
if(loc)
|
||||
loc.on_log(login)
|
||||
|
||||
/**
|
||||
* Causes effects when the atom gets hit by a rust effect from heretics
|
||||
*
|
||||
* Override this if you want custom behaviour in whatever gets hit by the rust
|
||||
*/
|
||||
/atom/proc/rust_heretic_act()
|
||||
return
|
||||
|
||||
///Called when something resists while this atom is its loc
|
||||
/atom/proc/container_resist_act(mob/living/user)
|
||||
return
|
||||
|
||||
/**
|
||||
* Respond to an RCD acting on our item
|
||||
*
|
||||
* Default behaviour is to send [COMSIG_ATOM_RCD_ACT] and return FALSE
|
||||
*/
|
||||
/atom/proc/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, list/rcd_data)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_RCD_ACT, user, the_rcd, rcd_data["[RCD_DESIGN_MODE]"])
|
||||
return FALSE
|
||||
|
||||
///Return the values you get when an RCD eats you?
|
||||
/atom/proc/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
|
||||
return FALSE
|
||||
|
||||
///This atom has been hit by a hulkified mob in hulk mode (user)
|
||||
/atom/proc/attack_hulk(mob/living/carbon/human/user)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_HULK_ATTACK, user)
|
||||
@@ -0,0 +1,112 @@
|
||||
/atom
|
||||
///overlays managed by [update_overlays][/atom/proc/update_overlays] to prevent removing overlays that weren't added by the same proc. Single items are stored on their own, not in a list.
|
||||
var/list/managed_overlays
|
||||
|
||||
/**
|
||||
* Updates the appearence of the icon
|
||||
*
|
||||
* Mostly delegates to update_name, update_desc, and update_icon
|
||||
*
|
||||
* Arguments:
|
||||
* - updates: A set of bitflags dictating what should be updated. Defaults to [ALL]
|
||||
*/
|
||||
/atom/proc/update_appearance(updates=ALL)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
|
||||
. = NONE
|
||||
updates &= ~SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_APPEARANCE, updates)
|
||||
if(updates & UPDATE_NAME)
|
||||
. |= update_name(updates)
|
||||
if(updates & UPDATE_DESC)
|
||||
. |= update_desc(updates)
|
||||
if(updates & UPDATE_ICON)
|
||||
. |= update_icon(updates)
|
||||
|
||||
/// Updates the name of the atom
|
||||
/atom/proc/update_name(updates=ALL)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
return SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_NAME, updates)
|
||||
|
||||
/// Updates the description of the atom
|
||||
/atom/proc/update_desc(updates=ALL)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
return SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_DESC, updates)
|
||||
|
||||
/// Updates the icon of the atom
|
||||
/atom/proc/update_icon(updates=ALL)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
|
||||
. = NONE
|
||||
updates &= ~SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_ICON, updates)
|
||||
if(updates & UPDATE_ICON_STATE)
|
||||
update_icon_state()
|
||||
. |= UPDATE_ICON_STATE
|
||||
|
||||
if(updates & UPDATE_OVERLAYS)
|
||||
if(LAZYLEN(managed_vis_overlays))
|
||||
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
|
||||
|
||||
var/list/new_overlays = update_overlays(updates)
|
||||
var/nulls = 0
|
||||
for(var/i in 1 to length(new_overlays))
|
||||
var/atom/maybe_not_an_atom = new_overlays[i]
|
||||
if(isnull(maybe_not_an_atom))
|
||||
nulls++
|
||||
continue
|
||||
if(istext(maybe_not_an_atom) || isicon(maybe_not_an_atom))
|
||||
continue
|
||||
new_overlays[i] = maybe_not_an_atom.appearance
|
||||
if(nulls)
|
||||
for(var/i in 1 to nulls)
|
||||
new_overlays -= null
|
||||
|
||||
var/identical = FALSE
|
||||
var/new_length = length(new_overlays)
|
||||
if(!managed_overlays && !new_length)
|
||||
identical = TRUE
|
||||
else if(!islist(managed_overlays))
|
||||
if(new_length == 1 && managed_overlays == new_overlays[1])
|
||||
identical = TRUE
|
||||
else if(length(managed_overlays) == new_length)
|
||||
identical = TRUE
|
||||
for(var/i in 1 to length(managed_overlays))
|
||||
if(managed_overlays[i] != new_overlays[i])
|
||||
identical = FALSE
|
||||
break
|
||||
|
||||
if(!identical)
|
||||
var/full_control = FALSE
|
||||
if(managed_overlays)
|
||||
full_control = length(overlays) == (islist(managed_overlays) ? length(managed_overlays) : 1)
|
||||
if(full_control)
|
||||
overlays = null
|
||||
else
|
||||
cut_overlay(managed_overlays)
|
||||
|
||||
switch(length(new_overlays))
|
||||
if(0)
|
||||
if(full_control)
|
||||
POST_OVERLAY_CHANGE(src)
|
||||
managed_overlays = null
|
||||
if(1)
|
||||
add_overlay(new_overlays)
|
||||
managed_overlays = new_overlays[1]
|
||||
else
|
||||
add_overlay(new_overlays)
|
||||
managed_overlays = new_overlays
|
||||
|
||||
. |= UPDATE_OVERLAYS
|
||||
|
||||
. |= SEND_SIGNAL(src, COMSIG_ATOM_UPDATED_ICON, updates, .)
|
||||
|
||||
/// Updates the icon state of the atom
|
||||
/atom/proc/update_icon_state()
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
return SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_ICON_STATE)
|
||||
|
||||
/// Updates the overlays of the atom
|
||||
/atom/proc/update_overlays()
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
. = list()
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_OVERLAYS, .)
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
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"
|
||||
*/
|
||||
|
||||
/atom
|
||||
/**
|
||||
* used to store the different colors on an atom
|
||||
*
|
||||
* its inherent color, the colored paint applied on it, special color effect etc...
|
||||
*/
|
||||
var/list/atom_colours
|
||||
|
||||
///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)
|
||||
return
|
||||
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()
|
||||
|
||||
/**
|
||||
* Checks if this atom has the passed color
|
||||
* Can optionally be supplied with a range of priorities, IE only checking "washable" or above
|
||||
*/
|
||||
/atom/proc/is_atom_colour(looking_for_color, min_priority_index = 1, max_priority_index = COLOUR_PRIORITY_AMOUNT)
|
||||
// make sure uppertext hex strings don't mess with lowertext hex strings
|
||||
looking_for_color = lowertext(looking_for_color)
|
||||
|
||||
if(!LAZYLEN(atom_colours))
|
||||
// no atom colors list has been set up, just check the color var
|
||||
return lowertext(color) == looking_for_color
|
||||
|
||||
for(var/i in min_priority_index to max_priority_index)
|
||||
if(lowertext(atom_colours[i]) == looking_for_color)
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
///Resets the atom's color to null, and then sets it to the highest priority colour available
|
||||
/atom/proc/update_atom_colour()
|
||||
color = null
|
||||
if(!atom_colours)
|
||||
return
|
||||
for(var/checked_color in atom_colours)
|
||||
if(islist(checked_color))
|
||||
var/list/color_list = checked_color
|
||||
if(color_list.len)
|
||||
color = color_list
|
||||
return
|
||||
else if(checked_color)
|
||||
color = checked_color
|
||||
return
|
||||
@@ -1,3 +1,17 @@
|
||||
/atom
|
||||
///any atom that uses integrity and can be damaged must set this to true, otherwise the integrity procs will throw an error
|
||||
var/uses_integrity = FALSE
|
||||
|
||||
VAR_PROTECTED/datum/armor/armor_type = /datum/armor/none
|
||||
VAR_PRIVATE/datum/armor/armor
|
||||
|
||||
VAR_PRIVATE/atom_integrity //defaults to max_integrity
|
||||
var/max_integrity = 500
|
||||
var/integrity_failure = 0 //0 if we have no special broken behavior, otherwise is a percentage of at what point the atom breaks. 0.5 being 50%
|
||||
///Damage under this value will be completely ignored
|
||||
var/damage_deflection = 0
|
||||
|
||||
var/resistance_flags = NONE // INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ON_FIRE | UNACIDABLE | ACID_PROOF
|
||||
|
||||
/// The essential proc to call when an atom must receive damage of any kind.
|
||||
/atom/proc/take_damage(damage_amount, damage_type = BRUTE, damage_flag = "", sound_effect = TRUE, attack_dir, armour_penetration = 0)
|
||||
@@ -0,0 +1,110 @@
|
||||
/atom
|
||||
///If non-null, overrides a/an/some in all cases
|
||||
var/article
|
||||
|
||||
/**
|
||||
* Called when a mob examines (shift click or verb) this atom
|
||||
*
|
||||
* Default behaviour is to get the name and icon of the object and it's reagents where
|
||||
* the [TRANSPARENT] flag is set on the reagents holder
|
||||
*
|
||||
* Produces a signal [COMSIG_ATOM_EXAMINE]
|
||||
*/
|
||||
/atom/proc/examine(mob/user)
|
||||
var/examine_string = get_examine_string(user, thats = TRUE)
|
||||
if(examine_string)
|
||||
. = list("[examine_string].", EXAMINE_SECTION_BREAK) // SKYRAT EDIT CHANGE
|
||||
else
|
||||
. = list()
|
||||
|
||||
. += get_name_chaser(user)
|
||||
if(desc)
|
||||
. += desc
|
||||
|
||||
if(custom_materials)
|
||||
// SKYRAT EDIT ADDITION BEGIN - HR sections
|
||||
if(length(custom_materials) > 1)
|
||||
. += EXAMINE_SECTION_BREAK //SKYRAT EDIT ADDITION
|
||||
//SKYRAT EDIT ADDITION END
|
||||
var/list/materials_list = list()
|
||||
for(var/custom_material in custom_materials)
|
||||
var/datum/material/current_material = GET_MATERIAL_REF(custom_material)
|
||||
materials_list += "[current_material.name]"
|
||||
. += "<u>It is made out of [english_list(materials_list)]</u>."
|
||||
// SKYRAT EDIT ADDITION BEGIN - HR sections
|
||||
if(length(custom_materials) > 1)
|
||||
. += EXAMINE_SECTION_BREAK //SKYRAT EDIT ADDITION
|
||||
//SKYRAT EDIT ADDITION END
|
||||
|
||||
if(reagents)
|
||||
var/user_sees_reagents = user.can_see_reagents()
|
||||
var/reagent_sigreturn = SEND_SIGNAL(src, COMSIG_ATOM_REAGENT_EXAMINE, user, ., user_sees_reagents)
|
||||
if(!(reagent_sigreturn & STOP_GENERIC_REAGENT_EXAMINE))
|
||||
if(reagents.flags & TRANSPARENT)
|
||||
if(reagents.total_volume)
|
||||
. += "It contains <b>[reagents.total_volume]</b> units of various reagents[user_sees_reagents ? ":" : "."]"
|
||||
if(user_sees_reagents) //Show each individual reagent for detailed examination
|
||||
for(var/datum/reagent/current_reagent as anything in reagents.reagent_list)
|
||||
. += "• [round(current_reagent.volume, CHEMICAL_VOLUME_ROUNDING)] units of [current_reagent.name]"
|
||||
if(reagents.is_reacting)
|
||||
. += span_warning("It is currently reacting!")
|
||||
. += span_notice("The solution's pH is [round(reagents.ph, 0.01)] and has a temperature of [reagents.chem_temp]K.")
|
||||
|
||||
else
|
||||
. += "It contains:<br>Nothing."
|
||||
else if(reagents.flags & AMOUNT_VISIBLE)
|
||||
if(reagents.total_volume)
|
||||
. += span_notice("It has [reagents.total_volume] unit\s left.")
|
||||
else
|
||||
. += span_danger("It's empty.")
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_EXAMINE, user, .)
|
||||
|
||||
/**
|
||||
* Called when a mob examines (shift click or verb) this atom twice (or more) within EXAMINE_MORE_WINDOW (default 1 second)
|
||||
*
|
||||
* This is where you can put extra information on something that may be superfluous or not important in critical gameplay
|
||||
* moments, while allowing people to manually double-examine to take a closer look
|
||||
*
|
||||
* Produces a signal [COMSIG_ATOM_EXAMINE_MORE]
|
||||
*/
|
||||
/atom/proc/examine_more(mob/user)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
RETURN_TYPE(/list)
|
||||
|
||||
. = list()
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_EXAMINE_MORE, user, .)
|
||||
SEND_SIGNAL(user, COMSIG_MOB_EXAMINING_MORE, src, .)
|
||||
|
||||
/**
|
||||
* Get the name of this object for examine
|
||||
*
|
||||
* You can override what is returned from this proc by registering to listen for the
|
||||
* [COMSIG_ATOM_GET_EXAMINE_NAME] signal
|
||||
*/
|
||||
/atom/proc/get_examine_name(mob/user)
|
||||
. = "\a <b>[src]</b>"
|
||||
var/list/override = list(gender == PLURAL ? "some" : "a", " ", "[name]")
|
||||
if(article)
|
||||
. = "[article] <b>[src]</b>"
|
||||
override[EXAMINE_POSITION_ARTICLE] = article
|
||||
if(SEND_SIGNAL(src, COMSIG_ATOM_GET_EXAMINE_NAME, user, override) & COMPONENT_EXNAME_CHANGED)
|
||||
. = 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)]"
|
||||
|
||||
/**
|
||||
* Returns an extended list of examine strings for any contained ID cards.
|
||||
*
|
||||
* Arguments:
|
||||
* * user - The user who is doing the examining.
|
||||
*/
|
||||
/atom/proc/get_id_examine_strings(mob/user)
|
||||
. = list()
|
||||
return
|
||||
|
||||
///Used to insert text after the name but before the description in examine()
|
||||
/atom/proc/get_name_chaser(mob/user, list/name_chaser = list())
|
||||
return name_chaser
|
||||
@@ -0,0 +1,30 @@
|
||||
/atom
|
||||
///The config type to use for greyscaled sprites. Both this and greyscale_colors must be assigned to work.
|
||||
var/greyscale_config
|
||||
///A string of hex format colors to be used by greyscale sprites, ex: "#0054aa#badcff"
|
||||
var/greyscale_colors
|
||||
|
||||
/// Handles updates to greyscale value updates.
|
||||
/// The colors argument can be either a list or the full color string.
|
||||
/// Child procs should call parent last so the update happens after all changes.
|
||||
/atom/proc/set_greyscale(list/colors, new_config)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(istype(colors))
|
||||
colors = colors.Join("")
|
||||
if(!isnull(colors) && greyscale_colors != colors) // If you want to disable greyscale stuff then give a blank string
|
||||
greyscale_colors = colors
|
||||
|
||||
if(!isnull(new_config) && greyscale_config != new_config)
|
||||
greyscale_config = new_config
|
||||
|
||||
update_greyscale()
|
||||
|
||||
/// Checks if this atom uses the GAGS system and if so updates the icon
|
||||
/atom/proc/update_greyscale()
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(greyscale_colors && greyscale_config)
|
||||
icon = SSgreyscale.GetColoredIconByType(greyscale_config, greyscale_colors)
|
||||
if(!smoothing_flags) // This is a bitfield but we're just checking that some sort of smoothing is happening
|
||||
return
|
||||
update_atom_colour()
|
||||
QUEUE_SMOOTH(src)
|
||||
@@ -0,0 +1,72 @@
|
||||
// Index defines
|
||||
#define INVISIBILITY_VALUE 1
|
||||
#define INVISIBILITY_PRIORITY 2
|
||||
|
||||
/atom
|
||||
VAR_PRIVATE/list/invisibility_sources
|
||||
VAR_PRIVATE/current_invisibility_priority = -INFINITY
|
||||
|
||||
/atom/proc/RecalculateInvisibility()
|
||||
PRIVATE_PROC(TRUE)
|
||||
|
||||
if(!invisibility_sources)
|
||||
current_invisibility_priority = -INFINITY
|
||||
invisibility = initial(invisibility)
|
||||
return
|
||||
|
||||
var/highest_priority
|
||||
var/list/highest_priority_invisibility_data
|
||||
for(var/entry in invisibility_sources)
|
||||
var/list/priority_data
|
||||
if(islist(entry))
|
||||
priority_data = entry
|
||||
else
|
||||
priority_data = invisibility_sources[entry]
|
||||
|
||||
var/priority = priority_data[INVISIBILITY_PRIORITY]
|
||||
if(highest_priority > priority) // In the case of equal priorities, we use the last thing in the list so that more recent changes apply first
|
||||
continue
|
||||
|
||||
highest_priority = priority
|
||||
highest_priority_invisibility_data = priority_data
|
||||
|
||||
current_invisibility_priority = highest_priority
|
||||
invisibility = highest_priority_invisibility_data[INVISIBILITY_VALUE]
|
||||
|
||||
/**
|
||||
* Sets invisibility according to priority.
|
||||
* If you want to be able to undo the value you set back to what it would be otherwise,
|
||||
* you should provide an id here and remove it using RemoveInvisibility(id)
|
||||
*/
|
||||
/atom/proc/SetInvisibility(desired_value, id, priority=0)
|
||||
if(!invisibility_sources)
|
||||
invisibility_sources = list()
|
||||
|
||||
if(id)
|
||||
invisibility_sources[id] = list(desired_value, priority)
|
||||
else
|
||||
invisibility_sources += list(list(desired_value, priority))
|
||||
|
||||
if(current_invisibility_priority > priority)
|
||||
return
|
||||
|
||||
RecalculateInvisibility()
|
||||
|
||||
/// Removes the specified invisibility source from the tracker
|
||||
/atom/proc/RemoveInvisibility(id)
|
||||
if(!invisibility_sources)
|
||||
return
|
||||
|
||||
var/list/priority_data = invisibility_sources[id]
|
||||
invisibility_sources -= id
|
||||
|
||||
if(length(invisibility_sources) == 0)
|
||||
invisibility_sources = null
|
||||
|
||||
if(current_invisibility_priority > priority_data[INVISIBILITY_PRIORITY])
|
||||
return
|
||||
|
||||
RecalculateInvisibility()
|
||||
|
||||
#undef INVISIBILITY_VALUE
|
||||
#undef INVISIBILITY_PRIORITY
|
||||
@@ -0,0 +1,128 @@
|
||||
/atom
|
||||
///The custom materials this atom is made of, used by a lot of things like furniture, walls, and floors (if I finish the functionality, that is.)
|
||||
///The list referenced by this var can be shared by multiple objects and should not be directly modified. Instead, use [set_custom_materials][/atom/proc/set_custom_materials].
|
||||
var/list/datum/material/custom_materials
|
||||
///Bitfield for how the atom handles materials.
|
||||
var/material_flags = NONE
|
||||
///Modifier that raises/lowers the effect of the amount of a material, prevents small and easy to get items from being death machines.
|
||||
var/material_modifier = 1
|
||||
|
||||
/// Sets the custom materials for an item.
|
||||
/atom/proc/set_custom_materials(list/materials, multiplier = 1)
|
||||
if(custom_materials && material_flags & MATERIAL_EFFECTS) //Only runs if custom materials existed at first and affected src.
|
||||
for(var/current_material in custom_materials)
|
||||
var/datum/material/custom_material = GET_MATERIAL_REF(current_material)
|
||||
custom_material.on_removed(src, custom_materials[current_material] * material_modifier, material_flags) //Remove the current materials
|
||||
|
||||
if(!length(materials))
|
||||
custom_materials = null
|
||||
return
|
||||
|
||||
if(material_flags & MATERIAL_EFFECTS)
|
||||
for(var/current_material in materials)
|
||||
var/datum/material/custom_material = GET_MATERIAL_REF(current_material)
|
||||
custom_material.on_applied(src, materials[current_material] * multiplier * material_modifier, material_flags)
|
||||
|
||||
custom_materials = SSmaterials.FindOrCreateMaterialCombo(materials, multiplier)
|
||||
|
||||
/**
|
||||
* Returns the material composition of the atom.
|
||||
*
|
||||
* Used when recycling items, specifically to turn alloys back into their component mats.
|
||||
*
|
||||
* Exists because I'd need to add a way to un-alloy alloys or otherwise deal
|
||||
* with people converting the entire stations material supply into alloys.
|
||||
*
|
||||
* Arguments:
|
||||
* - flags: A set of flags determining how exactly the materials are broken down.
|
||||
*/
|
||||
/atom/proc/get_material_composition(breakdown_flags=NONE)
|
||||
. = list()
|
||||
if(!(breakdown_flags & BREAKDOWN_INCLUDE_ALCHEMY) && HAS_TRAIT(src, TRAIT_MAT_TRANSMUTED))
|
||||
return
|
||||
|
||||
var/list/cached_materials = custom_materials
|
||||
for(var/mat in cached_materials)
|
||||
var/datum/material/material = GET_MATERIAL_REF(mat)
|
||||
var/list/material_comp = material.return_composition(cached_materials[mat], breakdown_flags)
|
||||
for(var/comp_mat in material_comp)
|
||||
.[comp_mat] += material_comp[comp_mat]
|
||||
|
||||
/**
|
||||
* Fetches a list of all of the materials this object has of the desired type. Returns null if there is no valid materials of the type
|
||||
*
|
||||
* Arguments:
|
||||
* - [required_material][/datum/material]: The type of material we are checking for
|
||||
* - mat_amount: The minimum required amount of material
|
||||
*/
|
||||
/atom/proc/has_material_type(datum/material/required_material, mat_amount = 0)
|
||||
var/list/cached_materials = custom_materials
|
||||
if(!length(cached_materials))
|
||||
return null
|
||||
|
||||
var/materials_of_type
|
||||
for(var/current_material in cached_materials)
|
||||
if(cached_materials[current_material] < mat_amount)
|
||||
continue
|
||||
var/datum/material/material = GET_MATERIAL_REF(current_material)
|
||||
if(!istype(material, required_material))
|
||||
continue
|
||||
LAZYSET(materials_of_type, material, cached_materials[current_material])
|
||||
|
||||
return materials_of_type
|
||||
|
||||
/**
|
||||
* Fetches a list of all of the materials this object has with the desired material category.
|
||||
*
|
||||
* Arguments:
|
||||
* - category: The category to check for
|
||||
* - any_flags: Any bitflags that must be present for the category
|
||||
* - all_flags: All bitflags that must be present for the category
|
||||
* - no_flags: Any bitflags that must not be present for the category
|
||||
* - mat_amount: The minimum amount of materials that must be present
|
||||
*/
|
||||
/atom/proc/has_material_category(category, any_flags=0, all_flags=0, no_flags=0, mat_amount=0)
|
||||
var/list/cached_materials = custom_materials
|
||||
if(!length(cached_materials))
|
||||
return null
|
||||
|
||||
var/materials_of_category
|
||||
for(var/current_material in cached_materials)
|
||||
if(cached_materials[current_material] < mat_amount)
|
||||
continue
|
||||
var/datum/material/material = GET_MATERIAL_REF(current_material)
|
||||
var/category_flags = material?.categories[category]
|
||||
if(isnull(category_flags))
|
||||
continue
|
||||
if(any_flags && !(category_flags & any_flags))
|
||||
continue
|
||||
if(all_flags && (all_flags != (category_flags & all_flags)))
|
||||
continue
|
||||
if(no_flags && (category_flags & no_flags))
|
||||
continue
|
||||
LAZYSET(materials_of_category, material, cached_materials[current_material])
|
||||
return materials_of_category
|
||||
|
||||
/**
|
||||
* Gets the most common material in the object.
|
||||
*/
|
||||
/atom/proc/get_master_material()
|
||||
var/list/cached_materials = custom_materials
|
||||
if(!length(cached_materials))
|
||||
return null
|
||||
|
||||
var/most_common_material = null
|
||||
var/max_amount = 0
|
||||
for(var/material in cached_materials)
|
||||
if(cached_materials[material] > max_amount)
|
||||
most_common_material = material
|
||||
max_amount = cached_materials[material]
|
||||
|
||||
if(most_common_material)
|
||||
return GET_MATERIAL_REF(most_common_material)
|
||||
|
||||
/**
|
||||
* Gets the total amount of materials in this atom.
|
||||
*/
|
||||
/atom/proc/get_custom_material_amount()
|
||||
return isnull(custom_materials) ? 0 : counterlist_sum(custom_materials)
|
||||
@@ -0,0 +1,14 @@
|
||||
/atom
|
||||
///Holds merger groups currently active on the atom. Do not access directly, use GetMergeGroup() instead.
|
||||
var/list/datum/merger/mergers
|
||||
|
||||
/// Gets a merger datum representing the connected blob of objects in the allowed_types argument
|
||||
/atom/proc/GetMergeGroup(id, list/allowed_types)
|
||||
RETURN_TYPE(/datum/merger)
|
||||
var/datum/merger/candidate
|
||||
if(mergers)
|
||||
candidate = mergers[id]
|
||||
if(!candidate)
|
||||
new /datum/merger(id, allowed_types, src)
|
||||
candidate = mergers[id]
|
||||
return candidate
|
||||
@@ -0,0 +1,33 @@
|
||||
/atom
|
||||
///Reference to atom being orbited
|
||||
var/atom/orbit_target
|
||||
///The orbiter component, if there's anything orbiting this atom
|
||||
var/datum/component/orbiter/orbiters
|
||||
|
||||
/**
|
||||
* Recursive getter method to return a list of all ghosts orbitting this atom
|
||||
*
|
||||
* This will work fine without manually passing arguments.
|
||||
* * processed - The list of atoms we've already convered
|
||||
* * source - Is this the atom for who we're counting up all the orbiters?
|
||||
* * ignored_stealthed_admins - If TRUE, don't count admins who are stealthmoded and orbiting this
|
||||
*/
|
||||
/atom/proc/get_all_orbiters(list/processed, source = TRUE, ignore_stealthed_admins = TRUE)
|
||||
var/list/output = list()
|
||||
if(!processed)
|
||||
processed = list()
|
||||
else if(src in processed)
|
||||
return output
|
||||
|
||||
if(!source)
|
||||
output += src
|
||||
|
||||
processed += src
|
||||
for(var/atom/atom_orbiter as anything in orbiters?.orbiter_list)
|
||||
output += atom_orbiter.get_all_orbiters(processed, source = FALSE)
|
||||
return output
|
||||
|
||||
/mob/get_all_orbiters(list/processed, source = TRUE, ignore_stealthed_admins = TRUE)
|
||||
if(!source && ignore_stealthed_admins && client?.holder?.fakekey)
|
||||
return list()
|
||||
return ..()
|
||||
@@ -0,0 +1,41 @@
|
||||
/atom
|
||||
/// the datum handler for our contents - see create_storage() for creation method
|
||||
var/datum/storage/atom_storage
|
||||
|
||||
/// A quick and easy way to create a storage datum for an atom
|
||||
/atom/proc/create_storage(
|
||||
max_slots,
|
||||
max_specific_storage,
|
||||
max_total_storage,
|
||||
numerical_stacking = FALSE,
|
||||
allow_quick_gather = FALSE,
|
||||
allow_quick_empty = FALSE,
|
||||
collection_mode = COLLECT_ONE,
|
||||
attack_hand_interact = TRUE,
|
||||
list/canhold,
|
||||
list/canthold,
|
||||
storage_type = /datum/storage,
|
||||
)
|
||||
|
||||
if(atom_storage)
|
||||
QDEL_NULL(atom_storage)
|
||||
|
||||
atom_storage = new storage_type(src, max_slots, max_specific_storage, max_total_storage, numerical_stacking, allow_quick_gather, collection_mode, attack_hand_interact)
|
||||
|
||||
if(canhold || canthold)
|
||||
atom_storage.set_holdable(canhold, canthold)
|
||||
|
||||
return atom_storage
|
||||
|
||||
/// A quick and easy way to /clone/ a storage datum for an atom (does not copy over contents, only the datum details)
|
||||
/atom/proc/clone_storage(datum/storage/cloning)
|
||||
if(atom_storage)
|
||||
QDEL_NULL(atom_storage)
|
||||
|
||||
atom_storage = new cloning.type(src, cloning.max_slots, cloning.max_specific_storage, cloning.max_total_storage, cloning.numerical_stacking, cloning.allow_quick_gather, cloning.collection_mode, cloning.attack_hand_interact)
|
||||
|
||||
if(cloning.can_hold || cloning.cant_hold)
|
||||
if(!atom_storage.can_hold && !atom_storage.cant_hold) //In the event that the can/can't hold lists are already in place (such as from storage objects added on initialize).
|
||||
atom_storage.set_holdable(cloning.can_hold, cloning.cant_hold)
|
||||
|
||||
return atom_storage
|
||||
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
*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.
|
||||
*
|
||||
* Must return parent proc ..() in the end if overridden
|
||||
*/
|
||||
/atom/proc/tool_act(mob/living/user, obj/item/tool, tool_type, is_right_clicking)
|
||||
var/act_result
|
||||
var/signal_result
|
||||
|
||||
var/is_left_clicking = !is_right_clicking
|
||||
|
||||
if(is_left_clicking) // Left click first for sensibility
|
||||
var/list/processing_recipes = list() //List of recipes that can be mutated by sending the signal
|
||||
signal_result = SEND_SIGNAL(src, COMSIG_ATOM_TOOL_ACT(tool_type), user, tool, processing_recipes)
|
||||
if(signal_result & COMPONENT_BLOCK_TOOL_ATTACK) // The COMSIG_ATOM_TOOL_ACT signal is blocking the act
|
||||
return TOOL_ACT_SIGNAL_BLOCKING
|
||||
if(processing_recipes.len)
|
||||
process_recipes(user, tool, processing_recipes)
|
||||
if(QDELETED(tool))
|
||||
return TRUE
|
||||
else
|
||||
signal_result = SEND_SIGNAL(src, COMSIG_ATOM_SECONDARY_TOOL_ACT(tool_type), user, tool)
|
||||
if(signal_result & COMPONENT_BLOCK_TOOL_ATTACK) // The COMSIG_ATOM_TOOL_ACT signal is blocking the act
|
||||
return TOOL_ACT_SIGNAL_BLOCKING
|
||||
|
||||
switch(tool_type)
|
||||
if(TOOL_CROWBAR)
|
||||
act_result = is_left_clicking ? crowbar_act(user, tool) : crowbar_act_secondary(user, tool)
|
||||
if(TOOL_MULTITOOL)
|
||||
act_result = is_left_clicking ? multitool_act(user, tool) : multitool_act_secondary(user, tool)
|
||||
if(TOOL_SCREWDRIVER)
|
||||
act_result = is_left_clicking ? screwdriver_act(user, tool) : screwdriver_act_secondary(user, tool)
|
||||
if(TOOL_WRENCH)
|
||||
act_result = is_left_clicking ? wrench_act(user, tool) : wrench_act_secondary(user, tool)
|
||||
if(TOOL_WIRECUTTER)
|
||||
act_result = is_left_clicking ? wirecutter_act(user, tool) : wirecutter_act_secondary(user, tool)
|
||||
if(TOOL_WELDER)
|
||||
act_result = is_left_clicking ? welder_act(user, tool) : welder_act_secondary(user, tool)
|
||||
if(TOOL_ANALYZER)
|
||||
act_result = is_left_clicking ? analyzer_act(user, tool) : analyzer_act_secondary(user, tool)
|
||||
if(!act_result)
|
||||
return
|
||||
|
||||
// A tooltype_act has completed successfully
|
||||
if(is_left_clicking)
|
||||
log_tool("[key_name(user)] used [tool] on [src] at [AREACOORD(src)]")
|
||||
SEND_SIGNAL(tool, COMSIG_TOOL_ATOM_ACTED_PRIMARY(tool_type), src)
|
||||
else
|
||||
log_tool("[key_name(user)] used [tool] on [src] (right click) at [AREACOORD(src)]")
|
||||
SEND_SIGNAL(tool, COMSIG_TOOL_ATOM_ACTED_SECONDARY(tool_type), src)
|
||||
return TOOL_ACT_TOOLTYPE_SUCCESS
|
||||
|
||||
//! Tool-specific behavior procs.
|
||||
///
|
||||
|
||||
/// Called on an object when a tool with crowbar capabilities is used to left click an object
|
||||
/atom/proc/crowbar_act(mob/living/user, obj/item/tool)
|
||||
return
|
||||
|
||||
/// Called on an object when a tool with crowbar capabilities is used to right click an object
|
||||
/atom/proc/crowbar_act_secondary(mob/living/user, obj/item/tool)
|
||||
return
|
||||
|
||||
/// Called on an object when a tool with multitool capabilities is used to left click an object
|
||||
/atom/proc/multitool_act(mob/living/user, obj/item/tool)
|
||||
return
|
||||
|
||||
/// Called on an object when a tool with multitool capabilities is used to right click an object
|
||||
/atom/proc/multitool_act_secondary(mob/living/user, obj/item/tool)
|
||||
return
|
||||
|
||||
///Check if an item supports a data buffer (is a multitool)
|
||||
/atom/proc/multitool_check_buffer(user, obj/item/multitool, silent = FALSE)
|
||||
if(!istype(multitool, /obj/item/multitool))
|
||||
if(user && !silent)
|
||||
to_chat(user, span_warning("[multitool] has no data buffer!"))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/// Called on an object when a tool with screwdriver capabilities is used to left click an object
|
||||
/atom/proc/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
return
|
||||
|
||||
/// Called on an object when a tool with screwdriver capabilities is used to right click an object
|
||||
/atom/proc/screwdriver_act_secondary(mob/living/user, obj/item/tool)
|
||||
return
|
||||
|
||||
/// Called on an object when a tool with wrench capabilities is used to left click an object
|
||||
/atom/proc/wrench_act(mob/living/user, obj/item/tool)
|
||||
return
|
||||
|
||||
/// Called on an object when a tool with wrench capabilities is used to right click an object
|
||||
/atom/proc/wrench_act_secondary(mob/living/user, obj/item/tool)
|
||||
return
|
||||
|
||||
/// Called on an object when a tool with wirecutter capabilities is used to left click an object
|
||||
/atom/proc/wirecutter_act(mob/living/user, obj/item/tool)
|
||||
return
|
||||
|
||||
/// Called on an object when a tool with wirecutter capabilities is used to right click an object
|
||||
/atom/proc/wirecutter_act_secondary(mob/living/user, obj/item/tool)
|
||||
return
|
||||
|
||||
/// Called on an object when a tool with welder capabilities is used to left click an object
|
||||
/atom/proc/welder_act(mob/living/user, obj/item/tool)
|
||||
return
|
||||
|
||||
/// Called on an object when a tool with welder capabilities is used to right click an object
|
||||
/atom/proc/welder_act_secondary(mob/living/user, obj/item/tool)
|
||||
return
|
||||
|
||||
/// Called on an object when a tool with analyzer capabilities is used to left click an object
|
||||
/atom/proc/analyzer_act(mob/living/user, obj/item/tool)
|
||||
return
|
||||
|
||||
/// Called on an object when a tool with analyzer capabilities is used to right click an object
|
||||
/atom/proc/analyzer_act_secondary(mob/living/user, obj/item/tool)
|
||||
return
|
||||
@@ -0,0 +1,271 @@
|
||||
/**
|
||||
* Return the markup to for the dropdown list for the VV panel for this atom
|
||||
*
|
||||
* Override in subtypes to add custom VV handling in the VV panel
|
||||
*/
|
||||
/atom/vv_get_dropdown()
|
||||
. = ..()
|
||||
VV_DROPDOWN_OPTION("", "---------")
|
||||
if(!ismovable(src))
|
||||
var/turf/curturf = get_turf(src)
|
||||
if(curturf)
|
||||
. += "<option value='?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[curturf.x];Y=[curturf.y];Z=[curturf.z]'>Jump To</option>"
|
||||
VV_DROPDOWN_OPTION(VV_HK_MODIFY_TRANSFORM, "Modify Transform")
|
||||
VV_DROPDOWN_OPTION(VV_HK_SPIN_ANIMATION, "SpinAnimation")
|
||||
VV_DROPDOWN_OPTION(VV_HK_STOP_ALL_ANIMATIONS, "Stop All Animations")
|
||||
VV_DROPDOWN_OPTION(VV_HK_SHOW_HIDDENPRINTS, "Show Hiddenprint log")
|
||||
VV_DROPDOWN_OPTION(VV_HK_ADD_REAGENT, "Add Reagent")
|
||||
VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EMP, "EMP Pulse")
|
||||
VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EXPLOSION, "Explosion")
|
||||
VV_DROPDOWN_OPTION(VV_HK_EDIT_FILTERS, "Edit Filters")
|
||||
VV_DROPDOWN_OPTION(VV_HK_EDIT_COLOR_MATRIX, "Edit Color as Matrix")
|
||||
VV_DROPDOWN_OPTION(VV_HK_TEST_MATRIXES, "Test Matrices")
|
||||
VV_DROPDOWN_OPTION(VV_HK_ADD_AI, "Add AI controller")
|
||||
VV_DROPDOWN_OPTION(VV_HK_ARMOR_MOD, "Modify Armor")
|
||||
if(greyscale_colors)
|
||||
VV_DROPDOWN_OPTION(VV_HK_MODIFY_GREYSCALE, "Modify greyscale colors")
|
||||
|
||||
/atom/vv_do_topic(list/href_list)
|
||||
. = ..()
|
||||
if(href_list[VV_HK_ADD_REAGENT] && check_rights(R_VAREDIT))
|
||||
if(!reagents)
|
||||
var/amount = input(usr, "Specify the reagent size of [src]", "Set Reagent Size", 50) as num|null
|
||||
if(amount)
|
||||
create_reagents(amount)
|
||||
|
||||
if(reagents)
|
||||
var/chosen_id
|
||||
switch(tgui_alert(usr, "Choose a method.", "Add Reagents", list("Search", "Choose from a list", "I'm feeling lucky")))
|
||||
if("Search")
|
||||
var/valid_id
|
||||
while(!valid_id)
|
||||
chosen_id = input(usr, "Enter the ID of the reagent you want to add.", "Search reagents") as null|text
|
||||
if(isnull(chosen_id)) //Get me out of here!
|
||||
break
|
||||
if (!ispath(text2path(chosen_id)))
|
||||
chosen_id = pick_closest_path(chosen_id, make_types_fancy(subtypesof(/datum/reagent)))
|
||||
if (ispath(chosen_id))
|
||||
valid_id = TRUE
|
||||
else
|
||||
valid_id = TRUE
|
||||
if(!valid_id)
|
||||
to_chat(usr, span_warning("A reagent with that ID doesn't exist!"))
|
||||
if("Choose from a list")
|
||||
chosen_id = input(usr, "Choose a reagent to add.", "Choose a reagent.") as null|anything in sort_list(subtypesof(/datum/reagent), GLOBAL_PROC_REF(cmp_typepaths_asc))
|
||||
if("I'm feeling lucky")
|
||||
chosen_id = pick(subtypesof(/datum/reagent))
|
||||
if(chosen_id)
|
||||
var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", reagents.maximum_volume) as num|null
|
||||
if(amount)
|
||||
reagents.add_reagent(chosen_id, amount)
|
||||
log_admin("[key_name(usr)] has added [amount] units of [chosen_id] to [src]")
|
||||
message_admins(span_notice("[key_name(usr)] has added [amount] units of [chosen_id] to [src]"))
|
||||
|
||||
if(href_list[VV_HK_TRIGGER_EXPLOSION] && check_rights(R_FUN))
|
||||
usr.client.cmd_admin_explosion(src)
|
||||
|
||||
if(href_list[VV_HK_TRIGGER_EMP] && check_rights(R_FUN))
|
||||
usr.client.cmd_admin_emp(src)
|
||||
|
||||
if(href_list[VV_HK_SHOW_HIDDENPRINTS] && check_rights(R_ADMIN))
|
||||
usr.client.cmd_show_hiddenprints(src)
|
||||
|
||||
if(href_list[VV_HK_ARMOR_MOD])
|
||||
var/list/pickerlist = list()
|
||||
var/list/armorlist = get_armor().get_rating_list()
|
||||
|
||||
for (var/i in armorlist)
|
||||
pickerlist += list(list("value" = armorlist[i], "name" = i))
|
||||
|
||||
var/list/result = presentpicker(usr, "Modify armor", "Modify armor: [src]", Button1="Save", Button2 = "Cancel", Timeout=FALSE, inputtype = "text", values = pickerlist)
|
||||
var/list/armor_all = ARMOR_LIST_ALL()
|
||||
|
||||
if (islist(result))
|
||||
if (result["button"] != 2) // If the user pressed the cancel button
|
||||
// text2num conveniently returns a null on invalid values
|
||||
var/list/converted = list()
|
||||
for(var/armor_key in armor_all)
|
||||
converted[armor_key] = text2num(result["values"][armor_key])
|
||||
set_armor(get_armor().generate_new_with_specific(converted))
|
||||
var/message = "[key_name(usr)] modified the armor on [src] ([type]) to: "
|
||||
for(var/armor_key in armor_all)
|
||||
message += "[armor_key]=[get_armor_rating(armor_key)],"
|
||||
message = copytext(message, 1, -1)
|
||||
log_admin(span_notice(message))
|
||||
message_admins(span_notice(message))
|
||||
|
||||
if(href_list[VV_HK_ADD_AI])
|
||||
if(!check_rights(R_VAREDIT))
|
||||
return
|
||||
var/result = input(usr, "Choose the AI controller to apply to this atom WARNING: Not all AI works on all atoms.", "AI controller") as null|anything in subtypesof(/datum/ai_controller)
|
||||
if(!result)
|
||||
return
|
||||
ai_controller = new result(src)
|
||||
|
||||
if(href_list[VV_HK_MODIFY_TRANSFORM] && check_rights(R_VAREDIT))
|
||||
var/result = input(usr, "Choose the transformation to apply","Transform Mod") as null|anything in list("Scale","Translate","Rotate","Shear")
|
||||
var/matrix/M = transform
|
||||
if(!result)
|
||||
return
|
||||
switch(result)
|
||||
if("Scale")
|
||||
var/x = input(usr, "Choose x mod","Transform Mod") as null|num
|
||||
var/y = input(usr, "Choose y mod","Transform Mod") as null|num
|
||||
if(isnull(x) || isnull(y))
|
||||
return
|
||||
transform = M.Scale(x,y)
|
||||
if("Translate")
|
||||
var/x = input(usr, "Choose x mod (negative = left, positive = right)","Transform Mod") as null|num
|
||||
var/y = input(usr, "Choose y mod (negative = down, positive = up)","Transform Mod") as null|num
|
||||
if(isnull(x) || isnull(y))
|
||||
return
|
||||
transform = M.Translate(x,y)
|
||||
if("Shear")
|
||||
var/x = input(usr, "Choose x mod","Transform Mod") as null|num
|
||||
var/y = input(usr, "Choose y mod","Transform Mod") as null|num
|
||||
if(isnull(x) || isnull(y))
|
||||
return
|
||||
transform = M.Shear(x,y)
|
||||
if("Rotate")
|
||||
var/angle = input(usr, "Choose angle to rotate","Transform Mod") as null|num
|
||||
if(isnull(angle))
|
||||
return
|
||||
transform = M.Turn(angle)
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_VV_MODIFY_TRANSFORM)
|
||||
|
||||
if(href_list[VV_HK_SPIN_ANIMATION] && check_rights(R_VAREDIT))
|
||||
var/num_spins = input(usr, "Do you want infinite spins?", "Spin Animation") in list("Yes", "No")
|
||||
if(num_spins == "No")
|
||||
num_spins = input(usr, "How many spins?", "Spin Animation") as null|num
|
||||
else
|
||||
num_spins = -1
|
||||
if(!num_spins)
|
||||
return
|
||||
var/spin_speed = input(usr, "How fast?", "Spin Animation") as null|num
|
||||
if(!spin_speed)
|
||||
return
|
||||
var/direction = input(usr, "Which direction?", "Spin Animation") in list("Clockwise", "Counter-clockwise")
|
||||
switch(direction)
|
||||
if("Clockwise")
|
||||
direction = 1
|
||||
if("Counter-clockwise")
|
||||
direction = 0
|
||||
else
|
||||
return
|
||||
SpinAnimation(spin_speed, num_spins, direction)
|
||||
|
||||
if(href_list[VV_HK_STOP_ALL_ANIMATIONS] && check_rights(R_VAREDIT))
|
||||
var/result = input(usr, "Are you sure?", "Stop Animating") in list("Yes", "No")
|
||||
if(result == "Yes")
|
||||
animate(src, transform = null, flags = ANIMATION_END_NOW) // Literally just fucking stop animating entirely because admin said so
|
||||
return
|
||||
|
||||
if(href_list[VV_HK_AUTO_RENAME] && check_rights(R_VAREDIT))
|
||||
var/newname = input(usr, "What do you want to rename this to?", "Automatic Rename") as null|text
|
||||
// Check the new name against the chat filter. If it triggers the IC chat filter, give an option to confirm.
|
||||
if(newname && !(is_ic_filtered(newname) || is_soft_ic_filtered(newname) && tgui_alert(usr, "Your selected name contains words restricted by IC chat filters. Confirm this new name?", "IC Chat Filter Conflict", list("Confirm", "Cancel")) != "Confirm"))
|
||||
vv_auto_rename(newname)
|
||||
|
||||
if(href_list[VV_HK_EDIT_FILTERS] && check_rights(R_VAREDIT))
|
||||
usr.client?.open_filter_editor(src)
|
||||
|
||||
if(href_list[VV_HK_EDIT_COLOR_MATRIX] && check_rights(R_VAREDIT))
|
||||
usr.client?.open_color_matrix_editor(src)
|
||||
|
||||
if(href_list[VV_HK_TEST_MATRIXES] && check_rights(R_VAREDIT))
|
||||
usr.client?.open_matrix_tester(src)
|
||||
|
||||
/atom/vv_get_header()
|
||||
. = ..()
|
||||
var/refid = REF(src)
|
||||
. += "[VV_HREF_TARGETREF(refid, VV_HK_AUTO_RENAME, "<b id='name'>[src]</b>")]"
|
||||
. += "<br><font size='1'><a href='?_src_=vars;[HrefToken()];rotatedatum=[refid];rotatedir=left'><<</a> <a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=dir' id='dir'>[dir2text(dir) || dir]</a> <a href='?_src_=vars;[HrefToken()];rotatedatum=[refid];rotatedir=right'>>></a></font>"
|
||||
|
||||
/**
|
||||
* call back when a var is edited on this atom
|
||||
*
|
||||
* Can be used to implement special handling of vars
|
||||
*
|
||||
* At the atom level, if you edit a var named "color" it will add the atom colour with
|
||||
* admin level priority to the atom colours list
|
||||
*
|
||||
* Also, if GLOB.Debug2 is FALSE, it sets the [ADMIN_SPAWNED_1] flag on [flags_1][/atom/var/flags_1], which signifies
|
||||
* the object has been admin edited
|
||||
*/
|
||||
/atom/vv_edit_var(var_name, var_value)
|
||||
var/old_light_flags = light_flags
|
||||
// Disable frozen lights for now, so we can actually modify it
|
||||
light_flags &= ~LIGHT_FROZEN
|
||||
switch(var_name)
|
||||
if(NAMEOF(src, light_range))
|
||||
if(light_system == STATIC_LIGHT)
|
||||
set_light(l_range = var_value)
|
||||
else
|
||||
set_light_range(var_value)
|
||||
. = TRUE
|
||||
if(NAMEOF(src, light_power))
|
||||
if(light_system == STATIC_LIGHT)
|
||||
set_light(l_power = var_value)
|
||||
else
|
||||
set_light_power(var_value)
|
||||
. = TRUE
|
||||
if(NAMEOF(src, light_color))
|
||||
if(light_system == STATIC_LIGHT)
|
||||
set_light(l_color = var_value)
|
||||
else
|
||||
set_light_color(var_value)
|
||||
. = TRUE
|
||||
if(NAMEOF(src, light_angle))
|
||||
if(light_system == STATIC_LIGHT)
|
||||
set_light(l_angle = var_value)
|
||||
. = TRUE
|
||||
if(NAMEOF(src, light_dir))
|
||||
if(light_system == STATIC_LIGHT)
|
||||
set_light(l_dir = var_value)
|
||||
. = TRUE
|
||||
if(NAMEOF(src, light_height))
|
||||
if(light_system == STATIC_LIGHT)
|
||||
set_light(l_height = var_value)
|
||||
. = TRUE
|
||||
if(NAMEOF(src, light_on))
|
||||
if(light_system == STATIC_LIGHT)
|
||||
set_light(l_on = var_value)
|
||||
else
|
||||
set_light_on(var_value)
|
||||
. = TRUE
|
||||
if(NAMEOF(src, light_flags))
|
||||
set_light_flags(var_value)
|
||||
// I'm sorry
|
||||
old_light_flags = var_value
|
||||
. = TRUE
|
||||
if(NAMEOF(src, smoothing_junction))
|
||||
set_smoothed_icon_state(var_value)
|
||||
. = TRUE
|
||||
if(NAMEOF(src, opacity))
|
||||
set_opacity(var_value)
|
||||
. = TRUE
|
||||
if(NAMEOF(src, base_pixel_x))
|
||||
set_base_pixel_x(var_value)
|
||||
. = TRUE
|
||||
if(NAMEOF(src, base_pixel_y))
|
||||
set_base_pixel_y(var_value)
|
||||
. = TRUE
|
||||
|
||||
light_flags = old_light_flags
|
||||
if(!isnull(.))
|
||||
datum_flags |= DF_VAR_EDITED
|
||||
return
|
||||
|
||||
if(!GLOB.Debug2)
|
||||
flags_1 |= ADMIN_SPAWNED_1
|
||||
|
||||
. = ..()
|
||||
|
||||
switch(var_name)
|
||||
if(NAMEOF(src, color))
|
||||
add_atom_colour(color, ADMIN_COLOUR_PRIORITY)
|
||||
update_appearance()
|
||||
|
||||
/atom/proc/vv_auto_rename(newname)
|
||||
name = newname
|
||||
+35
@@ -52,6 +52,27 @@
|
||||
|
||||
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, ...)
|
||||
//atom creation method that preloads variables at creation
|
||||
if(GLOB.use_preloader && src.type == GLOB._preloader_path)//in case the instanciated atom is creating other atoms in New()
|
||||
world.preloader_load(src)
|
||||
|
||||
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
|
||||
*
|
||||
@@ -126,3 +147,17 @@
|
||||
ai_controller = new ai_controller(src)
|
||||
|
||||
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
|
||||
-2323
File diff suppressed because it is too large
Load Diff
+17
-5
@@ -464,7 +464,6 @@
|
||||
#include "code\__HELPERS\_string_lists.dm"
|
||||
#include "code\__HELPERS\admin.dm"
|
||||
#include "code\__HELPERS\ai.dm"
|
||||
#include "code\__HELPERS\animations.dm"
|
||||
#include "code\__HELPERS\areas.dm"
|
||||
#include "code\__HELPERS\atmospherics.dm"
|
||||
#include "code\__HELPERS\atoms.dm"
|
||||
@@ -544,6 +543,7 @@
|
||||
#include "code\__HELPERS\varset_callback.dm"
|
||||
#include "code\__HELPERS\verbs.dm"
|
||||
#include "code\__HELPERS\view.dm"
|
||||
#include "code\__HELPERS\visual_effects.dm"
|
||||
#include "code\__HELPERS\weakref.dm"
|
||||
#include "code\__HELPERS\logging\_logging.dm"
|
||||
#include "code\__HELPERS\logging\admin.dm"
|
||||
@@ -1899,10 +1899,6 @@
|
||||
#include "code\datums\wounds\slash.dm"
|
||||
#include "code\datums\wounds\scars\_scars.dm"
|
||||
#include "code\datums\wounds\scars\_static_scar_data.dm"
|
||||
#include "code\game\alternate_appearance.dm"
|
||||
#include "code\game\atom_defense.dm"
|
||||
#include "code\game\atoms.dm"
|
||||
#include "code\game\atoms_initializing_EXPENSIVE.dm"
|
||||
#include "code\game\atoms_movable.dm"
|
||||
#include "code\game\communications.dm"
|
||||
#include "code\game\data_huds.dm"
|
||||
@@ -1938,6 +1934,22 @@
|
||||
#include "code\game\area\areas\station\service.dm"
|
||||
#include "code\game\area\areas\station\solars.dm"
|
||||
#include "code\game\area\areas\station\telecomm.dm"
|
||||
#include "code\game\atom\_atom.dm"
|
||||
#include "code\game\atom\alternate_appearance.dm"
|
||||
#include "code\game\atom\atom_act.dm"
|
||||
#include "code\game\atom\atom_appearance.dm"
|
||||
#include "code\game\atom\atom_color.dm"
|
||||
#include "code\game\atom\atom_defense.dm"
|
||||
#include "code\game\atom\atom_examine.dm"
|
||||
#include "code\game\atom\atom_greyscale.dm"
|
||||
#include "code\game\atom\atom_invisibility.dm"
|
||||
#include "code\game\atom\atom_materials.dm"
|
||||
#include "code\game\atom\atom_merger.dm"
|
||||
#include "code\game\atom\atom_orbit.dm"
|
||||
#include "code\game\atom\atom_storage.dm"
|
||||
#include "code\game\atom\atom_tool_acts.dm"
|
||||
#include "code\game\atom\atom_vv.dm"
|
||||
#include "code\game\atom\atoms_initializing_EXPENSIVE.dm"
|
||||
#include "code\game\gamemodes\events.dm"
|
||||
#include "code\game\gamemodes\game_mode.dm"
|
||||
#include "code\game\gamemodes\objective.dm"
|
||||
|
||||
Reference in New Issue
Block a user