From 8e9c75cfc949cb974e82151e05b2fe8edd459dde Mon Sep 17 00:00:00 2001 From: Morrow Date: Mon, 24 Jul 2023 16:33:33 -0400 Subject: [PATCH 01/17] Initial --- code/__DEFINES/xeno.dm | 6 ++ code/game/machinery/telecomms/presets.dm | 73 ++++++++++++++++++ .../structures/special/pylon_core.dm | 72 ++++++++++++++++- code/modules/cm_aliens/weeds.dm | 6 ++ .../living/carbon/xenomorph/xeno_defines.dm | 7 ++ .../obj/structures/machinery/comm_tower3.dmi | Bin 11910 -> 23363 bytes 6 files changed, 160 insertions(+), 4 deletions(-) diff --git a/code/__DEFINES/xeno.dm b/code/__DEFINES/xeno.dm index ac783b6f426e..523a7804cec0 100644 --- a/code/__DEFINES/xeno.dm +++ b/code/__DEFINES/xeno.dm @@ -164,6 +164,12 @@ /// The amount of time after round start before buried larva spawns are disallowed #define XENO_BURIED_LARVA_TIME_LIMIT (30 MINUTES) +/// The time when xenos can start taking over comm towers +#define XENO_COMM_ACQUISITION_TIME (90 MINUTES) + +/// The time it takes for a pylon to give one larva while activated +#define XENO_PYLON_ACTIVATION_COOLDOWN (5 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 diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index a25293aebbd3..bb3395c878a5 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -211,6 +211,13 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) bound_width = 64 freq_listening = list(COLONY_FREQ) var/toggle_cooldown = 0 + var/corrupted = FALSE + var/image/corruption_image = null + +/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/Initialize() + . = ..() + + RegisterSignal(get_turf(src), COMSIG_WEEDNODE_GROWTH, PROC_REF(handle_xeno_acquisition)) /obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/attack_hand(mob/user) if(user.action_busy) @@ -218,6 +225,9 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) if(toggle_cooldown > world.time) //cooldown only to prevent spam toggling to_chat(user, SPAN_WARNING("\The [src]'s processors are still cooling! Wait before trying to flip the switch again.")) return + if(corrupted) + to_chat(user, SPAN_WARNING("[src] is entangled in resin. Impossible to interact with.")) + return var/current_state = on if(!do_after(user, 20, INTERRUPT_NO_NEEDHAND|BEHAVIOR_IMMOBILE, BUSY_ICON_FRIENDLY, src)) return @@ -282,6 +292,69 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) else update_icon() +/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/proc/handle_xeno_acquisition(turf/weeded_turf) + SIGNAL_HANDLER + + if(!weeded_turf.weeds) + return + + if(weeded_turf.weeds.weed_strength < WEED_LEVEL_HIVE) + return + + if(!weeded_turf.weeds.parent) + return + + if(!istypestrict(weeded_turf.weeds.parent, /obj/effect/alien/weeds/node/pylon/cluster)) + return + + if(ROUND_TIME < XENO_COMM_ACQUISITION_TIME) + addtimer(CALLBACK(src, PROC_REF(handle_xeno_acquisition), weeded_turf), (XENO_COMM_ACQUISITION_TIME - ROUND_TIME)) + 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 + var/cluster_loc = cluster_parent.loc + var/linked_hive = cluster_parent.linked_hive + + parent_node.children = list() + + qdel(cluster_parent) + + var/obj/effect/alien/resin/special/pylon/new_pylon = new(cluster_loc, linked_hive) + new_pylon.node.children = held_children_weeds + + for(var/obj/effect/alien/weeds/weed in new_pylon.node.children) + weed.parent = new_pylon.node + + RegisterSignal(new_pylon, COMSIG_PARENT_QDELETING, PROC_REF(uncorrupt)) + + corrupted = TRUE + + corruption_image = image(icon, icon_state = "resin_growing") //seems to start at the end of the loop for some reason?, figure out why before merge - Morrow + + flick_overlay(src, corruption_image, (4 SECONDS)) + addtimer(CALLBACK(src, PROC_REF(switch_to_idle_corruption)), (4 SECONDS)) + + new_pylon.comms_relay_connection() + +/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/proc/uncorrupt(datum/deleting_datum) + SIGNAL_HANDLER + + corrupted = FALSE + + overlays -= corruption_image + +/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/proc/switch_to_idle_corruption() + if(!corrupted) + return + + corruption_image = image(icon, icon_state = "resin_idle") + + overlays += corruption_image + /obj/structure/machinery/telecomms/relay/preset/telecomms id = "Telecomms Relay" autolinkers = list("relay") diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm index a29b49b7745a..23c32820ac21 100644 --- a/code/modules/cm_aliens/structures/special/pylon_core.dm +++ b/code/modules/cm_aliens/structures/special/pylon_core.dm @@ -12,11 +12,14 @@ block_range = 0 var/cover_range = WEED_RANGE_PYLON var/node_type = /obj/effect/alien/weeds/node/pylon + var/obj/effect/alien/weeds/node/node var/linked_turfs = list() var/damaged = FALSE var/plasma_stored = 0 var/plasma_required_to_repair = 1000 + var/activated = FALSE + COOLDOWN_DECLARE(larva_given_time) var/protection_level = TURF_PROTECTION_CAS @@ -25,7 +28,7 @@ /obj/effect/alien/resin/special/pylon/Initialize(mapload, hive_ref) . = ..() - place_node() + node = place_node() for(var/turf/A in range(round(cover_range*PYLON_COVERAGE_MULT), loc)) LAZYADD(A.linked_pylons, src) linked_turfs += A @@ -34,9 +37,27 @@ for(var/turf/A as anything in linked_turfs) LAZYREMOVE(A.linked_pylons, src) - var/obj/effect/alien/weeds/node/pylon/W = locate() in loc - if(W) - qdel(W) + if(node) + qdel(node) + + if(activated) + for(var/obj/effect/alien/resin/structure as anything in linked_hive.hive_structures) + if(!istypestrict(structure, /obj/effect/alien/resin/special/pylon)) + continue + var/obj/effect/alien/resin/special/pylon/pylon = structure + pylon.activated = FALSE + + marine_announcement("ALERT.\n\nEnergy build up around communication relays halted.", "[MAIN_AI_SYSTEM] Biological Scanner") // Ask lore team for a better AI system name, honestly a second look for these announcements may be good - Morrow + for(var/hivenumber in GLOB.hive_datum) + var/datum/hive_status/checked_hive = GLOB.hive_datum[hivenumber] + if(!length(checked_hive.totalXenos)) + continue + + if(checked_hive == linked_hive) + xeno_announcement(SPAN_XENOANNOUNCE("We have lost our control of the tall's communication relays."), hivenumber, XENO_GENERAL_ANNOUNCE) + else + xeno_announcement(SPAN_XENOANNOUNCE("Another hive has lost control of the tall's communication relays."), hivenumber, XENO_GENERAL_ANNOUNCE) + . = ..() /obj/effect/alien/resin/special/pylon/attack_alien(mob/living/carbon/xenomorph/M) @@ -89,6 +110,49 @@ /obj/effect/alien/resin/special/pylon/proc/place_node() var/obj/effect/alien/weeds/node/pylon/W = new node_type(loc, null, null, linked_hive) W.resin_parent = src + return W + +/obj/effect/alien/resin/special/pylon/proc/comms_relay_connection() + var/check = TRUE + + for(var/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/checked_comms_relay in GLOB.all_static_telecomms_towers) + if(!checked_comms_relay.corrupted) + check = FALSE + break + + if(!check) + return FALSE + + marine_announcement("ALERT.\n\nIrregular build up of energy around communication relays.", "[MAIN_AI_SYSTEM] Biological Scanner") // Ask lore team for a better AI system name, honestly a second look for these announcements may be good - Morrow + for(var/hivenumber in GLOB.hive_datum) + var/datum/hive_status/checked_hive = GLOB.hive_datum[hivenumber] + if(!length(checked_hive.totalXenos)) + continue + + if(checked_hive == linked_hive) + xeno_announcement(SPAN_XENOANNOUNCE("We have harnessed the tall's communication relays. Hold them!"), hivenumber, XENO_GENERAL_ANNOUNCE) + else + xeno_announcement(SPAN_XENOANNOUNCE("Another hive has harnessed the tall's communication relays.[linked_hive.faction_is_ally(checked_hive.name) ? "" : " Stop them!"]"), hivenumber, XENO_GENERAL_ANNOUNCE) + + for(var/obj/effect/alien/resin/special/pylon/structure as anything in linked_hive.hive_structures[XENO_STRUCTURE_PYLON]) + structure.activated = TRUE + addtimer(CALLBACK(structure, PROC_REF(give_larva)), XENO_PYLON_ACTIVATION_COOLDOWN) + +/obj/effect/alien/resin/special/pylon/proc/give_larva() + if(!activated) + return + + if(!COOLDOWN_FINISHED(src, larva_given_time)) //Somehow out of sync or doubled timers so we kill this "recursion" + return + + if(!linked_hive.hive_location || !linked_hive.living_xeno_queen) //without a queen and a hive core we do not give larva but we don't deactivate either + addtimer(CALLBACK(src, PROC_REF(give_larva)), XENO_PYLON_ACTIVATION_COOLDOWN) + return + + linked_hive.stored_larva++ + linked_hive.hive_ui.update_burrowed_larva() + COOLDOWN_START(src, larva_given_time, (XENO_PYLON_ACTIVATION_COOLDOWN - 1)) //Hypothetically stops any stacked timers, there is probably a better way to do this but I'm having a brain fart, ask Harry - Morrow + addtimer(CALLBACK(src, PROC_REF(give_larva)), XENO_PYLON_ACTIVATION_COOLDOWN) //Hive Core - Generates strong weeds, supports other buildings /obj/effect/alien/resin/special/pylon/core diff --git a/code/modules/cm_aliens/weeds.dm b/code/modules/cm_aliens/weeds.dm index f20fa842e446..07dec0406e17 100644 --- a/code/modules/cm_aliens/weeds.dm +++ b/code/modules/cm_aliens/weeds.dm @@ -591,6 +591,9 @@ 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 @@ -617,6 +620,9 @@ return /obj/effect/alien/weeds/node/pylon/cluster/set_parent_damaged() + if(!resin_parent) + return + var/obj/effect/alien/resin/special/cluster/parent_cluster = resin_parent parent_cluster.damaged = TRUE diff --git a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm index 060c3aea2814..07ab7fba7dfd 100644 --- a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm +++ b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm @@ -318,6 +318,7 @@ XENO_STRUCTURE_EGGMORPH = 6, XENO_STRUCTURE_EVOPOD = 2, XENO_STRUCTURE_RECOVERY = 6, + XENO_STRUCTURE_PYLON = 10, ) var/global/list/hive_structure_types = list( @@ -367,6 +368,7 @@ return RegisterSignal(SSdcs, COMSIG_GLOB_POST_SETUP, PROC_REF(setup_evolution_announcements)) + RegisterSignal(SSdcs, COMSIG_GLOB_POST_SETUP, PROC_REF(setup_pylon_limits)) /datum/hive_status/proc/setup_evolution_announcements() SIGNAL_HANDLER @@ -377,6 +379,11 @@ addtimer(CALLBACK(src, PROC_REF(announce_evolve_available), GLOB.xeno_evolve_times[time]), text2num(time)) +/datum/hive_status/proc/setup_pylon_limits() + SIGNAL_HANDLER + + hive_structures_limit[XENO_STRUCTURE_PYLON] = length(GLOB.all_static_telecomms_towers) ? length(GLOB.all_static_telecomms_towers) : 2 + /datum/hive_status/proc/announce_evolve_available(list/datum/caste_datum/available_castes) var/list/castes_available = list() diff --git a/icons/obj/structures/machinery/comm_tower3.dmi b/icons/obj/structures/machinery/comm_tower3.dmi index 931d6f77514a39125b5bf319e65ff518490023ec..8a5aa1f68fe31acf75321f5620bb43c65b65ffb0 100644 GIT binary patch literal 23363 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 WWQ?8;@xiIsklj)IFO^5UX#WA-f!{U& literal 11910 zcmbt)bySp5*Y87vG)kw6N~e@`cb9a7A|Z{`3@9MdQc4?igLDjybax9#cMr_Week{C zckjA?-F5G*S!-sVIeVXTcAfp(`$TAIC=%YIxd#9Mp|X;k4gjEmU(oJ>MSu zDDcyJ=_zODVdMV#t>O(tCDZsZ4HM5$fF%xtMrdTn`ddu*rUxnZBe1046|LPFl}5eLutB*Tx}m6INC_HOTNTfOdYZ z*SD0~o=)s5hq7*KoD;3@(`H*^F8*@6$a$TyWL4E|9b=ZX%EZu68H_#qzLUhKAIdw% zY?*?Y??2|+kYdzerkdn8{ep3G_VIo5W2QF8tAO6kStm{P^D>%iM95yj1umcvWa zpv}vr+0IT(+z_6pPn+*ck$eb>Lu10lki~{F5fD%VAv`>`0B(Eh|L4Ok7l4crB|I%k z=ywA39~gn7)-w+Ie+4yVhq)RG!-M`=Ch!{s&D7RT-O9eFzpd>{JZ6E*#j|*l0!}A z+#zjD8tKAqXDZ?5aX~h_t`B}={MXK+4zMj>y;3@4-nzFfRP%2cB$(eA8)$&o9*nHv zIznkBSjD*zdV@b;US{}z4*S26h}t3n)cuUHIv)CI-_<+u2P!`rQ_l%f^@9$f=**mL zeG@UKC4_O*lfqR{`et!?FWs+SW74bSCM`ps!oY00AuFFS5$nH}`yWMk@dIs^T3%+m zNc-?JS`)|*83sU_ii!`ww6gpSkbDRRg-In2Q-nvCSh#u$01{clBR|?d-)$We{Hef5 z9CJtZINP5B%7lwx!jK}t4pUcCn|Sga6zSX56Rh{rvxrk)G2HMD>Um?gcBL^_Cq(q8 zoXmK;+6$efqdi0kE+{Uf!p~A8=>2CJJXW(w6z26MNt}}Z9)IZjZ&T5&m5~zY?&+!T zS!;8UIHi_t2>iJ`1E)nh0dQp$!9Tp{QCfx=mS;K^|0V(60hr$~?vy-q2@5V;sQU;* z?!u-9@kbVc4;|eMXvt@^ny9NQVacFd;ax&PCU=Rj$oJga$rOu(pb+qmPj)kif?cpz zhC0IQ=Nhz`5Zz;v5)wm`=19^W>E_RvQqM5nZmxC&Y?hhp>95i3tHPU3_@hJICM}oah>stwVkn(Wy?r~N~bH5GB<=yi~R0Mw#V#N(E;jN&#yNbdM z7*c+w@4G3t&&RY>+nKz_QzE*TeJ@1pel*^ zGwVz!HOQ{us%=}V?7t}_H{^VX_z5FF zGfc$N+8z4Z%xNLH_2og27shtLNYeH@UsLZ%4>=(fPPa)~kYl9t8&8A)CkDxVN!*Y& z%dnjOO(NFeQU8TA6(*3)=y}Q_k<{!L+2_{3mvR+^AKATZH15_{1?9v2Og%am#(@zh z9%Q1}h{KRVPrsiT<%|ZiaM>dv3MWnZNr0c9ycwaY(=CDqlYF+YS2r=HcSmW6bg@UI zR{axv3!O@>@!V7+y8~=|H2HCUZ5ek*2Hq8-5-UpixCx7~&jYX&NHvm7rB6|ct;40? zXSm(PuqbjY-~lC9k`K#ABT>Ka<1`-z-WrZK*aGEij!RzVn zJ*KNjBBuaE#OM8dtXTi{#5kL*dm6%-;)2GAf0ZJeu%$3p+-6rjf7!_iN?2n90lUVl zAFytbAvZ}BJRJf$zhZ~HgC|I~MS|>=4JPI%gI_sS@8N(-4vH@|m@0Dwmb}kOOdse8 z(>uRy6vXDDV&q+GKQo0Znyh}9-Mb+0>0UctX}>-N##}y;EQ}tsP3)lqQc;xLBYd`> zm4>gBh!1Y${nGdbWfG>sp&;8ITf@A7OjEhv_d*#=Un@VNV=4HrjM^N3!9g5Bj>Vx2 z+IhL)FtW5oqO$2U8+!j6I0*r^M@+0L8J)L@Lfx!eS5{N12JK&<4)~d-uV7O|J!R4_ zD+O1E#h*D)0Xe=8#pcnwF(}@xf9?#$Kk;_E#pA5?NSHbkVuteArO0H(qa18frJ26>n|~ zZvTuGH|-ZNYV;YX9L@ZQ1s(1YmvUuY9dp~}=|e7MDth`sVI(M!y7TTp>Q(z5toY0V z)@;uG20Ig}ip;Y5C!lr}CbFymIe~B%so(Y@4;1ECveVyMwdEpCKXx1N?q{XMlJ6!Y zBv4z;?0FLq5`v6-e|-Dsl{K8=(Zp9A;MRNnvrU@g1_9LkzDcCuDKF=Eqxb$!wAE) zG<0w~YIPAqwTl3>gb&b>(VdZO_!a8=Ara1ffsXT-n_TJ}ABv(>pNES1S_*NQXLNyf zW=ol`19HJJHiT$nWOI;^?lCZYnBV9;#ES`}xcf$9%2g?fgBKSzGeTl@Q*0<5^0=%Cj0 zt1gW1e0C1LJd+Ryf$XNR-cC(<4h3vV5lfsumPG#fD-p1EqOjk(_nG?#_BS#F79q4! z?s<86y47T&^`{MiPfto~Ybk@Jq-5PahWlMuM&~CV=2efC0iZU{N4V$6i&38;dAsN1 z&cs1JqHk~2$bfRYaS|pUM1dMa*$CR&UfCp07r#EG7FuXf*(mYXyqpI;SW4qOoMJ*n zt%wk0Q$3Z%`#8?-M@HKP^nN>&X)9f~q90H!bX`K0dJnCGw7~LQxxm(DhG3iKlVk2dbl(G%`DXz;N2EG?;3)iXk8{z*XQ{k!75g(1zKi05 zE?s!5_Zy6rO^IqTnFk$@S;QzDce87VwNX9#*pBTmB$Bf=y^f}*1AISUh@|9Be&AC7 zq-O(+Es!Uhb9)!FFC=+dFbcmbme!yivkL=t8B8s4>+U(umfb zI#MMF|N1w)?-kph$MSlCk1_;I&ZB;fFIK!oJnqRScaRp#eaGeCaL|K1XoP~UPG~}i z2}W#-Ok}|<)@@%&?Vmqgk+@fgmqelZikEnt7Vm%TJ_X%VbEI*Ni20GEJP%c(1#)Qw zK>rr)O=eA_U0rj(xf$bS`nU_GI{|dePHW1atqX@D+0D*R;zkeHHqz+iH4c-cSbWr9 zGQ|3v*}aAq4EEY*R?MK$8N<<5&bG%-TG}|xM2tefP_~LTCn|_hrz|i)w|2FjurnVo z_{pH=Th15c=X+@K(C^o|R86hho{vay?^2Y_Q#(21s2Fcec`k#N`o@_yMPU%!5h^7w!g*KGDH`s!K}^4$m$hDMS= zbilwcP!R;UcZPSYM#ZbOua=uS7M$ZV6&fXa{mkLWv!~Qcdu5;3SX+bvh9&ZJxp*)m zaooY-6Nd)Ci5X_1>qF&DO%BPJf^bONKdxCS+@215QX zz5eD8f9)6!qJPA|9~6AFKwt6^|C{G!Wo=U90}72I`h%sH zYgEr=OnY%K6V=+)!!|@=7mL(Yl1%&Zg@tM+Bb?Yn`ySgf&p=FFI|&v#qW<~Lmw)>_ z&a!DdxjpJsId3*4r6pyUjKlLNK-m&+S0QMUgRi^XNbi z>R9s=11iO5;UR6c!A{RBUxI(F3es4+Q_MgWVR}Y=5B(2sjbv3;n>GeDUfxf9se$O5drXfnO^6e z8oLZ!S#snBTvZT=O&9C^L>}_X@i7UQC?TiDEZkM4f-8-FGI1%ZKWQPmJF&44cCLXQvs;Xx2!{O^$R|LGx^(!c3x2{Jx>zJ>Q+ z@LKFc_#Mc<1LD)PW`xkulK)^vDIp9JMp{V(2}1~_IcE1AvIjxg)H2IfCJ29JBtht3 z6R{TFboA&WlixE9x-oWoKWPx*!nBz{eDps{6b-b{hXmUhm}U<_(lVijyZxTY8e*&j z<49bcsr_eK5CmTWO-DQb$FTSRb{x5c$7D=dJHLP7EB3>_>KfP#K%JePHCDw^-!2^o zP6Y>3QrQ%xpHe}|0e&DC&2%+AtKNHmZup7v=ben8$5PnPe75H1<{J)*{(Zm&?dV?j z7d(KvDq+~*xCen zc#g811?PRJZ6GmoO}8RE-7dUogIS`!M=P~AH#f^Xyu9BI%t_=yRVK>2x*ig~fB&AC zzZ;p(`*)O;+C=^7I7HHWZ)V!x&+lRGvtP}CY z7-kl0`0QpYj*JTJgYJIsTijB1$A31M z3fDaaSDk=>pecj*LNq7+ezd}}fT*ab(O%v5_BO-}xziDRqML$e;{+SDzd?V8-UW)} zK~7$t17<6ZiumxhXN%cx#WzUcI?d)SWlncIarX>+hQ_A&2X?c!_lV^Vce6CRr1;v$Hdv?!g*iTR&RRg+eYZEtM8x%~)%xw!Uba+skcf zX>sZP!XB{VrwD$mOOPko-Zuqu&@=eYP+o8aYKm> zc?Xh%38Xe=;5RoGgH-c4*^E%iPm~75K7lvL42sANR$vA>i)vW3<)gn0*t)D~hzsep zg>x?|9`5jdRf7=&`!IMRQTNOnud&DD)6+f}Hcp26==^Dx;BLRcV2~Q6*UPH<5t?W= zdqbI-nf{x9|JoPPdsoR~XQRX6@CHtbem6k$Ohc8k{3S=NfrwHO$liZ_n+g+1KV{dC zxepA02FU`|oMzg~Rk)OCRp>iR{xs`^Bw-7H>*2Rm=)RiELKy zZ2RDxQ~#C+Bfx0fDE+fgH6}Fn;z<<^&ivlN*O2qUeJC8^5XCw1NTYiuSqOGL zILTr13J)xpaq=*j%D>n9qUxw_0->@IsF!vYt*J)axr8`7JJ(aVp+mc@MP3$_r;#sK z0fTC6N$}jI*ZI5xtdA@Ggf_hVKliSyaQ?vrhOUvup^L?FX!%ea2H%yc^i$Ysx+Dfu ztH`EbUO^wnB(t6_vWJT%ddg{wJE2!E<@jDIo**x;cFIR|8$}KL6z-4Nd&qYy(p0Na z&Vw(ke$MZE`*?abedWDq*$XT(gotpMBAGu|-nfR~vHs+%c@i%-UsIAY@#jlwYT>-0 zlcnX#o2UwmNnF(eh*yvVFDjWh6UY5fvi8ets}IaGPy#{DCnO*M9zbCg6%{mc<6;w& z7`UaV2(OKcJ;dPeKJW#`LP?LIEWPO z{w;}(wjsudsN0{ot4em*QJ?eR)y8m`2Qq)|qQ=>TJAymy1V3-V;0L#b5pzPXLm_qM z2qkjVV>RFsl@oj0t3DZ}i?_L;eJ4~ljC?}w-3+MX(aL+`OzgKcsaEbohA9k?7m2Q@ zmcScFBZ1HPRx|2&)KD6dXobyl4Os#3a9abz24fN3-f?wkS9O4Bt;?b@KSnDRJLG3P zMUD%$)ZhlY9fbdQ4J=1*O6z)DtIn2DR#jCkZ>CFXy%u(!uQC6Vj`H;LgZGCXz$P8N zCR8Lho1PGO2s|Xt#@?H)%KN5r!nQF{po?l1K|#o|JzhII@4EoUGC1{%E)Jo`>!G}Y zW_Rm1Bb4G#xiWl@&3-)GpDFJD8N_T2qDd;^dPCRgrw-pow<@HV;zs*4_mOF8xv7M_ znJPJj#+jq{!0Oy9>)}lCUNGH_eUi{Cxsh%$;%f}`Kvvuw!cYfYU0vnL_k}m*6^RR> z`~n1xtfS4MZ>g+i&NM#6{ETxvVnF*kFf=3~AS85owzaiYB)nN>7e$Xb0=jjlNGxA> zsoM|)oGjDa)HFSgS($BOMqvYaIl;1h49=J}!LpYt?}H)roKaj{ya0@x4rpQ~`{mR& z^M&+(Uq}LMRIW|(qn!9Fw4wpV&WkLarSP!Hsc4y&8&|%sj(lB)pd%P?wmW-!@&YXt z9eF+v#mDqWr1#pnWT}H^^q0$>7mw8+;n6yU@u6QIp!&ICPS{%K(n`XcE#UNdh4e1$ z*{T$+M567uHr!*~5>Q~Td^i4qnWd%DL#!N9OP(Q10g!I6%zse=sLsc3A_mkSmxh#9 z1Ec4XKia2JQJ?w{5cTS{m2{M~yZgy9$gxOj5-KO#svh-KE%&iLk>FRgr;>ByA`owIqQ~Glkp!L-Tc2L{K${VRuKC8hl0(<)CnqO2etv!@ z-Xc#0v-toSp_dMgU8k3j=bd|kVQijJDmgmO9PI6p6!Ly_WVB$X#WVO_y8ZC8C2`w> z3u9e!gVD0s?%PmMINS!$yt=;~7(sI?e&jt#x_-{A^pZw&?xX}Qr%1QM(F;XKH#S+2 z>`GYo-22S4aNcJ7x`)`zVU~B~X-!H|mPe34l1j6OpI@puk}tmq4W#vh1A+=)iONuT zL@QFNv}oHq6Xlg%HjW5Q%kbu$=+?2B(eWD}L~7u0a~4C5^KPwSzGSZm%+<+iAoMU@F;Kpgh}RpYC*KL<$-B{b?IE|cZ6JKd|Sh- zTMrl6WF5Nx5h3>nGBi9aG%)gdP-T%&ipt8#2&Fqez4J3J#15h9Y{AY4CKWOCq8H&~ z7R~-|`fS6na^25*L^hW{by=gD>gtqa{q-Zj+>d-c3tlqPV(@K5cIgv#>%MnmEJ)?n zJ+u2YBIyU@UMni1%X+y9OxLVS#$N073I4OoB(B?$&R$u^`NU17I1+ZAr?LdR`Q#+Y z_YF%}lXC|(gKTChoLM^L$ul4)&6w9OaJoQ44{h9Q+#ebr%(e*mKx=V(oaQ7rze!~? zjrL^QVl7=VN$n}@7z|euqPL@(h)$xL#(Q1*u80yDuux6ZxR7zW2VWp{oUe>vdc@t; z?-EYWRkt2E`Kc)RfvRrHK{M;m^=qK3f2eic*^!5*ez)9ri`ERa=e)?!xQG<6RqxSP zf&>ITthj2{ZEGQ32=r$nc?pbpTw)zvhc%)~WaN#2>e8m!`9C&mg*k9CW&%q9;E8@+ z_h2~Ugl@j`Sk`#0P$+baIjlzAG(($naec*I!k6%C^i<;J%i41bvYs~)u+01}M(GDJ zlDC5g!OMZ_LeLKsh;Nh-(j*NvQxjkK_FFnKGK-)+UN_Un%P52FTsz>n;&`0FDe8ny zj%Q6Zi(52X>{)sb^f^XE5r4;1dG$ABy;0nOEfqlG=DL3{4XJ$<@37*sfTjN=``mq{ z2a}Bc$gZRjL&mR{S=ZXd_cJPoC)h4w)GYG=%jwQ{Qq2oNfkz)(u?&|GlTrT>REkMm zYt8^(HbIg0d3exG?6b0)TXET%41YQ)D?|h(mqNg0;JcyYKk2#BFKCaEwfF1!=2fpVFK*I0V} zr;##z$F*VA1hLtq=RPj8uNRTm{xyx>2XPL|`s0kvzO3H+@3WfSH<}?H0vCT~Usf%l z3}mWs%I~}ocU##^e#tBXBPN})fjE%*Ae|9OK+I&(mUTkMBvh7iSIYOrog0l&zfY`J ztyf2fpm@n=Zq780@!RkyPpk)Bb%>WR2j-t(x9fmBd-2AnR$#t}6rSMGCU*wOB1lIp zAs!y13(X^3^*_-7qt7p2n1-|0p%aUd5QkI^9Mj4ZLV2(semI!|UP)hDhLLLId5JG3 zN#ItGa5te@5pe4^i(^fI`s6btA;T~t37 z#$|`aTi6MHwy9wa?tnMiB+2$Wis8OVSFaH}YZM5}%8e0dn zi4j>ypS5*lmN1_!!&c2RvLZ3$c#2^u;wao|Qxjt}k(-2=2}&ZfC2O%HyyJ!1Zw#MT zTfSByQ_^hjr1I|>{h>HKI4~e)+9&W@UN39tE?UZ0r(+P+ttMYChL{|w-sX@p=h2E;L0J%3}Le<~a+E1XE`;%)j!TpDwO+wOu= ztC*7AsW2JoGD9lMvDr^AjY&X2XX=9A+7>T`PAB$5o*C#QRivG>#TfYwuTAqQ-=?M4 z0AWrHLiD1R^WvwI*^)Dbu+vi)fwY&OJQN@Oe&;DrFHWa&vXNBX*=`+zWq<$M*EbR6 zhn1ck8;fqb91k0%la^3}uEGlsOMMKy3(p%f9ho|Sk7Ih;(9h8<6Qtawh@#*>earFXE!nZ(V6gmu4gJWosv`t*0xc- z4wQPp+KaEKsv~i0=U3sj#RuwM%U7Jd8!2Rl4mqXl6t9u)GJIy2WUVI#qM+3ahN)gG=6#v-2*mMa$43b8z z+$&vqVfw5Qnxs=2v|8yvdBIxCdRgFnpE)kBADheSM|gz`d=`HT^?rHx0GZL)@O3s( zTjJputNB*p&ZY3cOjVcFd{q}3aB*JuVtTEzBLg<0#q{o zv?Ayr6dGEIy6x)C#Wy=?xC*f?!)QgPcwW6>;7xDfQq_@}fNh7YrLkyrKVv^dUhmul zd!l70m*om8xFQy;_@jevJxul=H=2<#&rDg=ILV75fujLxJ(}{CtJLYM+z;jS6E>RvldT@h)&^I z6mpEdQaFeh!G!ZF$gjaBkJfLVYmv>ZlM`jk^~gLYqXMj?E1QpiqlR({(;aYsG>?tu{P^exHZ{8)g_ik>P!%vXY@o4*g@?ugKGR;W8&l~OJ!)j3{^Mi^tR$Hea z=*fmB#^2rtkK%Eup#dn#&RP#k!!iJa)+Aw*>NY#ASnN( zmYl&omN{0|G~+GGeqRvOihoyoC`!w8w2T_59)!8;_D=uMXZ2H*#Vv?gElc8@dE|4M z-qY0dU{{5~7(V_v`8-<(@m&&fkF~y4#mG0u_K85*Ya>m>-elQZfA0gX#gJlMe1x?T zTLr(v<9JGoLe1B130gXwP|~LdEOM;y3<39)UG?Gk%ZHC8}yZku!OsxQPNy$ z6573KkooA?>bK?UKghl~VA}K(Mlw0Y&64xiau7yB3_ex~b{(zlAE6RqI zFws0Mjwl|3@(?TzTRjxHfACY@+44!K)H`^RMZPt6@T<|hP(K3%Bonjec=^EOF(9-YS`Nr@rUq~0pVo0@t1A=+?#iWiT zyp(GHRoPbVIxTnU!cLh?V(xNrL3Cqs_j8p>i!0-uT2GfsHu8^@ChHYl_*@Nhsc{EX zKL`9Nf9N3`H;dv`o{}QkBfcJ8X5!828^0xc%}3CB2X9ikiLw~F-wsU^OAU1}DhS&! zr|`6cQG+QYRUFVB%yoLK)#px8RjBS+HNF_iW!jz-lAvUu3!CE3{=#Ky^h*DgNJxCc z_T^mh(+&3Gfa}>EW5?^pVa((8uW|c2TAxl>ewMftIZtbuIJ&|*svT;7IN!u!{B0ln zpgNh=Y}#S0AsM3QDNubS*}^xN34d4j0HMI#gF!-!7KhqJXIfj0eZ+?1$}8mY{~o84 z;>colH3H8{PAdyX?xAf7*l{~N zB)CF{Es{c(@wn!#!ixsqv~PKbZ?ABr_^c2I9 zb@h+BKG&-P{>YH0I?LBJ8k4%Tj4ci?864=m^tB78=Y>b>#2Pq$gN-mzf)OtN{-u& zuz-J(d<(}JbzFqp)Rff3q`A8L6D_T{o56bQyhT(q3%UF*0z6kmmkGJV;Bp^xbf`m# zjL%}DqmyXtRJBih0q>dBa7mjv?hOKwpey|%Pvfq8Z^m4`*KGsn=fk+{T-n2G!dn77 zG&N)WNCT3LOic-HBm#yLeZSg#oLEOb1Jcvd_!r9^rZoT@wWs4Q-80@mVEXA`6fe%^ z0y+~q6R;u%9S3W3H@sD^yU#y~zYSa&E@WNgNfZz*ue<3+@`)TF96 zwm?wGgZldV**}U?F~$ohux325x3?z(JU6hQXWelpR8JRsAj4wwz<}vA41+djMa7+wrNq_f&{?wb5OOh)$6vcOV}iBb%}@ z3pQMuC=eA7Yn@LwCF&N}-BOFL|KJO6Mi%JpNDdASnHPA^biL}jaXsUMg7@#rwfQo| z&xL?@5YKs zX(=%$Cuei5xf=~gaPP@<!Ctx)+36j^}M~7*qo_mE92u4+$G>j*G96f{-X@kwoju?rvHk_=0 z@z5JeIg-GwBHx211%(1h6c1UCYk$F=?Db4FSeJ`9U z6k74QhahY0Z5OTm5raO>ZdJ~&$_M|x7MkXzj9X9V=ItJGA7cEHnHkjJ!u$RJQlwRb zrse%!!1`faG3x6!`3?VNnH*`?LIaX1WGh2>^ueU%hV|LaGFzfPHn4t3R3w&5e%B0K zc1&~v!k%g{uo>V^a70V>1>aqPEz-VglfI%T{ArX5F~AsGrh!K Date: Mon, 24 Jul 2023 16:50:55 -0400 Subject: [PATCH 02/17] woops --- .../mob/living/carbon/xenomorph/xeno_defines.dm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm index 07ab7fba7dfd..f2890dba0163 100644 --- a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm +++ b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm @@ -367,12 +367,15 @@ if(hivenumber != XENO_HIVE_NORMAL) return - RegisterSignal(SSdcs, COMSIG_GLOB_POST_SETUP, PROC_REF(setup_evolution_announcements)) - RegisterSignal(SSdcs, COMSIG_GLOB_POST_SETUP, PROC_REF(setup_pylon_limits)) + RegisterSignal(SSdcs, COMSIG_GLOB_POST_SETUP, PROC_REF(post_setup)) -/datum/hive_status/proc/setup_evolution_announcements() +/datum/hive_status/proc/post_setup() SIGNAL_HANDLER + setup_evolution_announcements() + setup_pylon_limits() + +/datum/hive_status/proc/setup_evolution_announcements() for(var/time in GLOB.xeno_evolve_times) if(time == "0") continue @@ -380,8 +383,6 @@ addtimer(CALLBACK(src, PROC_REF(announce_evolve_available), GLOB.xeno_evolve_times[time]), text2num(time)) /datum/hive_status/proc/setup_pylon_limits() - SIGNAL_HANDLER - hive_structures_limit[XENO_STRUCTURE_PYLON] = length(GLOB.all_static_telecomms_towers) ? length(GLOB.all_static_telecomms_towers) : 2 /datum/hive_status/proc/announce_evolve_available(list/datum/caste_datum/available_castes) From 5c5efe5eaa8b484cb59e9cd9ed68183028055b3b Mon Sep 17 00:00:00 2001 From: Morrow Date: Mon, 24 Jul 2023 17:19:25 -0400 Subject: [PATCH 03/17] no capturing twice --- code/game/machinery/telecomms/presets.dm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index bb3395c878a5..597d5ae6afd3 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -295,6 +295,9 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) /obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/proc/handle_xeno_acquisition(turf/weeded_turf) SIGNAL_HANDLER + if(corrupted) + return + if(!weeded_turf.weeds) return From ab0e3d64efcdcc8c40967390f2a775cf595bc6f0 Mon Sep 17 00:00:00 2001 From: morrowwolf Date: Wed, 26 Jul 2023 05:21:56 -0400 Subject: [PATCH 04/17] Update code/modules/cm_aliens/structures/special/pylon_core.dm Co-authored-by: Segrain --- code/modules/cm_aliens/structures/special/pylon_core.dm | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm index f9f49c5c88cf..a0308d20feda 100644 --- a/code/modules/cm_aliens/structures/special/pylon_core.dm +++ b/code/modules/cm_aliens/structures/special/pylon_core.dm @@ -41,11 +41,9 @@ qdel(node) if(activated) - for(var/obj/effect/alien/resin/structure as anything in linked_hive.hive_structures) - if(!istypestrict(structure, /obj/effect/alien/resin/special/pylon)) - continue - var/obj/effect/alien/resin/special/pylon/pylon = structure - pylon.activated = FALSE + if(XENO_STRUCTURE_PYLON in linked_hive.hive_structures) + for(var/obj/effect/alien/resin/special/pylon/pylon as anything in linked_hive.hive_structures[XENO_STRUCTURE_PYLON] + pylon.activated = FALSE marine_announcement("ALERT.\n\nEnergy build up around communication relays halted.", "[MAIN_AI_SYSTEM] Biological Scanner") // Ask lore team for a better AI system name, honestly a second look for these announcements may be good - Morrow for(var/hivenumber in GLOB.hive_datum) From b692acb1fb0e330f907f59e85d037ca5b11a4725 Mon Sep 17 00:00:00 2001 From: Morrow Date: Wed, 26 Jul 2023 05:27:20 -0400 Subject: [PATCH 05/17] woops --- code/modules/cm_aliens/structures/special/pylon_core.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm index a0308d20feda..97b7762b527a 100644 --- a/code/modules/cm_aliens/structures/special/pylon_core.dm +++ b/code/modules/cm_aliens/structures/special/pylon_core.dm @@ -42,7 +42,7 @@ if(activated) if(XENO_STRUCTURE_PYLON in linked_hive.hive_structures) - for(var/obj/effect/alien/resin/special/pylon/pylon as anything in linked_hive.hive_structures[XENO_STRUCTURE_PYLON] + for(var/obj/effect/alien/resin/special/pylon/pylon as anything in linked_hive.hive_structures[XENO_STRUCTURE_PYLON]) pylon.activated = FALSE marine_announcement("ALERT.\n\nEnergy build up around communication relays halted.", "[MAIN_AI_SYSTEM] Biological Scanner") // Ask lore team for a better AI system name, honestly a second look for these announcements may be good - Morrow From ff56b09f8637dfcd65bfd2569099a43868885887 Mon Sep 17 00:00:00 2001 From: Morrow Date: Thu, 27 Jul 2023 12:22:09 -0400 Subject: [PATCH 06/17] fixes and changes, PARTIAL review --- code/__DEFINES/xeno.dm | 4 +- code/game/machinery/telecomms/presets.dm | 14 ++-- .../structures/special/pylon_core.dm | 70 ++++++++----------- code/modules/cm_aliens/weeds.dm | 6 +- .../living/carbon/xenomorph/xeno_defines.dm | 2 +- 5 files changed, 48 insertions(+), 48 deletions(-) diff --git a/code/__DEFINES/xeno.dm b/code/__DEFINES/xeno.dm index e9eb4ca4c1ed..5907bb51f487 100644 --- a/code/__DEFINES/xeno.dm +++ b/code/__DEFINES/xeno.dm @@ -166,10 +166,10 @@ #define XENO_BURIED_LARVA_TIME_LIMIT (30 MINUTES) /// The time when xenos can start taking over comm towers -#define XENO_COMM_ACQUISITION_TIME (90 MINUTES) +#define XENO_COMM_ACQUISITION_TIME (0 MINUTES) //RETURN TO 90 MINUTES BEFORE TM - MORROW /// The time it takes for a pylon to give one larva while activated -#define XENO_PYLON_ACTIVATION_COOLDOWN (5 MINUTES) +#define XENO_PYLON_ACTIVATION_COOLDOWN (30 SECONDS) //RETURN TO 5 MINUTES BEFORE TM - MORROW /// The time against away_timer when an AFK xeno larva can be replaced #define XENO_LEAVE_TIMER_LARVA 80 //80 seconds diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index 597d5ae6afd3..d22dcc3aa5e3 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -211,7 +211,11 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) bound_width = 64 freq_listening = list(COLONY_FREQ) var/toggle_cooldown = 0 + + /// Tower has been taken over by xenos, is not usable var/corrupted = FALSE + + /// Held image for the current overlay on the tower from xeno corruption var/image/corruption_image = null /obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/Initialize() @@ -307,7 +311,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) if(!weeded_turf.weeds.parent) return - if(!istypestrict(weeded_turf.weeds.parent, /obj/effect/alien/weeds/node/pylon/cluster)) + if(!istype(weeded_turf.weeds.parent, /obj/effect/alien/weeds/node/pylon/cluster)) return if(ROUND_TIME < XENO_COMM_ACQUISITION_TIME) @@ -326,7 +330,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) qdel(cluster_parent) - var/obj/effect/alien/resin/special/pylon/new_pylon = new(cluster_loc, linked_hive) + var/obj/effect/alien/resin/special/pylon/endgame/new_pylon = new(cluster_loc, linked_hive) new_pylon.node.children = held_children_weeds for(var/obj/effect/alien/weeds/weed in new_pylon.node.children) @@ -336,10 +340,10 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) corrupted = TRUE - corruption_image = image(icon, icon_state = "resin_growing") //seems to start at the end of the loop for some reason?, figure out why before merge - Morrow + corruption_image = image(icon, icon_state = "resin_growing") - flick_overlay(src, corruption_image, (4 SECONDS)) - addtimer(CALLBACK(src, PROC_REF(switch_to_idle_corruption)), (4 SECONDS)) + flick_overlay(src, corruption_image, (2 SECONDS)) + addtimer(CALLBACK(src, PROC_REF(switch_to_idle_corruption)), (2 SECONDS)) new_pylon.comms_relay_connection() diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm index 97b7762b527a..65336d42f746 100644 --- a/code/modules/cm_aliens/structures/special/pylon_core.dm +++ b/code/modules/cm_aliens/structures/special/pylon_core.dm @@ -18,8 +18,6 @@ var/damaged = FALSE var/plasma_stored = 0 var/plasma_required_to_repair = 1000 - var/activated = FALSE - COOLDOWN_DECLARE(larva_given_time) var/protection_level = TURF_PROTECTION_CAS @@ -39,23 +37,6 @@ if(node) qdel(node) - - if(activated) - if(XENO_STRUCTURE_PYLON in linked_hive.hive_structures) - for(var/obj/effect/alien/resin/special/pylon/pylon as anything in linked_hive.hive_structures[XENO_STRUCTURE_PYLON]) - pylon.activated = FALSE - - marine_announcement("ALERT.\n\nEnergy build up around communication relays halted.", "[MAIN_AI_SYSTEM] Biological Scanner") // Ask lore team for a better AI system name, honestly a second look for these announcements may be good - Morrow - for(var/hivenumber in GLOB.hive_datum) - var/datum/hive_status/checked_hive = GLOB.hive_datum[hivenumber] - if(!length(checked_hive.totalXenos)) - continue - - if(checked_hive == linked_hive) - xeno_announcement(SPAN_XENOANNOUNCE("We have lost our control of the tall's communication relays."), hivenumber, XENO_GENERAL_ANNOUNCE) - else - xeno_announcement(SPAN_XENOANNOUNCE("Another hive has lost control of the tall's communication relays."), hivenumber, XENO_GENERAL_ANNOUNCE) - . = ..() /obj/effect/alien/resin/special/pylon/attack_alien(mob/living/carbon/xenomorph/M) @@ -106,20 +87,37 @@ playsound(loc, "alien_resin_build", 25) /obj/effect/alien/resin/special/pylon/proc/place_node() - var/obj/effect/alien/weeds/node/pylon/W = new node_type(loc, null, null, linked_hive) - W.resin_parent = src - return W + var/obj/effect/alien/weeds/node/pylon/pylon_node = new node_type(loc, null, null, linked_hive) + pylon_node.resin_parent = src + return pylon_node -/obj/effect/alien/resin/special/pylon/proc/comms_relay_connection() - var/check = TRUE +/obj/effect/alien/resin/special/pylon/endgame + cover_range = WEED_RANGE_CORE + var/activated = FALSE +/obj/effect/alien/resin/special/pylon/endgame/Destroy() + if(activated) + if(XENO_STRUCTURE_PYLON in linked_hive.hive_structures) + for(var/obj/effect/alien/resin/special/pylon/endgame/pylon as anything in linked_hive.hive_structures[XENO_STRUCTURE_PYLON]) + pylon.activated = FALSE + + marine_announcement("ALERT.\n\nEnergy build up around communication relays halted.", "[MAIN_AI_SYSTEM] Biological Scanner") // Ask lore team for a better AI system name, honestly a second look for these announcements may be good - Morrow + for(var/hivenumber in GLOB.hive_datum) + var/datum/hive_status/checked_hive = GLOB.hive_datum[hivenumber] + if(!length(checked_hive.totalXenos)) + continue + + if(checked_hive == linked_hive) + xeno_announcement(SPAN_XENOANNOUNCE("We have lost our control of the tall's communication relays."), hivenumber, XENO_GENERAL_ANNOUNCE) + else + xeno_announcement(SPAN_XENOANNOUNCE("Another hive has lost control of the tall's communication relays."), hivenumber, XENO_GENERAL_ANNOUNCE) + + . = ..() + +/obj/effect/alien/resin/special/pylon/endgame/proc/comms_relay_connection() for(var/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/checked_comms_relay in GLOB.all_static_telecomms_towers) if(!checked_comms_relay.corrupted) - check = FALSE - break - - if(!check) - return FALSE + return marine_announcement("ALERT.\n\nIrregular build up of energy around communication relays.", "[MAIN_AI_SYSTEM] Biological Scanner") // Ask lore team for a better AI system name, honestly a second look for these announcements may be good - Morrow for(var/hivenumber in GLOB.hive_datum) @@ -132,25 +130,19 @@ else xeno_announcement(SPAN_XENOANNOUNCE("Another hive has harnessed the tall's communication relays.[linked_hive.faction_is_ally(checked_hive.name) ? "" : " Stop them!"]"), hivenumber, XENO_GENERAL_ANNOUNCE) - for(var/obj/effect/alien/resin/special/pylon/structure as anything in linked_hive.hive_structures[XENO_STRUCTURE_PYLON]) + for(var/obj/effect/alien/resin/special/pylon/endgame/structure in linked_hive.hive_structures[XENO_STRUCTURE_PYLON]) structure.activated = TRUE - addtimer(CALLBACK(structure, PROC_REF(give_larva)), XENO_PYLON_ACTIVATION_COOLDOWN) + addtimer(CALLBACK(structure, PROC_REF(give_larva)), XENO_PYLON_ACTIVATION_COOLDOWN, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_LOOP|TIMER_DELETE_ME) -/obj/effect/alien/resin/special/pylon/proc/give_larva() +/obj/effect/alien/resin/special/pylon/endgame/proc/give_larva() if(!activated) return - if(!COOLDOWN_FINISHED(src, larva_given_time)) //Somehow out of sync or doubled timers so we kill this "recursion" - return - - if(!linked_hive.hive_location || !linked_hive.living_xeno_queen) //without a queen and a hive core we do not give larva but we don't deactivate either - addtimer(CALLBACK(src, PROC_REF(give_larva)), XENO_PYLON_ACTIVATION_COOLDOWN) + if(!linked_hive.hive_location || !linked_hive.living_xeno_queen) return linked_hive.stored_larva++ linked_hive.hive_ui.update_burrowed_larva() - COOLDOWN_START(src, larva_given_time, (XENO_PYLON_ACTIVATION_COOLDOWN - 1)) //Hypothetically stops any stacked timers, there is probably a better way to do this but I'm having a brain fart, ask Harry - Morrow - addtimer(CALLBACK(src, PROC_REF(give_larva)), XENO_PYLON_ACTIVATION_COOLDOWN) //Hive Core - Generates strong weeds, supports other buildings /obj/effect/alien/resin/special/pylon/core diff --git a/code/modules/cm_aliens/weeds.dm b/code/modules/cm_aliens/weeds.dm index 07dec0406e17..01140beae304 100644 --- a/code/modules/cm_aliens/weeds.dm +++ b/code/modules/cm_aliens/weeds.dm @@ -55,7 +55,7 @@ linked_hive = GLOB.hive_datum[hivenumber] set_hive_data(src, hivenumber) - if(spread_on_semiweedable) + if(spread_on_semiweedable && weed_strength < WEED_LEVEL_HIVE) if(color) var/list/RGB = ReadRGB(color) RGB[1] = Clamp(RGB[1] + 35, 0, 255) @@ -588,6 +588,7 @@ weed_strength = WEED_LEVEL_HIVE node_range = WEED_RANGE_PYLON overlay_node = FALSE + spread_on_semiweedable = TRUE var/obj/effect/alien/resin/special/resin_parent /obj/effect/alien/weeds/node/pylon/proc/set_parent_damaged() @@ -619,6 +620,9 @@ /obj/effect/alien/weeds/node/pylon/acid_spray_act() return +/obj/effect/alien/weeds/node/pylon/cluster + spread_on_semiweedable = FALSE + /obj/effect/alien/weeds/node/pylon/cluster/set_parent_damaged() if(!resin_parent) return diff --git a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm index c8e8b1eb82c9..ab5028b12844 100644 --- a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm +++ b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm @@ -316,7 +316,7 @@ XENO_STRUCTURE_EGGMORPH = 6, XENO_STRUCTURE_EVOPOD = 2, XENO_STRUCTURE_RECOVERY = 6, - XENO_STRUCTURE_PYLON = 10, + XENO_STRUCTURE_PYLON = 2, ) var/global/list/hive_structure_types = list( From b1d0d1adfbbd40be1e78e0c1f9a88567313850d6 Mon Sep 17 00:00:00 2001 From: Morrow Date: Thu, 27 Jul 2023 13:03:52 -0400 Subject: [PATCH 07/17] some review, forgotten test code SMH --- code/__DEFINES/xeno.dm | 4 ++-- code/game/machinery/telecomms/presets.dm | 4 ++++ code/modules/cm_aliens/structures/special/pylon_core.dm | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/code/__DEFINES/xeno.dm b/code/__DEFINES/xeno.dm index 5907bb51f487..e9eb4ca4c1ed 100644 --- a/code/__DEFINES/xeno.dm +++ b/code/__DEFINES/xeno.dm @@ -166,10 +166,10 @@ #define XENO_BURIED_LARVA_TIME_LIMIT (30 MINUTES) /// The time when xenos can start taking over comm towers -#define XENO_COMM_ACQUISITION_TIME (0 MINUTES) //RETURN TO 90 MINUTES BEFORE TM - MORROW +#define XENO_COMM_ACQUISITION_TIME (90 MINUTES) /// The time it takes for a pylon to give one larva while activated -#define XENO_PYLON_ACTIVATION_COOLDOWN (30 SECONDS) //RETURN TO 5 MINUTES BEFORE TM - MORROW +#define XENO_PYLON_ACTIVATION_COOLDOWN (5 MINUTES) /// The time against away_timer when an AFK xeno larva can be replaced #define XENO_LEAVE_TIMER_LARVA 80 //80 seconds diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index d22dcc3aa5e3..9842a30c3652 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -296,6 +296,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) else update_icon() +/// 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) SIGNAL_HANDLER @@ -314,6 +315,9 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) if(!istype(weeded_turf.weeds.parent, /obj/effect/alien/weeds/node/pylon/cluster)) return + if(SSticker.mode.is_in_endgame) + return + if(ROUND_TIME < XENO_COMM_ACQUISITION_TIME) addtimer(CALLBACK(src, PROC_REF(handle_xeno_acquisition), weeded_turf), (XENO_COMM_ACQUISITION_TIME - ROUND_TIME)) return diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm index 65336d42f746..6265d57ba209 100644 --- a/code/modules/cm_aliens/structures/special/pylon_core.dm +++ b/code/modules/cm_aliens/structures/special/pylon_core.dm @@ -36,7 +36,7 @@ LAZYREMOVE(A.linked_pylons, src) if(node) - qdel(node) + qdel_null(node) . = ..() /obj/effect/alien/resin/special/pylon/attack_alien(mob/living/carbon/xenomorph/M) @@ -114,6 +114,7 @@ . = ..() +/// Checks if all comms towers are connected and then starts end game content on all pylons if they are /obj/effect/alien/resin/special/pylon/endgame/proc/comms_relay_connection() for(var/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/checked_comms_relay in GLOB.all_static_telecomms_towers) if(!checked_comms_relay.corrupted) @@ -134,6 +135,7 @@ structure.activated = TRUE addtimer(CALLBACK(structure, PROC_REF(give_larva)), XENO_PYLON_ACTIVATION_COOLDOWN, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_LOOP|TIMER_DELETE_ME) +/// Looped proc via timer to give larva after time /obj/effect/alien/resin/special/pylon/endgame/proc/give_larva() if(!activated) return From 700e5d8d9bb10f8c5b29b0280785395a3dc5ebd7 Mon Sep 17 00:00:00 2001 From: Morrow Date: Thu, 27 Jul 2023 13:04:58 -0400 Subject: [PATCH 08/17] caps --- code/modules/cm_aliens/structures/special/pylon_core.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm index 6265d57ba209..3fafdb8e2176 100644 --- a/code/modules/cm_aliens/structures/special/pylon_core.dm +++ b/code/modules/cm_aliens/structures/special/pylon_core.dm @@ -36,7 +36,7 @@ LAZYREMOVE(A.linked_pylons, src) if(node) - qdel_null(node) + QDEL_NULL(node) . = ..() /obj/effect/alien/resin/special/pylon/attack_alien(mob/living/carbon/xenomorph/M) From 5d8a9ed39ef4e9cbcefce3fde494eb7a5ea9cef8 Mon Sep 17 00:00:00 2001 From: Morrow Date: Thu, 27 Jul 2023 13:21:15 -0400 Subject: [PATCH 09/17] cap and percent gain --- .../cm_aliens/structures/special/pylon_core.dm | 18 +++++++++++++++++- .../living/carbon/xenomorph/xeno_defines.dm | 4 ++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm index 3fafdb8e2176..47654bf20bce 100644 --- a/code/modules/cm_aliens/structures/special/pylon_core.dm +++ b/code/modules/cm_aliens/structures/special/pylon_core.dm @@ -135,6 +135,9 @@ structure.activated = TRUE addtimer(CALLBACK(structure, PROC_REF(give_larva)), XENO_PYLON_ACTIVATION_COOLDOWN, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_LOOP|TIMER_DELETE_ME) +#define ENDGAME_LARVA_CAP_MULTIPLIER 0.4 +#define LARVA_ADDITION_MULTIPLIER 0.05 + /// Looped proc via timer to give larva after time /obj/effect/alien/resin/special/pylon/endgame/proc/give_larva() if(!activated) @@ -143,9 +146,22 @@ if(!linked_hive.hive_location || !linked_hive.living_xeno_queen) return - linked_hive.stored_larva++ + var/list/hive_xenos = linked_hive.totalXenos + + for(var/mob/living/carbon/xenomorph/xeno in hive_xenos) + if(!xeno.counts_for_slots) + hive_xenos -= xeno + + if(length(hive_xenos) > (length(GLOB.alive_human_list) * ENDGAME_LARVA_CAP_MULTIPLIER)) + return + + linked_hive.partial_larva += length(hive_xenos) * LARVA_ADDITION_MULTIPLIER + linked_hive.convert_partial_larva_to_full_larva() linked_hive.hive_ui.update_burrowed_larva() +#undef ENDGAME_LARVA_CAP_MULTIPLIER +#undef LARVA_ADDITION_MULTIPLIER + //Hive Core - Generates strong weeds, supports other buildings /obj/effect/alien/resin/special/pylon/core name = XENO_STRUCTURE_CORE diff --git a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm index ab5028b12844..2efbdb38eb88 100644 --- a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm +++ b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm @@ -1114,6 +1114,10 @@ /datum/hive_status/proc/increase_larva_after_burst() var/extra_per_burst = CONFIG_GET(number/extra_larva_per_burst) partial_larva += extra_per_burst + convert_partial_larva_to_full_larva() + +///Called after times when partial larva are added to process them to stored larva +/datum/hive_status/proc/convert_partial_larva_to_full_larva() for(var/i = 1 to partial_larva) partial_larva-- stored_larva++ From 48336c4b999ef9b1045dc3a1dc2c2da5a180e71a Mon Sep 17 00:00:00 2001 From: Morrow Date: Tue, 1 Aug 2023 22:20:09 -0400 Subject: [PATCH 10/17] BUFFS --- code/game/machinery/telecomms/presets.dm | 2 ++ .../structures/special/pylon_core.dm | 27 ++++++++----------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index 9842a30c3652..46a507eacb27 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -351,6 +351,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) new_pylon.comms_relay_connection() +/// Handles removing corruption effects from the comms relay /obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/proc/uncorrupt(datum/deleting_datum) SIGNAL_HANDLER @@ -358,6 +359,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) overlays -= corruption_image +/// Handles moving the overlay from growing to idle /obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/proc/switch_to_idle_corruption() if(!corrupted) return diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm index 47654bf20bce..bba6c55c64f8 100644 --- a/code/modules/cm_aliens/structures/special/pylon_core.dm +++ b/code/modules/cm_aliens/structures/special/pylon_core.dm @@ -97,46 +97,41 @@ /obj/effect/alien/resin/special/pylon/endgame/Destroy() if(activated) - if(XENO_STRUCTURE_PYLON in linked_hive.hive_structures) - for(var/obj/effect/alien/resin/special/pylon/endgame/pylon as anything in linked_hive.hive_structures[XENO_STRUCTURE_PYLON]) - pylon.activated = FALSE + activated = FALSE + + marine_announcement("ALERT.\n\nEnergy build up around communication relay at [get_area(src)] halted.", "[MAIN_AI_SYSTEM] Biological Scanner") // Ask lore team for a better AI system name, honestly a second look for these announcements may be good - Morrow - marine_announcement("ALERT.\n\nEnergy build up around communication relays halted.", "[MAIN_AI_SYSTEM] Biological Scanner") // Ask lore team for a better AI system name, honestly a second look for these announcements may be good - Morrow for(var/hivenumber in GLOB.hive_datum) var/datum/hive_status/checked_hive = GLOB.hive_datum[hivenumber] if(!length(checked_hive.totalXenos)) continue if(checked_hive == linked_hive) - xeno_announcement(SPAN_XENOANNOUNCE("We have lost our control of the tall's communication relays."), hivenumber, XENO_GENERAL_ANNOUNCE) + xeno_announcement(SPAN_XENOANNOUNCE("We have lost our control of the tall's communication relay at [get_area(src)]."), hivenumber, XENO_GENERAL_ANNOUNCE) else - xeno_announcement(SPAN_XENOANNOUNCE("Another hive has lost control of the tall's communication relays."), hivenumber, XENO_GENERAL_ANNOUNCE) + xeno_announcement(SPAN_XENOANNOUNCE("Another hive has lost control of the tall's communication relay at [get_area(src)]."), hivenumber, XENO_GENERAL_ANNOUNCE) . = ..() /// Checks if all comms towers are connected and then starts end game content on all pylons if they are /obj/effect/alien/resin/special/pylon/endgame/proc/comms_relay_connection() - for(var/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/checked_comms_relay in GLOB.all_static_telecomms_towers) - if(!checked_comms_relay.corrupted) - return + marine_announcement("ALERT.\n\nIrregular build up of energy around communication relays at [get_area(src)].", "[MAIN_AI_SYSTEM] Biological Scanner") // Ask lore team for a better AI system name, honestly a second look for these announcements may be good - Morrow - marine_announcement("ALERT.\n\nIrregular build up of energy around communication relays.", "[MAIN_AI_SYSTEM] Biological Scanner") // Ask lore team for a better AI system name, honestly a second look for these announcements may be good - Morrow for(var/hivenumber in GLOB.hive_datum) var/datum/hive_status/checked_hive = GLOB.hive_datum[hivenumber] if(!length(checked_hive.totalXenos)) continue if(checked_hive == linked_hive) - xeno_announcement(SPAN_XENOANNOUNCE("We have harnessed the tall's communication relays. Hold them!"), hivenumber, XENO_GENERAL_ANNOUNCE) + xeno_announcement(SPAN_XENOANNOUNCE("We have harnessed the tall's communication relay at [get_area(src)]. Hold it!"), hivenumber, XENO_GENERAL_ANNOUNCE) else - xeno_announcement(SPAN_XENOANNOUNCE("Another hive has harnessed the tall's communication relays.[linked_hive.faction_is_ally(checked_hive.name) ? "" : " Stop them!"]"), hivenumber, XENO_GENERAL_ANNOUNCE) + xeno_announcement(SPAN_XENOANNOUNCE("Another hive has harnessed the tall's communication relay at [get_area(src)].[linked_hive.faction_is_ally(checked_hive.name) ? "" : " Stop them!"]"), hivenumber, XENO_GENERAL_ANNOUNCE) - for(var/obj/effect/alien/resin/special/pylon/endgame/structure in linked_hive.hive_structures[XENO_STRUCTURE_PYLON]) - structure.activated = TRUE - addtimer(CALLBACK(structure, PROC_REF(give_larva)), XENO_PYLON_ACTIVATION_COOLDOWN, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_LOOP|TIMER_DELETE_ME) + activated = TRUE + addtimer(CALLBACK(src, PROC_REF(give_larva)), XENO_PYLON_ACTIVATION_COOLDOWN, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_LOOP|TIMER_DELETE_ME) #define ENDGAME_LARVA_CAP_MULTIPLIER 0.4 -#define LARVA_ADDITION_MULTIPLIER 0.05 +#define LARVA_ADDITION_MULTIPLIER 0.10 /// Looped proc via timer to give larva after time /obj/effect/alien/resin/special/pylon/endgame/proc/give_larva() From c3b6e3b273775d95300efebf45fcbb924b3a940f Mon Sep 17 00:00:00 2001 From: Morrow Date: Wed, 2 Aug 2023 16:43:50 -0400 Subject: [PATCH 11/17] no messages on hijack delete --- code/modules/cm_aliens/structures/special/pylon_core.dm | 3 +++ code/modules/cm_aliens/structures/special_structure.dm | 3 +++ code/modules/mob/living/carbon/xenomorph/xeno_defines.dm | 1 + 3 files changed, 7 insertions(+) diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm index bba6c55c64f8..96a0e5dee72c 100644 --- a/code/modules/cm_aliens/structures/special/pylon_core.dm +++ b/code/modules/cm_aliens/structures/special/pylon_core.dm @@ -99,6 +99,9 @@ if(activated) activated = FALSE + if(hijack_delete) + return ..() + marine_announcement("ALERT.\n\nEnergy build up around communication relay at [get_area(src)] halted.", "[MAIN_AI_SYSTEM] Biological Scanner") // Ask lore team for a better AI system name, honestly a second look for these announcements may be good - Morrow for(var/hivenumber in GLOB.hive_datum) diff --git a/code/modules/cm_aliens/structures/special_structure.dm b/code/modules/cm_aliens/structures/special_structure.dm index caa729f1df87..69bdcc2438ac 100644 --- a/code/modules/cm_aliens/structures/special_structure.dm +++ b/code/modules/cm_aliens/structures/special_structure.dm @@ -39,6 +39,9 @@ plane = FLOOR_PLANE + /// Tells the structure if they are being deleted because of hijack + var/hijack_delete = FALSE + /obj/effect/alien/resin/special/Initialize(mapload, hive_ref) . = ..() maxhealth = health diff --git a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm index 2efbdb38eb88..641dce4503a3 100644 --- a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm +++ b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm @@ -898,6 +898,7 @@ for(var/obj/effect/alien/resin/special/S in hive_structures[name_ref]) if(get_area(S) == hijacked_dropship) continue + S.hijack_delete = TRUE hive_structures[name_ref] -= S qdel(S) for(var/mob/living/carbon/xenomorph/xeno as anything in totalXenos) From 0821f4107df8c1c5050a4f7c6f2759a012dc9377 Mon Sep 17 00:00:00 2001 From: Morrow Date: Sun, 6 Aug 2023 04:46:14 -0400 Subject: [PATCH 12/17] bam, fixed signal failure --- code/game/machinery/telecomms/presets.dm | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index 46a507eacb27..faa8510cbb7b 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -221,7 +221,8 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) /obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/Initialize() . = ..() - RegisterSignal(get_turf(src), COMSIG_WEEDNODE_GROWTH, PROC_REF(handle_xeno_acquisition)) + RegisterSignal(src, COMSIG_ATOM_TURF_CHANGE, PROC_REF(register_with_turf)) + register_with_turf() /obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/attack_hand(mob/user) if(user.action_busy) @@ -368,6 +369,11 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) overlays += corruption_image +/obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/proc/register_with_turf() + SIGNAL_HANDLER + + RegisterSignal(get_turf(src), COMSIG_WEEDNODE_GROWTH, PROC_REF(handle_xeno_acquisition)) + /obj/structure/machinery/telecomms/relay/preset/telecomms id = "Telecomms Relay" autolinkers = list("relay") From 581af11449bb38613acc9e814b65a50486cc9c5c Mon Sep 17 00:00:00 2001 From: Morrow Date: Sun, 6 Aug 2023 04:53:22 -0400 Subject: [PATCH 13/17] commento --- code/game/machinery/telecomms/presets.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index faa8510cbb7b..64c7757392a4 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -369,6 +369,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) overlays += corruption_image +/// Handles re-registering signals on new turfs if changed /obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/proc/register_with_turf() SIGNAL_HANDLER From 56b1f705cc697904c03c1d2cfe364e66f861a169 Mon Sep 17 00:00:00 2001 From: Morrow Date: Sun, 6 Aug 2023 04:55:54 -0400 Subject: [PATCH 14/17] Comments and || --- code/modules/mob/living/carbon/xenomorph/xeno_defines.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm index 641dce4503a3..fbf75f16ca8d 100644 --- a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm +++ b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm @@ -383,8 +383,9 @@ addtimer(CALLBACK(src, PROC_REF(announce_evolve_available), GLOB.xeno_evolve_times[time]), text2num(time)) +/// Sets up limits on pylons in New() for potential futureproofing with more static comms /datum/hive_status/proc/setup_pylon_limits() - hive_structures_limit[XENO_STRUCTURE_PYLON] = length(GLOB.all_static_telecomms_towers) ? length(GLOB.all_static_telecomms_towers) : 2 + hive_structures_limit[XENO_STRUCTURE_PYLON] = length(GLOB.all_static_telecomms_towers) || 2 /datum/hive_status/proc/announce_evolve_available(list/datum/caste_datum/available_castes) From 43aaa6a14899a0412b029fd006eb7118ae422042 Mon Sep 17 00:00:00 2001 From: Morrow Date: Sun, 6 Aug 2023 04:58:00 -0400 Subject: [PATCH 15/17] removes to-dos --- code/modules/cm_aliens/structures/special/pylon_core.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm index 96a0e5dee72c..f890e8848550 100644 --- a/code/modules/cm_aliens/structures/special/pylon_core.dm +++ b/code/modules/cm_aliens/structures/special/pylon_core.dm @@ -102,7 +102,7 @@ if(hijack_delete) return ..() - marine_announcement("ALERT.\n\nEnergy build up around communication relay at [get_area(src)] halted.", "[MAIN_AI_SYSTEM] Biological Scanner") // Ask lore team for a better AI system name, honestly a second look for these announcements may be good - Morrow + marine_announcement("ALERT.\n\nEnergy build up around communication relay at [get_area(src)] halted.", "[MAIN_AI_SYSTEM] Biological Scanner") for(var/hivenumber in GLOB.hive_datum) var/datum/hive_status/checked_hive = GLOB.hive_datum[hivenumber] @@ -118,7 +118,7 @@ /// Checks if all comms towers are connected and then starts end game content on all pylons if they are /obj/effect/alien/resin/special/pylon/endgame/proc/comms_relay_connection() - marine_announcement("ALERT.\n\nIrregular build up of energy around communication relays at [get_area(src)].", "[MAIN_AI_SYSTEM] Biological Scanner") // Ask lore team for a better AI system name, honestly a second look for these announcements may be good - Morrow + marine_announcement("ALERT.\n\nIrregular build up of energy around communication relays at [get_area(src)].", "[MAIN_AI_SYSTEM] Biological Scanner") for(var/hivenumber in GLOB.hive_datum) var/datum/hive_status/checked_hive = GLOB.hive_datum[hivenumber] From bd5663ee950792ee91c01426a18e8301467aca09 Mon Sep 17 00:00:00 2001 From: morrowwolf Date: Tue, 8 Aug 2023 00:53:20 -0400 Subject: [PATCH 16/17] Update code/game/machinery/telecomms/presets.dm Co-authored-by: harryob --- code/game/machinery/telecomms/presets.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index 64c7757392a4..68d67b6e702f 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -216,7 +216,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) var/corrupted = FALSE /// Held image for the current overlay on the tower from xeno corruption - var/image/corruption_image = null + var/image/corruption_image /obj/structure/machinery/telecomms/relay/preset/tower/mapcomms/Initialize() . = ..() From 329fe47cd7a146dd3a619f062f35be47123ee8cf Mon Sep 17 00:00:00 2001 From: morrowwolf Date: Tue, 8 Aug 2023 00:53:33 -0400 Subject: [PATCH 17/17] Update code/modules/cm_aliens/structures/special/pylon_core.dm Co-authored-by: harryob --- code/modules/cm_aliens/structures/special/pylon_core.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm index f890e8848550..068ffeb659eb 100644 --- a/code/modules/cm_aliens/structures/special/pylon_core.dm +++ b/code/modules/cm_aliens/structures/special/pylon_core.dm @@ -114,7 +114,7 @@ else xeno_announcement(SPAN_XENOANNOUNCE("Another hive has lost control of the tall's communication relay at [get_area(src)]."), hivenumber, XENO_GENERAL_ANNOUNCE) - . = ..() + return ..() /// Checks if all comms towers are connected and then starts end game content on all pylons if they are /obj/effect/alien/resin/special/pylon/endgame/proc/comms_relay_connection()