diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index 1eafc222a52a..204755a9ad9b 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -313,15 +313,25 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) /obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/update_state() ..() if(inoperable()) - handle_xeno_acquisition(get_turf(src)) + handle_xeno_acquisition() + +/// Locates a nearby cluster from GLOB.all_xeno_pylon_cluster_nodes otherwise null +/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/proc/find_nearby_cluster() + for(var/obj/effect/alien/weeds/node/pylon/cluster/cluster as anything in GLOB.all_xeno_pylon_cluster_nodes) + if(cluster.is_in_range(src)) + return cluster + return null /// Handles xenos corrupting the tower when weeds touch the turf it is located on -/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/proc/handle_xeno_acquisition(turf/weeded_turf) +/// caller argument just used to simplify the need for calling find_nearby_cluster if needed +/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/proc/handle_xeno_acquisition(obj/effect/alien/weeds/signal_source, obj/effect/alien/weeds/node/pylon/invoking_pylon) SIGNAL_HANDLER if(corrupted) return + var/turf/weeded_turf = get_turf(src) + if(!weeded_turf.weeds) return @@ -331,37 +341,43 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) if(!weeded_turf.weeds.parent) return - if(!istype(weeded_turf.weeds.parent, /obj/effect/alien/weeds/node/pylon/cluster)) - return - if(SSticker.mode.is_in_endgame) return if(operable()) return + // This might not actually be a cluster node but we'll assert that in a moment + var/obj/effect/alien/weeds/node/pylon/cluster/effective_parent = weeded_turf.weeds.parent + if(!istype(effective_parent, /obj/effect/alien/weeds/node/pylon/cluster)) + if(!istype(effective_parent, /obj/effect/alien/weeds/node/pylon/core)) + return + // Core weeds can override cluster weeds so manually look for a cluster if not already passed in args + effective_parent = invoking_pylon || find_nearby_cluster() + if(!effective_parent) + return + if(ROUND_TIME < XENO_COMM_ACQUISITION_TIME) - addtimer(CALLBACK(src, PROC_REF(handle_xeno_acquisition), weeded_turf), (XENO_COMM_ACQUISITION_TIME - ROUND_TIME), TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_NO_HASH_WAIT) + addtimer(CALLBACK(src, PROC_REF(handle_xeno_acquisition)), (XENO_COMM_ACQUISITION_TIME - ROUND_TIME), TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_NO_HASH_WAIT) return if(!COOLDOWN_FINISHED(src, corruption_delay)) - addtimer(CALLBACK(src, PROC_REF(handle_xeno_acquisition), weeded_turf), (COOLDOWN_TIMELEFT(src, corruption_delay)), TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_NO_HASH_WAIT) + addtimer(CALLBACK(src, PROC_REF(handle_xeno_acquisition)), (COOLDOWN_TIMELEFT(src, corruption_delay)), TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_NO_HASH_WAIT) return - var/obj/effect/alien/weeds/node/pylon/cluster/parent_node = weeded_turf.weeds.parent - - var/obj/effect/alien/resin/special/cluster/cluster_parent = parent_node.resin_parent - - var/list/held_children_weeds = parent_node.children + // Prepare to upgrade the cluster + var/obj/effect/alien/resin/special/cluster/cluster_parent = effective_parent.resin_parent + var/list/held_children_weeds = effective_parent.children - effective_parent // why does it put itself into children... var/cluster_loc = cluster_parent.loc var/linked_hive = cluster_parent.linked_hive - parent_node.children = list() - + // Delete the old (but don't touch our list) + effective_parent.children = list() qdel(cluster_parent) + // Make a new endgame pylon var/obj/effect/alien/resin/special/pylon/endgame/new_pylon = new(cluster_loc, linked_hive) - new_pylon.node.children = held_children_weeds + new_pylon.node.children += held_children_weeds for(var/obj/effect/alien/weeds/weed in new_pylon.node.children) weed.parent = new_pylon.node @@ -388,9 +404,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) SIGNAL_HANDLER corrupted = FALSE - overlays -= corruption_image - COOLDOWN_START(src, corruption_delay, XENO_PYLON_DESTRUCTION_DELAY) /// Handles moving the overlay from growing to idle @@ -399,7 +413,6 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) return corruption_image = image(icon, icon_state = "resin_idle") - overlays += corruption_image /obj/structure/machinery/telecomms/relay/preset/telecomms diff --git a/code/modules/cm_aliens/weeds.dm b/code/modules/cm_aliens/weeds.dm index 3d2b3021a254..123752374f80 100644 --- a/code/modules/cm_aliens/weeds.dm +++ b/code/modules/cm_aliens/weeds.dm @@ -579,10 +579,9 @@ /obj/effect/alien/weeds/node/Destroy() // When the node is removed, weeds should start dying out // Make all the children look for a new parent node - for(var/X in children) - var/obj/effect/alien/weeds/W = X - remove_child(W) - addtimer(CALLBACK(W, PROC_REF(avoid_orphanage)), WEED_BASE_DECAY_SPEED + rand(0, 1 SECONDS)) // Slight variation whilst decaying + for(var/obj/effect/alien/weeds/child as anything in children) + remove_child(child) + addtimer(CALLBACK(child, PROC_REF(avoid_orphanage)), WEED_BASE_DECAY_SPEED + rand(0, 1 SECONDS)) // Slight variation whilst decaying . = ..() @@ -595,6 +594,13 @@ )) health = NODE_HEALTH_STANDARD +/obj/effect/alien/weeds/node/proc/is_in_range(atom/thing) + if(!thing?.loc) + return FALSE + var/x_diff = abs(thing.x - x) + var/y_diff = abs(thing.y - y) + return (x_diff <= node_range && y_diff < node_range) || (x_diff < node_range && y_diff <= node_range) + /obj/effect/alien/weeds/node/alpha hivenumber = XENO_HIVE_ALPHA @@ -618,16 +624,6 @@ spread_on_semiweedable = TRUE var/obj/effect/alien/resin/special/resin_parent -/obj/effect/alien/weeds/node/pylon/proc/set_parent_damaged() - if(!resin_parent) - return - - var/obj/effect/alien/resin/special/pylon/parent_pylon = resin_parent - parent_pylon.damaged = TRUE - -/obj/effect/alien/weeds/node/pylon/core - node_range = WEED_RANGE_CORE - /obj/effect/alien/weeds/node/pylon/Destroy() resin_parent = null return ..() @@ -647,12 +643,41 @@ /obj/effect/alien/weeds/node/pylon/acid_spray_act() return +/obj/effect/alien/weeds/node/pylon/proc/set_parent_damaged() + if(!resin_parent) + return + + var/obj/effect/alien/resin/special/pylon/parent_pylon = resin_parent + parent_pylon.damaged = TRUE + +/obj/effect/alien/weeds/node/pylon/core + node_range = WEED_RANGE_CORE + /obj/effect/alien/weeds/node/pylon/hunted hivenumber = XENO_HIVE_HUNTED +GLOBAL_LIST_EMPTY(all_xeno_pylon_cluster_nodes) + /obj/effect/alien/weeds/node/pylon/cluster spread_on_semiweedable = TRUE +/obj/effect/alien/weeds/node/pylon/cluster/Initialize(mapload, obj/effect/alien/weeds/node/node, mob/living/carbon/xenomorph/xeno, datum/hive_status/hive) + GLOB.all_xeno_pylon_cluster_nodes += src + return ..() + +/obj/effect/alien/weeds/node/pylon/cluster/Destroy() + GLOB.all_xeno_pylon_cluster_nodes -= src + return ..() + +/obj/effect/alien/weeds/node/pylon/cluster/complete_growth() + . = ..() + + if(length(children) != 1) + return + for(var/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/tower in GLOB.all_static_telecomms_towers) + if(is_in_range(tower)) + tower.handle_xeno_acquisition(invoking_pylon=src) + /obj/effect/alien/weeds/node/pylon/cluster/set_parent_damaged() if(!resin_parent) return