diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index e4e8ff64c19c..1eb555fceaf7 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -505,7 +505,11 @@ name = "queen locator" icon = 'icons/mob/hud/alien_standard.dmi' icon_state = "trackoff" - var/list/track_state = list(TRACKER_QUEEN, 0) + /// A weak reference to the atom currently being tracked. + /// (Note: This is null for `TRACKER_QUEEN` and `TRACKER_HIVE`, as those are accessed through the user's hive datum.) + var/datum/weakref/tracking_ref = null + /// The 'category' of the atom currently being tracked. (Defaults to `TRACKER_QUEEN`) + var/tracker_type = TRACKER_QUEEN /atom/movable/screen/queen_locator/clicked(mob/living/carbon/xenomorph/user, mods) if(!istype(user)) @@ -520,28 +524,26 @@ if(mods["alt"]) var/list/options = list() if(user.hive.living_xeno_queen) - options["Queen"] = list(TRACKER_QUEEN, 0) + // Don't need weakrefs to this or the hive core, since there's only one possible target. + options["Queen"] = list(null, TRACKER_QUEEN) if(user.hive.hive_location) - options["Hive Core"] = list(TRACKER_HIVE, 0) + options["Hive Core"] = list(null, TRACKER_HIVE) - var/xeno_leader_index = 1 - for(var/xeno in user.hive.xeno_leader_list) - var/mob/living/carbon/xenomorph/xeno_lead = user.hive.xeno_leader_list[xeno_leader_index] - if(xeno_lead) - options["Xeno Leader [xeno_lead]"] = list(TRACKER_LEADER, xeno_leader_index) - xeno_leader_index++ + for(var/mob/living/carbon/xenomorph/leader in user.hive.xeno_leader_list) + options["Xeno Leader [leader]"] = list(leader, TRACKER_LEADER) var/list/sorted_tunnels = sort_list_dist(user.hive.tunnels, get_turf(user)) - var/tunnel_index = 1 - for(var/obj/structure/tunnel/tunnel in sorted_tunnels) - options["Tunnel [tunnel.tunnel_desc]"] = list(TRACKER_TUNNEL, tunnel_index) - tunnel_index++ + for(var/obj/structure/tunnel/tunnel as anything in sorted_tunnels) + options["Tunnel [tunnel.tunnel_desc]"] = list(tunnel, TRACKER_TUNNEL) - var/selected = tgui_input_list(user, "Select what you want the locator to track.", "Locator Options", options) + var/list/selected = tgui_input_list(user, "Select what you want the locator to track.", "Locator Options", options) if(selected) - track_state = options[selected] + var/selected_data = options[selected] + tracking_ref = WEAKREF(selected_data[1]) // Weakref to the tracked atom (or null) + tracker_type = selected_data[2] // Tracker category return + if(!user.hive.living_xeno_queen) to_chat(user, SPAN_WARNING("Our hive doesn't have a living queen!")) return FALSE @@ -549,6 +551,12 @@ return FALSE user.overwatch(user.hive.living_xeno_queen) +// Reset to the defaults +/atom/movable/screen/queen_locator/proc/reset_tracking() + icon_state = "trackoff" + tracking_ref = null + tracker_type = TRACKER_QUEEN + /atom/movable/screen/xenonightvision icon = 'icons/mob/hud/alien_standard.dmi' name = "toggle night vision" diff --git a/code/modules/mob/living/carbon/xenomorph/life.dm b/code/modules/mob/living/carbon/xenomorph/life.dm index aab61776118d..d5ca8a41fa39 100644 --- a/code/modules/mob/living/carbon/xenomorph/life.dm +++ b/code/modules/mob/living/carbon/xenomorph/life.dm @@ -391,75 +391,52 @@ Make sure their actual health updates immediately.*/ hud_set_plasma() //update plasma amount on the plasma mob_hud /mob/living/carbon/xenomorph/proc/queen_locator() - if(!hud_used || !hud_used.locate_leader) + if(!hud_used?.locate_leader) return - var/atom/movable/screen/queen_locator/QL = hud_used.locate_leader - if(!loc) - QL.icon_state = "trackoff" + var/atom/movable/screen/queen_locator/locator = hud_used.locate_leader + if(!loc || !hive) + locator.reset_tracking() return var/atom/tracking_atom - switch(QL.track_state[1]) + switch(locator.tracker_type) if(TRACKER_QUEEN) - if(!hive || !hive.living_xeno_queen) - QL.icon_state = "trackoff" - return tracking_atom = hive.living_xeno_queen if(TRACKER_HIVE) - if(!hive || !hive.hive_location) - QL.icon_state = "trackoff" - return tracking_atom = hive.hive_location if(TRACKER_LEADER) - if(!QL.track_state[2]) - QL.icon_state = "trackoff" - return - - var/leader_tracker = QL.track_state[2] - - if(!hive || !hive.xeno_leader_list) - QL.icon_state = "trackoff" - return - if(leader_tracker > hive.xeno_leader_list.len) - QL.icon_state = "trackoff" - return - if(!hive.xeno_leader_list[leader_tracker]) - QL.icon_state = "trackoff" - return - tracking_atom = hive.xeno_leader_list[leader_tracker] + var/atom/leader = locator.tracking_ref?.resolve() + // If the leader exists, and is actually in the leader list. + if(leader && (leader in hive.xeno_leader_list)) + tracking_atom = leader if(TRACKER_TUNNEL) - if(!QL.track_state[2]) - QL.icon_state = "trackoff" - return + tracking_atom = locator.tracking_ref?.resolve() - var/tunnel_tracker = QL.track_state[2] + // If the atom can't be found/has been deleted. + if(!tracking_atom) + var/already_tracking_queen = (locator.tracker_type == TRACKER_QUEEN) - if(!hive || !hive.tunnels) - QL.icon_state = "trackoff" - return - if(tunnel_tracker > hive.tunnels.len) - QL.icon_state = "trackoff" - return - if(!hive.tunnels[tunnel_tracker]) - QL.icon_state = "trackoff" - return - tracking_atom = hive.tunnels[tunnel_tracker] + // Reset the tracker back to the queen. + locator.reset_tracking() - if(!tracking_atom) - QL.icon_state = "trackoff" + // If it wasn't the queen that couldn't be found above, try again with her as the target. + // This is just to avoid the tracker going blank for one life tick. + // (There's no risk of an infinite loop here since `locator.tracker_type` just got set to `TRACKER_QUEEN`.) + if(!already_tracking_queen) + queen_locator() return if(tracking_atom.loc.z != loc.z || get_dist(src, tracking_atom) < 1 || src == tracking_atom) - QL.icon_state = "trackondirect" + locator.icon_state = "trackondirect" else - var/area/A = get_area(loc) - var/area/QA = get_area(tracking_atom.loc) - if(A.fake_zlevel == QA.fake_zlevel) - QL.setDir(Get_Compass_Dir(src, tracking_atom)) - QL.icon_state = "trackon" + var/area/our_area = get_area(loc) + var/area/target_area = get_area(tracking_atom.loc) + if(our_area.fake_zlevel == target_area.fake_zlevel) + locator.setDir(Get_Compass_Dir(src, tracking_atom)) + locator.icon_state = "trackon" else - QL.icon_state = "trackondirect" + locator.icon_state = "trackondirect" /mob/living/carbon/xenomorph/proc/mark_locator() if(!hud_used || !hud_used.locate_marker || !tracked_marker.loc || !loc)