mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-24 00:21:52 +00:00
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
434 lines
16 KiB
Plaintext
434 lines
16 KiB
Plaintext
///Returns location. Returns null if no location was found.
|
|
/proc/get_teleport_loc(turf/location, mob/target, distance = 1, density_check = FALSE, closed_turf_check = FALSE, errorx = 0, errory = 0, eoffsetx = 0, eoffsety = 0)
|
|
/*
|
|
Location where the teleport begins, target that will teleport, distance to go, density checking 0/1(yes/no), closed turf checking.
|
|
Random error in tile placement x, error in tile placement y, and block offset.
|
|
Block offset tells the proc how to place the box. Behind teleport location, relative to starting location, forward, etc.
|
|
Negative values for offset are accepted, think of it in relation to North, -x is west, -y is south. Error defaults to positive.
|
|
Turf and target are separate in case you want to teleport some distance from a turf the target is not standing on or something.
|
|
*/
|
|
|
|
var/dirx = 0//Generic location finding variable.
|
|
var/diry = 0
|
|
|
|
var/xoffset = 0//Generic counter for offset location.
|
|
var/yoffset = 0
|
|
|
|
var/b1xerror = 0//Generic placing for point A in box. The lower left.
|
|
var/b1yerror = 0
|
|
var/b2xerror = 0//Generic placing for point B in box. The upper right.
|
|
var/b2yerror = 0
|
|
|
|
errorx = abs(errorx)//Error should never be negative.
|
|
errory = abs(errory)
|
|
|
|
switch(target.dir)//This can be done through equations but switch is the simpler method. And works fast to boot.
|
|
//Directs on what values need modifying.
|
|
if(1)//North
|
|
diry += distance
|
|
yoffset += eoffsety
|
|
xoffset += eoffsetx
|
|
b1xerror -= errorx
|
|
b1yerror -= errory
|
|
b2xerror += errorx
|
|
b2yerror += errory
|
|
if(2)//South
|
|
diry -= distance
|
|
yoffset -= eoffsety
|
|
xoffset += eoffsetx
|
|
b1xerror -= errorx
|
|
b1yerror -= errory
|
|
b2xerror += errorx
|
|
b2yerror += errory
|
|
if(4)//East
|
|
dirx += distance
|
|
yoffset += eoffsetx//Flipped.
|
|
xoffset += eoffsety
|
|
b1xerror -= errory//Flipped.
|
|
b1yerror -= errorx
|
|
b2xerror += errory
|
|
b2yerror += errorx
|
|
if(8)//West
|
|
dirx -= distance
|
|
yoffset -= eoffsetx//Flipped.
|
|
xoffset += eoffsety
|
|
b1xerror -= errory//Flipped.
|
|
b1yerror -= errorx
|
|
b2xerror += errory
|
|
b2yerror += errorx
|
|
|
|
var/turf/destination = locate(location.x+dirx,location.y+diry,location.z)
|
|
|
|
if(!destination)//If there isn't a destination.
|
|
return
|
|
|
|
if(!errorx && !errory)//If errorx or y were not specified.
|
|
if(density_check && destination.density)
|
|
return
|
|
if(closed_turf_check && isclosedturf(destination))
|
|
return//If closed was specified.
|
|
if(destination.x>world.maxx || destination.x<1)
|
|
return
|
|
if(destination.y>world.maxy || destination.y<1)
|
|
return
|
|
|
|
var/destination_list[] = list()//To add turfs to list.
|
|
//destination_list = new()
|
|
/*This will draw a block around the target turf, given what the error is.
|
|
Specifying the values above will basically draw a different sort of block.
|
|
If the values are the same, it will be a square. If they are different, it will be a rectangle.
|
|
In either case, it will center based on offset. Offset is position from center.
|
|
Offset always calculates in relation to direction faced. In other words, depending on the direction of the teleport,
|
|
the offset should remain positioned in relation to destination.*/
|
|
|
|
var/turf/center = locate((destination.x + xoffset), (destination.y + yoffset), location.z)//So now, find the new center.
|
|
|
|
//Now to find a box from center location and make that our destination.
|
|
var/width = (b2xerror - b1xerror) + 1
|
|
var/height = (b2yerror - b1yerror) + 1
|
|
for(var/turf/current_turf as anything in CORNER_BLOCK_OFFSET(center, width, height, b1xerror, b1yerror))
|
|
if(density_check && current_turf.density)
|
|
continue//If density was specified.
|
|
if(closed_turf_check && isclosedturf(current_turf))
|
|
continue//If closed was specified.
|
|
if(current_turf.x > world.maxx || current_turf.x < 1)
|
|
continue//Don't want them to teleport off the map.
|
|
if(current_turf.y > world.maxy || current_turf.y < 1)
|
|
continue
|
|
destination_list += current_turf
|
|
|
|
if(!destination_list.len)
|
|
return
|
|
|
|
destination = pick(destination_list)
|
|
return destination
|
|
|
|
/**
|
|
* Returns the top-most atom sitting on the turf.
|
|
* For example, using this on a disk, which is in a bag, on a mob,
|
|
* will return the mob because it's on the turf.
|
|
*
|
|
* Arguments
|
|
* * something_in_turf - a movable within the turf, somewhere.
|
|
* * stop_type - optional - stops looking if stop_type is found in the turf, returning that type (if found).
|
|
**/
|
|
/proc/get_atom_on_turf(atom/movable/something_in_turf, stop_type)
|
|
if(!istype(something_in_turf))
|
|
CRASH("get_atom_on_turf was not passed an /atom/movable! Got [isnull(something_in_turf) ? "null":"type: [something_in_turf.type]"]")
|
|
|
|
var/atom/movable/topmost_thing = something_in_turf
|
|
|
|
while(topmost_thing?.loc && !isturf(topmost_thing.loc))
|
|
topmost_thing = topmost_thing.loc
|
|
if(stop_type && istype(topmost_thing, stop_type))
|
|
break
|
|
|
|
return topmost_thing
|
|
|
|
///Returns the turf located at the map edge in the specified direction relative to target_atom used for mass driver
|
|
/proc/get_edge_target_turf(atom/target_atom, direction)
|
|
var/turf/target = locate(target_atom.x, target_atom.y, target_atom.z)
|
|
if(!target_atom || !target)
|
|
return 0
|
|
//since NORTHEAST == NORTH|EAST, etc, doing it this way allows for diagonal mass drivers in the future
|
|
//and isn't really any more complicated
|
|
|
|
var/x = target_atom.x
|
|
var/y = target_atom.y
|
|
if(direction & NORTH)
|
|
y = world.maxy
|
|
else if(direction & SOUTH) //you should not have both NORTH and SOUTH in the provided direction
|
|
y = 1
|
|
if(direction & EAST)
|
|
x = world.maxx
|
|
else if(direction & WEST)
|
|
x = 1
|
|
if(ISDIAGONALDIR(direction)) //let's make sure it's accurately-placed for diagonals
|
|
var/lowest_distance_to_map_edge = min(abs(x - target_atom.x), abs(y - target_atom.y))
|
|
return get_ranged_target_turf(target_atom, direction, lowest_distance_to_map_edge)
|
|
return locate(x,y,target_atom.z)
|
|
|
|
// returns turf relative to target_atom in given direction at set range
|
|
// result is bounded to map size
|
|
// note range is non-pythagorean
|
|
// used for disposal system
|
|
/proc/get_ranged_target_turf(atom/target_atom, direction, range)
|
|
|
|
var/x = target_atom.x
|
|
var/y = target_atom.y
|
|
if(direction & NORTH)
|
|
y = min(world.maxy, y + range)
|
|
else if(direction & SOUTH)
|
|
y = max(1, y - range)
|
|
if(direction & EAST)
|
|
x = min(world.maxx, x + range)
|
|
else if(direction & WEST) //if you have both EAST and WEST in the provided direction, then you're gonna have issues
|
|
x = max(1, x - range)
|
|
|
|
return locate(x,y,target_atom.z)
|
|
|
|
/**
|
|
* Get ranged target turf, but with direct targets as opposed to directions
|
|
*
|
|
* Starts at atom starting_atom and gets the exact angle between starting_atom and target
|
|
* Moves from starting_atom with that angle, Range amount of times, until it stops, bound to map size
|
|
* Arguments:
|
|
* * starting_atom - Initial Firer / Position
|
|
* * target - Target to aim towards
|
|
* * range - Distance of returned target turf from starting_atom
|
|
* * offset - Angle offset, 180 input would make the returned target turf be in the opposite direction
|
|
*/
|
|
/proc/get_ranged_target_turf_direct(atom/starting_atom, atom/target, range, offset)
|
|
var/angle = ATAN2(target.x - starting_atom.x, target.y - starting_atom.y)
|
|
if(offset)
|
|
angle += offset
|
|
var/turf/starting_turf = get_turf(starting_atom)
|
|
for(var/i in 1 to range)
|
|
var/turf/check = locate(starting_atom.x + cos(angle) * i, starting_atom.y + sin(angle) * i, starting_atom.z)
|
|
if(!check)
|
|
break
|
|
starting_turf = check
|
|
|
|
return starting_turf
|
|
|
|
|
|
/// returns turf relative to target_atom offset in dx and dy tiles, bound to map limits
|
|
/proc/get_offset_target_turf(atom/target_atom, dx, dy)
|
|
var/x = min(world.maxx, max(1, target_atom.x + dx))
|
|
var/y = min(world.maxy, max(1, target_atom.y + dy))
|
|
return locate(x, y, target_atom.z)
|
|
|
|
/**
|
|
* Lets the turf this atom's *ICON* appears to inhabit
|
|
* it takes into account:
|
|
* Pixel_x/y
|
|
* Matrix x/y
|
|
* NOTE: if your atom has non-standard bounds then this proc
|
|
* will handle it, but:
|
|
* if the bounds are even, then there are an even amount of "middle" turfs, the one to the EAST, NORTH, or BOTH is picked
|
|
* this may seem bad, but you're at least as close to the center of the atom as possible, better than byond's default loc being all the way off)
|
|
* if the bounds are odd, the true middle turf of the atom is returned
|
|
**/
|
|
/proc/get_turf_pixel(atom/checked_atom)
|
|
var/turf/atom_turf = get_turf(checked_atom) //use checked_atom's turfs, as its coords are the same as checked_atom's AND checked_atom's coords are lost if it is inside another atom
|
|
if(!atom_turf)
|
|
return null
|
|
if(checked_atom.flags_1 & IGNORE_TURF_PIXEL_OFFSET_1)
|
|
return atom_turf
|
|
|
|
var/list/offsets = get_visual_offset(checked_atom)
|
|
return pixel_offset_turf(atom_turf, offsets)
|
|
|
|
/**
|
|
* Returns how visually "off" the atom is from its source turf as a list of x, y (in pixel steps)
|
|
* it takes into account:
|
|
* Pixel_x/y
|
|
* Matrix x/y
|
|
* Icon width/height
|
|
**/
|
|
/proc/get_visual_offset(atom/checked_atom)
|
|
//Find checked_atom's matrix so we can use its X/Y pixel shifts
|
|
var/matrix/atom_matrix = matrix(checked_atom.transform)
|
|
|
|
var/pixel_x_offset = checked_atom.pixel_x + checked_atom.pixel_w + atom_matrix.get_x_shift()
|
|
var/pixel_y_offset = checked_atom.pixel_y + checked_atom.pixel_z + atom_matrix.get_y_shift()
|
|
|
|
//Irregular objects
|
|
var/list/icon_dimensions = get_icon_dimensions(checked_atom.icon)
|
|
var/checked_atom_icon_height = icon_dimensions["height"]
|
|
var/checked_atom_icon_width = icon_dimensions["width"]
|
|
if(checked_atom_icon_height != ICON_SIZE_Y || checked_atom_icon_width != ICON_SIZE_X)
|
|
pixel_x_offset += ((checked_atom_icon_width / ICON_SIZE_X) - 1) * (ICON_SIZE_X * 0.5)
|
|
pixel_y_offset += ((checked_atom_icon_height / ICON_SIZE_Y) - 1) * (ICON_SIZE_Y * 0.5)
|
|
|
|
return list(pixel_x_offset, pixel_y_offset)
|
|
|
|
/**
|
|
* Takes a turf, and a list of x and y pixel offsets and returns the turf that the offset position best lands in
|
|
**/
|
|
/proc/pixel_offset_turf(turf/offset_from, list/offsets)
|
|
//DY and DX
|
|
var/rough_x = round(round(offsets[1], ICON_SIZE_X) / ICON_SIZE_X)
|
|
var/rough_y = round(round(offsets[2], ICON_SIZE_Y) / ICON_SIZE_Y)
|
|
|
|
var/final_x = clamp(offset_from.x + rough_x, 1, world.maxx)
|
|
var/final_y = clamp(offset_from.y + rough_y, 1, world.maxy)
|
|
|
|
if(final_x || final_y)
|
|
return locate(final_x, final_y, offset_from.z)
|
|
return offset_from
|
|
|
|
///Returns a turf based on text inputs, original turf and viewing client
|
|
/proc/parse_caught_click_modifiers(list/modifiers, turf/origin, client/viewing_client)
|
|
if(!modifiers)
|
|
return null
|
|
|
|
var/screen_loc = splittext(LAZYACCESS(modifiers, SCREEN_LOC), ",")
|
|
var/list/actual_view = getviewsize(viewing_client ? viewing_client.view : world.view)
|
|
var/click_turf_x = splittext(screen_loc[1], ":")
|
|
var/click_turf_y = splittext(screen_loc[2], ":")
|
|
var/click_turf_z = origin.z
|
|
|
|
var/click_turf_px = text2num(click_turf_x[2])
|
|
var/click_turf_py = text2num(click_turf_y[2])
|
|
click_turf_x = origin.x + text2num(click_turf_x[1]) - round(actual_view[1] / 2) - 1
|
|
click_turf_y = origin.y + text2num(click_turf_y[1]) - round(actual_view[2] / 2) - 1
|
|
|
|
var/turf/click_turf = locate(clamp(click_turf_x, 1, world.maxx), clamp(click_turf_y, 1, world.maxy), click_turf_z)
|
|
LAZYSET(modifiers, ICON_X, "[(click_turf_px - click_turf.pixel_x) + ((click_turf_x - click_turf.x) * ICON_SIZE_X)]")
|
|
LAZYSET(modifiers, ICON_Y, "[(click_turf_py - click_turf.pixel_y) + ((click_turf_y - click_turf.y) * ICON_SIZE_Y)]")
|
|
return click_turf
|
|
|
|
///Almost identical to the params_to_turf(), but unused (remove?)
|
|
/proc/screen_loc_to_turf(text, turf/origin, client/C)
|
|
if(!text)
|
|
return null
|
|
var/tZ = splittext(text, ",")
|
|
var/tX = splittext(tZ[1], "-")
|
|
var/tY = text2num(tX[2])
|
|
tX = splittext(tZ[2], "-")
|
|
tX = text2num(tX[2])
|
|
tZ = origin.z
|
|
var/list/actual_view = getviewsize(C ? C.view : world.view)
|
|
tX = clamp(origin.x + round(actual_view[1] / 2) - tX, 1, world.maxx)
|
|
tY = clamp(origin.y + round(actual_view[2] / 2) - tY, 1, world.maxy)
|
|
return locate(tX, tY, tZ)
|
|
|
|
///similar function to RANGE_TURFS(), but will search spiralling outwards from the center (like the above, but only turfs)
|
|
/proc/spiral_range_turfs(dist = 0, center = usr, orange = FALSE, list/outlist = list(), tick_checked)
|
|
outlist.Cut()
|
|
if(!dist)
|
|
outlist += center
|
|
return outlist
|
|
|
|
var/turf/t_center = get_turf(center)
|
|
if(!t_center)
|
|
return outlist
|
|
|
|
var/list/turf_list = outlist
|
|
var/turf/checked_turf
|
|
var/y
|
|
var/x
|
|
var/c_dist = 1
|
|
|
|
if(!orange)
|
|
turf_list += t_center
|
|
|
|
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)
|
|
turf_list += checked_turf
|
|
|
|
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)
|
|
turf_list += checked_turf
|
|
|
|
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)
|
|
turf_list += checked_turf
|
|
|
|
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)
|
|
turf_list += checked_turf
|
|
c_dist++
|
|
if(tick_checked)
|
|
CHECK_TICK
|
|
|
|
return turf_list
|
|
|
|
///Returns a random turf on the station
|
|
/proc/get_random_station_turf()
|
|
var/list/turfs = get_area_turfs(pick(GLOB.the_station_areas))
|
|
if (length(turfs))
|
|
return pick(turfs)
|
|
|
|
///Returns a random turf on the station, excludes dense turfs (like walls) and areas that have valid_territory set to FALSE
|
|
/proc/get_safe_random_station_turf(list/areas_to_pick_from = GLOB.the_station_areas)
|
|
for (var/i in 1 to 5)
|
|
var/list/turf_list = get_area_turfs(pick(areas_to_pick_from))
|
|
var/turf/target
|
|
while (turf_list.len && !target)
|
|
var/I = rand(1, turf_list.len)
|
|
var/turf/checked_turf = turf_list[I]
|
|
var/area/turf_area = get_area(checked_turf)
|
|
if(!checked_turf.density && (turf_area.area_flags & VALID_TERRITORY) && !isgroundlessturf(checked_turf))
|
|
var/clear = TRUE
|
|
for(var/obj/checked_object in checked_turf)
|
|
if(checked_object.density)
|
|
clear = FALSE
|
|
break
|
|
if(clear)
|
|
target = checked_turf
|
|
if (!target)
|
|
turf_list.Cut(I, I + 1)
|
|
if (target)
|
|
return target
|
|
|
|
/**
|
|
* Checks whether the target turf is in a valid state to accept a directional construction
|
|
* such as windows or railings.
|
|
*
|
|
* Returns FALSE if the target turf cannot accept a directional construction.
|
|
* Returns TRUE otherwise.
|
|
*
|
|
* Arguments:
|
|
* * dest_turf - The destination turf to check for existing directional constructions
|
|
* * test_dir - The prospective dir of some atom you'd like to put on this turf.
|
|
* * is_fulltile - Whether the thing you're attempting to move to this turf takes up the entire tile or whether it supports multiple movable atoms on its tile.
|
|
*/
|
|
/proc/valid_build_direction(turf/dest_turf, test_dir, is_fulltile = FALSE)
|
|
if(!dest_turf)
|
|
return FALSE
|
|
for(var/obj/turf_content in dest_turf)
|
|
if(turf_content.obj_flags & BLOCKS_CONSTRUCTION_DIR)
|
|
if(is_fulltile) // for making it so fulltile things can't be built over directional things--a special case
|
|
return FALSE
|
|
if(turf_content.dir == test_dir)
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/**
|
|
* Checks whether or not a particular typepath or subtype of it is present on a turf
|
|
*
|
|
* Returns the first instance located if an instance of the desired type or a subtype of it is found
|
|
* Returns null if the type is not found, or if no turf is supplied
|
|
*
|
|
* Arguments:
|
|
* * location - The turf to be checked for the desired type
|
|
* * type_to_find - The typepath whose presence you are checking for
|
|
*/
|
|
/proc/is_type_on_turf(turf/location, type_to_find)
|
|
if(!location)
|
|
return
|
|
var/found_type = locate(type_to_find) in location
|
|
return found_type
|
|
|
|
/**
|
|
* get_blueprint_data
|
|
* Gets a list of turfs around a central turf and gets the blueprint data in a list
|
|
* Args:
|
|
* - central_turf: The center turf we're getting data from.
|
|
* - viewsize: The viewsize we're getting the turfs around central_turf of.
|
|
*/
|
|
/proc/get_blueprint_data(turf/central_turf, viewsize)
|
|
var/list/blueprint_data_returned = list()
|
|
var/list/dimensions = getviewsize(viewsize)
|
|
var/horizontal_radius = dimensions[1] / 2
|
|
var/vertical_radius = dimensions[2] / 2
|
|
for(var/turf/nearby_turf as anything in RECT_TURFS(horizontal_radius, vertical_radius, central_turf))
|
|
if(nearby_turf.blueprint_data)
|
|
blueprint_data_returned += nearby_turf.blueprint_data
|
|
return blueprint_data_returned
|