Files
Bubberstation/code/__HELPERS/atoms.dm
Waterpig bb70889f6e TG Upstream Part 1
3591 individual conflicts

Update build.js

Update install_node.sh

Update byond.js

oh my fucking god

hat

slow

huh

holy shit

we all fall down

2 more I missed

2900 individual conflicts

2700 Individual conflicts

replaces yarn file with tg version, bumping us down to 2200-ish

Down to 2000 individual conflicts

140 down

mmm

aaaaaaaaaaaaaaaaaaa

not yt

575

soon

900 individual conflicts

600 individual conflicts, 121 file conflicts

im not okay

160 across 19 files

29 in 4 files

0 conflicts, compiletime fix time

some minor incap stuff

missed ticks

weird dupe definition stuff

missed ticks 2

incap fixes

undefs and pie fix

Radio update and some extra minor stuff

returns a single override

no more dupe definitions, 175 compiletime errors

Unticked file fix

sound and emote stuff

honk and more radio stuff
2024-10-19 08:04:33 -07:00

342 lines
10 KiB
Plaintext

///Returns the src and all recursive contents as a list.
/atom/proc/get_all_contents(ignore_flag_1)
. = list(src)
var/i = 0
while(i < length(.))
var/atom/checked_atom = .[++i]
if(checked_atom.flags_1 & ignore_flag_1)
continue
. += checked_atom.contents
///identical to get_all_contents but returns a list of atoms of the type passed in the argument.
/atom/proc/get_all_contents_type(type)
var/list/processing_list = list(src)
. = list()
while(length(processing_list))
var/atom/checked_atom = processing_list[1]
processing_list.Cut(1, 2)
processing_list += checked_atom.contents
if(istype(checked_atom, type))
. += checked_atom
///Like get_all_contents_type, but uses a typecache list as argument
/atom/proc/get_all_contents_ignoring(list/ignore_typecache)
if(!length(ignore_typecache))
return get_all_contents()
var/list/processing = list(src)
. = list()
var/i = 0
while(i < length(processing))
var/atom/checked_atom = processing[++i]
if(ignore_typecache[checked_atom.type])
continue
processing += checked_atom.contents
. += checked_atom
///Returns the src and all recursive contents, but skipping going any deeper if an atom has a specific trait.
/atom/proc/get_all_contents_skipping_traits(skipped_trait)
. = list(src)
if(!skipped_trait)
CRASH("get_all_contents_skipping_traits called without a skipped_trait")
var/i = 0
while(i < length(.))
var/atom/checked_atom = .[++i]
if(HAS_TRAIT(checked_atom, skipped_trait))
continue
. += checked_atom.contents
///Returns a list of all locations (except the area) the movable is within.
/proc/get_nested_locs(atom/movable/atom_on_location, include_turf = FALSE)
. = list()
var/atom/location = atom_on_location.loc
var/turf/our_turf = get_turf(atom_on_location)
while(location && location != our_turf)
. += location
location = location.loc
if(our_turf && include_turf) //At this point, only the turf is left, provided it exists.
. += our_turf
///Step-towards method of determining whether one atom can see another. Similar to viewers()
///note: this is a line of sight algorithm, view() does not do any sort of raycasting and cannot be emulated by it accurately
/proc/can_see(atom/source, atom/target, length=5) // I couldnt be arsed to do actual raycasting :I This is horribly inaccurate.
var/turf/current = get_turf(source)
var/turf/target_turf = get_turf(target)
if(get_dist(source, target) > length)
return FALSE
if(current == target_turf)
return TRUE
var/steps = 1
if(current == target_turf)//they are on the same turf, source can see the target
return TRUE
current = get_step_towards(current, target_turf)
while(current != target_turf)
if(steps > length)
return FALSE
if(IS_OPAQUE_TURF(current))
return FALSE
current = get_step_towards(current, target_turf)
steps++
return TRUE
///Get the cardinal direction between two atoms
/proc/get_cardinal_dir(atom/start, atom/end)
var/dx = abs(end.x - start.x)
var/dy = abs(end.y - start.y)
return get_dir(start, end) & (rand() * (dx+dy) < dy ? 3 : 12)
/**
* Finds the distance between two atoms, in pixels \
* centered = FALSE counts from turf edge to edge \
* centered = TRUE counts from turf center to turf center \
* of course mathematically this is just adding world.icon_size on again
**/
/proc/get_pixel_distance(atom/start, atom/end, centered = TRUE)
if(!istype(start) || !istype(end))
return 0
. = bounds_dist(start, end) + sqrt((((start.pixel_x + end.pixel_x) ** 2) + ((start.pixel_y + end.pixel_y) ** 2)))
if(centered)
. += ICON_SIZE_ALL
/**
* Check if there is already a wall item on the turf loc
* floor_loc = floor tile in front of the wall
* dir_toward_wall = direction from the floor tile in front of the wall towards the wall
* check_external = truthy if we should be checking against items coming out of the wall, rather than visually on top of the wall.
**/
/proc/check_wall_item(floor_loc, dir_toward_wall, check_external = 0)
var/wall_loc = get_step(floor_loc, dir_toward_wall)
for(var/obj/checked_object in floor_loc)
if(is_type_in_typecache(checked_object, GLOB.WALLITEMS_INTERIOR) && !check_external)
//Direction works sometimes
if(checked_object.dir == dir_toward_wall)
return TRUE
//Some stuff doesn't use dir properly, so we need to check pixel instead
//That's exactly what get_turf_pixel() does
if(get_turf_pixel(checked_object) == wall_loc)
return TRUE
if(is_type_in_typecache(checked_object, GLOB.WALLITEMS_EXTERIOR) && check_external)
if(checked_object.dir == dir_toward_wall)
return TRUE
//Some stuff is placed directly on the wallturf (signs).
//If we're only checking for external entities, we don't need to look though these.
if (check_external)
return FALSE
for(var/obj/checked_object in wall_loc)
if(is_type_in_typecache(checked_object, GLOB.WALLITEMS_INTERIOR))
if(checked_object.pixel_x == 0 && checked_object.pixel_y == 0)
return TRUE
return FALSE
///Forces the atom to take a step in a random direction
/proc/random_step(atom/movable/moving_atom, steps, chance)
var/initial_chance = chance
while(steps > 0)
if(prob(chance))
step(moving_atom, pick(GLOB.alldirs))
chance = max(chance - (initial_chance / steps), 0)
steps--
/**
* Compare source's dir, the clockwise dir of source and the anticlockwise dir of source
* To the opposite dir of the dir returned by get_dir(target,source)
* If one of them is a match, then source is facing target
**/
/proc/is_source_facing_target(atom/source,atom/target)
if(!istype(source) || !istype(target))
return FALSE
if(isliving(source))
var/mob/living/source_mob = source
if(source_mob.body_position == LYING_DOWN)
return FALSE
var/goal_dir = get_dir(source, target)
var/clockwise_source_dir = turn(source.dir, -45)
var/anticlockwise_source_dir = turn(source.dir, 45)
if(source.dir == goal_dir || clockwise_source_dir == goal_dir || anticlockwise_source_dir == goal_dir)
return TRUE
return FALSE
/*
rough example of the "cone" made by the 3 dirs checked
* \
* \
* >
* <
* \
* \
*B --><-- A
* /
* /
* <
* >
* /
* /
*/
///ultra range (no limitations on distance, faster than range for distances > 8); including areas drastically decreases performance
/proc/urange(dist = 0, atom/center = usr, orange = FALSE, areas = FALSE)
if(!dist)
if(!orange)
return list(center)
else
return list()
var/list/turfs = RANGE_TURFS(dist, center)
if(orange)
turfs -= get_turf(center)
. = list()
for(var/turf/checked_turf as anything in turfs)
. += checked_turf
. += checked_turf.contents
if(areas)
. |= checked_turf.loc
///similar function to range(), but with no limitations on the distance; will search spiralling outwards from the center
/proc/spiral_range(dist = 0, center = usr, orange = FALSE)
var/list/atom_list = list()
var/turf/t_center = get_turf(center)
if(!t_center)
return list()
if(!orange)
atom_list += t_center
atom_list += t_center.contents
if(!dist)
return atom_list
var/turf/checked_turf
var/y
var/x
var/c_dist = 1
while( c_dist <= dist )
y = t_center.y + c_dist
x = t_center.x - c_dist + 1
for(x in x to t_center.x + c_dist)
checked_turf = locate(x, y, t_center.z)
if(checked_turf)
atom_list += checked_turf
atom_list += checked_turf.contents
y = t_center.y + c_dist - 1
x = t_center.x + c_dist
for(y in t_center.y - c_dist to y)
checked_turf = locate(x, y, t_center.z)
if(checked_turf)
atom_list += checked_turf
atom_list += checked_turf.contents
y = t_center.y - c_dist
x = t_center.x + c_dist - 1
for(x in t_center.x - c_dist to x)
checked_turf = locate(x, y, t_center.z)
if(checked_turf)
atom_list += checked_turf
atom_list += checked_turf.contents
y = t_center.y - c_dist + 1
x = t_center.x - c_dist
for(y in y to t_center.y + c_dist)
checked_turf = locate(x, y, t_center.z)
if(checked_turf)
atom_list += checked_turf
atom_list += checked_turf.contents
c_dist++
return atom_list
///Returns the closest atom of a specific type in a list from a source
/proc/get_closest_atom(type, list/atom_list, source)
var/closest_atom
var/closest_distance
for(var/atom in atom_list)
if(!istype(atom, type))
continue
var/distance = get_dist(source, atom)
if(!closest_atom)
closest_distance = distance
closest_atom = atom
else
if(closest_distance > distance)
closest_distance = distance
closest_atom = atom
return closest_atom
///Returns a chosen path that is the closest to a list of matches
/proc/pick_closest_path(value, list/matches = get_fancy_list_of_atom_types())
if (value == FALSE) //nothing should be calling us with a number, so this is safe
value = input("Enter type to find (blank for all, cancel to cancel)", "Search for type") as null|text
if (isnull(value))
return
value = trim(value)
var/random = FALSE
if(findtext(value, "?"))
value = replacetext(value, "?", "")
random = TRUE
if(!isnull(value) && value != "")
matches = filter_fancy_list(matches, value)
if(matches.len == 0)
return
var/chosen
if(matches.len == 1)
chosen = matches[1]
else if(random)
chosen = pick(matches) || null
else
chosen = input("Select a type", "Pick Type", matches[1]) as null|anything in sort_list(matches)
if(!chosen)
return
chosen = matches[chosen]
return chosen
///Creates new items inside an atom based on a list
/proc/generate_items_inside(list/items_list, where_to)
for(var/each_item in items_list)
for(var/i in 1 to items_list[each_item])
new each_item(where_to)
///Returns the atom type in the specified loc
/proc/get(atom/loc, type)
while(loc)
if(istype(loc, type))
return loc
loc = loc.loc
return null
///Returns true if the src countain the atom target
/atom/proc/contains(atom/target)
if(!target)
return FALSE
for(var/atom/location = target.loc, location, location = location.loc)
if(location == src)
return TRUE
///A do nothing proc
/proc/pass(...)
return
/// Returns an x and y value require to reverse the transformations made to center an oversized icon
/atom/proc/get_oversized_icon_offsets()
if (pixel_x == 0 && pixel_y == 0)
return list("x" = 0, "y" = 0)
var/list/icon_dimensions = get_icon_dimensions(icon)
var/icon_width = icon_dimensions["width"]
var/icon_height = icon_dimensions["height"]
return list(
"x" = icon_width > ICON_SIZE_X && pixel_x != 0 ? (icon_width - ICON_SIZE_X) * 0.5 : 0,
"y" = icon_height > ICON_SIZE_Y && pixel_y != 0 ? (icon_height - ICON_SIZE_Y) * 0.5 : 0,
)