Files
Bubberstation/code/__HELPERS/levels.dm
Leland Kemble d99f49d7af Prevent escape pods from being considered "planetary" by the Spacer perk (#92768)
## About The Pull Request

The Spacer perk checked is_on_a_planet(), which checked a few other
things including onSyndieBase(), but onSyndieBase() was made for scoring
purposes(I think) so onSyndieBase() end returns on_escaped_shuttle(),
which is true for escape pods so onSyndieBase() was returning true for
escape pods, so escape pods got syndicate gravity.

This pr only lets the syndicate base give gravity if it's not on a
shuttle, and makes reserved areas by default space(except syndie base).

## Why It's Good For The Game

fixes #81750
fixes #89960

## Changelog
🆑

fix: Escape pods no longer have planetary gravity

/🆑
2025-09-07 11:45:15 +02:00

118 lines
4.2 KiB
Plaintext

/**
* - is_valid_z_level
*
* Checks if source_loc and checking_loc is both on the station, or on the same z level.
* This is because the station's several levels aren't considered the same z, so multi-z stations need this special case.
*
* Args:
* source_loc - turf of the source we're comparing.
* checking_loc - turf we are comparing to source_loc.
*
* returns TRUE if connection is valid, FALSE otherwise.
*/
/proc/is_valid_z_level(turf/source_loc, turf/checking_loc)
// if we're both on "station", regardless of multi-z, we'll pass by.
if(is_station_level(source_loc.z) && is_station_level(checking_loc.z))
return TRUE
if(source_loc.z == checking_loc.z)
return TRUE
return FALSE
/**
* Checks if the passed non-area atom is on a "planet".
*
* A planet is defined as anything with planetary atmos that has gravity, with some hardcoded exceptions.
*
* * Nullspace counts as "not a planet", so you may want to check that separately.
* * The mining z-level (Lavaland) is always considered a planet.
* * The station z-level is considered a planet if the map config says so.
* * Central Command is always not a planet.
* * Syndicate recon outpost is always on a planet.
*
* Returns TRUE if we are on a planet.
* Returns FALSE if we are not in a planet, or otherwise, "in space".
*/
/proc/is_on_a_planet(atom/what)
ASSERT(!isarea(what))
var/turf/open/what_turf = get_turf(what)
if(isnull(what_turf))
// Nullspace is, well, not a planet?
return FALSE
if(is_mining_level(what_turf.z))
// Always assume Lavaland / mining level is a planet. (Asteroid mining crying right now)
return TRUE
if(is_station_level(what_turf.z))
// Station levels rely on the map config, I.E. Icebox is planetary but Meta is not
return SSmapping.is_planetary()
if(is_centcom_level(what_turf.z))
// Central Command is definitely in space
return FALSE
if(what.onSyndieBase() && !what.on_escaped_shuttle())
// Syndicate recon outpost is on some moon or something
return TRUE
if(is_reserved_level(what_turf.z))
// Reserved levels are primarily shuttles aside from syndie base
return FALSE
// Finally, more specific checks are ran for edge cases, such as lazily loaded map templates or away missions. Not perfect.
return istype(what_turf) && what_turf.planetary_atmos && what_turf.has_gravity()
/**
* Gets the angle between two linked z-levels.
* Returns an angle (in degrees) if the z-levels are crosslinked/neighbors,
* or null if they are not.
*
* Arguments:
* * start: The starting Z level. Can either be a numeric z-level, or a [/datum/space_level].
* * end: The destination Z level. Can either be a numeric z-level, or a [/datum/space_level].
*/
/proc/get_linked_z_angle(datum/space_level/start, datum/space_level/end)
if(isnum(start))
start = SSmapping.get_level(start)
if(isnum(end))
end = SSmapping.get_level(end)
// Check the neighbors first, and return the appropiate angle if it is a neighbor.
for(var/direction in start.neigbours)
var/datum/space_level/neighbor = start.neigbours[direction]
if(neighbor == end)
var/angle = GLOB.cardinal_angles[direction]
if(!isnull(angle))
return angle
// Otherwise, if they're both crosslinked, calculate the angle using their grid coordinates.
if(start.linkage == CROSSLINKED && end.linkage == CROSSLINKED)
var/dx = end.xi - start.xi
var/dy = end.yi - start.yi
return round(delta_to_angle(dy, dx))
return null
/**
* Gets all connected z-levels within a given manhattan distance of center.
*
* Arguments:
* * center: The starting Z level. Can either be a numeric z-level, or a [/datun/space_level].
* * dist: The maximum distance to search.
*/
/proc/get_linked_z_levels_in_range(datum/space_level/center, dist)
if(isnum(center))
center = SSmapping.get_level(center)
var/list/to_check = list(center)
var/list/checked = list()
var/total_search_distance = 0
while(to_check.len && total_search_distance <= dist)
var/list/current_pass = to_check.Copy()
to_check.Cut()
for(var/datum/space_level/level as anything in current_pass)
checked[level] = TRUE
for(var/direction in level.neigbours)
var/datum/space_level/neighbor = level.neigbours[direction]
if(!checked[neighbor])
to_check |= neighbor
total_search_distance++
return checked