From 2fd2feec50bf12faa1a95c511d695330c5107529 Mon Sep 17 00:00:00 2001 From: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Date: Sat, 4 Mar 2023 02:09:33 -0600 Subject: [PATCH] Fixes hijacked shuttles not counting as escaped, cleans up associated code (#73623) ## About The Pull Request Fixes #72240 So, in the past, `onCentCom` ran a check at the end that said "if we're on centcom z, in centcom area, or in shuttle that is endgame launched: return TRUE" Meanwhile its brother `onSyndieBase` did not need to run the same checks, because it was also on the centcom z-level. This meant that for the purposes of `considered_escaped`, `onCentCom` pretty much entirely eclipsed `onSyndieBase`, only mattering for, well, Nuke Ops So the fix was simple - add the check for "in shuttle that is engame launched" to `onSyndieBase`. I took this opportunity to do a quick audit of associated "escaped" and "alive" code. Did you know that hardcore random only checked that you were on centcom to award survival points? Instead of any other checks for escaped like stat? Also the ancient "romerol zombies can't be used as an easy way to greentext escape" was broken, because it checked the wrong species ID? Bonus performance optimization: `in area` -> `in area.get_contained_turfs()` ## Why It's Good For The Game Hijack does not turn around to become an L ## Changelog :cl: Melbert fix: Hijacked shuttles now count as "escaping alive" once agian fix: Hardcore random survival now actually checks that you've escaped alive, and not just made it to centcom fix: Intelligent zombies can now escape. fix: Infectious zombies now don't count as escaped as intended. /:cl: --- code/__DEFINES/shuttles.dm | 3 ++ code/__HELPERS/game.dm | 26 +++++++++--- code/__HELPERS/roundend.dm | 2 +- code/game/atoms.dm | 67 +++++++++++++++++++++---------- code/game/gamemodes/objective.dm | 13 +++++- code/modules/shuttle/emergency.dm | 5 +-- code/modules/shuttle/shuttle.dm | 3 +- 7 files changed, 85 insertions(+), 34 deletions(-) diff --git a/code/__DEFINES/shuttles.dm b/code/__DEFINES/shuttles.dm index 1d721ef3f1d..5380268e979 100644 --- a/code/__DEFINES/shuttles.dm +++ b/code/__DEFINES/shuttles.dm @@ -29,8 +29,11 @@ //Launching Shuttles to CentCom #define NOLAUNCH -1 #define UNLAUNCHED 0 +/// This shuttle launched to head to end game (or has arrived there), it will not update further #define ENDGAME_LAUNCHED 1 #define EARLY_LAUNCHED 2 +/// "Endgame transit" denotes shuttles which "fly into the sunset" when the round ends, such as the whiteship. +/// These shuttles leave when the main emergency shuttle does but don't dock anywhere (to save space), so this counts as "escaped". #define ENDGAME_TRANSIT 3 //positive value = cannot puchase diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 87434afaa3d..cdd9d6b7e4f 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -68,16 +68,30 @@ return player_mob return null -///Returns true if the mob that a player is controlling is alive +/** + * Checks if the passed mind has a mob that is "alive" + * + * * player_mind - who to check for alive status + * * enforce_human - if TRUE, the checks fails if the mind's mob is a silicon, brain, or infectious zombie. + * + * Returns TRUE if they're alive, FALSE otherwise + */ /proc/considered_alive(datum/mind/player_mind, enforce_human = TRUE) if(player_mind?.current) if(enforce_human) - var/mob/living/carbon/human/player_mob - if(ishuman(player_mind.current)) - player_mob = player_mind.current - return player_mind.current.stat != DEAD && !issilicon(player_mind.current) && !isbrain(player_mind.current) && (!player_mob || player_mob.dna.species.id != SPECIES_ZOMBIE) + var/mob/living/carbon/human/player_mob = player_mind.current + + if(player_mob.stat == DEAD) + return FALSE + if(issilicon(player_mob) || isbrain(player_mob)) + return FALSE + if(istype(player_mob) && (player_mob.dna?.species?.id == SPECIES_ZOMBIE_INFECTIOUS)) + return FALSE + return TRUE + else if(isliving(player_mind.current)) - return player_mind.current.stat != DEAD + return (player_mind.current.stat != DEAD) + return FALSE /** diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 4fbae9e45ca..8692c635609 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -197,7 +197,7 @@ if(!didthegamerwin) return FALSE player_client.give_award(/datum/award/score/hardcore_random, human_mob, round(human_mob.hardcore_survival_score * 2)) - else if(human_mob.onCentCom()) + else if(considered_escaped(human_mob)) player_client.give_award(/datum/award/score/hardcore_random, human_mob, round(human_mob.hardcore_survival_score)) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index f15babe17eb..ac05c5b082c 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -409,42 +409,36 @@ return !density /** - * Is this atom currently located on centcom + * 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 shuttleshuttle during endgame transit + * 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)) - for(var/obj/docking_port/mobile/mobile_docking_port as anything in SSshuttle.mobile_docking_ports) - if(mobile_docking_port.launch_status != ENDGAME_TRANSIT) - continue - for(var/area/shuttle/shuttle_area as anything in mobile_docking_port.shuttle_areas) - if(current_turf in shuttle_area) - return TRUE + return on_escaped_shuttle(ENDGAME_TRANSIT) - if(!is_centcom_level(current_turf.z))//if not, don't bother + // From here on we only concern ourselves with people actually on the centcom Z + if(!is_centcom_level(current_turf.z)) return FALSE - //Check for centcom itself if(istype(current_turf.loc, /area/centcom)) return TRUE - //Check for centcom shuttles - for(var/obj/docking_port/mobile/mobile_docking_port as anything in SSshuttle.mobile_docking_ports) - if(mobile_docking_port.launch_status == ENDGAME_LAUNCHED) - for(var/place as anything in mobile_docking_port.shuttle_areas) - var/area/shuttle/shuttle_area = place - if(current_turf in shuttle_area) - return TRUE + // Finally, check if we're on an escaped shuttle + return on_escaped_shuttle() /** * Is the atom in any of the syndicate areas @@ -452,18 +446,49 @@ * 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 - if(!is_reserved_level(current_turf.z))//if not, don't bother + // Syndicate base is loaded in a reserved level. If not reserved, we don't care. + if(!is_reserved_level(current_turf.z)) return FALSE - if(istype(current_turf.loc, /area/shuttle/syndicate) || istype(current_turf.loc, /area/centcom/syndicate_mothership) || istype(current_turf.loc, /area/shuttle/assault_pod)) + 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 /** diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 263e867756f..29413b6ae00 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -64,22 +64,31 @@ GLOBAL_LIST(admin_objective_list) //Prefilled admin assignable objective list * Escaped mobs are used to check certain antag objectives / results. * * Escaped includes minds with alive, non-exiled mobs generally. + * + * Returns TRUE if they're a free person, or FALSE if they failed */ /proc/considered_escaped(datum/mind/escapee) if(!considered_alive(escapee)) return FALSE if(considered_exiled(escapee)) return FALSE + // "Into the sunset" force escaping for forced escape success if(escapee.force_escaped) return TRUE - if(SSticker.force_ending || GLOB.station_was_nuked) // Just let them win. + // Station destroying events (blob, cult, nukies)? Just let them win, even if there was no hope of escape + if(SSticker.force_ending || GLOB.station_was_nuked) return TRUE + // Escape hasn't happened yet if(SSshuttle.emergency.mode != SHUTTLE_ENDGAME) return FALSE var/area/current_area = get_area(escapee.current) - if(!current_area || istype(current_area, /area/shuttle/escape/brig)) // Fails if they are in the shuttle brig + // In custody (shuttle brig) does not count as escaping + if(!current_area || istype(current_area, /area/shuttle/escape/brig)) return FALSE var/turf/current_turf = get_turf(escapee.current) + if(!current_turf) + return FALSE + // Finally, if we made it to centcom (or the syndie base - got hijacked), we're home free return current_turf.onCentCom() || current_turf.onSyndieBase() /datum/objective/proc/check_completion() diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index c9ae3ff0bad..3f4838fc438 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -540,9 +540,8 @@ if(time_left <= 0) //move each escape pod to its corresponding escape dock - for(var/A in SSshuttle.mobile_docking_ports) - var/obj/docking_port/mobile/M = A - M.on_emergency_dock() + for(var/obj/docking_port/mobile/port as anything in SSshuttle.mobile_docking_ports) + port.on_emergency_dock() // now move the actual emergency shuttle to centcom // unless the shuttle is "hijacked" diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index a4cc3a543d6..d287511fe9e 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -1135,7 +1135,8 @@ //Called when emergency shuttle docks at centcom /obj/docking_port/mobile/proc/on_emergency_dock() - //Mapping a new docking point for each ship mappers could potentially want docking with centcom would take up lots of space, just let them keep flying off into the sunset for their greentext + // Mapping a new docking point for each ship mappers could potentially want docking with centcom would take up lots of space, + // just let them keep flying off "into the sunset" for their greentext. if(launch_status == ENDGAME_LAUNCHED) launch_status = ENDGAME_TRANSIT