Files
LordMEandGitHub 8ef9cb5abe fixes overflow spawnpoints not being registered (#5830)
<!-- Write **BELOW** The Headers and **ABOVE** The comments else it may
not be viewable. -->
<!-- You can view Contributing.MD for a detailed description of the pull
request process. -->

## About The Pull Request

<!-- Describe The Pull Request. Please be sure every change is
documented or this can delay review and even discourage maintainers from
merging your PR! -->

## Why It's Good For The Game

<!-- Argue for the merits of your changes and how they benefit the game,
especially if they are controversial and/or far reaching. If you can't
actually explain WHY what you are doing will improve the game, then it
probably isn't good for the game in the first place. -->

## Changelog

<!-- If your PR modifies aspects of the game that can be concretely
observed by players or admins you should add a changelog. If your change
does NOT meet this description, remove this section. Be sure to properly
mark your PRs to prevent unnecessary GBP loss. You can read up on GBP
and it's effects on PRs in the tgstation guides for contributors. Please
note that maintainers freely reserve the right to remove and add tags
should they deem it appropriate. You can attempt to finagle the system
all you want, but it's best to shoot for clear communication right off
the bat. -->

🆑
fix: Fixed the subsystem not registering overflow spawnpoints
/🆑

<!-- Both 🆑's are required for the changelog to work! You can put
your name to the right of the first 🆑 if you want to overwrite your
GitHub username as author ingame. -->
<!-- You can use multiple of the same prefix (they're only used for the
icon ingame) and delete the unneeded ones. Despite some of the tags,
changelogs should generally represent how a player might be affected by
the changes rather than a summary of the PR's contents. -->
2023-08-04 22:36:52 -07:00

214 lines
7.3 KiB
Plaintext

//* This file is explicitly licensed under the MIT license. *//
//* Copyright (c) 2023 Citadel Station developers. *//
/datum/controller/subsystem/job
/// All spawnpoints
var/static/list/spawnpoints = list()
/// Job spawnpoints keyed to job id/typepath
var/static/list/job_spawnpoints = list()
/// Generic latejoin spawnpoints, nested list faction = list()
var/static/list/latejoin_spawnpoints = list()
/// Generic overflow spawnpoints, nested list faction = list()
var/static/list/overflow_spawnpoints = list()
/// Custom spawnpoints, nested list key = list()
var/static/list/custom_spawnpoints = list()
/**
* Fully resets spawnpoints list and ensures validity
*/
/datum/controller/subsystem/job/proc/reconstruct_spawnpoints()
spawnpoints = list()
job_spawnpoints = list()
latejoin_spawnpoints = list()
overflow_spawnpoints = list()
custom_spawnpoints = list()
// O(2n) but sue me
for(var/obj/landmark/spawnpoint/S in GLOB.landmarks_list)
spawnpoints += S
for(var/obj/landmark/spawnpoint/job/S in GLOB.landmarks_list)
if(!S.job_path)
continue
LAZYDISTINCTADD(job_spawnpoints[S.job_path], S)
for(var/obj/landmark/spawnpoint/latejoin/S in GLOB.landmarks_list)
if(!S.faction)
continue
LAZYDISTINCTADD(latejoin_spawnpoints[S.faction], S)
for(var/obj/landmark/spawnpoint/overflow/S in GLOB.landmarks_list)
if(!S.faction)
continue
LAZYDISTINCTADD(overflow_spawnpoints[S.faction], S)
for(var/obj/landmark/spawnpoint/custom/S in GLOB.landmarks_list)
if(!S.key)
continue
LAZYDISTINCTADD(custom_spawnpoints[S.key], S)
/**
* Gets a valid spawnpoint to use for a roundstart spawn
*
* @params
* - M - the mob being spawned
* - C - (optional) the client of the player
* - job_path - (optional) path to job
* - faction - what faction the player is in terms of job factions
* - random - deterministic first pick or random?
* - harder - used when the first iteration failed, tells spawnpoints to skip certain checks
*
*/
/datum/controller/subsystem/job/proc/get_roundstart_spawnpoint(mob/M, client/C, job_path, faction, random = TRUE, harder = FALSE)
RETURN_TYPE(/obj/landmark/spawnpoint)
if(random)
. = list()
// Priority 1: Job specific spawnpoints
if(job_path && length(job_spawnpoints[job_path]))
for(var/obj/landmark/spawnpoint/job/J as anything in job_spawnpoints[job_path])
if(!J.roundstart)
continue
if(!J.Available(M, C, harder))
continue
if(random)
. += J
else
return J
if(random && length(.))
return pick(.)
// Priority 2: Overflow spawnpoints as a last resort
if(length(overflow_spawnpoints[faction]))
for(var/obj/landmark/spawnpoint/overflow/S as anything in overflow_spawnpoints[faction])
if(!S.Available(M, C, harder))
continue
if(random)
. += S
else
return S
if(random && length(.))
return pick(.)
if(!harder)
subsystem_log("get_roundstart_spawnpoint() failed to get a spawnpoint, trying against with harder = TRUE")
return get_roundstart_spawnpoint(M, C, job_path, faction, random, TRUE)
else
CRASH("get_roundstart_spawnpoint() failed to get a spawnpoint.")
/**
* Gets a spawnpoint to use for a latejoin spawn
* Note that there's no mob argument, since latejoin won't make the mob until there's a free spawnpoint
*
* This is not a random pick, this is first priority-availability first server and fully deterministic.
*
* @params
* - C - (optional) the client of the player
* - job_path - (optional) path to job
* - faction - what faction the player is in terms of job factions
* - method - (optional) required method for the spawnpoint - this will make the proc return null instead of an overflow, if it can't find something for the method.
* - random - deterministic first pick or random?
* - harder - used when the first iteration failed, tells spawnpoints to skip certain checks
*/
/datum/controller/subsystem/job/proc/get_latejoin_spawnpoint(client/C, job_path, faction = JOB_FACTION_STATION, method, random = TRUE, harder = FALSE)
RETURN_TYPE(/obj/landmark/spawnpoint)
if(random)
. = list() // Priority 1: Job specific spawnpoints
if(job_path && length(job_spawnpoints[job_path]))
for(var/obj/landmark/spawnpoint/job/J as anything in job_spawnpoints[job_path])
if(!J.latejoin)
continue
if(!J.latejoin_override && method && (method != J.method))
continue
if(!J.Available(null, C, harder))
continue
if(random)
. += J
else
return J
if(random && length(.))
return pick(.)
// Priority 2: Latejoin spawnpoints, if latejoin
if(length(latejoin_spawnpoints[faction]))
for(var/obj/landmark/spawnpoint/latejoin/S as anything in latejoin_spawnpoints[faction])
if(!S.Available(null, C, harder))
continue
if(method && (S.method != method))
continue
if(random)
. += S
else
return S
if(random && length(.))
return pick(.)
// Priority 3: Overflow spawnpoints as a last resort
if(length(overflow_spawnpoints[faction]))
for(var/obj/landmark/spawnpoint/overflow/S as anything in overflow_spawnpoints[faction])
if(!S.Available(null, C, harder))
continue
if(random)
. += S
else
return S
if(random)
if(length(.))
return pick(.)
else
. = null
if(!harder)
subsystem_log("get_latejoin_spawnpoint() failed to get a spawnpoint, trying against with harder = TRUE")
return get_roundstart_spawnpoint(C, job_path, faction, method, random, TRUE)
else
. = null
CRASH("get_latejoin_spawnpoint() failed to get a spawnpoint.")
/**
* Gets a list of possible join methods
*
* If latejoining and a job-specific spawnpoint has latejoin override, only that method will be returned
*
* The "harder" argument is automatically set to TRUE here, as we're checking for all possibilities.
*
* @params
* - C - (optional) the client of the player
* - job_path - (optional) path to job
* - faction - what faction the player is in terms of job factions
*/
/datum/controller/subsystem/job/proc/possible_latejoin_spawnpoints(client/C, job_path, faction)
. = list()
// Get all job specific methods, and allow for override if needed
if(job_path && length(job_spawnpoints[job_path]))
for(var/obj/landmark/spawnpoint/job/J as anything in job_spawnpoints[job_path])
if(!J.latejoin)
continue
if(J.latejoin_override)
return list(J.method)
if(J.Available(null, C, TRUE))
continue
. |= J.method
// Get all standard latejoin methods
if(length(latejoin_spawnpoints[faction]))
for(var/obj/landmark/spawnpoint/latejoin/S as anything in latejoin_spawnpoints[faction])
if(!S.Available(null, C, TRUE))
continue
. |= S.method
// If there's none, add overflow method if overflow spawnpoints exist
if(!length(.) && length(overflow_spawnpoints[faction]))
for(var/obj/landmark/spawnpoint/overflow/S as anything in overflow_spawnpoints[faction])
if(S.Available(null, C, TRUE))
return list("Overflow")
/**
* Gets a valid custom spawnpoint to use by key
*
* @params
* - M - (optional) mob being spawned
* - C - (optional) client of player
* - key - spawnpoint key to look for
*/
/datum/controller/subsystem/job/proc/get_custom_spawnpoint(mob/M, client/C, key)
if(!length(custom_spawnpoints[key]))
return
for(var/obj/landmark/spawnpoint/S as anything in custom_spawnpoints[key])
if(!S.Available(M, C))
continue
return S
/**
* Get all spawnpoint landmarks
*/
/datum/controller/subsystem/job/proc/get_all_spawnpoints()
return spawnpoints