diff --git a/code/modules/mob/living/carbon/xenomorph/Embryo.dm b/code/modules/mob/living/carbon/xenomorph/Embryo.dm
index b599e9b5567a..3d660b56f09b 100644
--- a/code/modules/mob/living/carbon/xenomorph/Embryo.dm
+++ b/code/modules/mob/living/carbon/xenomorph/Embryo.dm
@@ -147,59 +147,92 @@
affected_mob.take_limb_damage(1)
if(5)
become_larva()
- if(6)
+ if(7) // Stage 6 is while we are trying to find a candidate in become_larva
larva_autoburst_countdown--
if(!larva_autoburst_countdown)
var/mob/living/carbon/xenomorph/larva/larva_embryo = locate() in affected_mob
if(larva_embryo)
larva_embryo.chest_burst(affected_mob)
-//We look for a candidate. If found, we spawn the candidate as a larva
-//Order of priority is bursted individual (if xeno is enabled), then random candidate, and then it's up for grabs and spawns braindead
+///We look for a candidate. If found, we spawn the candidate as a larva
+///Order of priority is bursted individual (if xeno is enabled), then player hugger, then random candidate, and then it's up for grabs and spawns braindead
/obj/item/alien_embryo/proc/become_larva()
// We do not allow chest bursts on the Centcomm Z-level, to prevent
// stranded players from admin experiments and other issues
if(!affected_mob || is_admin_level(affected_mob.z))
return
- var/datum/hive_status/hive = GLOB.hive_datum[hivenumber]
+ stage = 6 // Increase the stage value to prevent this proc getting repeated
+ var/datum/hive_status/hive = GLOB.hive_datum[hivenumber]
var/mob/picked
+ var/mob/dead/observer/hugger = null
+ var/is_nested = istype(affected_mob.buckled, /obj/structure/bed/nest)
+
// If the bursted person themselves has Xeno enabled, they get the honor of first dibs on the new larva.
- if((!isyautja(affected_mob) || (isyautja(affected_mob) && prob(20))) && istype(affected_mob.buckled, /obj/structure/bed/nest))
+ if((!isyautja(affected_mob) || (isyautja(affected_mob) && prob(20))) && is_nested)
if(affected_mob.first_xeno || (affected_mob.client?.prefs?.be_special & BE_ALIEN_AFTER_DEATH && !jobban_isbanned(affected_mob, JOB_XENOMORPH)))
picked = affected_mob
else if(affected_mob.mind?.ghost_mob && affected_mob.client?.prefs?.be_special & BE_ALIEN_AFTER_DEATH && !jobban_isbanned(affected_mob, JOB_XENOMORPH))
picked = affected_mob.mind.ghost_mob // This currently doesn't look possible
else if(affected_mob.persistent_ckey)
for(var/mob/dead/observer/cur_obs as anything in GLOB.observer_list)
+ if(!cur_obs)
+ continue
if(cur_obs.ckey != affected_mob.persistent_ckey)
continue
- if(cur_obs?.client?.prefs?.be_special & BE_ALIEN_AFTER_DEATH && !jobban_isbanned(cur_obs, JOB_XENOMORPH))
+ if(cur_obs.client?.prefs?.be_special & BE_ALIEN_AFTER_DEATH && !jobban_isbanned(cur_obs, JOB_XENOMORPH))
picked = cur_obs
break
if(!picked)
// Get a candidate from observers
var/list/candidates = get_alien_candidates(hive)
- if(candidates && candidates.len)
+ if(candidates && length(candidates))
// If they were facehugged by a player thats still in queue, they get second dibs on the new larva.
if(hugger_ckey)
for(var/mob/dead/observer/cur_obs as anything in candidates)
if(cur_obs.ckey == hugger_ckey)
- picked = cur_obs
- candidates -= cur_obs
- message_alien_candidates(candidates, dequeued = 0)
- for(var/obj/item/alien_embryo/embryo as anything in GLOB.player_embryo_list)
- if(embryo.hugger_ckey == cur_obs.ckey && embryo != src)
- // Skipping src just in case an admin wants to quickly check before this thing fully deletes
- // If this nulls out any embryo, wow
- embryo.hugger_ckey = null
+ hugger = cur_obs
+ if(!is_nested)
+ cur_obs.ManualFollow(affected_mob)
+ if(cur_obs.client.prefs?.toggles_flashing & FLASH_POOLSPAWN)
+ window_flash(cur_obs.client)
+ if(is_nested || tgui_alert(cur_obs, "An unnested host you hugged is about to burst! Do you want to control the new larva?", "Larva maturation", list("Yes", "No"), 10 SECONDS) == "Yes")
+ picked = cur_obs
+ candidates -= cur_obs
+ message_alien_candidates(candidates, dequeued = 0)
+ for(var/obj/item/alien_embryo/embryo as anything in GLOB.player_embryo_list)
+ if(!embryo)
+ continue
+ if(embryo.hugger_ckey == cur_obs.ckey && embryo != src)
+ // Skipping src just in case an admin wants to quickly check before this thing fully deletes
+ // If this nulls out any embryo, wow
+ embryo.hugger_ckey = null
break
+ // Get a candidate from the front of the queue
if(!picked)
- picked = candidates[1]
- message_alien_candidates(candidates, dequeued = 1)
+ if(is_nested)
+ picked = candidates[1]
+ message_alien_candidates(candidates, dequeued = 1)
+ else
+ // Make up to 10 attempts from the queue for an unnested host
+ // At 10s per candidate, for 11 candidates (facehugger is the +1) this means we may have delayed an unnested autoburst up to 110 seconds
+ for(var/i in 1 to min(10, length(candidates)))
+ var/mob/dead/observer/cur_candidate = candidates[i]
+ if(!cur_candidate?.client) // Make sure they are still a valid candidate since tgui_alerts may have delayed us to this point
+ continue
+ if(cur_candidate == hugger)
+ continue // They were already asked
+ cur_candidate.ManualFollow(affected_mob)
+ if(cur_candidate.client.prefs?.toggles_flashing & FLASH_POOLSPAWN)
+ window_flash(cur_candidate.client)
+ if(tgui_alert(cur_candidate, "An unnested host is about to burst! Do you want to control the new larva?", "Larva maturation", list("Yes", "No"), 10 SECONDS) == "Yes")
+ picked = cur_candidate
+ candidates -= cur_candidate
+ message_alien_candidates(candidates, dequeued = 0)
+ break
// Spawn the larva
var/mob/living/carbon/xenomorph/larva/new_xeno
@@ -247,7 +280,7 @@
to_chat(observer, SPAN_DEADSAY("A [new_xeno.hive.prefix]Larva is about to chestburst out of [affected_mob]! [OBSERVER_JMP(observer, affected_mob)]"))
to_chat(src, SPAN_DEADSAY("A [new_xeno.hive.prefix]Larva is about to chestburst out of [affected_mob]!"))
- stage = 6
+ stage = 7 // Begin the autoburst countdown
/mob/living/carbon/xenomorph/larva/proc/cause_unbearable_pain(mob/living/carbon/victim)
if(loc != victim)