From cac959e33bc577c5de7ea8b89e10f005074a4f26 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Wed, 14 Jun 2023 22:29:00 -0700 Subject: [PATCH 01/10] Xeno candidate queue --- code/__HELPERS/cmp.dm | 4 +++ code/__HELPERS/game.dm | 36 ++++++++++++------- .../structures/special/pylon_core.dm | 2 +- .../mob/living/carbon/xenomorph/Embryo.dm | 2 +- .../mob/living/carbon/xenomorph/death.dm | 16 +++++---- 5 files changed, 39 insertions(+), 21 deletions(-) diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm index 4ca0edcf43d0..4955a8f6ee6a 100644 --- a/code/__HELPERS/cmp.dm +++ b/code/__HELPERS/cmp.dm @@ -57,3 +57,7 @@ var/atom/cmp_dist_origin=null /proc/cmp_typepaths_asc(A, B) return sorttext("[B]","[A]") + +/// Compares mobs based on their timeofdeath value in ascending order +/proc/cmp_mob_deathtime_asc(mob/A, mob/B) + return A.timeofdeath - B.timeofdeath diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index a0bb9dd98423..f2c5eb93f96a 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -241,32 +241,44 @@ else return get_step(start, EAST) -// Same as above but for alien candidates. -/proc/get_alien_candidates() +/// Get a list of observers that can be alien candidates, optionally sorted by timeofdeath +/proc/get_alien_candidates(sorted = TRUE) var/list/candidates = list() for(var/i in GLOB.observer_list) - var/mob/dead/observer/O = i + var/mob/dead/observer/cur_obs = i + // Preference check + if(!cur_obs.client || !cur_obs.client.prefs || !(cur_obs.client.prefs.be_special & BE_ALIEN_AFTER_DEATH)) + continue + // Jobban check - if(!O.client || !O.client.prefs || !(O.client.prefs.be_special & BE_ALIEN_AFTER_DEATH) || jobban_isbanned(O, JOB_XENOMORPH)) + if(jobban_isbanned(cur_obs, JOB_XENOMORPH)) continue //players that can still be revived are skipped - if(O.mind && O.mind.original && ishuman(O.mind.original)) - var/mob/living/carbon/human/H = O.mind.original - if (H.check_tod() && H.is_revivable()) + if(cur_obs.mind && cur_obs.mind.original && ishuman(cur_obs.mind.original)) + var/mob/living/carbon/human/cur_human = cur_obs.mind.original + if(cur_human.check_tod() && cur_human.is_revivable()) continue // copied from join as xeno - var/deathtime = world.time - O.timeofdeath - if(deathtime < 3000 && ( !O.client.admin_holder || !(O.client.admin_holder.rights & R_ADMIN)) ) + var/deathtime = world.time - cur_obs.timeofdeath + if(deathtime < 3000 && ( !cur_obs.client.admin_holder || !(cur_obs.client.admin_holder.rights & R_ADMIN)) ) continue - // Admins and AFK players cannot be drafted - if(O.client.inactivity / 600 > ALIEN_SELECT_AFK_BUFFER + 5 || (O.client.admin_holder && (O.client.admin_holder.rights & R_MOD)) && O.adminlarva == 0) + // AFK players cannot be drafted + if(cur_obs.client.inactivity / 600 > ALIEN_SELECT_AFK_BUFFER + 5) continue - candidates += O + // Mods with larva protection cannot be drafted + if((cur_obs.client.admin_holder && (cur_obs.client.admin_holder.rights & R_MOD)) && cur_obs.adminlarva == 0) + continue + + candidates += cur_obs + + // Optionally sort by timeofdeath + if(sorted && candidates.len) + candidates = sort_list(candidates, GLOBAL_PROC_REF(cmp_mob_deathtime_asc)) return candidates diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm index 9376e2b6e914..24efc450c3b8 100644 --- a/code/modules/cm_aliens/structures/special/pylon_core.dm +++ b/code/modules/cm_aliens/structures/special/pylon_core.dm @@ -146,7 +146,7 @@ last_larva_time = world.time var/list/players_with_xeno_pref = get_alien_candidates() if(players_with_xeno_pref && players_with_xeno_pref.len && can_spawn_larva()) - spawn_burrowed_larva(pick(players_with_xeno_pref)) + spawn_burrowed_larva(players_with_xeno_pref[1]) if(linked_hive.hijack_burrowed_surge && (last_surge_time + surge_cooldown) < world.time) last_surge_time = world.time diff --git a/code/modules/mob/living/carbon/xenomorph/Embryo.dm b/code/modules/mob/living/carbon/xenomorph/Embryo.dm index e03f225ccade..29c87c3935dd 100644 --- a/code/modules/mob/living/carbon/xenomorph/Embryo.dm +++ b/code/modules/mob/living/carbon/xenomorph/Embryo.dm @@ -157,7 +157,7 @@ var/list/candidates = get_alien_candidates() if(candidates && candidates.len) - picked = pick(candidates) + picked = candidates[1] // Spawn the larva var/mob/living/carbon/xenomorph/larva/new_xeno diff --git a/code/modules/mob/living/carbon/xenomorph/death.dm b/code/modules/mob/living/carbon/xenomorph/death.dm index ce3f55700753..7ba30c4ade1b 100644 --- a/code/modules/mob/living/carbon/xenomorph/death.dm +++ b/code/modules/mob/living/carbon/xenomorph/death.dm @@ -37,12 +37,13 @@ if(GLOB.hive_datum[hivenumber].stored_larva) GLOB.hive_datum[hivenumber].stored_larva = round(GLOB.hive_datum[hivenumber].stored_larva * 0.5) //Lose half on dead queen - var/turf/larva_spawn + var/list/players_with_xeno_pref = get_alien_candidates() - while(GLOB.hive_datum[hivenumber].stored_larva > 0 && istype(GLOB.hive_datum[hivenumber].hive_location, /obj/effect/alien/resin/special/pylon/core)) // stil some left - larva_spawn = get_turf(GLOB.hive_datum[hivenumber].hive_location) - if(players_with_xeno_pref && players_with_xeno_pref.len) - var/mob/xeno_candidate = pick(players_with_xeno_pref) + if(players_with_xeno_pref && istype(GLOB.hive_datum[hivenumber].hive_location, /obj/effect/alien/resin/special/pylon/core)) + var/turf/larva_spawn = get_turf(GLOB.hive_datum[hivenumber].hive_location) + var/count = 1 + while(GLOB.hive_datum[hivenumber].stored_larva > 0 && count <= players_with_xeno_pref.len) // stil some left + var/mob/xeno_candidate = players_with_xeno_pref[count++] var/mob/living/carbon/xenomorph/larva/new_xeno = new /mob/living/carbon/xenomorph/larva(larva_spawn) new_xeno.set_hive_and_update(hivenumber) @@ -50,11 +51,12 @@ if(!SSticker.mode.transfer_xeno(xeno_candidate, new_xeno)) qdel(new_xeno) return + new_xeno.visible_message(SPAN_XENODANGER("A larva suddenly burrows out of the ground!"), SPAN_XENODANGER("You burrow out of the ground after feeling an immense tremor through the hive, which quickly fades into complete silence...")) - GLOB.hive_datum[hivenumber].stored_larva-- - GLOB.hive_datum[hivenumber].hive_ui.update_burrowed_larva() + GLOB.hive_datum[hivenumber].stored_larva-- + GLOB.hive_datum[hivenumber].hive_ui.update_burrowed_larva() if(hive && hive.living_xeno_queen == src) xeno_message(SPAN_XENOANNOUNCE("A sudden tremor ripples through the hive... the Queen has been slain! Vengeance!"),3, hivenumber) From cf148b5c0f65357e416831fbe32163bac4364c31 Mon Sep 17 00:00:00 2001 From: Drathek <76988376+Drulikar@users.noreply.github.com> Date: Fri, 16 Jun 2023 00:36:01 -0700 Subject: [PATCH 02/10] Apply suggestions from code review Co-authored-by: harryob --- code/__HELPERS/game.dm | 2 +- code/modules/mob/living/carbon/xenomorph/death.dm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index f2c5eb93f96a..092c9455b4a5 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -277,7 +277,7 @@ candidates += cur_obs // Optionally sort by timeofdeath - if(sorted && candidates.len) + if(sorted && length(candidates)) candidates = sort_list(candidates, GLOBAL_PROC_REF(cmp_mob_deathtime_asc)) return candidates diff --git a/code/modules/mob/living/carbon/xenomorph/death.dm b/code/modules/mob/living/carbon/xenomorph/death.dm index 7ba30c4ade1b..673a6d12a67b 100644 --- a/code/modules/mob/living/carbon/xenomorph/death.dm +++ b/code/modules/mob/living/carbon/xenomorph/death.dm @@ -42,7 +42,7 @@ if(players_with_xeno_pref && istype(GLOB.hive_datum[hivenumber].hive_location, /obj/effect/alien/resin/special/pylon/core)) var/turf/larva_spawn = get_turf(GLOB.hive_datum[hivenumber].hive_location) var/count = 1 - while(GLOB.hive_datum[hivenumber].stored_larva > 0 && count <= players_with_xeno_pref.len) // stil some left + while(GLOB.hive_datum[hivenumber].stored_larva > 0 && count <= length(players_with_xeno_pref)) // still some left var/mob/xeno_candidate = players_with_xeno_pref[count++] var/mob/living/carbon/xenomorph/larva/new_xeno = new /mob/living/carbon/xenomorph/larva(larva_spawn) new_xeno.set_hive_and_update(hivenumber) From 3008686b35aa6b29137e165f10b7eb790a59e886 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Sun, 18 Jun 2023 05:36:31 -0700 Subject: [PATCH 03/10] Add larva queue messages as it moves --- code/modules/cm_aliens/structures/special/pylon_core.dm | 2 ++ code/modules/mob/living/carbon/xenomorph/Embryo.dm | 2 ++ 2 files changed, 4 insertions(+) diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm index 24efc450c3b8..2c0c1c7845de 100644 --- a/code/modules/cm_aliens/structures/special/pylon_core.dm +++ b/code/modules/cm_aliens/structures/special/pylon_core.dm @@ -147,6 +147,8 @@ var/list/players_with_xeno_pref = get_alien_candidates() if(players_with_xeno_pref && players_with_xeno_pref.len && can_spawn_larva()) spawn_burrowed_larva(players_with_xeno_pref[1]) + for(var/i in 2 to players_with_xeno_pref.len) + to_chat(players_with_xeno_pref[i], SPAN_XENONOTICE("You are now [i-1]\th in the larva queue.")) if(linked_hive.hijack_burrowed_surge && (last_surge_time + surge_cooldown) < world.time) last_surge_time = world.time diff --git a/code/modules/mob/living/carbon/xenomorph/Embryo.dm b/code/modules/mob/living/carbon/xenomorph/Embryo.dm index 29c87c3935dd..d46e58f99ad8 100644 --- a/code/modules/mob/living/carbon/xenomorph/Embryo.dm +++ b/code/modules/mob/living/carbon/xenomorph/Embryo.dm @@ -158,6 +158,8 @@ if(candidates && candidates.len) picked = candidates[1] + for(var/i in 2 to candidates.len) + to_chat(candidates[i], SPAN_XENONOTICE("You are now [i-1]\th in the larva queue.")) // Spawn the larva var/mob/living/carbon/xenomorph/larva/new_xeno From efe04359a6c979af6380cd4193dd0965a29dc7c3 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Mon, 19 Jun 2023 12:08:46 -0700 Subject: [PATCH 04/10] Added repeated message every 2 minutes to update players about the queue. Added count of new players in queue message. Added queue message for queen death event. --- code/__HELPERS/game.dm | 22 +++++++++++++++++++ .../structures/special/pylon_core.dm | 15 ++++++++----- .../mob/living/carbon/xenomorph/Embryo.dm | 3 +-- .../mob/living/carbon/xenomorph/death.dm | 8 ++++--- 4 files changed, 38 insertions(+), 10 deletions(-) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 092c9455b4a5..46086452d293 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -282,6 +282,28 @@ return candidates +/** + * Messages observers that are currently candidates an update on the queue. + * + * Arguments: + * * candidates - The list of observers from get_alien_candidates() with atleast one + * * dequeued - How many candidates to skip messaging because they were dequeued + */ +/proc/message_alien_candidates(list/candidates, dequeued) + var/new_players = 0 + if(dequeued) + for(var/i in (1 + dequeued) to candidates.len) + to_chat(candidates[i], SPAN_XENONOTICE("You are now [i-dequeued]\th in the larva queue. There are [new_players] ahead of you that have yet to play this round.")) + var/mob/dead/observer/cur_obs = candidates[i] + if (!cur_obs.timeofdeath) + new_players++ + else + for(var/i in 1 to candidates.len) + to_chat(candidates[i], SPAN_XENONOTICE("You are currently [i]\th in the larva queue. There are [new_players] ahead of you that have yet to play this round.")) + var/mob/dead/observer/cur_obs = candidates[i] + if (!cur_obs.timeofdeath) + new_players++ + /proc/convert_k2c(temp) return ((temp - T0C)) diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm index 2c0c1c7845de..0b57c4ff3bd2 100644 --- a/code/modules/cm_aliens/structures/special/pylon_core.dm +++ b/code/modules/cm_aliens/structures/special/pylon_core.dm @@ -108,6 +108,7 @@ var/last_healed = 0 var/last_attempt = 0 // logs time of last attempt to prevent spam. if you want to destroy it, you must commit. var/last_larva_time = 0 + var/last_larva_queue_time = 0 var/last_surge_time = 0 var/spawn_cooldown = 30 SECONDS var/surge_cooldown = 90 SECONDS @@ -142,13 +143,17 @@ linked_hive.hive_ui.update_burrowed_larva() qdel(L) - if((last_larva_time + spawn_cooldown) < world.time && can_spawn_larva()) // every minute + var/spawning_larva = can_spawn_larva() && (last_larva_time + spawn_cooldown) < world.time + if(spawning_larva) last_larva_time = world.time + if(spawning_larva || (last_larva_queue_time + spawn_cooldown * 4) < world.time) + last_larva_queue_time = world.time var/list/players_with_xeno_pref = get_alien_candidates() - if(players_with_xeno_pref && players_with_xeno_pref.len && can_spawn_larva()) - spawn_burrowed_larva(players_with_xeno_pref[1]) - for(var/i in 2 to players_with_xeno_pref.len) - to_chat(players_with_xeno_pref[i], SPAN_XENONOTICE("You are now [i-1]\th in the larva queue.")) + if(players_with_xeno_pref && players_with_xeno_pref.len) + if(spawning_larva && spawn_burrowed_larva(players_with_xeno_pref[1])) + message_alien_candidates(players_with_xeno_pref, 1) + else + message_alien_candidates(players_with_xeno_pref, 0) if(linked_hive.hijack_burrowed_surge && (last_surge_time + surge_cooldown) < world.time) last_surge_time = world.time diff --git a/code/modules/mob/living/carbon/xenomorph/Embryo.dm b/code/modules/mob/living/carbon/xenomorph/Embryo.dm index d46e58f99ad8..ee556b2b6fe4 100644 --- a/code/modules/mob/living/carbon/xenomorph/Embryo.dm +++ b/code/modules/mob/living/carbon/xenomorph/Embryo.dm @@ -158,8 +158,7 @@ if(candidates && candidates.len) picked = candidates[1] - for(var/i in 2 to candidates.len) - to_chat(candidates[i], SPAN_XENONOTICE("You are now [i-1]\th in the larva queue.")) + message_alien_candidates(candidates, 1) // Spawn the larva var/mob/living/carbon/xenomorph/larva/new_xeno diff --git a/code/modules/mob/living/carbon/xenomorph/death.dm b/code/modules/mob/living/carbon/xenomorph/death.dm index 673a6d12a67b..9870c485e15a 100644 --- a/code/modules/mob/living/carbon/xenomorph/death.dm +++ b/code/modules/mob/living/carbon/xenomorph/death.dm @@ -41,9 +41,9 @@ var/list/players_with_xeno_pref = get_alien_candidates() if(players_with_xeno_pref && istype(GLOB.hive_datum[hivenumber].hive_location, /obj/effect/alien/resin/special/pylon/core)) var/turf/larva_spawn = get_turf(GLOB.hive_datum[hivenumber].hive_location) - var/count = 1 - while(GLOB.hive_datum[hivenumber].stored_larva > 0 && count <= length(players_with_xeno_pref)) // still some left - var/mob/xeno_candidate = players_with_xeno_pref[count++] + var/count = 0 + while(GLOB.hive_datum[hivenumber].stored_larva > 0 && count < length(players_with_xeno_pref)) // still some left + var/mob/xeno_candidate = players_with_xeno_pref[++count] var/mob/living/carbon/xenomorph/larva/new_xeno = new /mob/living/carbon/xenomorph/larva(larva_spawn) new_xeno.set_hive_and_update(hivenumber) @@ -57,6 +57,8 @@ GLOB.hive_datum[hivenumber].stored_larva-- GLOB.hive_datum[hivenumber].hive_ui.update_burrowed_larva() + if(count) + message_alien_candidates(players_with_xeno_pref, count) if(hive && hive.living_xeno_queen == src) xeno_message(SPAN_XENOANNOUNCE("A sudden tremor ripples through the hive... the Queen has been slain! Vengeance!"),3, hivenumber) From 13ea554900c8fd769465e24c5c92acd136fb9580 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Mon, 19 Jun 2023 12:41:45 -0700 Subject: [PATCH 05/10] Refactor message_alien_candidates --- code/__HELPERS/game.dm | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 46086452d293..4d6ef5fa75ab 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -291,18 +291,11 @@ */ /proc/message_alien_candidates(list/candidates, dequeued) var/new_players = 0 - if(dequeued) - for(var/i in (1 + dequeued) to candidates.len) - to_chat(candidates[i], SPAN_XENONOTICE("You are now [i-dequeued]\th in the larva queue. There are [new_players] ahead of you that have yet to play this round.")) - var/mob/dead/observer/cur_obs = candidates[i] - if (!cur_obs.timeofdeath) - new_players++ - else - for(var/i in 1 to candidates.len) - to_chat(candidates[i], SPAN_XENONOTICE("You are currently [i]\th in the larva queue. There are [new_players] ahead of you that have yet to play this round.")) - var/mob/dead/observer/cur_obs = candidates[i] - if (!cur_obs.timeofdeath) - new_players++ + for(var/i in (1 + dequeued) to candidates.len) + to_chat(candidates[i], SPAN_XENONOTICE("You are [dequeued ? "now" : "currently"] [i-dequeued]\th in the larva queue. There are [new_players] ahead of you that have yet to play this round.")) + var/mob/dead/observer/cur_obs = candidates[i] + if(!cur_obs.timeofdeath) + new_players++ /proc/convert_k2c(temp) return ((temp - T0C)) From a7b64511d461f5dbbd71961c0cd6ce233133c386 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Thu, 22 Jun 2023 07:01:48 -0700 Subject: [PATCH 06/10] Facehugger death/infect and admin level deaths no longer affect your queue ordering value Queue messages are now cached and can be queried with the join xeno action Refactoring --- code/__HELPERS/cmp.dm | 5 ++++ code/__HELPERS/game.dm | 30 ++++++++++++------- code/game/gamemodes/cm_initialize.dm | 22 +++++++++++++- code/modules/client/client_defines.dm | 2 ++ .../structures/special/pylon_core.dm | 4 +-- code/modules/mob/dead/observer/observer.dm | 15 ++++++++-- .../mob/living/carbon/xenomorph/Embryo.dm | 2 +- .../carbon/xenomorph/castes/Facehugger.dm | 1 + .../mob/living/carbon/xenomorph/death.dm | 2 +- code/modules/shuttle/shuttle.dm | 16 +++++----- 10 files changed, 72 insertions(+), 27 deletions(-) diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm index 4955a8f6ee6a..888e3c2ce657 100644 --- a/code/__HELPERS/cmp.dm +++ b/code/__HELPERS/cmp.dm @@ -61,3 +61,8 @@ var/atom/cmp_dist_origin=null /// Compares mobs based on their timeofdeath value in ascending order /proc/cmp_mob_deathtime_asc(mob/A, mob/B) return A.timeofdeath - B.timeofdeath + +/// Compares observers based on their larva_queue_time value in ascending order +/// Assumes the client on the observer is not null +/proc/cmp_obs_larvaqueuetime_asc(mob/dead/observer/A, mob/dead/observer/B) + return A.client.larva_queue_time - B.client.larva_queue_time diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 4d6ef5fa75ab..e3191628f688 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -241,12 +241,11 @@ else return get_step(start, EAST) -/// Get a list of observers that can be alien candidates, optionally sorted by timeofdeath +/// Get a list of observers that can be alien candidates, optionally sorted by larva_queue_time /proc/get_alien_candidates(sorted = TRUE) var/list/candidates = list() - for(var/i in GLOB.observer_list) - var/mob/dead/observer/cur_obs = i + for(var/mob/dead/observer/cur_obs as anything in GLOB.observer_list) // Preference check if(!cur_obs.client || !cur_obs.client.prefs || !(cur_obs.client.prefs.be_special & BE_ALIEN_AFTER_DEATH)) continue @@ -263,22 +262,22 @@ // copied from join as xeno var/deathtime = world.time - cur_obs.timeofdeath - if(deathtime < 3000 && ( !cur_obs.client.admin_holder || !(cur_obs.client.admin_holder.rights & R_ADMIN)) ) + if(deathtime < (5 MINUTES) && ( !cur_obs.client.admin_holder || !(cur_obs.client.admin_holder.rights & R_ADMIN)) ) continue // AFK players cannot be drafted - if(cur_obs.client.inactivity / 600 > ALIEN_SELECT_AFK_BUFFER + 5) + if(cur_obs.client.inactivity / (1 MINUTES) > ALIEN_SELECT_AFK_BUFFER + 5) continue // Mods with larva protection cannot be drafted - if((cur_obs.client.admin_holder && (cur_obs.client.admin_holder.rights & R_MOD)) && cur_obs.adminlarva == 0) + if((cur_obs.client.admin_holder && (cur_obs.client.admin_holder.rights & R_MOD)) && !cur_obs.adminlarva) continue candidates += cur_obs - // Optionally sort by timeofdeath + // Optionally sort by larva_queue_time if(sorted && length(candidates)) - candidates = sort_list(candidates, GLOBAL_PROC_REF(cmp_mob_deathtime_asc)) + candidates = sort_list(candidates, GLOBAL_PROC_REF(cmp_obs_larvaqueuetime_asc)) return candidates @@ -288,13 +287,22 @@ * Arguments: * * candidates - The list of observers from get_alien_candidates() with atleast one * * dequeued - How many candidates to skip messaging because they were dequeued + * * cache_only - Whether to not actually send a to_chat message and instead only update larva_queue_cached_message */ -/proc/message_alien_candidates(list/candidates, dequeued) +/proc/message_alien_candidates(list/candidates, dequeued, cache_only = FALSE) var/new_players = 0 for(var/i in (1 + dequeued) to candidates.len) - to_chat(candidates[i], SPAN_XENONOTICE("You are [dequeued ? "now" : "currently"] [i-dequeued]\th in the larva queue. There are [new_players] ahead of you that have yet to play this round.")) var/mob/dead/observer/cur_obs = candidates[i] - if(!cur_obs.timeofdeath) + + // Generate the messages + var/cached_message = SPAN_XENONOTICE("You are currently [i-dequeued]\th in the larva queue. There are [new_players] ahead of you that have yet to play this round.") + cur_obs.larva_queue_cached_message = cached_message + if(!cache_only) + var/chat_message = dequeued ? replacetext(cached_message, "currently", "now") : cached_message + to_chat(candidates[i], chat_message) + + // Count how many are prioritized + if(cur_obs.client.larva_queue_time < 2) // 0 and 1 because facehuggers/t-domers are slightly deprioritized new_players++ /proc/convert_k2c(temp) diff --git a/code/game/gamemodes/cm_initialize.dm b/code/game/gamemodes/cm_initialize.dm index 8237fc63b7e2..bc588c82c12f 100644 --- a/code/game/gamemodes/cm_initialize.dm +++ b/code/game/gamemodes/cm_initialize.dm @@ -364,7 +364,27 @@ Additional game mode variables. available_xenos[larva_option] = list(hive) if(!available_xenos.len || (instant_join && !available_xenos_non_ssd.len)) - to_chat(xeno_candidate, SPAN_WARNING("There aren't any available xenomorphs or burrowed larvae. You can try getting spawned as a chestburster larva by toggling your Xenomorph candidacy in Preferences -> Toggle SpecialRole Candidacy.")) + if(!xeno_candidate.client || !xeno_candidate.client.prefs || !(xeno_candidate.client.prefs.be_special & BE_ALIEN_AFTER_DEATH)) + to_chat(xeno_candidate, SPAN_WARNING("There aren't any available xenomorphs or burrowed larvae. You can try getting spawned as a chestburster larva by toggling your Xenomorph candidacy in Preferences -> Toggle SpecialRole Candidacy.")) + return FALSE + to_chat(xeno_candidate, SPAN_WARNING("There aren't any available xenomorphs or burrowed larvae.")) + + // Give the player a cached message of their queue status if they are an observer + var/mob/dead/observer/candidate_observer = xeno_candidate + if(istype(candidate_observer)) + if(candidate_observer.larva_queue_cached_message) + to_chat(xeno_candidate, candidate_observer.larva_queue_cached_message) + return FALSE + + // No cache, lets check now then + message_alien_candidates(get_alien_candidates(), dequeued = 0, cache_only = TRUE) + if(candidate_observer.larva_queue_cached_message) + to_chat(xeno_candidate, candidate_observer.larva_queue_cached_message) + return FALSE + + // We aren't in queue yet, lets teach them about the queue then + candidate_observer.larva_queue_cached_message = SPAN_XENONOTICE("You are currently still awaiting assignment in the larva queue. Priority is given to players who have yet to play in the round, but otherwise the ordering is based on your time of death. When you have been dead long enough and are not inactive, you will periodically receive messages where you are in the queue relative to other currently valid xeno candidates. Note: Playing as a facehugger or in the thunderdome will not alter your time of death. This means you won't lose your relative place in queue if you step away, disconnect, play as a facehugger, or play in the thunderdome.") + to_chat(xeno_candidate, candidate_observer.larva_queue_cached_message) return FALSE var/mob/living/carbon/xenomorph/new_xeno diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index 8f0939474427..fbec4aa13f36 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -26,6 +26,8 @@ var/adminobs = null var/area = null var/time_died_as_mouse = null //when the client last died as a mouse + /// The descriminator for larva queue ordering: Generally set to timeofdeath except for facehuggers/admin z-level play + var/larva_queue_time var/donator = 0 var/adminhelped = 0 diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm index 0b57c4ff3bd2..f3f271ea2ca5 100644 --- a/code/modules/cm_aliens/structures/special/pylon_core.dm +++ b/code/modules/cm_aliens/structures/special/pylon_core.dm @@ -151,9 +151,9 @@ var/list/players_with_xeno_pref = get_alien_candidates() if(players_with_xeno_pref && players_with_xeno_pref.len) if(spawning_larva && spawn_burrowed_larva(players_with_xeno_pref[1])) - message_alien_candidates(players_with_xeno_pref, 1) + message_alien_candidates(players_with_xeno_pref, dequeued = 1) else - message_alien_candidates(players_with_xeno_pref, 0) + message_alien_candidates(players_with_xeno_pref, dequeued = 0) if(linked_hive.hijack_burrowed_surge && (last_surge_time + surge_cooldown) < world.time) last_surge_time = world.time diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index f48efa96578d..f59ba19d6c74 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -33,8 +33,8 @@ plane = GHOST_PLANE layer = ABOVE_FLY_LAYER stat = DEAD - var/adminlarva = 0 - var/ghostvision = 1 + var/adminlarva = FALSE + var/ghostvision = TRUE var/can_reenter_corpse var/started_as_observer //This variable is set to 1 when you enter the game as an observer. //If you died in the game and are a ghost - this will remain as null. @@ -45,7 +45,7 @@ "Squad HUD" = FALSE, "Xeno Status HUD" = FALSE ) - universal_speak = 1 + universal_speak = TRUE var/updatedir = TRUE //Do we have to update our dir as the ghost moves around? var/atom/movable/following = null var/datum/orbit_menu/orbit_menu @@ -55,6 +55,8 @@ var/own_orbit_size = 0 var/observer_actions = list(/datum/action/observer_action/join_xeno) var/datum/action/minimap/observer/minimap + var/larva_queue_cached_message + alpha = 127 /mob/dead/observer/verb/toggle_ghostsee() @@ -363,6 +365,12 @@ Works together with spawning an observer, noted above. if(ghost.client.player_data) ghost.client.player_data.load_timestat_data() + // Larva queue: We use the larger of their existing queue time or the new timeofdeath except for facehuggers + // We don't change facehugger timeofdeath because they are still on cooldown if they died as a hugger + // Facehuggers are atleast 1 because they did get some action compared to those at 0 timeofdeath + var/new_tod = isfacehugger(src) ? 1 : ghost.timeofdeath + ghost.client.larva_queue_time = max(ghost.client.larva_queue_time, new_tod) + ghost.set_huds_from_prefs() return ghost @@ -405,6 +413,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp var/mob/dead/observer/ghost = ghostize((is_nested && nest && !QDELETED(nest))) //FALSE parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3 if(ghost && !is_admin_level(z)) ghost.timeofdeath = world.time + ghost.client?.larva_queue_time = world.time if(is_nested && nest && !QDELETED(nest)) ghost.can_reenter_corpse = FALSE diff --git a/code/modules/mob/living/carbon/xenomorph/Embryo.dm b/code/modules/mob/living/carbon/xenomorph/Embryo.dm index ee556b2b6fe4..a74c82026dbe 100644 --- a/code/modules/mob/living/carbon/xenomorph/Embryo.dm +++ b/code/modules/mob/living/carbon/xenomorph/Embryo.dm @@ -158,7 +158,7 @@ if(candidates && candidates.len) picked = candidates[1] - message_alien_candidates(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/castes/Facehugger.dm b/code/modules/mob/living/carbon/xenomorph/castes/Facehugger.dm index d9ab8a1e849d..c0b57af9d3db 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Facehugger.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Facehugger.dm @@ -155,6 +155,7 @@ for(var/mob/dead/observer/observer as anything in GLOB.observer_list) to_chat(observer, SPAN_DEADSAY("[human] has been facehugged by [src]" + " [OBSERVER_JMP(observer, human)]")) to_chat(src, SPAN_DEADSAY("[human] has been facehugged by [src]")) + timeofdeath = 1 // Ever so slightly deprioritized for larva queue qdel(src) if(hug_area) xeno_message(SPAN_XENOMINORWARNING("You sense that [src] has facehugged a host at \the [hug_area]!"), 1, src.hivenumber) diff --git a/code/modules/mob/living/carbon/xenomorph/death.dm b/code/modules/mob/living/carbon/xenomorph/death.dm index 9870c485e15a..f3534318f673 100644 --- a/code/modules/mob/living/carbon/xenomorph/death.dm +++ b/code/modules/mob/living/carbon/xenomorph/death.dm @@ -58,7 +58,7 @@ GLOB.hive_datum[hivenumber].stored_larva-- GLOB.hive_datum[hivenumber].hive_ui.update_burrowed_larva() if(count) - message_alien_candidates(players_with_xeno_pref, count) + message_alien_candidates(players_with_xeno_pref, dequeued = count) if(hive && hive.living_xeno_queen == src) xeno_message(SPAN_XENOANNOUNCE("A sudden tremor ripples through the hive... the Queen has been slain! Vengeance!"),3, hivenumber) diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 77ba9681ebb6..7e181ed470cb 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -628,15 +628,15 @@ /obj/docking_port/mobile/proc/intoTheSunset() // Loop over mobs - for(var/t in return_turfs()) - var/turf/T = t - for(var/mob/living/L in T.GetAllContents()) + for(var/turf/turf as anything in return_turfs()) + for(var/mob/living/mob in turf.GetAllContents()) // Ghostize them and put them in nullspace stasis (for stat & possession checks) - //L.notransform = TRUE - var/mob/dead/observer/O = L.ghostize(FALSE) - if(O) - O.timeofdeath = world.time - L.moveToNullspace() + //mob.notransform = TRUE + var/mob/dead/observer/obs = mob.ghostize(FALSE) + if(obs) + obs.timeofdeath = world.time + obs.client?.larva_queue_time = world.time + mob.moveToNullspace() // Now that mobs are stowed, delete the shuttle jumpToNullSpace() From 684f02c49782f66ea33a301833c043998c062207 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Thu, 22 Jun 2023 07:02:06 -0700 Subject: [PATCH 07/10] Fix gibbed humans not properly checking admin z-level --- code/modules/mob/dead/observer/observer.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index f59ba19d6c74..44ecf5b5e781 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -329,8 +329,8 @@ Works together with spawning an observer, noted above. ghost.langchat_make_image() SStgui.on_transfer(src, ghost) - if(is_admin_level(z)) - ghost.timeofdeath = 0 // Bypass respawn limit if you die on the admin zlevel + if(is_admin_level((get_turf(src))?.z)) // Gibbed humans ghostize the brain in their head which itself is z 0 + ghost.timeofdeath = 1 // Bypass respawn limit if you die on the admin zlevel ghost.key = key ghost.mind = mind From 0c787214731fc7694bec0ddff4e90b27b5424bc5 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Thu, 22 Jun 2023 07:02:35 -0700 Subject: [PATCH 08/10] Fix shuttle.intoTheSunset() throwing bad del errors --- code/modules/shuttle/helpers.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/modules/shuttle/helpers.dm b/code/modules/shuttle/helpers.dm index 14cfcc3cd691..1d841581faa0 100644 --- a/code/modules/shuttle/helpers.dm +++ b/code/modules/shuttle/helpers.dm @@ -8,7 +8,8 @@ /datum/door_controller/aggregate/Destroy(force, ...) . = ..() - QDEL_NULL_LIST(door_controllers) + QDEL_LIST_ASSOC_VAL(door_controllers) + door_controllers = null /datum/door_controller/aggregate/proc/set_label(label) for(var/datum/door_controller/single/cont in door_controllers) From 20e40053ba122ee2be73ca44e75990c056b89406 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Thu, 22 Jun 2023 07:44:07 -0700 Subject: [PATCH 09/10] Fix/add some comments --- code/__HELPERS/game.dm | 2 +- code/modules/cm_aliens/structures/special/pylon_core.dm | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index e3191628f688..f2721a5ccb00 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -285,7 +285,7 @@ * Messages observers that are currently candidates an update on the queue. * * Arguments: - * * candidates - The list of observers from get_alien_candidates() with atleast one + * * candidates - The list of observers from get_alien_candidates() * * dequeued - How many candidates to skip messaging because they were dequeued * * cache_only - Whether to not actually send a to_chat message and instead only update larva_queue_cached_message */ diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm index f3f271ea2ca5..08aa2f86c1bc 100644 --- a/code/modules/cm_aliens/structures/special/pylon_core.dm +++ b/code/modules/cm_aliens/structures/special/pylon_core.dm @@ -151,8 +151,10 @@ var/list/players_with_xeno_pref = get_alien_candidates() if(players_with_xeno_pref && players_with_xeno_pref.len) if(spawning_larva && spawn_burrowed_larva(players_with_xeno_pref[1])) + // We were in spawning_larva mode and successfully spawned someone message_alien_candidates(players_with_xeno_pref, dequeued = 1) else + // Just time to update everyone their queue status (or the spawn failed) message_alien_candidates(players_with_xeno_pref, dequeued = 0) if(linked_hive.hijack_burrowed_surge && (last_surge_time + surge_cooldown) < world.time) From e4b086161cf695d7a7181e6aeb7fb253394142c0 Mon Sep 17 00:00:00 2001 From: Drulikar Date: Thu, 22 Jun 2023 15:49:38 -0700 Subject: [PATCH 10/10] Standardize xeno wait times into defines --- code/__DEFINES/mobs.dm | 2 -- code/__DEFINES/xeno.dm | 16 ++++++++++++++++ code/__HELPERS/_time.dm | 4 ---- code/__HELPERS/game.dm | 4 ++-- code/_onclick/observer.dm | 4 ++-- code/game/gamemodes/cm_initialize.dm | 14 +++++++------- 6 files changed, 27 insertions(+), 17 deletions(-) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 495b5fb472c5..ba928e202cf0 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -11,8 +11,6 @@ #define OVEREAT_TIME 200 //================================================= -#define ALIEN_SELECT_AFK_BUFFER 1 // How many minutes that a person can be AFK before not being allowed to be an alien. - #define HEAT_DAMAGE_LEVEL_1 2 //Amount of damage applied when your body temperature just passes the 360.15k safety point #define HEAT_DAMAGE_LEVEL_2 4 //Amount of damage applied when your body temperature passes the 400K point #define HEAT_DAMAGE_LEVEL_3 8 //Amount of damage applied when your body temperature passes the 1000K point diff --git a/code/__DEFINES/xeno.dm b/code/__DEFINES/xeno.dm index 6d6bd64ea918..7741beecedef 100644 --- a/code/__DEFINES/xeno.dm +++ b/code/__DEFINES/xeno.dm @@ -154,6 +154,22 @@ #define WEED_BASE_GROW_SPEED (5 SECONDS) #define WEED_BASE_DECAY_SPEED (10 SECONDS) +/// The time you must be dead to join as a xeno larva +#define XENO_JOIN_DEAD_LARVA_TIME (2.5 MINUTES) +/// The time you must be dead to join as xeno (not larva) +#define XENO_JOIN_DEAD_TIME (5 MINUTES) +/// The time of inactivity you cannot exceed to join as a xeno +#define XENO_JOIN_AFK_TIME_LIMIT (5 MINUTES) +/// The amount of time after round start before buried larva spawns are disallowed +#define XENO_BURIED_LARVA_TIME_LIMIT (30 MINUTES) + +/// The time against away_timer when an AFK xeno larva can be replaced +#define XENO_LEAVE_TIMER_LARVA 80 //80 seconds +/// The time against away_timer when an AFK xeno (not larva) can be replaced +#define XENO_LEAVE_TIMER 300 //300 seconds +/// The time against away_timer when an AFK xeno gets listed in the available list so ghosts can get ready +#define XENO_AVAILABLE_TIMER 60 //60 seconds + /// Between 2% to 10% of explosion severity #define WEED_EXPLOSION_DAMAGEMULT rand(2, 10)*0.01 diff --git a/code/__HELPERS/_time.dm b/code/__HELPERS/_time.dm index 85acafa0e2f6..b929ae8636b3 100644 --- a/code/__HELPERS/_time.dm +++ b/code/__HELPERS/_time.dm @@ -15,10 +15,6 @@ #define DECISECONDS_TO_HOURS /36000 -#define XENO_LEAVE_TIMER_LARVA 80 //80 seconds -#define XENO_LEAVE_TIMER 300 //300 seconds -#define XENO_AVAILABLE_TIMER 60 //60 seconds, when to add a xeno to the avaliable list so ghosts can get ready - var/midnight_rollovers = 0 var/rollovercheck_last_timeofday = 0 diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index f2721a5ccb00..61976f4dc903 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -262,11 +262,11 @@ // copied from join as xeno var/deathtime = world.time - cur_obs.timeofdeath - if(deathtime < (5 MINUTES) && ( !cur_obs.client.admin_holder || !(cur_obs.client.admin_holder.rights & R_ADMIN)) ) + if(deathtime < XENO_JOIN_DEAD_TIME && ( !cur_obs.client.admin_holder || !(cur_obs.client.admin_holder.rights & R_ADMIN)) ) continue // AFK players cannot be drafted - if(cur_obs.client.inactivity / (1 MINUTES) > ALIEN_SELECT_AFK_BUFFER + 5) + if(cur_obs.client.inactivity > XENO_JOIN_AFK_TIME_LIMIT) continue // Mods with larva protection cannot be drafted diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm index 21ac66e5f222..5acfe74f2965 100644 --- a/code/_onclick/observer.dm +++ b/code/_onclick/observer.dm @@ -45,11 +45,11 @@ return FALSE var/deathtime = world.time - timeofdeath - if(deathtime < 2.5 MINUTES) + if(deathtime < XENO_JOIN_DEAD_LARVA_TIME) var/message = "You have been dead for [DisplayTimeText(deathtime)]." message = SPAN_WARNING("[message]") to_chat(src, message) - to_chat(src, SPAN_WARNING("You must wait 2.5 minutes before rejoining the game!")) + to_chat(src, SPAN_WARNING("You must wait atleast 2.5 minutes before rejoining the game!")) ManualFollow(target) return FALSE diff --git a/code/game/gamemodes/cm_initialize.dm b/code/game/gamemodes/cm_initialize.dm index bc588c82c12f..2f6dc6e38118 100644 --- a/code/game/gamemodes/cm_initialize.dm +++ b/code/game/gamemodes/cm_initialize.dm @@ -354,7 +354,7 @@ Additional game mode variables. var/datum/hive_status/hive for(var/hivenumber in GLOB.hive_datum) hive = GLOB.hive_datum[hivenumber] - if(!hive.hardcore && hive.stored_larva && (hive.hive_location || (world.time < 30 MINUTES + SSticker.round_start_time))) + if(!hive.hardcore && hive.stored_larva && (hive.hive_location || (world.time < XENO_BURIED_LARVA_TIME_LIMIT + SSticker.round_start_time))) if(SSticker.mode && (SSticker.mode.flags_round_type & MODE_RANDOM_HIVE)) available_xenos |= "any buried larva" LAZYADD(available_xenos["any buried larva"], hive) @@ -397,11 +397,11 @@ Additional game mode variables. if(!xeno_bypass_timer) var/deathtime = world.time - xeno_candidate.timeofdeath if(isnewplayer(xeno_candidate)) - deathtime = 2.5 MINUTES //so new players don't have to wait to latejoin as xeno in the round's first 5 mins. - if(deathtime < 2.5 MINUTES && !check_client_rights(xeno_candidate.client, R_ADMIN, FALSE)) + deathtime = XENO_JOIN_DEAD_LARVA_TIME //so new players don't have to wait to latejoin as xeno in the round's first 5 mins. + if(deathtime < XENO_JOIN_DEAD_LARVA_TIME && !check_client_rights(xeno_candidate.client, R_ADMIN, FALSE)) var/message = SPAN_WARNING("You have been dead for [DisplayTimeText(deathtime)].") to_chat(xeno_candidate, message) - to_chat(xeno_candidate, SPAN_WARNING("You must wait 2.5 minutes before rejoining the game as a buried larva!")) + to_chat(xeno_candidate, SPAN_WARNING("You must wait 2 minutes and 30 seconds before rejoining the game as a buried larva!")) return FALSE for(var/mob_name in picked_hive.banished_ckeys) @@ -413,7 +413,7 @@ Additional game mode variables. noob.close_spawn_windows() if(picked_hive.hive_location) picked_hive.hive_location.spawn_burrowed_larva(xeno_candidate) - else if((world.time < 30 MINUTES + SSticker.round_start_time)) + else if((world.time < XENO_BURIED_LARVA_TIME_LIMIT + SSticker.round_start_time)) picked_hive.do_buried_larva_spawn(xeno_candidate) else to_chat(xeno_candidate, SPAN_WARNING("Seems like something went wrong. Try again?")) @@ -437,8 +437,8 @@ Additional game mode variables. if(!xeno_bypass_timer) var/deathtime = world.time - xeno_candidate.timeofdeath if(istype(xeno_candidate, /mob/new_player)) - deathtime = 5 MINUTES //so new players don't have to wait to latejoin as xeno in the round's first 5 mins. - if(deathtime < 5 MINUTES && !check_client_rights(xeno_candidate.client, R_ADMIN, FALSE)) + deathtime = XENO_JOIN_DEAD_TIME //so new players don't have to wait to latejoin as xeno in the round's first 5 mins. + if(deathtime < XENO_JOIN_DEAD_TIME && !check_client_rights(xeno_candidate.client, R_ADMIN, FALSE)) var/message = "You have been dead for [DisplayTimeText(deathtime)]." message = SPAN_WARNING("[message]") to_chat(xeno_candidate, message)