diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index 187f179094b2..e2203aadce0c 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -23,6 +23,7 @@ GLOBAL_LIST_EMPTY_TYPED(alive_human_list, /mob/living/carbon/human) // list of a GLOBAL_LIST_EMPTY_TYPED(xeno_mob_list, /mob/living/carbon/xenomorph) GLOBAL_LIST_EMPTY_TYPED(living_xeno_list, /mob/living/carbon/xenomorph) GLOBAL_LIST_EMPTY_TYPED(xeno_cultists, /mob/living/carbon/human) +GLOBAL_LIST_EMPTY_TYPED(player_embryo_list, /obj/item/alien_embryo) GLOBAL_LIST_EMPTY_TYPED(hellhound_list, /mob/living/carbon/xenomorph/hellhound) GLOBAL_LIST_EMPTY_TYPED(zombie_list, /mob/living/carbon/human) diff --git a/code/modules/mob/living/carbon/xenomorph/Embryo.dm b/code/modules/mob/living/carbon/xenomorph/Embryo.dm index a74c82026dbe..29779480f143 100644 --- a/code/modules/mob/living/carbon/xenomorph/Embryo.dm +++ b/code/modules/mob/living/carbon/xenomorph/Embryo.dm @@ -12,6 +12,8 @@ var/hivenumber = XENO_HIVE_NORMAL var/faction = FACTION_XENOMORPH var/flags_embryo = FALSE // Used in /ciphering/predator property + /// The ckey of any player hugger that made this embryo + var/hugger_ckey /obj/item/alien_embryo/Initialize(mapload, ...) . = ..() @@ -33,6 +35,7 @@ C.med_hud_set_status() STOP_PROCESSING(SSobj, src) affected_mob = null + GLOB.player_embryo_list -= src . = ..() /obj/item/alien_embryo/process() @@ -145,20 +148,33 @@ var/mob/picked // 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))) && istype(affected_mob.buckled, /obj/structure/bed/nest)) if(affected_mob.first_xeno || (affected_mob.client && affected_mob.client.prefs && (affected_mob.client.prefs.be_special & BE_ALIEN_AFTER_DEATH) && !jobban_isbanned(affected_mob, JOB_XENOMORPH))) picked = affected_mob else if(affected_mob.mind && affected_mob.mind.ghost_mob && affected_mob.client && affected_mob.client.prefs && (affected_mob.client.prefs.be_special & BE_ALIEN_AFTER_DEATH) && !jobban_isbanned(affected_mob, JOB_XENOMORPH)) picked = affected_mob.mind.ghost_mob - if(!picked) // Get a candidate from observers var/list/candidates = get_alien_candidates() - if(candidates && candidates.len) - picked = candidates[1] - message_alien_candidates(candidates, dequeued = 1) + // 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 + break + + if(!picked) + picked = candidates[1] + message_alien_candidates(candidates, dequeued = 1) // Spawn the larva var/mob/living/carbon/xenomorph/larva/new_xeno diff --git a/code/modules/mob/living/carbon/xenomorph/Facehuggers.dm b/code/modules/mob/living/carbon/xenomorph/Facehuggers.dm index 121a231b7bf8..212688c8c98f 100644 --- a/code/modules/mob/living/carbon/xenomorph/Facehuggers.dm +++ b/code/modules/mob/living/carbon/xenomorph/Facehuggers.dm @@ -241,46 +241,46 @@ throw_atom(target, 3, SPEED_FAST) return TRUE -/obj/item/clothing/mask/facehugger/proc/attach(mob/living/M, silent = FALSE, knockout_mod = 1) - if(attached || !can_hug(M, hivenumber)) +/obj/item/clothing/mask/facehugger/proc/attach(mob/living/living_mob, silent = FALSE, knockout_mod = 1, hugger_ckey = null) + if(attached || !can_hug(living_mob, hivenumber)) return FALSE // This is always going to be valid because of the can_hug check above - var/mob/living/carbon/human/H = M + var/mob/living/carbon/human/human = living_mob if(!silent) - H.visible_message(SPAN_DANGER("[src] leaps at [H]'s face!")) + human.visible_message(SPAN_DANGER("[src] leaps at [human]'s face!")) if(isxeno(loc)) //Being carried? Drop it var/mob/living/carbon/xenomorph/X = loc X.drop_inv_item_on_ground(src) - if(isturf(H.loc)) - forceMove(H.loc)//Just checkin + if(isturf(human.loc)) + forceMove(human.loc)//Just checkin - if(!H.handle_hugger_attachment(src)) + if(!human.handle_hugger_attachment(src)) return FALSE attached = TRUE - forceMove(H) + forceMove(human) icon_state = initial(icon_state) - H.equip_to_slot(src, WEAR_FACE) - H.update_inv_wear_mask() - H.disable_lights() - H.disable_special_items() - if(ishuman_strict(H)) - playsound(loc, H.gender == "male" ? 'sound/misc/facehugged_male.ogg' : 'sound/misc/facehugged_female.ogg' , 25, 0) - else if(isyautja(H)) + human.equip_to_slot(src, WEAR_FACE) + human.update_inv_wear_mask() + human.disable_lights() + human.disable_special_items() + if(ishuman_strict(human)) + playsound(loc, human.gender == "male" ? 'sound/misc/facehugged_male.ogg' : 'sound/misc/facehugged_female.ogg' , 25, 0) + else if(isyautja(human)) playsound(loc, 'sound/voice/pred_facehugged.ogg', 65, FALSE) if(!sterile) - if(!H.species || !(H.species.flags & IS_SYNTHETIC)) //synthetics aren't paralyzed - H.apply_effect(MIN_IMPREGNATION_TIME * 0.5 * knockout_mod, PARALYZE) //THIS MIGHT NEED TWEAKS + if(!human.species || !(human.species.flags & IS_SYNTHETIC)) //synthetics aren't paralyzed + human.apply_effect(MIN_IMPREGNATION_TIME * 0.5 * knockout_mod, PARALYZE) //THIS MIGHT NEED TWEAKS - addtimer(CALLBACK(src, PROC_REF(impregnate), H), rand(MIN_IMPREGNATION_TIME, MAX_IMPREGNATION_TIME)) + addtimer(CALLBACK(src, PROC_REF(impregnate), human, hugger_ckey), rand(MIN_IMPREGNATION_TIME, MAX_IMPREGNATION_TIME)) return TRUE -/obj/item/clothing/mask/facehugger/proc/impregnate(mob/living/carbon/human/target) +/obj/item/clothing/mask/facehugger/proc/impregnate(mob/living/carbon/human/target, hugger_ckey = null) if(!target || target.wear_mask != src) //Was taken off or something return if(SEND_SIGNAL(target, COMSIG_HUMAN_IMPREGNATE, src) & COMPONENT_NO_IMPREGNATE) @@ -295,6 +295,8 @@ if(!embryos) var/obj/item/alien_embryo/embryo = new /obj/item/alien_embryo(target) embryo.hivenumber = hivenumber + embryo.hugger_ckey = hugger_ckey + GLOB.player_embryo_list += embryo embryo.flags_embryo = flags_embryo flags_embryo = NO_FLAGS diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Facehugger.dm b/code/modules/mob/living/carbon/xenomorph/castes/Facehugger.dm index c0b57af9d3db..1b8ac2ee05dc 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Facehugger.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Facehugger.dm @@ -143,9 +143,9 @@ /mob/living/carbon/xenomorph/facehugger/proc/handle_hug(mob/living/carbon/human/human) var/obj/item/clothing/mask/facehugger/hugger = new /obj/item/clothing/mask/facehugger(loc, hivenumber) - var/did_hug = hugger.attach(human, TRUE, 0.5) + var/did_hug = hugger.attach(human, TRUE, 0.5, client?.ckey) if(client) - client?.player_data?.adjust_stat(PLAYER_STAT_FACEHUGS, STAT_CATEGORY_XENO, 1) + client.player_data?.adjust_stat(PLAYER_STAT_FACEHUGS, STAT_CATEGORY_XENO, 1) var/area/hug_area = get_area(src) if(hug_area) for(var/mob/dead/observer/observer as anything in GLOB.observer_list)