From 3ea4a3ab2da15cdfc332b5352d3da8d556f6730f Mon Sep 17 00:00:00 2001 From: xen-42 Date: Wed, 15 Jan 2025 16:32:58 -0500 Subject: [PATCH 01/87] Make a config --- NewHorizons/External/Configs/AddonConfig.cs | 5 +++++ .../External/Configs/MainMenuConfig.cs | 19 +++++++++++++++++++ NewHorizons/Handlers/TitleSceneHandler.cs | 14 ++++++++++++++ NewHorizons/Main.cs | 2 ++ 4 files changed, 40 insertions(+) create mode 100644 NewHorizons/External/Configs/MainMenuConfig.cs diff --git a/NewHorizons/External/Configs/AddonConfig.cs b/NewHorizons/External/Configs/AddonConfig.cs index 66674575..d93d7b90 100644 --- a/NewHorizons/External/Configs/AddonConfig.cs +++ b/NewHorizons/External/Configs/AddonConfig.cs @@ -44,5 +44,10 @@ namespace NewHorizons.External.Configs /// The dimensions of the Echoes of the Eye subtitle is 669 x 67, so aim for that size /// public string subtitlePath = "subtitle.png"; + + /// + /// + /// + public MainMenuConfig mainMenuConfig; } } diff --git a/NewHorizons/External/Configs/MainMenuConfig.cs b/NewHorizons/External/Configs/MainMenuConfig.cs new file mode 100644 index 00000000..521a3275 --- /dev/null +++ b/NewHorizons/External/Configs/MainMenuConfig.cs @@ -0,0 +1,19 @@ +using NewHorizons.External.SerializableData; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NewHorizons.External.Configs +{ + [JsonObject] + public class MainMenuConfig + { + /// + /// Colour of the text on the main menu + /// + public MColor menuTextTint; + } +} diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index c0c3924c..c6e9ca8c 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -1,11 +1,13 @@ using NewHorizons.Builder.Body; using NewHorizons.External; +using NewHorizons.External.Configs; using NewHorizons.External.Modules; using NewHorizons.Utility; using NewHorizons.Utility.OWML; using System.Collections.Generic; using System.Linq; using UnityEngine; +using UnityEngine.UI; namespace NewHorizons.Handlers { @@ -25,6 +27,18 @@ namespace NewHorizons.Handlers subtitleContainer.AddComponent(); } + public static void SetUp(MainMenuConfig config) + { + if (config.menuTextTint != null) + { + var buttons = GameObject.FindObjectOfType()._mainMenu.GetComponentsInChildren(); + foreach (var button in buttons) + { + button.color = config.menuTextTint.ToColor(); + } + } + } + public static void DisplayBodyOnTitleScreen(List bodies) { // Try loading one planet why not diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index c964744f..42cc70b0 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -430,6 +430,8 @@ namespace NewHorizons NHLogger.LogError($"Failed to make title screen bodies: {e}"); } TitleSceneHandler.InitSubtitles(); + + TitleSceneHandler.SetUp(new MainMenuConfig() { menuTextTint = new External.SerializableData.MColor(128, 128, 255) }); } // EOTU fixes From 2e78a3ce6ea156405bb6e7818c65fe1228e3eed7 Mon Sep 17 00:00:00 2001 From: Ben C Date: Wed, 15 Jan 2025 21:35:13 +0000 Subject: [PATCH 02/87] Updated Schemas --- .../Schemas/addon_manifest_schema.json | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/NewHorizons/Schemas/addon_manifest_schema.json b/NewHorizons/Schemas/addon_manifest_schema.json index a1e1d34a..f6c52366 100644 --- a/NewHorizons/Schemas/addon_manifest_schema.json +++ b/NewHorizons/Schemas/addon_manifest_schema.json @@ -38,6 +38,9 @@ "type": "string", "description": "The path to the addons subtitle for the main menu.\nDefaults to \"subtitle.png\".\nThe dimensions of the Echoes of the Eye subtitle is 669 x 67, so aim for that size" }, + "mainMenuConfig": { + "$ref": "#/definitions/MainMenuConfig" + }, "$schema": { "type": "string", "description": "The schema to validate with" @@ -79,6 +82,51 @@ } } } + }, + "MainMenuConfig": { + "type": "object", + "additionalProperties": false, + "properties": { + "menuTextTint": { + "description": "Colour of the text on the main menu", + "$ref": "#/definitions/MColor" + } + } + }, + "MColor": { + "type": "object", + "additionalProperties": false, + "properties": { + "r": { + "type": "integer", + "description": "The red component of this colour from 0-255, higher values will make the colour glow if applicable.", + "format": "int32", + "maximum": 2147483647.0, + "minimum": 0.0 + }, + "g": { + "type": "integer", + "description": "The green component of this colour from 0-255, higher values will make the colour glow if applicable.", + "format": "int32", + "maximum": 2147483647.0, + "minimum": 0.0 + }, + "b": { + "type": "integer", + "description": "The blue component of this colour from 0-255, higher values will make the colour glow if applicable.", + "format": "int32", + "maximum": 2147483647.0, + "minimum": 0.0 + }, + "a": { + "type": "integer", + "description": "The alpha (opacity) component of this colour", + "format": "int32", + "default": 255, + "maximum": 255.0, + "minimum": 0.0 + } + } } }, "$docs": { From 165be74d230e2cb70b062c3aba13d1d049850493 Mon Sep 17 00:00:00 2001 From: xen-42 Date: Wed, 15 Jan 2025 17:05:45 -0500 Subject: [PATCH 03/87] Finished tinting the menu --- .../Assets/textures/MENU_OuterWildsLogo_d.png | Bin 0 -> 26559 bytes NewHorizons/Handlers/TitleSceneHandler.cs | 10 ++- .../TitleScreen/TitleScreenColourHandler.cs | 67 ++++++++++++++++++ 3 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 NewHorizons/Assets/textures/MENU_OuterWildsLogo_d.png create mode 100644 NewHorizons/Handlers/TitleScreen/TitleScreenColourHandler.cs diff --git a/NewHorizons/Assets/textures/MENU_OuterWildsLogo_d.png b/NewHorizons/Assets/textures/MENU_OuterWildsLogo_d.png new file mode 100644 index 0000000000000000000000000000000000000000..c960405b87ea88cc34294f212b663c5fe70c2fca GIT binary patch literal 26559 zcmeFYg;yKj6F6Fd7Aa0?k>Vjhad(Op4+RRvHHBhDf@_OAlu%p>MT@&baZ)5mA!u*{ z#WgrDe7?VT&O7hCKjH1kp1pf_XYSmYxnp+|@eZU&fJcS*;K2g|WhHs72M-=)K6vnu z9p?$A=flzVXUydxL`zZjLHP*H7Ul-aT1H*w!Go$e{A+V;%ssA?l0M|Y1H$h6^I^YZ z5g60?(p5pvRol_Z)x+H7+_^w(X*JIwP|EQ;IrL4^U00(n} z{ebEr_JfC*mI~&i{y%LDH4j)HKK`%&5vI-i@X-Te%+&yM+Js^K*Kdny-ydd}^B(^H zzW%=keen3fgZQTpurP1%@bU9J{P91m_Yl}W{)Z_M)4o3*VemZq?@cXH5lrj7wdI&$Spz4B_vL#EkB$d}Jl6nj-)n$;5UaXtb3`5hjFcNVQiY(Ov@ z#QI9$hxHU{#z!X8?=1h<)URJUb$5$v*=>vHR+QISxk25OuobDNG5}fECoOA6T|>YtmG{+8G0ZAqmbWG@#UK84kH^d{c=K7{$I*n3 z&m55*PcV-=f8mT#VhtWZt`Irb|852E@#_8$F9L8CvoMDgaX;L>=MR=lC0DM7HD(Gx z;KWXw#x}F0*nawu4cmW@#JVOhXbyp}_dm%JQA;F#Z>oti?(y5=-owDdn0@rBfh-d$ z5hy6}O$`{XaW)R#*Py`Aj8y`_kXYLr257OY7C9EhkT6ZoAQr^A>U(V2Dy;8G_#f$S zG3++{;&D(8laic4F<&KsQ!N$5M8mXxo(cnebgHG*C`6(6wD6E%fa|)VE)-zx95dD| z+u9HPV>#pl=u=Hn49FZVmNDug-R9$yRQ!5lp&zl2%<8qiK`zYoZe69KmP(*EBYV3m z*JHPJ*yZcZBH$Hn4@XBK_|fmhR1PgjAPepoWod*sbBk%UBS=^7QT_{bu% zO>$6?Io-hZ_H=Joznx!SHMa(CofUKiv{N=xzfdDwPODIDz&V_R-7@ME3&_-};Y~fL zQf9vK=9Ar8h81M>NDI%vfmcCb({E}aUYMC|r%)eXpQghy{0o3i#2ldTksoeqN&5C_ zN~k`ptlq+`G%P0!i>Y`5X7a>?1JBp;i2{2u@~p*!uXr%?>vJ&(5%GF;@KHXz=DlUa zh#vqxWP73imlcPCLEd_lu{Awmr307>s|MhhF}yZ`V>Cq2TuLVq_>mRI3W#}wiltk( zHNB9>S(h$YI&hZxJQ>-wV{T^D~!CPvd<6FbIfOyznUzm!@P23*a6FM}~kRT{z} zA-%hyA;Uv9#>e*QVc@YSEWA4;mU-jpZ^Kvk($Av0 z>XEBM7r#8ple}rc8eK2!J;=T$^7P@4;tOH}G3Ao{N8jxlxq4P46H;4LWvWn8&CLPFZPX-?WC%)VU~Mu%B^hU49$qAXZ|?*p-ZO}y6o5~bhakk69&>F3 zfyn8`^a|QUdo}L_=RzJWS5_PrfQwiVfWeoGv!~zFvKk14uzy2B>SQx3)HhH^7Htyx zQYPix68f$67{!E`L%09tm@2WjZN7$*B=|9CWw-fIV@;6e^6TNXan*JTc#2#b_XD}pRV>t!_gqLAS-Haq6vQVJDwtjcB?X;XQ$0+J#_ULw#ZcC{F=L} zr@jitST;4;@DVdm?fT~GIQ!vjW6ZmcVdI2nvk}wC47*ahC zh?qpN9P`^nXk?egHE08_fV;^5%&{9r8&VzzmQ*B@?Sqnft<=NeaHY4tcx}m{3tnPZ z-r_$GT`-oxX%b_|H+~3qewW*q-NTDhiPxU(pSvi!_X3^s^4=PwSQx@ZKj}Cf<{fz^ z1<#%C?o24YUtJfO6TvX4a*USL0WVM)V=L5R$hdIIb$KcA86I?vmH-5nK6SEY;eI07R{}fMTP#Bt83HkwFO{=pMsxr+K&2lH-qsUEXx=V{jU)96dXPpt=M{#0od}0p_UnCGRHBP@&%426=`Q^*n0?kU)-<|9L*wi=T^hR+>z? zaKzG+MS@zU5?h|npFcH-?ec&chHUi_r-oE0$UMfta^d`5RK@si=}m5{AM1ZkwS6tB zbC4s_7~I?4HA|@n_N5L`axCNEi8^QMmF3`=vy3Kp({CIV3dpA)FbclC;ssNa-%(8n zu||nlwqZsUI!>ccuEH~_;ho#%yDHpX zyEs)L4+ZB2LG4u|4uiuwP->wj5#-2|k@Uw8?q1Mbe z8*BT}HpWygLex$s%r(PII%_9A;iKd7OB|48K*W@m>_0Eg$b-x0B)P}U=W}2Ki-8X` zvr#S_VaQ3rLpZv^Z*%pzAgsd?E%XTo9%$WFvrLH_D7yU7*NN}A+vwa_Lq!N7<}_f+ zJZSd~-T9puvmnxhcTEuk(`1n&B)Kfpd_8LT^+KN15x+&HS{6II+3xsptN>}KoYQa?(1QZMs znVo-IZSR`jhAZW6lltMu*7D*8(u-ir6j@`I-*84h9UF6J?!DSs?S7A-!ze`m;{@X) zm##HB%tFKqJfKdPOnH4B4P<5#LJh4F1w!xNecQX9)~id$U7!o_3x9GXLu|A{1iksa zw@W`%!`{`wH&e*m;!~ZiL}9`IDU=vP!gP~k6Hz+Zn@ipD4!8RNZ;4|>hK|bWg)@oN zT?jbXirgM+_}&-?q4qJ%$Y*3UFOkY|EBncq%#IT%6>alV-X3X=0i4A|d^}G(Y66Uz z?zK0Rkx5kB?>zs%0Ff@VUh{GutZ{F-h3>6W=Nxphd?4d7Cv>Fl_@Wu?vCt+NrLa2L z(on)Qf?9lHplt&Mykc&QcHZ~)n;p(hlH*o)h`l_Tg!%5#e@eg*PJ{EjOt8nFy;Z7b zkgc|TN?Z6c{NE1;91se!J*d(Xd>|25Ga4Y6x_vqh{?(BTR-y(dTG$S6WIdIEU>LR0 z#Vo}vU5q`l4v`YpH4|t2BDW+9hYw43i~n z@5G*~qK1qgxAx3#%}dX8C!8)g8NJ@ua9;$MBMO06y0M$1Y6a?N6a4N6q*tdDRR9IOGm>OH|1pvT*3fPI@@+Gi5g>H*3dI90YSQXr5M--GOjeh{hK35U{~DMLS04iqQHst3r$C$=X>QP2AuRU!1BM4XI$# z1%O(H`wpjW9bE!;;lVyd7j_xB`}(#wXU-UXQSWHXYByB!Gsa|W+@}LnJ$)|#c6D(; zwVj^B*~n0?<=HC}Ra`iSNQ1j^kQrg0JxwOg*?nxlBZ&zvD0sc_^alqGW{;-;QH)KY zhNnH800}v#Co-a0i#ZO7CTVK>^YkehnCX|`=)cB_-vLE)uu0wQB{TcH;afgwf)MB= zi%V{z5{9cp^csyk7QG1T|A`U?0!H834Af9##A=VR4+dcf=xB>$byKf3MLO0PQ-Wxx z_2+Okon<`8nwcd33{B%+oZ8uUSV8lK|K5~jzYLGC(2k2>m_)-p5ANee&TDnP73kAg z;+0qFTF)dIDB&zsO?mXqm^}U`!I+U=t0$cu{w;^l%{)M&U#8M+C>aAOpm?(NY-*^V zdBXF0Fu~8NI)OrRg#IoS9Q(=Fr#gxDnWR7m7=6~a-JFQy{%aHk@UgGXL5Q2KqJR)` zI*osV%k2w}=ra!abAxYB#__1K$xILFh3R`CK36s6$ry%zt5^=h}AF&gtn#MGSP|5tGlki#%}nj$-C#~OMQcZI&^@+g)^xZX-KM0VWA&p3fI_w^C`#|)=Hmcc+WOyK$h++&4vFE=wy zjCt)8I-dn+xA^!_?`3efNZiY~_g=u;C_>on;=yG7Kq!dgTB`~{TeR&zQ zF!$5fyxR0WYt=c@NVpl^bExsvs}|owB9D||zE;=z)fpc$ZEjkyj=OoC3K!<6<%^}b zQmc;Wpbm@*|I*|O8Kb0?lYn2)EKw2-X81;=nG{`iblY^$okL9dVrCz}|E)uE<|^UF zq56lz(Bjee0QwmkbjfS_t#&++!w5^Tz*@0g+k6!!uSn}Cvm#WT%{T7IA z7oD-bjFK$ui@UyFoM|%_Mlg#>i&8pjv=?7=qATw{R)6>(kJ3uTi+f`QK2fgD_MEB< z2Z)W3CA87&XNN6-&vRh)EIpo?CfPeqTGHeX&KJOrvu$n5y)fFe9Znbrd4=j30>&4R z!m$xyb5ROz=4~_$&hmL@dB}&97Mrog6p-3JUg8YQp8NMLas!z7ZUywiM|bHvZjTfE z6ss*o&kK3N?t1oio15wnnyJh3)l3OrFq@3i6b#Xlxpo7WWe7I9u=?Gfx$es(XpC1bHZhFSU4*?W5|t;Pd6@N2+;GM0H zyc)qgw*v7ZILMF|(Qn9KAdU{w(5Uxzka0Dz->bP=wdYu;bXvvjWdl+MtrkN4_J^|r zMV(But9`B>#tBCAGW@l4m9sj(zS(9#t4t9D{K&r=3_{PqcG9xQ&P^l`a|DD>6iESMZoE$f@CZQNmrK0}IB z)WD+?$}9Bp{3p8AGivDJNOG)r@vD->c`FT+`KFhOKNBVTNGr;Ka6+wjd~x64q6tj2 z*p`_{r*g&#GidBscy|tgO0vxW!kKecISN|ft;}b4)jloCYuLBfdk%s^P`gQyLU~l3 ztm_}gn@OF4hfSOKl$k8e1W&l1_p3HeB1QXR9bbPR zEHqHDR*)zN7sSQqIHGqQ9gwD0wV=!U7Fq9Ohz-ADku`b!yOp!hov?pkmWNwXI(1kB zXY?b9Y5!R2%p@OV?$!JF9P_KmBZyhbb=3YI zrA)I!@<;8lEd@Swb%>>MaaKu9D*nmJSjjn#ykhvchK5S^m}baam3L^k|GWLDVZ8`9 zvtK)j*3Ts92QjZ4o|xMn`&}V)J$3nBv{PVK(~snjc#eg!5V4uKY1ysnRxip z;?aQ1_;ma^tzUoW`{c0 zZhYJTyc$oJex=B|z+aJ~goIl#Bw>@7{Q634MO=!TN$u)LGKurY`ITyJ7x(rwAS-z% zgLTKqBxV(tt#`|H87TQ&eQinVrz(FP0T~+4SVb{I4Q(0(* z%d$Zc5`roIuo1i+q%|iEoRIe{x6UI-3Ta`LAe~nm*q^~z=t-G3#QPmt98;ysPP)UK zBAwc0g-5*d&Eew)=b!!Q#ILgyM1P>4m0k5ghp$ zI)=%~Z;7TaZ|wy2ZU{q9Z_tLz-Ox!r4o}fQGyL#`q8~zW^54e1jOZqj8}R&r*vF#l zVdTHu`R#_Uw_V1ahehauBUzjUkh};#6 zP(%*;uxv-cqC9`;=t0!~rV$01C(`)y2=?{x8sZ-=8`V{#n9qwBv1f%5?UTCLRVw1@?Th;e*+36}nM zI?JQ7_)y&CrqjLyr%YR#{FjQRTykZMmAv4GsZ0SBzTk>D)V>q1Ad)XTk>gIkkPMz7 z7M9-*XY^8Y^uhIine0GD#F-re2m*%px-O!BuNQjw&uo z&Uw7aA}qg1=d@L*v--KMPQCZTh-7oZu^Hp}=M%Ge#7X<= zx;`M{)789q3fB(s$ktnY*}rZFUgds}UWR<80i!U|#y$G${M$n*>VSSBLD$s8oIRuW z6Bh|%wi-8Yo?k|S{%VbK{aOi|a@VY*$fGcnb9hA?Y*1D))ojChI)$>7YS>vQI*d;5 zSZO`|Si~uI{0Qy?gA|`mj~AY$40TB7xQZRH$ zC8ZA&j4xqUmWssXA`67HO&cA~D}5UcN>0`U;?PRkXsY6Yh-reun0|^{=lzTzoYG4V zwUGKI&icp8K_Lu+3qtE`rd9Gkv6Fw7_ty6V-)d7WAn&f@pRcgI>t!z&h#>d@O6ALL z6s+Lnit-INvW>v1OXQDvvDW-u9S+{gyHD%;32of^F@GO*K?Z?IMsr=1^R%+EMU_*J zqyf2vQWdTOsOzXM;$euK=LHSo=sNu02!n_N%lwD*thDV|XK26s7Oo!(WCGp(XF$L% zMa?LtIWf02&_1=a#dhKE^0hpN{wLrhwS-r+ao_I9Wg}vp4p8D19%Q#AHb7K2P+Kp` zVg65n8K)o+p)woC-zW`8C2)zUYvj&)C2POEz!hFpj2}8LOuM7VlHR;|K5~WNon8um zK-WF{V>rpKS92^qC%2}c0qXI~Z~^g%;?VbG;@vam#}w`l3uPkexO@ zXgm7q?Qi(EKb_xLT%|)%K=Cum;j5z`&p+UH5dC`mlKpJj!qd0-@iD+YyfHR(yY!(Sn*xm&7-sK~n=rxRI}GqgSnokICJ?4UKj1 z@|JbE;4A~sr1tH@4a0;szL~_piHu*rts`QZ>p0_xdLe#V{MTshI~KZ@osJGGbiK5k z0gGGJG)~*(Z){@rPZ2p~Iy=mQb~@9Cfnbmc-Jcs>~?!+CaVz(W=t3Vvtbo$o1!o)XFTf)!9E6w-=57#;g9mIL@DaJeH%ow8LMK ztpXI86sw#|b9@g!<;?=MO6r$MkRm~*d4OOdf<&pt0}pj8l8vq;RJ>y@ftuRiP`k%X(P zrY)M^4=oi6BM?|dk4=Ab{Qz+MO4h=ePcizs@nlx?z@0WyC)Zo``R}rKuWQ@gD-^fD z1vs!rZhxrv^>H+A_L`Cs={V$0;$FqZ{5;*#D|c7-Bs3g8B*$GDV=6C2NYohn=vG%K zv#juA%Xe&Am!vEb^#X@oIQA3!NG<{c3V*xuSaxq8JhaVxw2D73sjq4h3}M4+ZIzAd zr?50v5&y+iXfz2Ru9o$aWktLl9&HYDh{+O%76x<@<@Dq{ODO=$`j!ezhh~(e z!h$2i9Z3h546;Mo6n{LWjOJ#y=M(i5s~Z_J0=&@mROPsi$Gi^_?5^;tfoyVtkV3EP z=q#dsZ!sCC@9r(|b4H5MqC^MVc{< zZ*4=S)Vu5mo*%!v^{yuE#9c0!Az<2`@sr}aQOQ# zukfBT#y^M`W-L4=7LNK*O)k!lXl=1HHpF%&unnGCm=MgOUH7Mc8tHHA_RUkJx-5)) z*iE|0NBpH_z9ASJ?u&`nVo3?fVxer6EOkisc!&}~gzE#H?XKX2tU#5y*wsO6vVkfdDcX6EL#1>eCLfq5BZIfo}; ziE0FvbDsDcHakvwZ)?65>s8(l=1CS33m?%!B9EM6q1zDy$)O&`IPR_7=_!2-xhl&W`qgm(l@0Qjp7m*N!$k+YUrpqv&@zRl7g+=(V z3HCmJs;kdt8#%(8Vt(3uyZbmkTAC?)w=lwI zoJX@M@l!PnLDgz=*Ni={Y6-9$ik6Je({q(A`EKyIp^o^9ftGREq1-Eq@WnBJ$ofV3 zb^G~+yH$T{5iMzqe}%eJSDsenq4zI<{NVK3p_2-z;uRrZAI>FlRzoj%Zg`MUWY|kk zNJ^%XnTExMr;s!YK9AWza)=8bROMXrH3g-Y2H-epavzrv3JAV@<^MU+R4r+OPu~Bn zT^v;|^hKrBXMH<{vuANXlh~dJAX@*NF$9u5IT0no)kso)^ZHRsRCi`7_Pe^%I^D7s zcR?2HRW}D*BqhB6J+w(%l<@d_1!dHPd3v4?vv^X&E44wz9n+v@VnZS&A%(BsPO_Wu zqoT=>DqFG!3Zj+0KD!BgG@@7y13#^en5%>ebAOgu#z;=xMh=kc>&$88p>4xK(UKL{ z#E(kqhb8#j`GN5_nB^acH~S)%XoG7RvWbd#v)q`CWvWgMXXaS_6V>Zxro_*_ zT+68K4nw;mVw@C=k4bWA-(#D1rlhH1I9s^; zWDJPN#6T*tE~;2Qfm;W)=B#~D=geKtxDfp*mF$1kQP_^*88h9W=N>A$me<&;BI|y* z|76~IZrI^oN7sQ$3IMz)x{<5){r6k)b}HKcC?vQ3@!8nEQ6Ib50N2Tf%`rZQcia5 zCnY+P*mkP&3ikCu6JABJp5JVX6J43&Z6j>bU=+Ydwf>Gsiwk~4-@r<$Qf;9IX5|G zoGHo|2;iFxLuj2Y6uC959-%HK8RfIKYoKl7GcVPIFo$?5$EQ0Rz7@16Y>G?5i(7+1 z)P%RUctrx9W$oh7^xJU77_&R-9qqOS5DY04Rqv0toBka+RnEq)-0(5yI{gX(D`FF4 zK$rHtc@84i`W%yn1euUob$&2Lwb`MlW^G8xJ7W#7Q%&E~o!)-oo=@&X*Z5zDLuTdm_XLxkP)V0DF<+qA-slccKl zMg&yavQDA!fZI`xAUM%5FR5XoSS+%DPO30sarinZ+}{Rc*p@l+bH`kdVTt{yCvd{}<@HvsWjCEUKu z8j;9=N0OoIY{E3&Rne=1N^YfPZ?lK zUYVfUklIoZjQ=ySdrHk*fK$<3KG0(n`H(BFRKa%5{nEcI>vydHR%!`-k*%7GMDv=TJ{U<(s z>S>>Bz!(C<>2%gGe&g`(5j)Ka>WH4qfWqxjB9JL8`Knr%sO@5{9JZ!YqJjvt{blzm zS}|DF`fH=G!;ehUvTG3feY?LM&Dkbrr-ywN>O5ENxrt)T0i z_G|9O5T~^LRe9=9e4w2H+(hbP%Bok+`1mDNMPFjtSoDW+8=p(m;8ChG2#Ac4fmJ%_xGk~xlR#-DTT`?=SQf#!o0CRm$Ci~ zHh|6dspAJCpFHymiLDgW;9is3`X(w|o@v3Lb4Ou=EpIsea&lnC#X;5;6hx3VoH8XQ zWL+n0$sjgZoVqw;fwU|$2#gkxAQ|TTyz-P^$MY4IMa*p^Potqj&A~XBB8Rm053ZC_ z8LhQTyaBNaMbrG6q~%abG+}?N^j!%!t)qsjKOnY~zdzmlXi`eqBol5SH)_#5INu{! z6t!(r^f{YA0*H9S(Jvk?$SBxXzepi**i=1eG86bLLzn3S!QiaSwcc+e59c_ z{jE{5(5SJcMn$pHE2B6qH7b@kU8m^m_~wFx*0b1;zVG;SMya~QzvHn$7$^1an!&Mc zYng|oN8T&j&^F$gocK)AM{oQEi3Fhd>`zar$kvVV(Y!C?oT0}l>yuR4LL&WL^%8e| zJ~3T_v{yf9!W8}zTV(P zq^lE)p7yOxwCKAqfAuTJu({O1_}9qaERbHftxk1=w}4fQt>5$7<=uIJak2$z4Vfuf z7Fia&6~FfPteM+!%8mY4jn9b=47X^^rt-4Q_vE6763b}{n+!AjcGV~Bca2w$>VL)= z-gi|z^a>PwM@(_j?^&1%3(pbgawLm2WD7jOdX>0qZ+A{0LAGfTz zyL}j>$tBZJ*R^z-Wtih_7{EtYSRO7-ikLu#aU?evbt4rVN|4WBn-orne@(DDkxq+&TdneRT0`?}B z)KMcs9GT}i49wJXLSixwDnw=7J9UTPnE>XQrh_%MaCt>5JXH2;v*SfCIYZwmm4i0h zT9+vHO}_asVdib`qi_3hx)${E!84t&O-W6Jh2;@noBt|t4%X_yOzhf4di0p5^WVRc zdYo>>r2!1?Gv3tl>@s*JcYKlAx(5}d3$vy!?*Nll$DjID*KfOE`8ej)#u zam+#d-jFOqM*O8|SQO{Jq@#H7@(eeyhNp%K=wj^0p!l(CPBeDs&{u~K6kK8s8nbbl z8W?u2F>uI!Ph}DIbpO{A^DrQ$96D_q`G~ucIPa58#D}jy8N;+>fE{O?t-6t&fCZlC z;98T-;5yED@xlC>995wA-=SUm-C(JlB}XOQ)vH%Q$6v@~G^cd_x(>04X%0qNBjy+* zB~+dkKGoPfnRQ>2*RjdUu;T_d=*Fsxl}BOEjHO6y<@b*sQXH}#GalkKc-|f+{uSfC zoh>)y^xQTUHy`W=LUu|HO5K$K>BVNEwxWp#n6C|02W%?Vhb2Ru0|ZUrO$tEGcdI+P zD|v##61Kt9=IG-K%vX5b-3i~h#D19}GU$G4&BuQD?kHpdeX6I^K{J&0y|uLfj$tR2 zZSW_OtPy|WWFhr&*=TF8eNb=$5WNZ;a?A2bf9Q}<-j?E0*4QCfS>Mo@v$~naID}kh zZ_R>4fdZET7TY+xm`^ts<~E8*EW*BeaQ-baXviV)H{lPCRx#-%oC#NN6F;75TX2@i z`}6g6>a){J=4XNC^3X&7frZ+5QZg^?E&Y#u4xbUd-5>2W7HHWFjMe4JJ`?sSMIohT zdqW5GGD#Pu>AK8o>YKWSHz+cT>I_G1fA+rm=G#Q|ctWnV>7hrU5Az`YxL*A%OT_dL zCyQF&0_LzDV=Rg%%dK8LIRk=o2Nm6b*Bj$s3brdnuo zJu*+*tlU?D4>A4{_zn`OX7b6Q)OKE2zNEyvQF?D-8bnoi;JY9>v$K--w0~n+)JYx3 zN5Qbfy_{otOCVka&JI6tuiqpf2mM;!wRh|PKt`4vc|(d*z!@eU<6QihMa+aAUS_Es zwo>ZOkgJHi-m2FVxsIjCE=>DN8p$BCeSi-;syj);26B{peT~^(pzvmR{a`Rq8&r<` zH8Q~6EAinqx>=}inH>1sxJ!`4-DCK}?uC)8Yp(8ICiUSGW{ZHwS;_`ok8|N}SYd%O ze!UVOd`WLhCZ4KBfJ}-FnleAXiTZ9bOPA=c z_;?5E?kF7bwD0D1XOKpCU2J8RuPIq?{GoRTSibJ=4hVIVlu2!GLEgPi{mIWsSV%9S zGc>2ZO*k}tj7^(wmTg?n@D?xcY6!g%FA#)>%Gl=M8j2PF;M}T>#ZQhf z)tJjxuV=47Y2{9+mrPQ1_aZ(Q3flVhbAF&eu+k@>T-3trp1_$aT4AnAA9Jty8I&se z+ku)zyPDbCMWnPHm~Z|=^> zt`)EiC^9J_)l;Fis!3GowhX%Kr$#ESxf_RC6ay68o-zA+tBF~<&H}c$v?qeECRwG` zxn*;?KCs~F6syo}m!WV`UX8)TFXMuF^v>Q6U?RMeI^lrk^`tPCiIP)bSpbIOMCK z#X^TEgG$1!!qU+ia2q#6;oAr`!R=F{+>cr>Ui3ZEo8@|X*;r?=YdlL@G&%JS@b?q6 zcIpf$pFiJq#SGyaWbhhK5HlP1Fj{X(Xank_zXIk%eqX&AI%<_ODOAz+BmJhZm-Axa z*oGhVX^bXm<3i6Tyt%e5@#-f6%)_0JCLq+taYT6yJ=Jm#ZoD#bga?VL>@`uS6piVA z8a}=vFUt%4z0Dp{B3d{!o=Zjny7-*``0sDj%IC3Toy%8#!pMTMwV#KhGvB_?LlAkB zCZGKnu;L;{w9iMDmfhT&<khI@A2c)6(`np}56HZ!uR(y@oP z5peSAhCRc)%vkVsYv_Rdxoe!MTFc zg;OkJ%DMdF_#1tv&^T^HO{(uTg+wN%9BMzwB=Wb!EquS;9Znle`+n~GydA z842mo(SH4zO(tBV@IhHBMc3|L+0|t!IO^Ze|BXj3WdChk#eK1?*P=Mb*Rnbx>4g&Lvzk-gIs3t3FxazV)i+Zo8Nu1ZHG*J;@wlZY<(yelnN5vO zdtn&!JJ$rRE0O8Mux9Xm{AjP}?_ASaW;U$iZQ#Y!h&~*#u6Ik|36!)K# z`-iD7X+s@2_iIilhva4cTn87{NN*6xqN-r7xLYQ|h|WIahG$trm^f|82gLVCr$qSa z+kvNug)X>AGMyn)?w2x2>kT^EezuL>_C}8=FG<5g*RBw={OMP9|BBg8-RrLxE)RZ# z^NG@VtLy54w7v>X-m$b?4@8p@Xd(B!xHSp(OuB;Kk_p0p=FD?&D@=$>A8$YAg?(je z-4z{yl#2#8#OS%^#uBWHR!k%V2PMDYk~3U<4ojJKCFq}bAT+J6OE`>g%c|LqNRlrM zLF|=~zc?9dX&7F9$i1chuZ8V_{%iMz{1gGWdZJy=wDgplOkhX%!*-t3kicZ|eKjuz zDHpUmUo&(fD^dAJXl`dgaaHFccf| z<%WY%nPJ?>@2B0mS%VV(%7o+@rPW}jgSsnT`c&fqS01F?Fj%kgFBOWWotmLq$aiBL z+caxgFxVC6gid)QE%SAX3+Jsry8b0R)8Y}Nt7-*+23--DXqd#;v7B@BRy}o#?>G8G zCA^bNZ{l*Ok-W1YaeW18l)ClvC?BzaiZH&rBzK;2xm04C6T?gwgxyaEm$l1<(rc?} zJ~qkKeeu>jKH)21r>b6|qmS~aPGXsJwVj=%nOTH^BX^|@OHwvM4T*p8HcKX|rDL$) z%$-+;t>@4uM5xUF&G0HQawFX zEa~^oiTs(R^5MnEjopiF)zeWQyIiuaLP4&x(tm#RM`)Gw-bG8a`}3EL`Qo~kUCz;l z{V9NQI4-E`ebL+_%Zz0D=(qOn0ofsc7D+k^4}9wMwcIM6N4b6x3`VMEwQ!YaEY<_wBz;jOZ{AR19GheGs@_z30xf0PP z1M*A>k~)ef&%MjE(#V*y9XVOQu$}T9d?Cubo(kumIi}p|KR8g`eDSY*xyehjS{wOi z9zc&q`K%6Se~yCxkkzf@U`pW>>vElB`4#yW58=S8MqNq-FTZ$02eKNbP78Ep6=6u@ zm9MqBF15V)(do27o?W=XpWPY2-v=rq3;Lvq33?K$$zB*3)0jX@!Ng_xKf(`K3CdbP zc>3iJTL!hEZDA&h5{wlT{z;>k#XOOA8cs()eBG-doE;nj?ADxm-Y0DU$~gP?(NAUk zJb%bj*`Ig<`txEvg>Igu^A-zTyo>zoxWpjAudm)o3F((uIW`gtc744a?A(>}PQD~p zyIn5^-|nEnz?CUO-vw{NXfbA#4L1`{E-CbjaiJw=NO{Cg%z)pqtt_(`^g4crSM%cE zEp-jv$x)5XSFKW~(gU16){6cr-yC|qKz3wW2yEGvF?ii*C+8pgg`DYe7TAdv2AeT+E5{Br^XvpyNE?sCxU#`Z^AXL;mFABDn(g0mTOIT^Dgr}W^ z4?8Nqjh}sZwJ!l+k!x|zp6vJ*CT#T(Kaj0)`xf)bPZVA9P8gJgK5IA!Ja*X%&boqY zB(>!Mno@e~9KLz(j)YpK1TEC;d@uic^;W})=aq$=rKKG7!h?pcIVGB%&vxtOkX$&m zY+)b$=hJC<;j+K@;HMUE)MAV|;!+6*`CvWOJq8jc*S|Y&GG7KBSB5C#vKu_V z^#xTg9=&*_X0cbcm<(G^?B?A-BH3olZ&Oh9EyR}|oC_^faGLNfJz`Y;$xF2%K~s;XnLPk+@24JI!#BC@#{?G{T5YTi{J! z$2tRDUYWtEYi>b9%_Ol;4CF70Jt+a5j9r*HGMA8Qwvz%`9$;YKQKfqVU97_cA!-Yj zg6A`n0ZdZ-t=VXmq<%}ZN!mf2`sE(1s&{|%czm|4WZjKmf44Q75aoaaH;h;cMro4# z!s*S?BQE1XL@%ga%+yWo{Ge-H2sYhy@_B*QnU(+G)TLJ?m5DbX5q#2OGA7$~3pzm2WEFJ#7G*T0-`w-(EA~8Z=GL zvW696{(kW}Q%NOCO~WQ1VlZ^qE&e&PiIvsx%(W|TZ}6|#``gaoa|yxOhL>27`cSRO zPmGm6clT`l2>bB=EI57;ID0sn7KXcQn!dC)wk(-2i!8w`O}0&YDL zx=~b$*(Ug{(PG5mpS}mrY2Ydn(l5J?6j(x7!=Rh<`pYxko{~(C@d;d=>YtQ74Ng>z zmyLIvo;5aYvSixL-~I;EeIH^I%=h)<3xueefXKYdpOL4vneurh_PCjTRbD$bXh!tK zp;N7QO*NLKNYbL5B4LRO~WmknB zh&^k@jQc`SsRi2;+YS$O?$wnKks+qV1C^gr5sw<;e?21^y|nfR^JSTMI;kULTZ3DN zxLClne;80-t^(S*W+WYNU46o5fdC(GK5SdVyeZz6&dcf9)^T=jWJl7HNsJ^V+jOV% zn-|Yur{rJ1XTuD=V<9@n7uNH!b>X1D1G}|fOq=5&2h%rp4!#`#C-qkW1@9Cz{%X~` zk2Eh7ti0w_ejldVXGMDE#lQaEo4X@HSn(A2@E6&G>aeh|w=F+?Whdx>6LwIgoxu;l zt1&R>=7|4V0;#?tC^ydzI`)YIWq(TiOgFyN{He*zW6ricZ8E5mF z*dsU=R{&@k^mKyjJ&v)C7e%sswo{Yc{}n4F)Z0l|es?nP)IVhZs^w9)?a@&3|L^Dd zUBsu~^;5}sLX9K$l<550WWt-l2f6e9H3)*+LyVM?H{C%UtV5g*eT8SAInH`U(B3^6 z$4b}pDf%kK;x@u_O`;Puyqy-#qaRDvM2Nn$$SpN_oc}quj;nc^5g{bvZXxn zmNAc%^5*?(P!EoTzAdeW^fu>B^|K$GtgF$o@ce)?Y;B@*?cUBQy_^{??OcU87r(fF zC74PD(({w8qPndB8=r2NPkyD7f=mVkU-o1!iQn&Y5Wd3wMDpX4DIkl}VS*qyMXjia zV%wlTB9ncbcbp>%V241X3FGs6O0{#eGDP=oTJo)>dc8}HN_GVrr5?F42vy3Jn3^R{ z-QdCdf0FT*jm3j--(*|&s<~F5o$O1K*(7{ovZY1l5ZouBFQy`YZTHJ$T3T5fC#B3w zjp}vdRv2*Wo7$yOVDie{+aidT$ibb4zW2y8!x=)Tj-BT@DbzD)$@jf$^K`-&@9Q2u z1#jcrxsN7I0%Hy|SD!nDz&YzBf)hl{Rs^T}oy~61Lr&~SLvUuj0w5LQ=e(MViA=nX z6=khp!)Nnk(y{?m48;rTnOZV+r7vp|_(5Gla86H+b&lAPwiQf+W2!mdE@7@$iEf@3 zsogIP{f+1~mYVckA*RhynYMx{7+Q zQPkU#5!3|e+$kPIsIe%HDU`6|9~!O-f;B;u)N-zD#R1VGHeY?i>@d%3_-}rSIPM9)kyy$jpM9(9G}sKfJ&HIT_EI z96}RCP2uA6<{q6Y)#3BvyIQy`+LLx3*O|6F<>2wYkd+MVjeP%A{xkV@D zC@89N&aV5gr38Q1gb^GPs0j`4^*xiPlnWvVIDI;OZ{wPf%SW}UXyu=nB0pYxPCPj@T~|=*u)TuL|gW3@zi+lST_mWHaonRzBeI9a0)5;e+brp zoJ-poA zw)taEOBMuM#n`XWzm}MZeya0f9v|biG>@9&2Bj&kNp$iY_=0lY?v+gOLk*_(Jd_sL zlweRy-IKKR`k7$5;pnYn94p!}sb&v5;U@elu^ay0F8@%(5vNn-1`D$bnLIh!d;CSv z8}~(b0)kynQ}a|7wtt?CCx9K>Km@^7uz9Vup^J2ic^Nx5x!*bJ)r&QW&Sxa^1?9Xk z&9rNv0EQ5l0zY@^X7HDoQdHL{AmY})ru;u1#A6;oBJ|uu%VVuTr`Dw2MYa0(C-Y1Z zP+RgkPlb(d7Mhw^>rQaknLs%GO}n>2uz4Q4e?5hCB4P6{OeVU;;c$#N{&Ide8cyAh zOJw0`?YPKVayk`g@P_$vU!P1UkY}b=zrCq)AGxf5e)o1127xfFA{*Y5G58r4#~kLZ ziF+Uyu!Lv;d>MjMwcu0-3wWk}EEz#8KUcxfR=sjIf~8Hy`=AKSL>>aZ9+A`8E(C|o z*Qxs>rRXuqy7P*8P5PNA58NLSp7$m@mEIFfhYhri^H^*uF0LJG5S<2Q&ElbBbPGCa zQR8!GF>IkMIfdy`(Zd*`fM`Byi2HN!bQ=H8Tep$(JP6}&aWh~8Yurwa&0^%G)g?q{ zyKroLR5H<+E{Z4RdA=@L%=2xdhp?W~C0rDqYY4BODjxFXR0jJFeLCx(!_TkXOx@2b z5u7H-oa-p;T5{$*0YN0zq(%Xe%IuhkE+bE{1}aNcs>_R3q?GBlY04XvL3uhWVv1B6 zJxpCULQ~r)n?=tqfg9AJ_WTvpg@c8I#9Gxg^UAUO^q@U#4Dwm&W1)GTxqEw@)vGA+QP2 zu@LXQ5`BB%`;`_D`Houi1m}?#T&o!E5y^fknG=q@&k#+HuoPm?VG&-6E%wQ)B?Qew zqAkX;<3cTzUCd8sbDM%e)SSD5<*~^nEDw(iX1OSDsvP#(7nrt?q9devF|;GUrOfm6*+?UPNp^4s1rJZUevg6rE^wLP8OS@DY@Ij zsrzEibC^ajKP6o^+)r!OQCbz9RI(7&vB7xgQOKyA8!N~%nmU)_vzLfF-{H{9nIS|= zyqyF`jh+4z_pc>HX#Fx$B0K}UYI1sc&TNc?ZcBN2GMxjuxxz0>rT}is5QsJC7FoG3 zxlk{JXApc4>!CH<+R8E16`PmfZ7T`e2g`9XpS?xVY0=X&@Kh0wJhNlM$;4mk685u8 zb4ZASJ`dC>^e8*`puHkliMP|yd?nbamgf5T{1IBe%ugmG48JN_7B#%XHF7-vDjDIV zDn5stEe5snM_Xme95EYZ*Hjf~&?dFQ^uc+o6NIKbap7_i8{zUHYolmFuneURJT2pn z(wgWbICDQjVMHJN@WUIlr&M%l?wg-oQgGw*mwHPtr3sXZYu?V1g*QU$^I`Kr#N#Q|)y_*F-n#L~gFQLn28&ZGy&^acQJ=%-gl5TF zq1#5VPEMYL*plcpSbsK|#qbHqcnlRY9JVr2xvsSTkXi}i7TuFcuotM&CaI4H@P+%= zF_;9#p5|1VIso6%eGZ0UqxGs}*<0W`dKR4S(H8=i(6q7QfiMnqe&AhyXtH-C^Rq1$ zJQcw>EVw~koM9idkM*H%`1~B^H=E#K8A|WpsWixDM5hH#jvr5@1@R}6Wlvbw^T_+D za{ZW>jNmK1Q1CPKpd7=q_pf7-ui3`~_?l!M%CWf4V?>2(Q+kc%5ZX)x=ixPXk9ZyJ z_9vkkxhg#dJG0l9n_TjPq|B`)Mvb+f)VA+=2B@ym52oW?dwF*k2jn#B;N*pWx z9fOTZ}(ytL@F(BOspm$G+D59!x`x?k^c9rv=MVD*8`qp`}D84<>Jpg$_KN z#{^eCB}j<<(hilF@pEcSOfJ}=XXzZiPiY&Wp(3(0#O^!lC)$?>CMyxuc*g!UxIHcJaQ9wjQ4uJ?S39&=c zcVB@~x{EcDym|LFIKVxSx*)wmYouJQZu}9PUzSYR+xYG-zC5EP-e+Sdhtjntk?*LO z=xdWj+n=B{B9FFRY*382__x2*C=eBcYU-IN0qsA#reTt@d$Vzvyjx>#l9JUYyEm7JPz*v9Z?rl&JDL&nlpAy`oI5=c^ zN(=7X$M^2u-j=yVr^VAb&tIR+hx&$O$Ak!R+V!jvokK!?7H^f{c|je^ckN%#(e=oV z<&^Ng#2b>8e#bsVQ>FQ;KBLbX9OqOuzeUzq=1D&`3AnC9?!SBZFOu<|!td=KL_l~7 zwHwo8HbFtqGGjOQ!Ffc?O4f%iqIaj}!(cvy*Gsj<(L-+L7M=Pt@?h%2seq_ksosT$ z=g*V*e0TI0iI3mE_Qe8PDm?oX+wc^Y3bL`E(M>Hm7894+C)ohx+}pAEj7JAx&J09ltcv(tBBxW6YvH|9iztt#VxVpqMEIHaa}4>+>am7Pgd4{yv$`~{5%h*E@f?#b}Fe7YR7ZI|W zUd~u6+J#=DrF0T15}tF5PQuX#KetdS1Ujr{SM@yBTlVY8N-mOJ+^KU!xt~jRdAzWP z-*pTcu9tqtW8Z_=maj7wpDB*KY?Gf%R_dh>g0*1%IF-&7jKcvVwY;2&0;2Zu3@Oxh z1oJsg_W7Jsbn>JTZ)0-CsO+&5hMiNXC-7PO*F&7-Qi9eHH6UC|+b10>nko&gyYAs# zXov2`#B-rd(varzL9k{{MRS7T$O$ir@*Sd+&D(cxgT{~xE&80{G;|!fdv=PG?Gfh` zoqGSB%Hy1xQcs|K(!*jK6Ie-(kw;g`^E0o6JTd7ofUV^ua0N`J4OK z+cB5u)aQ}cYpFqHu`MkqIy|df?rF(GSGzUD>yn+@d0fJGaq3W}G_)SAFWTeqe(-j7 zPdB;-;yA^1LOAxBZ@)F!N9^ss$wbJE^K3ymB9TZq+PxI?Zuk~D_Q^n}g{n0chFM-W_?KVJa_YrqtW{^U3}p z+1T%AB6-E`Z4fjC?|>F+W5;%|9CC3T$IF{JBy7$Tq+s*f?m17DqonV2^QUqgVf{_J zx7CQ=spD|XY`hc?e|R!FPR$At=E=3+gXC& z>*1XeH(n*+Qr|JoHx62a_~0F=>8T0kV@Tx0qM5_#Je=2d&xJn!Aek_14N>Rkl|;Ud z!7&mi)s4q}%^R>R_J~0Gh8QjJdfp>h-)BY_gKj$|pXF@y;TlD!n>6IS>YB)Ps4)p# zLfDB%bqV6^+@Li~io{2FIJZqseG+PXTQcGFYr5yYzxmfX<9nB$#)n)uRP#D=h)4rl zqSnLr*;ya8#ypQSucvlLW4`OLp53P)P8IKUh38qWQFOv-EOUDT{k}Q#SLBV( z{T-u#Xc?m2$Z1T5CdCk(+k}X)xc*Tx3$4_rYs=jvER1vCpWw)2-L)uzn5kVj1P&2i zx+PEyJoZTKRw3Sbqr2<9dnQ#*I?<3qBN2k3P5=Eab8NTJ`XtvXI^Cq2XU6tnE-zhiH{xmlVv8&|;s(*DiR<&IwCl zk$h3Ik4-kmSce6Dsm1deu^{r;ltT2>$aQQ1^SkQwJ13LFddQgXI;G&0ex()9Qli7g zrJHiFrLk~`4atx1-ku~2Q#CFk1{`CxHgQi#_7l6ex8<5Wop^P!IlP_1+;a;~c({eU z=O7A*+DF@&t@4OuPS6*PNf$o}j?GOT!5vM$$wFKu`u3dCG38Can_P)Gu|GET1-p2-9P5k^QAZnlgdjGmL za*Hkt@Ro)3HRHVR;5b5=$L9Et+Q0TiPTo|J0yPawM_IZ(B|&8QTs)v#!CWYHK-BT> zd%N5IbuNrWdB#V%cF~Ec-Ro|^8+UIP!65WtO^GnYRp)7}gjsg7Ghv}%ycao_lehgX z$%5@M^~QP4nB%2yF>^8VzLh?h!s_}tE)DPBA?8GmnJpC-Wvt10UH(V=S9q4PO@YYn z$<(6|owwZbnq*T?XiJ|h`{HC%eMdi6NG52XId{8LBacmfmavdqKOv%SyO=JjRhe{} zV4Z9+7r7?Vx3o^3}>Gf%n~c|*ec`HjhH z<9D1r<~u~^ZkIS^YoVnY(RVRnPnAY+c2^TL#g=yS?@VU${K{mGf>R{LqheCMOEQ?> zRB{S6JvmtjmmoNec0x5FK;%s>?R3GV5PA-^iFn`Agm_rcg+f$9XP1(S+J0>pDHa zUj(aUj@|BV}w0ks+<-orxnSPqJ*A4glV#kCKojcr^DT-~DI$!n}Q+&rL zAPUyNhbFU-)a2Svfg*4Sowen`ttrLAW{L38$UBQno;ZRb=PxtO;q{xobT~(eC>;W4 z%hQsrd2Psfp2qkVqDjV*4GZt)6dekB-}4ZiAH=!nHFv>o!q7fxQ&Y2`$j^xaqF@co zedO(y5zfs5h|rnq9P9TbTeFw4FN7f>&zq?egWP2&$($;Z>+*5Q{J&Ww5gG)mP_g%4 zlx%9;BSKBeOG_NKOX`E`ZHz0zaX;n~?X|IS5$UvHsqNi_dv1>HbVRPMUEAMVYX#HY{6yUAla zRsU7@T*R|?1mW6`!92uGGO$V~)R!c4LQ0F+h1NLwQ*yFgkziRYSbdKNG&xLFP}VXQ z+Pvu2LRI|OA_g3C9``S{zi4 zd2CT&i$**;8SmrN!l(Rq99=Hw4p{KW+n zjLFOP|7nAA$YGADaH7dxiqD~#5bel?Io9mn_5^KTAnh|YZ9 z(7g_Dn$_W)X1>hV+gQq8E(?3#&$5)jJjF4m$k=tk{au5QKW651z#Z|1%bowvtiVzC%|)7G%C%gHJ!tk4@#tD0bW zhD@f{Bs%kC_oie7=VO!oWiolqZ%eiW7Aa{dnkQ%RNwm5rM8HS;iv{_@WL=@mi~fHn z`_DIjI*#wedp1YGahdY z!$#(3lBsvFp^@4!<+EWE$^pcaJ5>n%7{05%pO;eXawP5pYfp&I-$%xZ; z`->Sk_H6eVV}$e6bDn!DS8;0sa4Do2XcgEMM7*63Oh&+5^2{15Jh;7c`4(i!vEw>r zY-T+B$liAF7K)5&G1W(qS-(YZ>LGOF-yVv~#b4!TM-uqjjfKuw)a)WT+AYkX@mjnI#Y0MCh#@v-@(_5964)-rbFNA^imSaJ>{9v_yhPd&$B z{m9McG^*E+<9H|!)=<{cLdc-LcyhoI3^?J*V0p$Qi3=GLtJj3F&hjK_0cr)4@aOE_ z-fVQc@PNwqoO_dCBl@`A+Yj)VWL=NVA<=YyeYl_JJXM|-o~griaBYGUa&gyyl(#;o zAvutRKy?q#J(sodyEvWt2u@zk!@{kb`w*h@IAcVa8#2XNrcAW3 zJm*z&-wDio-w7R|;57+Oe8T>94G^9pSaKmx;hw1&SHNduFo*EWg0pY_E^p|eQ$&$d zh|V(%JsQ)3aqa0UGc&Hi<16ci}f$hl^U3{Q**{hL1ju0tPGoxoZjYGJcW-cEyWjh@`CQj(WR zbgp?KF6CUV)Lig#9yY7j`Jx4}30@Y@`>}$CTwu}_o^yQe|6%_c9LN30UQKQL6rioy zJ6Q`J^0BE%Eznn6)XrPwp(Gq_ScZ(D2PY#kyD36BH~2 z+a!Jb?(JmQ2t059x+cuqHZ0k*L?pD{CwfkfbyjfAc!JrbwS7qlznkKl9yt7>7Osou zdrWS*@pr7y%-?AP7oxKV9^iAHK!a8bgEiwjp7ZEB!6;~l(nWqu<@*-U_`2kX+gfzJ zoWy1erx6`Pcu!;a-0Kv=?oM~n_jE1@;5j^0Uf?{5R+a~u#-+|)#g)@5efH9rZ}%f z!P(`esq^mb4Ts0*8c$Q^T$Uc&+lQ`)vxWPS1rQM||JO6GC0}?khvAw3rDU&2_IJt7 z2_8i|#FmYfweK(mW@m35K9MAojaY=xBHWkH`3c9}7_-LR$#LM{jWF_L*xFdFj z)2Hxm-i{ER{W(0+2`1aQPYjuo{2e8v=U#oY4aVRiCC8T@(iK0~z>uTkUY_i?l6`Tq z+M>{P=N0sMJZG(YIiU(#QOY5{LoP6!YAl_LGOZE!ABO_-J;`D*ZjYQ=^5x0&o}7B~ zV@^c4N;hd26z>Cn0=mmC2Jwve+fBn#~Q{%q0y9r>C~9-UeioV-q8H{ z+;8ti!yE=+fsal6Iw3%LB1M~cKpnI(#h5c*hD1=0ImAxkXB(3Wq!)2Ggym z6L#8Ku4DH*o?C2!`8joN_??nj`0?IkAHI9ri)-<)*ihYZ_qG~5eO=^%*|fogo{zGIj7B+_vI)@@Bj}_wv7ScSnx`h`RIb%z0u1}5m z_a*CouY7;K=89!r(ku#UHVE(Dm+p0UOz^vQZ^LtW1$0C3wFRgm@4n+l3W1I!|1w!l zc{yZpv6%_cIgDL3V$AgGDWj_w#*7o8G*L$HAwv-aAgY2oNI z*aZDdGOf@4G+7gCd5F$o()._mainMenu.GetComponentsInChildren(); - foreach (var button in buttons) - { - button.color = config.menuTextTint.ToColor(); - } + TitleScreenColourHandler.SetColour((Color)config.menuTextTint.ToColor()); + } } diff --git a/NewHorizons/Handlers/TitleScreen/TitleScreenColourHandler.cs b/NewHorizons/Handlers/TitleScreen/TitleScreenColourHandler.cs new file mode 100644 index 00000000..23fafa63 --- /dev/null +++ b/NewHorizons/Handlers/TitleScreen/TitleScreenColourHandler.cs @@ -0,0 +1,67 @@ +using HarmonyLib; +using NewHorizons.Utility.Files; +using System.Linq; +using UnityEngine; +using UnityEngine.SceneManagement; +using UnityEngine.UI; + +namespace NewHorizons.Handlers.TitleScreen +{ + [HarmonyPatch] + public class TitleScreenColourHandler + { + public static void SetColour(Color colour) + { + var buttons = GameObject.FindObjectOfType()._mainMenu.GetComponentsInChildren(); + var footer = GameObject.Find("TitleMenu/TitleCanvas/FooterBlock").GetComponentsInChildren(); + foreach (var button in buttons.Concat(footer)) + { + button.color = colour; + } + _mainMenuColour = colour; + var logo = ImageUtilities.TintImage(ImageUtilities.GetTexture(Main.Instance, "Assets\\textures\\MENU_OuterWildsLogo_d.png"), (Color)_mainMenuColour); + GameObject.FindObjectOfType()._logoMaterial.mainTexture = logo; + GameObject.FindObjectOfType()._logoMaterialClone.mainTexture = logo; + } + + [HarmonyPrefix] + [HarmonyPatch(typeof(UIStyleApplier), nameof(UIStyleApplier.ChangeColors))] + public static bool UIStyleApplier_ChangeColors(UIStyleApplier __instance, UIElementState state) + { + if (SceneManager.GetActiveScene().name == "TitleScreen" && _mainMenuColour is Color colour && __instance.transform.parent.name == "MainMenuLayoutGroup") + { + // Wyrm didn't say to account for any of these states I win! + switch (state) + { + case UIElementState.INTERMEDIATELY_HIGHLIGHTED: + case UIElementState.HIGHLIGHTED: + case UIElementState.PRESSED: + case UIElementState.ROLLOVER_HIGHLIGHT: + Color.RGBToHSV(colour, out var h, out var s, out var v); + colour = Color.HSVToRGB(h, s * 0.2f, v * 1.2f); + break; + case UIElementState.DISABLED: + return true; + default: + break; + } + + for (int i = 0; i < __instance._foregroundGraphics.Length; i++) + { + __instance._foregroundGraphics[i].color = colour; + } + for (int j = 0; j < __instance._backgroundGraphics.Length; j++) + { + __instance._backgroundGraphics[j].color = colour; + } + return false; + } + else + { + return true; + } + } + + private static Color? _mainMenuColour; + } +} From e92a7ab121a63b19769ec9f4600ebeacd7526c5e Mon Sep 17 00:00:00 2001 From: xen-42 Date: Wed, 15 Jan 2025 17:10:21 -0500 Subject: [PATCH 04/87] Make config in code for testing --- NewHorizons/External/Configs/AddonConfig.cs | 5 ----- NewHorizons/Main.cs | 2 ++ 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/NewHorizons/External/Configs/AddonConfig.cs b/NewHorizons/External/Configs/AddonConfig.cs index d93d7b90..66674575 100644 --- a/NewHorizons/External/Configs/AddonConfig.cs +++ b/NewHorizons/External/Configs/AddonConfig.cs @@ -44,10 +44,5 @@ namespace NewHorizons.External.Configs /// The dimensions of the Echoes of the Eye subtitle is 669 x 67, so aim for that size /// public string subtitlePath = "subtitle.png"; - - /// - /// - /// - public MainMenuConfig mainMenuConfig; } } diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 42cc70b0..fd771d1d 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -431,6 +431,8 @@ namespace NewHorizons } TitleSceneHandler.InitSubtitles(); + // FOR TESTING!!!! + // Remove once actually loading a json file is implemented TitleSceneHandler.SetUp(new MainMenuConfig() { menuTextTint = new External.SerializableData.MColor(128, 128, 255) }); } From e494a82fea3bf99d1a72689f2813da082c65c43d Mon Sep 17 00:00:00 2001 From: Ben C Date: Wed, 15 Jan 2025 22:11:43 +0000 Subject: [PATCH 05/87] Updated Schemas --- .../Schemas/addon_manifest_schema.json | 48 ------------------- 1 file changed, 48 deletions(-) diff --git a/NewHorizons/Schemas/addon_manifest_schema.json b/NewHorizons/Schemas/addon_manifest_schema.json index f6c52366..a1e1d34a 100644 --- a/NewHorizons/Schemas/addon_manifest_schema.json +++ b/NewHorizons/Schemas/addon_manifest_schema.json @@ -38,9 +38,6 @@ "type": "string", "description": "The path to the addons subtitle for the main menu.\nDefaults to \"subtitle.png\".\nThe dimensions of the Echoes of the Eye subtitle is 669 x 67, so aim for that size" }, - "mainMenuConfig": { - "$ref": "#/definitions/MainMenuConfig" - }, "$schema": { "type": "string", "description": "The schema to validate with" @@ -82,51 +79,6 @@ } } } - }, - "MainMenuConfig": { - "type": "object", - "additionalProperties": false, - "properties": { - "menuTextTint": { - "description": "Colour of the text on the main menu", - "$ref": "#/definitions/MColor" - } - } - }, - "MColor": { - "type": "object", - "additionalProperties": false, - "properties": { - "r": { - "type": "integer", - "description": "The red component of this colour from 0-255, higher values will make the colour glow if applicable.", - "format": "int32", - "maximum": 2147483647.0, - "minimum": 0.0 - }, - "g": { - "type": "integer", - "description": "The green component of this colour from 0-255, higher values will make the colour glow if applicable.", - "format": "int32", - "maximum": 2147483647.0, - "minimum": 0.0 - }, - "b": { - "type": "integer", - "description": "The blue component of this colour from 0-255, higher values will make the colour glow if applicable.", - "format": "int32", - "maximum": 2147483647.0, - "minimum": 0.0 - }, - "a": { - "type": "integer", - "description": "The alpha (opacity) component of this colour", - "format": "int32", - "default": 255, - "maximum": 255.0, - "minimum": 0.0 - } - } } }, "$docs": { From d17221da92cc7b2af74f9de579d4915910b91df7 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 25 Jan 2025 04:19:45 -0500 Subject: [PATCH 06/87] Rename config to title screen config --- .../Configs/{MainMenuConfig.cs => TitleScreenConfig.cs} | 2 +- NewHorizons/Handlers/TitleSceneHandler.cs | 5 ++--- NewHorizons/Main.cs | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) rename NewHorizons/External/Configs/{MainMenuConfig.cs => TitleScreenConfig.cs} (91%) diff --git a/NewHorizons/External/Configs/MainMenuConfig.cs b/NewHorizons/External/Configs/TitleScreenConfig.cs similarity index 91% rename from NewHorizons/External/Configs/MainMenuConfig.cs rename to NewHorizons/External/Configs/TitleScreenConfig.cs index 521a3275..cd2e40fd 100644 --- a/NewHorizons/External/Configs/MainMenuConfig.cs +++ b/NewHorizons/External/Configs/TitleScreenConfig.cs @@ -9,7 +9,7 @@ using System.Threading.Tasks; namespace NewHorizons.External.Configs { [JsonObject] - public class MainMenuConfig + public class TitleScreenConfig { /// /// Colour of the text on the main menu diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 6ac1dc85..5c8a13d1 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -28,12 +28,11 @@ namespace NewHorizons.Handlers subtitleContainer.AddComponent(); } - public static void SetUp(MainMenuConfig config) + public static void SetUp(TitleScreenConfig config) { if (config.menuTextTint != null) { - TitleScreenColourHandler.SetColour((Color)config.menuTextTint.ToColor()); - + TitleScreenColourHandler.SetColour(config.menuTextTint.ToColor()); } } diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index fd771d1d..3885bfa0 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -433,7 +433,7 @@ namespace NewHorizons // FOR TESTING!!!! // Remove once actually loading a json file is implemented - TitleSceneHandler.SetUp(new MainMenuConfig() { menuTextTint = new External.SerializableData.MColor(128, 128, 255) }); + TitleSceneHandler.SetUp(new TitleScreenConfig() { menuTextTint = new External.SerializableData.MColor(128, 128, 255) }); } // EOTU fixes From 02c771d1b8e39abe23f179a9864586cf60f7fa98 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 25 Jan 2025 04:21:59 -0500 Subject: [PATCH 07/87] Add schema --- SchemaExporter/SchemaExporter.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SchemaExporter/SchemaExporter.cs b/SchemaExporter/SchemaExporter.cs index 00e37f02..4f4d6ddf 100644 --- a/SchemaExporter/SchemaExporter.cs +++ b/SchemaExporter/SchemaExporter.cs @@ -33,6 +33,9 @@ public static class SchemaExporter var translationSchema = new Schema("Translation Schema", "Schema for a translation file in New Horizons", $"{folderName}/translation_schema", settings); translationSchema.Output(); + var titleScreenSchema = new Schema("Title Screen Schema", + "Schema for the title screen config in New Horizons", $"{folderName}/title_screen_schema", settings); + titleScreenSchema.Output(); Console.WriteLine("Done!"); } From 8e5d7369d684f68899f777bae4d6492facc4dd59 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 25 Jan 2025 05:04:55 -0500 Subject: [PATCH 08/87] Move skybox module to separate file --- .../Builder/StarSystem/SkyboxBuilder.cs | 6 +-- .../External/Configs/StarSystemConfig.cs | 45 ----------------- NewHorizons/External/Modules/SkyboxModule.cs | 48 +++++++++++++++++++ 3 files changed, 51 insertions(+), 48 deletions(-) create mode 100644 NewHorizons/External/Modules/SkyboxModule.cs diff --git a/NewHorizons/Builder/StarSystem/SkyboxBuilder.cs b/NewHorizons/Builder/StarSystem/SkyboxBuilder.cs index 5d4b8548..d531c977 100644 --- a/NewHorizons/Builder/StarSystem/SkyboxBuilder.cs +++ b/NewHorizons/Builder/StarSystem/SkyboxBuilder.cs @@ -1,4 +1,4 @@ -using NewHorizons.External.Configs; +using NewHorizons.External.Modules; using NewHorizons.Utility; using NewHorizons.Utility.Files; using NewHorizons.Utility.OWML; @@ -13,13 +13,13 @@ namespace NewHorizons.Builder.StarSystem { private static readonly Shader _unlitShader = Shader.Find("Unlit/Texture"); - public static void Make(StarSystemConfig.SkyboxModule module, IModBehaviour mod) + public static void Make(SkyboxModule module, IModBehaviour mod) { NHLogger.Log("Building Skybox"); BuildSkySphere(module, mod); } - public static GameObject BuildSkySphere(StarSystemConfig.SkyboxModule module, IModBehaviour mod) + public static GameObject BuildSkySphere(SkyboxModule module, IModBehaviour mod) { var skybox = SearchUtilities.Find("Skybox"); diff --git a/NewHorizons/External/Configs/StarSystemConfig.cs b/NewHorizons/External/Configs/StarSystemConfig.cs index 08d0d968..6a1ba402 100644 --- a/NewHorizons/External/Configs/StarSystemConfig.cs +++ b/NewHorizons/External/Configs/StarSystemConfig.cs @@ -175,51 +175,6 @@ namespace NewHorizons.External.Configs public int[] z; } - [JsonObject] - public class SkyboxModule - { - - /// - /// Whether to destroy the star field around the player - /// - public bool destroyStarField; - - /// - /// Whether to use a cube for the skybox instead of a smooth sphere - /// - public bool useCube; - - /// - /// Relative filepath to the texture to use for the skybox's positive X direction - /// - public string rightPath; - - /// - /// Relative filepath to the texture to use for the skybox's negative X direction - /// - public string leftPath; - - /// - /// Relative filepath to the texture to use for the skybox's positive Y direction - /// - public string topPath; - - /// - /// Relative filepath to the texture to use for the skybox's negative Y direction - /// - public string bottomPath; - - /// - /// Relative filepath to the texture to use for the skybox's positive Z direction - /// - public string frontPath; - - /// - /// Relative filepath to the texture to use for the skybox's negative Z direction - /// - public string backPath; - } - [JsonObject] public class GlobalMusicModule { diff --git a/NewHorizons/External/Modules/SkyboxModule.cs b/NewHorizons/External/Modules/SkyboxModule.cs new file mode 100644 index 00000000..b9f27f13 --- /dev/null +++ b/NewHorizons/External/Modules/SkyboxModule.cs @@ -0,0 +1,48 @@ +using Newtonsoft.Json; + +namespace NewHorizons.External.Modules +{ + [JsonObject] + public class SkyboxModule + { + /// + /// Whether to destroy the star field around the player + /// + public bool destroyStarField; + + /// + /// Whether to use a cube for the skybox instead of a smooth sphere + /// + public bool useCube; + + /// + /// Relative filepath to the texture to use for the skybox's positive X direction + /// + public string rightPath; + + /// + /// Relative filepath to the texture to use for the skybox's negative X direction + /// + public string leftPath; + + /// + /// Relative filepath to the texture to use for the skybox's positive Y direction + /// + public string topPath; + + /// + /// Relative filepath to the texture to use for the skybox's negative Y direction + /// + public string bottomPath; + + /// + /// Relative filepath to the texture to use for the skybox's positive Z direction + /// + public string frontPath; + + /// + /// Relative filepath to the texture to use for the skybox's negative Z direction + /// + public string backPath; + } +} From 0c2709bff6dc1398a02222690a046bde1b7352cf Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 25 Jan 2025 05:05:31 -0500 Subject: [PATCH 09/87] Add simplified detail info to use later --- .../External/Modules/Props/DetailInfo.cs | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/NewHorizons/External/Modules/Props/DetailInfo.cs b/NewHorizons/External/Modules/Props/DetailInfo.cs index c16ff6b2..1cbad2da 100644 --- a/NewHorizons/External/Modules/Props/DetailInfo.cs +++ b/NewHorizons/External/Modules/Props/DetailInfo.cs @@ -7,15 +7,8 @@ using System.ComponentModel; namespace NewHorizons.External.Modules.Props { [JsonObject] - public class DetailInfo : GeneralPropInfo + public class SimplifiedDetailInfo : GeneralPropInfo { - public DetailInfo() { } - - public DetailInfo(GeneralPointPropInfo info) - { - JsonConvert.PopulateObject(JsonConvert.SerializeObject(info), this); - } - /// /// Relative filepath to an asset-bundle to load the prefab defined in `path` from /// @@ -47,6 +40,22 @@ namespace NewHorizons.External.Modules.Props /// Scale each axis of the prop. Overrides `scale`. /// public MVector3 stretch; + } + + [JsonObject] + public class DetailInfo : SimplifiedDetailInfo + { + public DetailInfo() { } + + public DetailInfo(GeneralPointPropInfo info) + { + JsonConvert.PopulateObject(JsonConvert.SerializeObject(info), this); + } + + public DetailInfo(SimplifiedDetailInfo info) + { + JsonConvert.PopulateObject(JsonConvert.SerializeObject(info), this); + } [Obsolete("Use QuantumDetailInfo")] public string quantumGroupID; From 5fc78411aca8cafdf097af84dc3426d8d75ec4f7 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 25 Jan 2025 05:06:10 -0500 Subject: [PATCH 10/87] I've gone past the point of insanity Starting out is a pain. So far I'm just sketching out what I will be implementing. How I will implement the merging of title screens is what is making me go insane. --- NewHorizons/Assets/title-screen.json | 11 +++ .../External/Configs/TitleScreenConfig.cs | 76 +++++++++++++++++-- NewHorizons/Handlers/TitleSceneHandler.cs | 75 +++++++++++++++++- NewHorizons/INewHorizons.cs | 13 ++++ NewHorizons/Main.cs | 27 ++++++- NewHorizons/NewHorizonsApi.cs | 24 ++++++ SchemaExporter/SchemaExporter.cs | 2 +- 7 files changed, 218 insertions(+), 10 deletions(-) create mode 100644 NewHorizons/Assets/title-screen.json diff --git a/NewHorizons/Assets/title-screen.json b/NewHorizons/Assets/title-screen.json new file mode 100644 index 00000000..cb6ea336 --- /dev/null +++ b/NewHorizons/Assets/title-screen.json @@ -0,0 +1,11 @@ +{ + "disableNHPlanets": false, + "mergeWithOtherTitles": true, + // FOR TESTING!!!! + // Remove once actually loading a json file is implemented + "menuTextTint": { + "r": 128, + "g": 128, + "b": 255 + } +} \ No newline at end of file diff --git a/NewHorizons/External/Configs/TitleScreenConfig.cs b/NewHorizons/External/Configs/TitleScreenConfig.cs index cd2e40fd..3ae2f0ee 100644 --- a/NewHorizons/External/Configs/TitleScreenConfig.cs +++ b/NewHorizons/External/Configs/TitleScreenConfig.cs @@ -1,10 +1,8 @@ +using NewHorizons.External.Modules; +using NewHorizons.External.Modules.Props; using NewHorizons.External.SerializableData; +using NewHorizons.Handlers; using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace NewHorizons.External.Configs { @@ -15,5 +13,73 @@ namespace NewHorizons.External.Configs /// Colour of the text on the main menu /// public MColor menuTextTint; + + /// + /// Ship log fact required for this title screen to appear. + /// + public string factRequiredForTitle; + + /// + /// Persistent condition required for this title screen to appear. + /// + public string conditionRequiredForTitle; + + /// + /// If set to true, NH generated planets will not show on the title screen. If false, this title screen has the same chance as other NH planet title screens to show. + /// + public bool disableNHPlanets = true; + + /// + /// If set to true, this custom title screen will merge with all other custom title screens with shareTitleScreen set to true. If false, NH will randomly select between this and other valid title screens that are loaded. + /// + public bool shareTitleScreen = true; + + /// + /// Customize the skybox for this title screen + /// + public SkyboxModule Skybox; + + /// + /// Relative path to music to replace the title screen music with. + /// + public string music; + + /// + /// Changes the speed the main menu planet and the skybox rotates. + /// + public float rotationSpeed; + + /// + /// Edit properties of the main menu planet + /// + public MenuPlanetModule MenuPlanet; + + [JsonObject] + public class MenuPlanetModule + { + /// + /// Disables the renderers of the main menu planet and all objects on it (this is to improve compatibility with other mods that don't use the NH title screen json). + /// + public bool destroyMenuPlanet = false; + + /// + /// Disables the renderers of objects at the provided paths + /// + public string[] removeChildren; + + /// + /// A list of DetailInfos to populate the main menu planet with. + /// + public SimplifiedDetailInfo[] details; + } + + /// + /// Extra data that may be used by extension mods + /// + public object extras; + + public bool KnowsFact() => string.IsNullOrEmpty(factRequiredForTitle) || ShipLogHandler.KnowsFact(factRequiredForTitle); + + public bool HasCondition() => string.IsNullOrEmpty(conditionRequiredForTitle) || PlayerData.GetPersistentCondition(conditionRequiredForTitle); } } diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 5c8a13d1..4aa0293f 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -1,10 +1,13 @@ using NewHorizons.Builder.Body; +using NewHorizons.Builder.StarSystem; using NewHorizons.External; using NewHorizons.External.Configs; using NewHorizons.External.Modules; +using NewHorizons.External.Modules.Props; using NewHorizons.Handlers.TitleScreen; using NewHorizons.Utility; using NewHorizons.Utility.OWML; +using OWML.Common; using System.Collections.Generic; using System.Linq; using UnityEngine; @@ -28,12 +31,82 @@ namespace NewHorizons.Handlers subtitleContainer.AddComponent(); } - public static void SetUp(TitleScreenConfig config) + public static void SetUp(IModBehaviour mod, TitleScreenConfig config) { if (config.menuTextTint != null) { TitleScreenColourHandler.SetColour(config.menuTextTint.ToColor()); } + + if (config.Skybox?.destroyStarField ?? false) + { + Object.Destroy(SearchUtilities.Find("Skybox/Starfield")); + } + + if (config.Skybox?.rightPath != null || + config.Skybox?.leftPath != null || + config.Skybox?.topPath != null || + config.Skybox?.bottomPath != null || + config.Skybox?.frontPath != null || + config.Skybox?.bottomPath != null) + { + SkyboxBuilder.Make(config.Skybox, mod); + } + + if (!string.IsNullOrEmpty(config.music)) + { + //TODO: Implement + } + + if (config.MenuPlanet != null) + { + if (config.MenuPlanet.destroyMenuPlanet) + { + //TODO: Implement + } + + if (config.MenuPlanet.removeChildren != null) + { + //TODO: Implement + //RemoveChildren(null, config.MenuPlanet.removeChildren); + } + + if (config.MenuPlanet.details != null) + { + foreach (var simplifiedDetail in config.MenuPlanet.details) + { + var detail = new DetailInfo(simplifiedDetail); + //TODO: Implement + } + } + } + } + + private static void RemoveChildren(GameObject go, string[] paths) + { + var goPath = go.transform.GetPath(); + var transforms = go.GetComponentsInChildren(true); + foreach (var childPath in paths) + { + // Multiple children can have the same path so we delete all that match + var path = $"{goPath}/{childPath}"; + + var flag = true; + foreach (var childObj in transforms.Where(x => x.GetPath() == path)) + { + flag = false; + // idk why we wait here but we do + Delay.FireInNUpdates(() => + { + if (childObj != null && childObj.gameObject != null) + { + childObj.gameObject.SetActive(false); + } + }, 2); + } + + if (flag) NHLogger.LogWarning($"Couldn't find \"{childPath}\"."); + } } public static void DisplayBodyOnTitleScreen(List bodies) diff --git a/NewHorizons/INewHorizons.cs b/NewHorizons/INewHorizons.cs index 350d0e2b..c9c3579e 100644 --- a/NewHorizons/INewHorizons.cs +++ b/NewHorizons/INewHorizons.cs @@ -96,6 +96,16 @@ namespace NewHorizons /// T QuerySystem(string path); + /// + /// Uses JSONPath to query a title screen config + /// + object QueryTitleScreen(Type outType, IModBehaviour mod, string path); + + /// + /// Uses JSONPath to query a title screen config + /// + T QueryTitleScreen(IModBehaviour mod, string path); + /// /// Register your own builder that will act on the given GameObject by reading the json string of its "extras" module /// @@ -222,5 +232,8 @@ namespace NewHorizons /// /// void SetNextSpawnID(string id); + + + void RegisterTitleScreenHandler(Action builder, bool deleteNHPlanets = true, bool shareTitleScreen = false, string conditionRequired = null, string factRequired = null); } } diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 3885bfa0..2e6295cd 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -55,6 +55,7 @@ namespace NewHorizons public static Dictionary> BodyDict = new(); public static List MountedAddons = new(); public static Dictionary AddonConfigs = new(); + public static Dictionary TitleScreenConfigs = new(); public static float SecondsElapsedInLoop = -1; @@ -269,6 +270,7 @@ namespace NewHorizons OnChangeStarSystem.AddListener(RichPresenceHandler.OnChangeStarSystem); LoadAddonManifest("Assets/addon-manifest.json", this); + LoadTitleScreenConfig("Assets/title-screen.json", this); } public override void SetupPauseMenu(IPauseMenuManager pauseMenu) @@ -431,9 +433,9 @@ namespace NewHorizons } TitleSceneHandler.InitSubtitles(); - // FOR TESTING!!!! - // Remove once actually loading a json file is implemented - TitleSceneHandler.SetUp(new TitleScreenConfig() { menuTextTint = new External.SerializableData.MColor(128, 128, 255) }); + // TODO: Select one title screen and if it has shareTitleScreen set to true do all the other ones that have it true too. + var (mod, config) = Main.TitleScreenConfigs.FirstOrDefault(kvp => kvp.Value.KnowsFact() && kvp.Value.HasCondition()); + TitleSceneHandler.SetUp(mod, config); } // EOTU fixes @@ -792,6 +794,10 @@ namespace NewHorizons { LoadAddonManifest("addon-manifest.json", mod); } + if (File.Exists(Path.Combine(folder, "title-screen.json"))) + { + LoadTitleScreenConfig("title-screen.json", mod); + } if (Directory.Exists(Path.Combine(folder, "translations"))) { LoadTranslations(folder, mod); @@ -840,6 +846,21 @@ namespace NewHorizons AddonConfigs[mod] = addonConfig; } + private void LoadTitleScreenConfig(string file, IModBehaviour mod) + { + NHLogger.LogVerbose($"Loading title screen config for {mod.ModHelper.Manifest.Name}"); + + var titleScreenConfig = mod.ModHelper.Storage.Load(file, false); + + if (titleScreenConfig == null) + { + NHLogger.LogError($"Title screen config for {mod.ModHelper.Manifest.Name} could not load, check your JSON"); + return; + } + + TitleScreenConfigs[mod] = titleScreenConfig; + } + private void LoadTranslations(string folder, IModBehaviour mod) { var foundFile = false; diff --git a/NewHorizons/NewHorizonsApi.cs b/NewHorizons/NewHorizonsApi.cs index 348991c0..85e1a1a4 100644 --- a/NewHorizons/NewHorizonsApi.cs +++ b/NewHorizons/NewHorizonsApi.cs @@ -178,6 +178,24 @@ namespace NewHorizons return default; } + public object QueryTitleScreen(Type outType, IModBehaviour mod, string jsonPath) + { + var titleScreenConfig = Main.TitleScreenConfigs[mod]; + return titleScreenConfig == null + ? null + : QueryJson(outType, Path.Combine(mod.ModHelper.Manifest.ModFolderPath, "title-screen.json"), jsonPath); + } + + public T QueryTitleScreen(IModBehaviour mod, string jsonPath) + { + var data = QueryTitleScreen(typeof(T), mod, jsonPath); + if (data is T result) + { + return result; + } + return default; + } + public GameObject SpawnObject(IModBehaviour mod, GameObject planet, Sector sector, string propToCopyPath, Vector3 position, Vector3 eulerAngles, float scale, bool alignRadial) { @@ -344,5 +362,11 @@ namespace NewHorizons public void AddSubtitle(IModBehaviour mod, string filePath) => SubtitlesHandler.RegisterAdditionalSubtitle(mod, filePath); public void SetNextSpawnID(string id) => PlayerSpawnHandler.TargetSpawnID = id; + + // TODO: Implement + public void RegisterTitleScreenHandler(Action builder, bool deleteNHPlanets = true, bool shareTitleScreen = false, string conditionRequired = null, string factRequired = null) + { + throw new NotImplementedException(); + } } } diff --git a/SchemaExporter/SchemaExporter.cs b/SchemaExporter/SchemaExporter.cs index 4f4d6ddf..5c5aad09 100644 --- a/SchemaExporter/SchemaExporter.cs +++ b/SchemaExporter/SchemaExporter.cs @@ -98,7 +98,7 @@ public static class SchemaExporter break; } - if (_title is "Star System Schema" or "Celestial Body Schema") + if (_title is "Star System Schema" or "Celestial Body Schema" or "Title Screen Schema") { schema.Properties["extras"] = new JsonSchemaProperty { Type = JsonObjectType.Object, From dafcb0687d9a487ebd9ef0e3fee8f0de9fe9e748 Mon Sep 17 00:00:00 2001 From: Ben C Date: Sat, 25 Jan 2025 10:32:37 +0000 Subject: [PATCH 11/87] Updated Schemas --- NewHorizons/Schemas/body_schema.json | 112 ++++----- NewHorizons/Schemas/title_screen_schema.json | 239 +++++++++++++++++++ 2 files changed, 295 insertions(+), 56 deletions(-) create mode 100644 NewHorizons/Schemas/title_screen_schema.json diff --git a/NewHorizons/Schemas/body_schema.json b/NewHorizons/Schemas/body_schema.json index 7ed834cb..a0205e87 100644 --- a/NewHorizons/Schemas/body_schema.json +++ b/NewHorizons/Schemas/body_schema.json @@ -1415,33 +1415,6 @@ "type": "object", "additionalProperties": false, "properties": { - "rotation": { - "description": "Rotation of the object", - "$ref": "#/definitions/MVector3" - }, - "alignRadial": { - "type": [ - "boolean", - "null" - ], - "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." - }, - "position": { - "description": "Position of the object", - "$ref": "#/definitions/MVector3" - }, - "isRelativeToParent": { - "type": "boolean", - "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." - }, - "parentPath": { - "type": "string", - "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." - }, - "rename": { - "type": "string", - "description": "An optional rename of this object" - }, "assetBundle": { "type": "string", "description": "Relative filepath to an asset-bundle to load the prefab defined in `path` from" @@ -1471,6 +1444,33 @@ "description": "Scale each axis of the prop. Overrides `scale`.", "$ref": "#/definitions/MVector3" }, + "rotation": { + "description": "Rotation of the object", + "$ref": "#/definitions/MVector3" + }, + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" + }, "keepLoaded": { "type": "boolean", "description": "Should this detail stay loaded (visible and collideable) even if you're outside the sector (good for very large props)?\nAlso makes this detail visible on the map.\nKeeping many props loaded is bad for performance so use this only when it's actually relevant\nMost logic/behavior scripts will still only work inside the sector, as most of those scripts break if a sector is not provided." @@ -3443,35 +3443,6 @@ "type": "object", "additionalProperties": false, "properties": { - "assetBundle": { - "type": "string", - "description": "Relative filepath to an asset-bundle to load the prefab defined in `path` from" - }, - "path": { - "type": "string", - "description": "Either the path in the scene hierarchy of the item to copy or the path to the object in the supplied asset bundle. \nIf empty, will make an empty game object. This can be useful for adding other props to it as its children." - }, - "removeChildren": { - "type": "array", - "description": "A list of children to remove from this detail", - "items": { - "type": "string" - } - }, - "removeComponents": { - "type": "boolean", - "description": "Do we reset all the components on this object? Useful for certain props that have dialogue components attached to\nthem." - }, - "scale": { - "type": "number", - "description": "Scale the prop", - "format": "float", - "default": 1.0 - }, - "stretch": { - "description": "Scale each axis of the prop. Overrides `scale`.", - "$ref": "#/definitions/MVector3" - }, "keepLoaded": { "type": "boolean", "description": "Should this detail stay loaded (visible and collideable) even if you're outside the sector (good for very large props)?\nAlso makes this detail visible on the map.\nKeeping many props loaded is bad for performance so use this only when it's actually relevant\nMost logic/behavior scripts will still only work inside the sector, as most of those scripts break if a sector is not provided." @@ -3522,6 +3493,35 @@ "description": "Should this detail be treated as a socket for an interactible item", "$ref": "#/definitions/ItemSocketInfo" }, + "assetBundle": { + "type": "string", + "description": "Relative filepath to an asset-bundle to load the prefab defined in `path` from" + }, + "path": { + "type": "string", + "description": "Either the path in the scene hierarchy of the item to copy or the path to the object in the supplied asset bundle. \nIf empty, will make an empty game object. This can be useful for adding other props to it as its children." + }, + "removeChildren": { + "type": "array", + "description": "A list of children to remove from this detail", + "items": { + "type": "string" + } + }, + "removeComponents": { + "type": "boolean", + "description": "Do we reset all the components on this object? Useful for certain props that have dialogue components attached to\nthem." + }, + "scale": { + "type": "number", + "description": "Scale the prop", + "format": "float", + "default": 1.0 + }, + "stretch": { + "description": "Scale each axis of the prop. Overrides `scale`.", + "$ref": "#/definitions/MVector3" + }, "rotation": { "description": "Rotation of the object", "$ref": "#/definitions/MVector3" diff --git a/NewHorizons/Schemas/title_screen_schema.json b/NewHorizons/Schemas/title_screen_schema.json new file mode 100644 index 00000000..4a3dbb08 --- /dev/null +++ b/NewHorizons/Schemas/title_screen_schema.json @@ -0,0 +1,239 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Title Screen Schema", + "type": "object", + "additionalProperties": false, + "properties": { + "menuTextTint": { + "description": "Colour of the text on the main menu", + "$ref": "#/definitions/MColor" + }, + "factRequiredForTitle": { + "type": "string", + "description": "Ship log fact required for this title screen to appear." + }, + "conditionRequiredForTitle": { + "type": "string", + "description": "Persistent condition required for this title screen to appear." + }, + "disableNHPlanets": { + "type": "boolean", + "description": "If set to true, NH generated planets will not show on the title screen. If false, this title screen has the same chance as other NH planet title screens to show." + }, + "shareTitleScreen": { + "type": "boolean", + "description": "If set to true, this custom title screen will merge with all other custom title screens with shareTitleScreen set to true. If false, NH will randomly select between this and other valid title screens that are loaded." + }, + "Skybox": { + "description": "Customize the skybox for this title screen", + "$ref": "#/definitions/SkyboxModule" + }, + "music": { + "type": "string", + "description": "Relative path to music to replace the title screen music with." + }, + "rotationSpeed": { + "type": "number", + "description": "Changes the speed the main menu planet and the skybox rotates.", + "format": "float" + }, + "MenuPlanet": { + "description": "Edit properties of the main menu planet", + "$ref": "#/definitions/MenuPlanetModule" + }, + "extras": { + "type": "object", + "description": "Extra data that may be used by extension mods", + "additionalProperties": { + "type": "object" + } + }, + "$schema": { + "type": "string", + "description": "The schema to validate with" + } + }, + "definitions": { + "MColor": { + "type": "object", + "additionalProperties": false, + "properties": { + "r": { + "type": "integer", + "description": "The red component of this colour from 0-255, higher values will make the colour glow if applicable.", + "format": "int32", + "maximum": 2147483647.0, + "minimum": 0.0 + }, + "g": { + "type": "integer", + "description": "The green component of this colour from 0-255, higher values will make the colour glow if applicable.", + "format": "int32", + "maximum": 2147483647.0, + "minimum": 0.0 + }, + "b": { + "type": "integer", + "description": "The blue component of this colour from 0-255, higher values will make the colour glow if applicable.", + "format": "int32", + "maximum": 2147483647.0, + "minimum": 0.0 + }, + "a": { + "type": "integer", + "description": "The alpha (opacity) component of this colour", + "format": "int32", + "default": 255, + "maximum": 255.0, + "minimum": 0.0 + } + } + }, + "SkyboxModule": { + "type": "object", + "additionalProperties": false, + "properties": { + "destroyStarField": { + "type": "boolean", + "description": "Whether to destroy the star field around the player" + }, + "useCube": { + "type": "boolean", + "description": "Whether to use a cube for the skybox instead of a smooth sphere" + }, + "rightPath": { + "type": "string", + "description": "Relative filepath to the texture to use for the skybox's positive X direction" + }, + "leftPath": { + "type": "string", + "description": "Relative filepath to the texture to use for the skybox's negative X direction" + }, + "topPath": { + "type": "string", + "description": "Relative filepath to the texture to use for the skybox's positive Y direction" + }, + "bottomPath": { + "type": "string", + "description": "Relative filepath to the texture to use for the skybox's negative Y direction" + }, + "frontPath": { + "type": "string", + "description": "Relative filepath to the texture to use for the skybox's positive Z direction" + }, + "backPath": { + "type": "string", + "description": "Relative filepath to the texture to use for the skybox's negative Z direction" + } + } + }, + "MenuPlanetModule": { + "type": "object", + "additionalProperties": false, + "properties": { + "destroyMenuPlanet": { + "type": "boolean", + "description": "Disables the renderers of the main menu planet and all objects on it (this is to improve compatibility with other mods that don't use the NH title screen json)." + }, + "removeChildren": { + "type": "array", + "description": "Disables the renderers of objects at the provided paths", + "items": { + "type": "string" + } + }, + "details": { + "type": "array", + "description": "A list of DetailInfos to populate the main menu planet with.", + "items": { + "$ref": "#/definitions/SimplifiedDetailInfo" + } + } + } + }, + "SimplifiedDetailInfo": { + "type": "object", + "additionalProperties": false, + "properties": { + "rotation": { + "description": "Rotation of the object", + "$ref": "#/definitions/MVector3" + }, + "alignRadial": { + "type": [ + "boolean", + "null" + ], + "description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else." + }, + "position": { + "description": "Position of the object", + "$ref": "#/definitions/MVector3" + }, + "isRelativeToParent": { + "type": "boolean", + "description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object." + }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "rename": { + "type": "string", + "description": "An optional rename of this object" + }, + "assetBundle": { + "type": "string", + "description": "Relative filepath to an asset-bundle to load the prefab defined in `path` from" + }, + "path": { + "type": "string", + "description": "Either the path in the scene hierarchy of the item to copy or the path to the object in the supplied asset bundle. \nIf empty, will make an empty game object. This can be useful for adding other props to it as its children." + }, + "removeChildren": { + "type": "array", + "description": "A list of children to remove from this detail", + "items": { + "type": "string" + } + }, + "removeComponents": { + "type": "boolean", + "description": "Do we reset all the components on this object? Useful for certain props that have dialogue components attached to\nthem." + }, + "scale": { + "type": "number", + "description": "Scale the prop", + "format": "float", + "default": 1.0 + }, + "stretch": { + "description": "Scale each axis of the prop. Overrides `scale`.", + "$ref": "#/definitions/MVector3" + } + } + }, + "MVector3": { + "type": "object", + "additionalProperties": false, + "properties": { + "x": { + "type": "number", + "format": "float" + }, + "y": { + "type": "number", + "format": "float" + }, + "z": { + "type": "number", + "format": "float" + } + } + } + }, + "$docs": { + "title": "Title Screen Schema", + "description": "Schema for the title screen config in New Horizons" + } +} \ No newline at end of file From 310301ceeeeb42e1840f2cf4073ee48fa28ed432 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 25 Jan 2025 06:23:20 -0500 Subject: [PATCH 12/87] grah --- NewHorizons/External/Modules/Props/DetailInfo.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NewHorizons/External/Modules/Props/DetailInfo.cs b/NewHorizons/External/Modules/Props/DetailInfo.cs index 1cbad2da..4c4ca70c 100644 --- a/NewHorizons/External/Modules/Props/DetailInfo.cs +++ b/NewHorizons/External/Modules/Props/DetailInfo.cs @@ -9,6 +9,13 @@ namespace NewHorizons.External.Modules.Props [JsonObject] public class SimplifiedDetailInfo : GeneralPropInfo { + public SimplifiedDetailInfo() { } + + public SimplifiedDetailInfo(GeneralPointPropInfo info) + { + JsonConvert.PopulateObject(JsonConvert.SerializeObject(info), this); + } + /// /// Relative filepath to an asset-bundle to load the prefab defined in `path` from /// From 3ae1e25975a22af36941023021b39837cee136c7 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 25 Jan 2025 06:02:24 -0500 Subject: [PATCH 13/87] Remove testing json --- NewHorizons/Assets/title-screen.json | 11 ----------- NewHorizons/Main.cs | 1 - 2 files changed, 12 deletions(-) delete mode 100644 NewHorizons/Assets/title-screen.json diff --git a/NewHorizons/Assets/title-screen.json b/NewHorizons/Assets/title-screen.json deleted file mode 100644 index cb6ea336..00000000 --- a/NewHorizons/Assets/title-screen.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "disableNHPlanets": false, - "mergeWithOtherTitles": true, - // FOR TESTING!!!! - // Remove once actually loading a json file is implemented - "menuTextTint": { - "r": 128, - "g": 128, - "b": 255 - } -} \ No newline at end of file diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 2e6295cd..e11ca7ba 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -270,7 +270,6 @@ namespace NewHorizons OnChangeStarSystem.AddListener(RichPresenceHandler.OnChangeStarSystem); LoadAddonManifest("Assets/addon-manifest.json", this); - LoadTitleScreenConfig("Assets/title-screen.json", this); } public override void SetupPauseMenu(IPauseMenuManager pauseMenu) From 0e1f63bfcbe8bfa93216afae54ddbff4507c6a1f Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 25 Jan 2025 05:55:16 -0500 Subject: [PATCH 14/87] always set alpha to 1 --- NewHorizons/Handlers/TitleSceneHandler.cs | 2 -- NewHorizons/Handlers/TitleScreen/TitleScreenColourHandler.cs | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 4aa0293f..88d682c4 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -147,8 +147,6 @@ namespace NewHorizons.Handlers planetSizes.Add(bodyInfo3); } - SearchUtilities.Find("Scene/Background/PlanetPivot/Prefab_HEA_Campfire").SetActive(false); - SearchUtilities.Find("Scene/Background/PlanetPivot/PlanetRoot").SetActive(false); var lightGO = new GameObject("Light"); lightGO.transform.parent = SearchUtilities.Find("Scene/Background").transform; diff --git a/NewHorizons/Handlers/TitleScreen/TitleScreenColourHandler.cs b/NewHorizons/Handlers/TitleScreen/TitleScreenColourHandler.cs index 23fafa63..2b20a410 100644 --- a/NewHorizons/Handlers/TitleScreen/TitleScreenColourHandler.cs +++ b/NewHorizons/Handlers/TitleScreen/TitleScreenColourHandler.cs @@ -12,6 +12,7 @@ namespace NewHorizons.Handlers.TitleScreen { public static void SetColour(Color colour) { + colour.a = 1; var buttons = GameObject.FindObjectOfType()._mainMenu.GetComponentsInChildren(); var footer = GameObject.Find("TitleMenu/TitleCanvas/FooterBlock").GetComponentsInChildren(); foreach (var button in buttons.Concat(footer)) From 2af8686818f22cd2ef50354187b3d7dfcc5dbb32 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 25 Jan 2025 06:01:56 -0500 Subject: [PATCH 15/87] parent campfire and ambient light to planet root --- NewHorizons/Handlers/TitleSceneHandler.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 88d682c4..6815ee5d 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -147,6 +147,12 @@ namespace NewHorizons.Handlers planetSizes.Add(bodyInfo3); } + var planetRoot = SearchUtilities.Find("Scene/Background/PlanetPivot/PlanetRoot"); + var campfire = SearchUtilities.Find("Scene/Background/PlanetPivot/Prefab_HEA_Campfire"); + campfire.transform.SetParent(planetRoot.transform, true); + var ambientLight = SearchUtilities.Find("Scene/Background/PlanetPivot/AmbientLight_CaveTwin"); + ambientLight.transform.SetParent(planetRoot.transform, true); + planetRoot.SetActive(false); var lightGO = new GameObject("Light"); lightGO.transform.parent = SearchUtilities.Find("Scene/Background").transform; From a8f48fcb545bc7ef30387ec69c27fa3e07d2b288 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 25 Jan 2025 06:02:10 -0500 Subject: [PATCH 16/87] implement music --- NewHorizons/Handlers/AudioTypeHandler.cs | 5 +++-- NewHorizons/Handlers/TitleSceneHandler.cs | 4 +++- NewHorizons/Main.cs | 2 ++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/NewHorizons/Handlers/AudioTypeHandler.cs b/NewHorizons/Handlers/AudioTypeHandler.cs index 9d25bb7e..1c0fb668 100644 --- a/NewHorizons/Handlers/AudioTypeHandler.cs +++ b/NewHorizons/Handlers/AudioTypeHandler.cs @@ -21,9 +21,10 @@ namespace NewHorizons.Handlers _customAudioTypes = new Dictionary(); _audioEntries = new List(); - Delay.RunWhen( + Delay.RunWhenAndInNUpdates( + PostInit, () => Locator.GetAudioManager()?._libraryAsset != null, - PostInit + 1 ); } diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 6815ee5d..8d04e7fa 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -55,7 +55,9 @@ namespace NewHorizons.Handlers if (!string.IsNullOrEmpty(config.music)) { - //TODO: Implement + var musicSource = SearchUtilities.Find("Scene/AudioSource_Music").GetComponent(); + var audioType = AudioTypeHandler.GetAudioType(config.music, mod); + Delay.FireOnNextUpdate(() => musicSource.AssignAudioLibraryClip(audioType)); } if (config.MenuPlanet != null) diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index e11ca7ba..0f6026ad 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -422,6 +422,8 @@ namespace NewHorizons if (isTitleScreen && CustomTitleScreen) { + AudioTypeHandler.Init(); + try { TitleSceneHandler.DisplayBodyOnTitleScreen(BodyDict.Values.ToList().SelectMany(x => x).ToList()); From b61ea5aaecfeb3251fd0e184dfc814480336e890 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 25 Jan 2025 06:29:26 -0500 Subject: [PATCH 17/87] grah 2 --- NewHorizons/Handlers/AudioTypeHandler.cs | 17 +++++++++++------ NewHorizons/Main.cs | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/NewHorizons/Handlers/AudioTypeHandler.cs b/NewHorizons/Handlers/AudioTypeHandler.cs index 1c0fb668..dbbc9681 100644 --- a/NewHorizons/Handlers/AudioTypeHandler.cs +++ b/NewHorizons/Handlers/AudioTypeHandler.cs @@ -16,16 +16,21 @@ namespace NewHorizons.Handlers private static Dictionary _customAudioTypes; private static List _audioEntries; - public static void Init() + public static void Init(bool titleScreen = false) { _customAudioTypes = new Dictionary(); _audioEntries = new List(); - Delay.RunWhenAndInNUpdates( - PostInit, - () => Locator.GetAudioManager()?._libraryAsset != null, - 1 - ); + if (titleScreen) + Delay.RunWhenAndInNUpdates( + PostInit, + () => Locator.GetAudioManager()?._libraryAsset != null, + 1 + ); + else + Delay.RunWhen(() => Locator.GetAudioManager()?._libraryAsset != null, + PostInit + ); } private static void PostInit() diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 0f6026ad..dcd0a659 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -422,7 +422,7 @@ namespace NewHorizons if (isTitleScreen && CustomTitleScreen) { - AudioTypeHandler.Init(); + AudioTypeHandler.Init(true); try { From c726b089e879fa83ff5406c0f7b5822ad2135d16 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 25 Jan 2025 06:36:19 -0500 Subject: [PATCH 18/87] do ambience too because might as well --- NewHorizons/External/Configs/TitleScreenConfig.cs | 7 ++++++- NewHorizons/Handlers/TitleSceneHandler.cs | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/NewHorizons/External/Configs/TitleScreenConfig.cs b/NewHorizons/External/Configs/TitleScreenConfig.cs index 3ae2f0ee..92ef0bbb 100644 --- a/NewHorizons/External/Configs/TitleScreenConfig.cs +++ b/NewHorizons/External/Configs/TitleScreenConfig.cs @@ -40,10 +40,15 @@ namespace NewHorizons.External.Configs public SkyboxModule Skybox; /// - /// Relative path to music to replace the title screen music with. + /// The music audio that will play on the title screen. Can be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list. /// public string music; + /// + /// The ambience audio that will play on the title screen. Can be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list. + /// + public string ambience; + /// /// Changes the speed the main menu planet and the skybox rotates. /// diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 8d04e7fa..9f72f6b9 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -60,6 +60,13 @@ namespace NewHorizons.Handlers Delay.FireOnNextUpdate(() => musicSource.AssignAudioLibraryClip(audioType)); } + if (!string.IsNullOrEmpty(config.ambience)) + { + var ambienceSource = SearchUtilities.Find("Scene/AudioSource_Ambience").GetComponent(); + var audioType = AudioTypeHandler.GetAudioType(config.ambience, mod); + Delay.FireOnNextUpdate(() => ambienceSource.AssignAudioLibraryClip(audioType)); + } + if (config.MenuPlanet != null) { if (config.MenuPlanet.destroyMenuPlanet) From 9e97e599349bd6304909d8810555564a9d007b41 Mon Sep 17 00:00:00 2001 From: Ben C Date: Sat, 25 Jan 2025 11:39:57 +0000 Subject: [PATCH 19/87] Updated Schemas --- NewHorizons/Schemas/title_screen_schema.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/NewHorizons/Schemas/title_screen_schema.json b/NewHorizons/Schemas/title_screen_schema.json index 4a3dbb08..deb26804 100644 --- a/NewHorizons/Schemas/title_screen_schema.json +++ b/NewHorizons/Schemas/title_screen_schema.json @@ -30,7 +30,11 @@ }, "music": { "type": "string", - "description": "Relative path to music to replace the title screen music with." + "description": "The music audio that will play on the title screen. Can be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list." + }, + "ambience": { + "type": "string", + "description": "The ambience audio that will play on the title screen. Can be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list." }, "rotationSpeed": { "type": "number", From dd917ade85f150d72e7a2e76bf273a032b0c62bc Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 25 Jan 2025 07:12:52 -0500 Subject: [PATCH 20/87] gabagool --- .../External/Configs/TitleScreenConfig.cs | 9 ++- NewHorizons/Handlers/TitleSceneHandler.cs | 65 ++++++++++++++----- NewHorizons/Main.cs | 15 +---- 3 files changed, 56 insertions(+), 33 deletions(-) diff --git a/NewHorizons/External/Configs/TitleScreenConfig.cs b/NewHorizons/External/Configs/TitleScreenConfig.cs index 92ef0bbb..459aff8a 100644 --- a/NewHorizons/External/Configs/TitleScreenConfig.cs +++ b/NewHorizons/External/Configs/TitleScreenConfig.cs @@ -50,9 +50,9 @@ namespace NewHorizons.External.Configs public string ambience; /// - /// Changes the speed the main menu planet and the skybox rotates. + /// Changes the speed the main menu planet and the skybox rotates. This is in degrees per second. /// - public float rotationSpeed; + public float rotationSpeed = 1; /// /// Edit properties of the main menu planet @@ -76,6 +76,11 @@ namespace NewHorizons.External.Configs /// A list of DetailInfos to populate the main menu planet with. /// public SimplifiedDetailInfo[] details; + + /// + /// Changes the speed the main menu planet. This is in degrees per second. + /// + public float rotationSpeed = 2; } /// diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 9f72f6b9..70f4c5f5 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -1,4 +1,6 @@ +using Epic.OnlineServices.Presence; using NewHorizons.Builder.Body; +using NewHorizons.Builder.Props; using NewHorizons.Builder.StarSystem; using NewHorizons.External; using NewHorizons.External.Configs; @@ -8,6 +10,7 @@ using NewHorizons.Handlers.TitleScreen; using NewHorizons.Utility; using NewHorizons.Utility.OWML; using OWML.Common; +using System; using System.Collections.Generic; using System.Linq; using UnityEngine; @@ -17,6 +20,21 @@ namespace NewHorizons.Handlers { public static class TitleSceneHandler { + public static void Init() + { + var planetRoot = SearchUtilities.Find("Scene/Background/PlanetPivot/PlanetRoot"); + var campfire = SearchUtilities.Find("Scene/Background/PlanetPivot/Prefab_HEA_Campfire"); + campfire.transform.SetParent(planetRoot.transform, true); + var ambientLight = SearchUtilities.Find("Scene/Background/PlanetPivot/AmbientLight_CaveTwin"); + ambientLight.transform.SetParent(planetRoot.transform, true); + + TitleSceneHandler.InitSubtitles(); + + // TODO: Select one title screen and if it has shareTitleScreen set to true do all the other ones that have it true too. + var (mod, config) = Main.TitleScreenConfigs.FirstOrDefault(kvp => kvp.Value.KnowsFact() && kvp.Value.HasCondition()); + TitleSceneHandler.SetUp(mod, config); + } + public static void InitSubtitles() { GameObject subtitleContainer = SearchUtilities.Find("TitleMenu/TitleCanvas/TitleLayoutGroup/Logo_EchoesOfTheEye"); @@ -33,6 +51,18 @@ namespace NewHorizons.Handlers public static void SetUp(IModBehaviour mod, TitleScreenConfig config) { + if (!config.disableNHPlanets) + { + try + { + TitleSceneHandler.DisplayBodyOnTitleScreen(Main.BodyDict.Values.ToList().SelectMany(x => x).ToList()); + } + catch (Exception e) + { + NHLogger.LogError($"Failed to make title screen bodies: {e}"); + } + } + if (config.menuTextTint != null) { TitleScreenColourHandler.SetColour(config.menuTextTint.ToColor()); @@ -40,7 +70,7 @@ namespace NewHorizons.Handlers if (config.Skybox?.destroyStarField ?? false) { - Object.Destroy(SearchUtilities.Find("Skybox/Starfield")); + UnityEngine.Object.Destroy(SearchUtilities.Find("Skybox/Starfield")); } if (config.Skybox?.rightPath != null || @@ -67,27 +97,33 @@ namespace NewHorizons.Handlers Delay.FireOnNextUpdate(() => ambienceSource.AssignAudioLibraryClip(audioType)); } + SearchUtilities.Find("Scene/Background").GetComponent()._degreesPerSecond = config.rotationSpeed; + if (config.MenuPlanet != null) { - if (config.MenuPlanet.destroyMenuPlanet) - { - //TODO: Implement - } + var menuPlanet = SearchUtilities.Find("Scene/Background/PlanetPivot/PlanetRoot"); if (config.MenuPlanet.removeChildren != null) { - //TODO: Implement - //RemoveChildren(null, config.MenuPlanet.removeChildren); + RemoveChildren(menuPlanet, config.MenuPlanet.removeChildren); } if (config.MenuPlanet.details != null) { foreach (var simplifiedDetail in config.MenuPlanet.details) { - var detail = new DetailInfo(simplifiedDetail); - //TODO: Implement + DetailBuilder.Make(menuPlanet, null, mod, new DetailInfo(simplifiedDetail)); } } + + var rotator = SearchUtilities.Find("Scene/Background/PlanetPivot").GetComponent(); + rotator._localAxis = Vector3.up; + rotator._degreesPerSecond = config.MenuPlanet.rotationSpeed; + + if (config.MenuPlanet.destroyMenuPlanet) + { + menuPlanet.SetActive(false); + } } } @@ -156,12 +192,7 @@ namespace NewHorizons.Handlers planetSizes.Add(bodyInfo3); } - var planetRoot = SearchUtilities.Find("Scene/Background/PlanetPivot/PlanetRoot"); - var campfire = SearchUtilities.Find("Scene/Background/PlanetPivot/Prefab_HEA_Campfire"); - campfire.transform.SetParent(planetRoot.transform, true); - var ambientLight = SearchUtilities.Find("Scene/Background/PlanetPivot/AmbientLight_CaveTwin"); - ambientLight.transform.SetParent(planetRoot.transform, true); - planetRoot.SetActive(false); + SearchUtilities.Find("Scene/Background/PlanetPivot/PlanetRoot").SetActive(false); var lightGO = new GameObject("Light"); lightGO.transform.parent = SearchUtilities.Find("Scene/Background").transform; @@ -250,11 +281,11 @@ namespace NewHorizons.Handlers } } - var pivot = Object.Instantiate(SearchUtilities.Find("Scene/Background/PlanetPivot"), SearchUtilities.Find("Scene/Background").transform); + var pivot = UnityEngine.Object.Instantiate(SearchUtilities.Find("Scene/Background/PlanetPivot"), SearchUtilities.Find("Scene/Background").transform); pivot.GetComponent()._degreesPerSecond = 10f; foreach (Transform child in pivot.transform) { - Object.Destroy(child.gameObject); + UnityEngine.Object.Destroy(child.gameObject); } pivot.name = "Pivot"; diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index dcd0a659..7ad0851c 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -423,20 +423,7 @@ namespace NewHorizons if (isTitleScreen && CustomTitleScreen) { AudioTypeHandler.Init(true); - - try - { - TitleSceneHandler.DisplayBodyOnTitleScreen(BodyDict.Values.ToList().SelectMany(x => x).ToList()); - } - catch (Exception e) - { - NHLogger.LogError($"Failed to make title screen bodies: {e}"); - } - TitleSceneHandler.InitSubtitles(); - - // TODO: Select one title screen and if it has shareTitleScreen set to true do all the other ones that have it true too. - var (mod, config) = Main.TitleScreenConfigs.FirstOrDefault(kvp => kvp.Value.KnowsFact() && kvp.Value.HasCondition()); - TitleSceneHandler.SetUp(mod, config); + TitleSceneHandler.Init(); } // EOTU fixes From 20d6502243236b8e391b0c94b8f02ca6a05f40c7 Mon Sep 17 00:00:00 2001 From: Ben C Date: Sat, 25 Jan 2025 12:14:58 +0000 Subject: [PATCH 21/87] Updated Schemas --- NewHorizons/Schemas/title_screen_schema.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/NewHorizons/Schemas/title_screen_schema.json b/NewHorizons/Schemas/title_screen_schema.json index deb26804..73c04d38 100644 --- a/NewHorizons/Schemas/title_screen_schema.json +++ b/NewHorizons/Schemas/title_screen_schema.json @@ -38,7 +38,7 @@ }, "rotationSpeed": { "type": "number", - "description": "Changes the speed the main menu planet and the skybox rotates.", + "description": "Changes the speed the main menu planet and the skybox rotates. This is in degrees per second.", "format": "float" }, "MenuPlanet": { @@ -152,6 +152,11 @@ "items": { "$ref": "#/definitions/SimplifiedDetailInfo" } + }, + "rotationSpeed": { + "type": "number", + "description": "Changes the speed the main menu planet. This is in degrees per second.", + "format": "float" } } }, From 79ffb99d0545f72a9ae3987f9b5f343d636ef4a8 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 25 Jan 2025 07:29:31 -0500 Subject: [PATCH 22/87] use the pivot instead --- NewHorizons/Handlers/TitleSceneHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 70f4c5f5..f120342e 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -101,7 +101,7 @@ namespace NewHorizons.Handlers if (config.MenuPlanet != null) { - var menuPlanet = SearchUtilities.Find("Scene/Background/PlanetPivot/PlanetRoot"); + var menuPlanet = SearchUtilities.Find("Scene/Background/PlanetPivot"); if (config.MenuPlanet.removeChildren != null) { @@ -116,7 +116,7 @@ namespace NewHorizons.Handlers } } - var rotator = SearchUtilities.Find("Scene/Background/PlanetPivot").GetComponent(); + var rotator = menuPlanet.GetComponent(); rotator._localAxis = Vector3.up; rotator._degreesPerSecond = config.MenuPlanet.rotationSpeed; From 1380bbb4e0cf60633bcf0036b3d87e73bd2fdc90 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 25 Jan 2025 07:30:16 -0500 Subject: [PATCH 23/87] bleh --- NewHorizons/External/Configs/TitleScreenConfig.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/External/Configs/TitleScreenConfig.cs b/NewHorizons/External/Configs/TitleScreenConfig.cs index 459aff8a..e08046ed 100644 --- a/NewHorizons/External/Configs/TitleScreenConfig.cs +++ b/NewHorizons/External/Configs/TitleScreenConfig.cs @@ -50,7 +50,7 @@ namespace NewHorizons.External.Configs public string ambience; /// - /// Changes the speed the main menu planet and the skybox rotates. This is in degrees per second. + /// Changes the speed the skybox rotates (and by extension the main menu planet). This is in degrees per second. /// public float rotationSpeed = 1; From 37bd3263f8d51827a5d4ac83c1545bdad3799b5f Mon Sep 17 00:00:00 2001 From: Ben C Date: Sat, 25 Jan 2025 12:31:42 +0000 Subject: [PATCH 24/87] Updated Schemas --- NewHorizons/Schemas/title_screen_schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/Schemas/title_screen_schema.json b/NewHorizons/Schemas/title_screen_schema.json index 73c04d38..2ea6af14 100644 --- a/NewHorizons/Schemas/title_screen_schema.json +++ b/NewHorizons/Schemas/title_screen_schema.json @@ -38,7 +38,7 @@ }, "rotationSpeed": { "type": "number", - "description": "Changes the speed the main menu planet and the skybox rotates. This is in degrees per second.", + "description": "Changes the speed the skybox rotates (and by extension the main menu planet). This is in degrees per second.", "format": "float" }, "MenuPlanet": { From 5d37898ce19e8ed0d85f6586a759b5b44b305b97 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 25 Jan 2025 22:17:44 -0500 Subject: [PATCH 25/87] null check --- NewHorizons/Builder/Props/ProjectionBuilder.cs | 1 + .../Components/EOTE/NHSlideCollectionContainer.cs | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/NewHorizons/Builder/Props/ProjectionBuilder.cs b/NewHorizons/Builder/Props/ProjectionBuilder.cs index 7df34b6c..354745e5 100644 --- a/NewHorizons/Builder/Props/ProjectionBuilder.cs +++ b/NewHorizons/Builder/Props/ProjectionBuilder.cs @@ -381,6 +381,7 @@ namespace NewHorizons.Builder.Props } slideCollectionContainer.slideCollection = slideCollection; + slideCollectionContainer._playWithShipLogFacts = Array.Empty(); StreamingHandler.SetUpStreaming(projectorObj, sector); diff --git a/NewHorizons/Components/EOTE/NHSlideCollectionContainer.cs b/NewHorizons/Components/EOTE/NHSlideCollectionContainer.cs index bcf979ec..cff36ed1 100644 --- a/NewHorizons/Components/EOTE/NHSlideCollectionContainer.cs +++ b/NewHorizons/Components/EOTE/NHSlideCollectionContainer.cs @@ -24,10 +24,13 @@ public class NHSlideCollectionContainer : SlideCollectionContainer __instance._changeSlidesAllowed = true; __instance._initialized = true; __instance._slideCollection.isVision = __instance._owningItem == null; - foreach (var factID in __instance._playWithShipLogFacts) + if (__instance._playWithShipLogFacts != null) { - var fact = Locator.GetShipLogManager().GetFact(factID); - fact?.RegisterSlideCollection(__instance._slideCollection); + foreach (var factID in __instance._playWithShipLogFacts) + { + var fact = Locator.GetShipLogManager().GetFact(factID); + fact?.RegisterSlideCollection(__instance._slideCollection); + } } return false; } From e5b964d7c7452a7e717812ddd6ceb6afe0e87ece Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 25 Jan 2025 22:18:58 -0500 Subject: [PATCH 26/87] shenanigans --- NewHorizons/Handlers/AudioTypeHandler.cs | 24 +++++++------- NewHorizons/Handlers/TitleSceneHandler.cs | 39 +++++++++++++++++------ NewHorizons/Main.cs | 1 - 3 files changed, 42 insertions(+), 22 deletions(-) diff --git a/NewHorizons/Handlers/AudioTypeHandler.cs b/NewHorizons/Handlers/AudioTypeHandler.cs index dbbc9681..ef6e71f3 100644 --- a/NewHorizons/Handlers/AudioTypeHandler.cs +++ b/NewHorizons/Handlers/AudioTypeHandler.cs @@ -15,28 +15,28 @@ namespace NewHorizons.Handlers { private static Dictionary _customAudioTypes; private static List _audioEntries; + private static bool _postInitialized = false; - public static void Init(bool titleScreen = false) + public static void Init() { _customAudioTypes = new Dictionary(); _audioEntries = new List(); + _postInitialized = false; - if (titleScreen) - Delay.RunWhenAndInNUpdates( - PostInit, - () => Locator.GetAudioManager()?._libraryAsset != null, - 1 - ); - else - Delay.RunWhen(() => Locator.GetAudioManager()?._libraryAsset != null, - PostInit - ); + Delay.RunWhen(() => Locator.GetAudioManager()?._libraryAsset != null && Locator.GetAudioManager()?._audioLibraryDict != null, + PostInit + ); } private static void PostInit() { NHLogger.LogVerbose($"Adding all custom AudioTypes to the library"); + _postInitialized = true; + ModifyAudioLibrary(); + } + private static void ModifyAudioLibrary() + { var library = Locator.GetAudioManager()._libraryAsset; var audioEntries = library.audioEntries; // store previous array library.audioEntries = library.audioEntries.Concat(_audioEntries).ToArray(); // concat custom entries @@ -94,6 +94,8 @@ namespace NewHorizons.Handlers _audioEntries.Add(new AudioLibrary.AudioEntry(audioType, audioClips)); _customAudioTypes.Add(id, audioType); + if (_postInitialized) ModifyAudioLibrary(); + return audioType; } } diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index f120342e..c503a44f 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -1,3 +1,4 @@ +using Epic.OnlineServices; using Epic.OnlineServices.Presence; using NewHorizons.Builder.Body; using NewHorizons.Builder.Props; @@ -28,11 +29,24 @@ namespace NewHorizons.Handlers var ambientLight = SearchUtilities.Find("Scene/Background/PlanetPivot/AmbientLight_CaveTwin"); ambientLight.transform.SetParent(planetRoot.transform, true); - TitleSceneHandler.InitSubtitles(); + InitSubtitles(); + AudioTypeHandler.Init(); + + // Load player data for fact and persistent condition checking + var profileManager = StandaloneProfileManager.SharedInstance; + profileManager.PreInitialize(); + profileManager.Initialize(); + PlayerData.Init(profileManager.currentProfileGameSave, + profileManager.currentProfileGameSettings, + profileManager.currentProfileGraphicsSettings, + profileManager.currentProfileInputJSON); // TODO: Select one title screen and if it has shareTitleScreen set to true do all the other ones that have it true too. var (mod, config) = Main.TitleScreenConfigs.FirstOrDefault(kvp => kvp.Value.KnowsFact() && kvp.Value.HasCondition()); - TitleSceneHandler.SetUp(mod, config); + if (config != null) + SetUp(mod, config); + else + DisplayBodiesOnTitleScreen(); } public static void InitSubtitles() @@ -53,14 +67,7 @@ namespace NewHorizons.Handlers { if (!config.disableNHPlanets) { - try - { - TitleSceneHandler.DisplayBodyOnTitleScreen(Main.BodyDict.Values.ToList().SelectMany(x => x).ToList()); - } - catch (Exception e) - { - NHLogger.LogError($"Failed to make title screen bodies: {e}"); - } + DisplayBodiesOnTitleScreen(); } if (config.menuTextTint != null) @@ -154,6 +161,18 @@ namespace NewHorizons.Handlers } } + public static void DisplayBodiesOnTitleScreen() + { + try + { + TitleSceneHandler.DisplayBodyOnTitleScreen(Main.BodyDict.Values.ToList().SelectMany(x => x).ToList()); + } + catch (Exception e) + { + NHLogger.LogError($"Failed to make title screen bodies: {e}"); + } + } + public static void DisplayBodyOnTitleScreen(List bodies) { // Try loading one planet why not diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 7ad0851c..c4cc2377 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -422,7 +422,6 @@ namespace NewHorizons if (isTitleScreen && CustomTitleScreen) { - AudioTypeHandler.Init(true); TitleSceneHandler.Init(); } From 64b0816d6202ae96df2621f7cd970a1915b989a7 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 25 Jan 2025 22:53:46 -0500 Subject: [PATCH 27/87] I don't understand why visual studio keeps adding in unused namespaces --- NewHorizons/Handlers/TitleSceneHandler.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index c503a44f..620494ff 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -1,5 +1,3 @@ -using Epic.OnlineServices; -using Epic.OnlineServices.Presence; using NewHorizons.Builder.Body; using NewHorizons.Builder.Props; using NewHorizons.Builder.StarSystem; From fcd4ab4fe6ebc716ec63d4b801db9c23e50c84bb Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Wed, 29 Jan 2025 00:10:21 -0500 Subject: [PATCH 28/87] Null check for profile --- NewHorizons/External/Configs/TitleScreenConfig.cs | 4 ++-- NewHorizons/Handlers/TitleSceneHandler.cs | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/NewHorizons/External/Configs/TitleScreenConfig.cs b/NewHorizons/External/Configs/TitleScreenConfig.cs index e08046ed..51541721 100644 --- a/NewHorizons/External/Configs/TitleScreenConfig.cs +++ b/NewHorizons/External/Configs/TitleScreenConfig.cs @@ -88,8 +88,8 @@ namespace NewHorizons.External.Configs /// public object extras; - public bool KnowsFact() => string.IsNullOrEmpty(factRequiredForTitle) || ShipLogHandler.KnowsFact(factRequiredForTitle); + public bool KnowsFact() => string.IsNullOrEmpty(factRequiredForTitle) || StandaloneProfileManager.SharedInstance.currentProfile != null && ShipLogHandler.KnowsFact(factRequiredForTitle); - public bool HasCondition() => string.IsNullOrEmpty(conditionRequiredForTitle) || PlayerData.GetPersistentCondition(conditionRequiredForTitle); + public bool HasCondition() => string.IsNullOrEmpty(conditionRequiredForTitle) || StandaloneProfileManager.SharedInstance.currentProfile != null && PlayerData.GetPersistentCondition(conditionRequiredForTitle); } } diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 620494ff..f441abd6 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -34,10 +34,12 @@ namespace NewHorizons.Handlers var profileManager = StandaloneProfileManager.SharedInstance; profileManager.PreInitialize(); profileManager.Initialize(); - PlayerData.Init(profileManager.currentProfileGameSave, - profileManager.currentProfileGameSettings, - profileManager.currentProfileGraphicsSettings, - profileManager.currentProfileInputJSON); + if (profileManager.currentProfile != null) + PlayerData.Init(profileManager.currentProfileGameSave, + profileManager.currentProfileGameSettings, + profileManager.currentProfileGraphicsSettings, + profileManager.currentProfileInputJSON); + // TODO: Select one title screen and if it has shareTitleScreen set to true do all the other ones that have it true too. var (mod, config) = Main.TitleScreenConfigs.FirstOrDefault(kvp => kvp.Value.KnowsFact() && kvp.Value.HasCondition()); From a980eef1d3e35bcf72905c1e054eb497e5ddad3c Mon Sep 17 00:00:00 2001 From: Ben C Date: Fri, 14 Feb 2025 22:53:38 +0000 Subject: [PATCH 29/87] Updated Schemas --- NewHorizons/Schemas/body_schema.json | 174 +++++++++++++-------------- 1 file changed, 87 insertions(+), 87 deletions(-) diff --git a/NewHorizons/Schemas/body_schema.json b/NewHorizons/Schemas/body_schema.json index 3c882955..1f779391 100644 --- a/NewHorizons/Schemas/body_schema.json +++ b/NewHorizons/Schemas/body_schema.json @@ -885,35 +885,6 @@ "type": "object", "additionalProperties": false, "properties": { - "assetBundle": { - "type": "string", - "description": "Relative filepath to an asset-bundle to load the prefab defined in `path` from" - }, - "path": { - "type": "string", - "description": "Either the path in the scene hierarchy of the item to copy or the path to the object in the supplied asset bundle. \nIf empty, will make an empty game object. This can be useful for adding other props to it as its children." - }, - "removeChildren": { - "type": "array", - "description": "A list of children to remove from this detail", - "items": { - "type": "string" - } - }, - "removeComponents": { - "type": "boolean", - "description": "Do we reset all the components on this object? Useful for certain props that have dialogue components attached to\nthem." - }, - "scale": { - "type": "number", - "description": "Scale the prop", - "format": "float", - "default": 1.0 - }, - "stretch": { - "description": "Scale each axis of the prop. Overrides `scale`.", - "$ref": "#/definitions/MVector3" - }, "keepLoaded": { "type": "boolean", "description": "Should this detail stay loaded (visible and collideable) even if you're outside the sector (good for very large props)?\nAlso makes this detail visible on the map.\nKeeping many props loaded is bad for performance so use this only when it's actually relevant\nMost logic/behavior scripts will still only work inside the sector, as most of those scripts break if a sector is not provided." @@ -964,6 +935,35 @@ "description": "Should this detail be treated as a socket for an interactible item", "$ref": "#/definitions/ItemSocketInfo" }, + "assetBundle": { + "type": "string", + "description": "Relative filepath to an asset-bundle to load the prefab defined in `path` from" + }, + "path": { + "type": "string", + "description": "Either the path in the scene hierarchy of the item to copy or the path to the object in the supplied asset bundle. \nIf empty, will make an empty game object. This can be useful for adding other props to it as its children." + }, + "removeChildren": { + "type": "array", + "description": "A list of children to remove from this detail", + "items": { + "type": "string" + } + }, + "removeComponents": { + "type": "boolean", + "description": "Do we reset all the components on this object? Useful for certain props that have dialogue components attached to\nthem." + }, + "scale": { + "type": "number", + "description": "Scale the prop", + "format": "float", + "default": 1.0 + }, + "stretch": { + "description": "Scale each axis of the prop. Overrides `scale`.", + "$ref": "#/definitions/MVector3" + }, "rotation": { "description": "Rotation of the object", "$ref": "#/definitions/MVector3" @@ -1470,35 +1470,6 @@ "type": "object", "additionalProperties": false, "properties": { - "assetBundle": { - "type": "string", - "description": "Relative filepath to an asset-bundle to load the prefab defined in `path` from" - }, - "path": { - "type": "string", - "description": "Either the path in the scene hierarchy of the item to copy or the path to the object in the supplied asset bundle. \nIf empty, will make an empty game object. This can be useful for adding other props to it as its children." - }, - "removeChildren": { - "type": "array", - "description": "A list of children to remove from this detail", - "items": { - "type": "string" - } - }, - "removeComponents": { - "type": "boolean", - "description": "Do we reset all the components on this object? Useful for certain props that have dialogue components attached to\nthem." - }, - "scale": { - "type": "number", - "description": "Scale the prop", - "format": "float", - "default": 1.0 - }, - "stretch": { - "description": "Scale each axis of the prop. Overrides `scale`.", - "$ref": "#/definitions/MVector3" - }, "keepLoaded": { "type": "boolean", "description": "Should this detail stay loaded (visible and collideable) even if you're outside the sector (good for very large props)?\nAlso makes this detail visible on the map.\nKeeping many props loaded is bad for performance so use this only when it's actually relevant\nMost logic/behavior scripts will still only work inside the sector, as most of those scripts break if a sector is not provided." @@ -1549,6 +1520,35 @@ "description": "Should this detail be treated as a socket for an interactible item", "$ref": "#/definitions/ItemSocketInfo" }, + "assetBundle": { + "type": "string", + "description": "Relative filepath to an asset-bundle to load the prefab defined in `path` from" + }, + "path": { + "type": "string", + "description": "Either the path in the scene hierarchy of the item to copy or the path to the object in the supplied asset bundle. \nIf empty, will make an empty game object. This can be useful for adding other props to it as its children." + }, + "removeChildren": { + "type": "array", + "description": "A list of children to remove from this detail", + "items": { + "type": "string" + } + }, + "removeComponents": { + "type": "boolean", + "description": "Do we reset all the components on this object? Useful for certain props that have dialogue components attached to\nthem." + }, + "scale": { + "type": "number", + "description": "Scale the prop", + "format": "float", + "default": 1.0 + }, + "stretch": { + "description": "Scale each axis of the prop. Overrides `scale`.", + "$ref": "#/definitions/MVector3" + }, "rotation": { "description": "Rotation of the object", "$ref": "#/definitions/MVector3" @@ -1586,35 +1586,6 @@ "type": "object", "additionalProperties": false, "properties": { - "assetBundle": { - "type": "string", - "description": "Relative filepath to an asset-bundle to load the prefab defined in `path` from" - }, - "path": { - "type": "string", - "description": "Either the path in the scene hierarchy of the item to copy or the path to the object in the supplied asset bundle. \nIf empty, will make an empty game object. This can be useful for adding other props to it as its children." - }, - "removeChildren": { - "type": "array", - "description": "A list of children to remove from this detail", - "items": { - "type": "string" - } - }, - "removeComponents": { - "type": "boolean", - "description": "Do we reset all the components on this object? Useful for certain props that have dialogue components attached to\nthem." - }, - "scale": { - "type": "number", - "description": "Scale the prop", - "format": "float", - "default": 1.0 - }, - "stretch": { - "description": "Scale each axis of the prop. Overrides `scale`.", - "$ref": "#/definitions/MVector3" - }, "keepLoaded": { "type": "boolean", "description": "Should this detail stay loaded (visible and collideable) even if you're outside the sector (good for very large props)?\nAlso makes this detail visible on the map.\nKeeping many props loaded is bad for performance so use this only when it's actually relevant\nMost logic/behavior scripts will still only work inside the sector, as most of those scripts break if a sector is not provided." @@ -1665,6 +1636,35 @@ "description": "Should this detail be treated as a socket for an interactible item", "$ref": "#/definitions/ItemSocketInfo" }, + "assetBundle": { + "type": "string", + "description": "Relative filepath to an asset-bundle to load the prefab defined in `path` from" + }, + "path": { + "type": "string", + "description": "Either the path in the scene hierarchy of the item to copy or the path to the object in the supplied asset bundle. \nIf empty, will make an empty game object. This can be useful for adding other props to it as its children." + }, + "removeChildren": { + "type": "array", + "description": "A list of children to remove from this detail", + "items": { + "type": "string" + } + }, + "removeComponents": { + "type": "boolean", + "description": "Do we reset all the components on this object? Useful for certain props that have dialogue components attached to\nthem." + }, + "scale": { + "type": "number", + "description": "Scale the prop", + "format": "float", + "default": 1.0 + }, + "stretch": { + "description": "Scale each axis of the prop. Overrides `scale`.", + "$ref": "#/definitions/MVector3" + }, "rotation": { "description": "Rotation of the object", "$ref": "#/definitions/MVector3" From 09ffa4b2bc548af8011e2bd1c9a76fe21068134c Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Fri, 14 Feb 2025 21:18:01 -0500 Subject: [PATCH 30/87] Add comments and start on handlers --- NewHorizons/Handlers/TitleSceneHandler.cs | 28 +++++++++++++++++++++++ NewHorizons/INewHorizons.cs | 13 +++++++++-- NewHorizons/NewHorizonsApi.cs | 7 ++---- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index f441abd6..e7062c76 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -19,6 +19,8 @@ namespace NewHorizons.Handlers { public static class TitleSceneHandler { + internal static Dictionary TitleScreenBuilders = new(); + public static void Init() { var planetRoot = SearchUtilities.Find("Scene/Background/PlanetPivot/PlanetRoot"); @@ -41,6 +43,7 @@ namespace NewHorizons.Handlers profileManager.currentProfileInputJSON); + // TODO: Implement handlers as well // TODO: Select one title screen and if it has shareTitleScreen set to true do all the other ones that have it true too. var (mod, config) = Main.TitleScreenConfigs.FirstOrDefault(kvp => kvp.Value.KnowsFact() && kvp.Value.HasCondition()); if (config != null) @@ -369,5 +372,30 @@ namespace NewHorizons.Handlers return meshRenderer; } + + public static void RegisterBuilder(IModBehaviour mod, Action builder, bool disableNHPlanets, bool shareTitleScreen, string conditionRequired, string factRequired) + { + TitleScreenBuilders.SafeAdd(mod, new TitleScreenBuilder(mod, builder, disableNHPlanets, shareTitleScreen, conditionRequired, factRequired)); + } + + internal class TitleScreenBuilder + { + public IModBehaviour mod; + public Action builder; + public bool disableNHPlanets; + public bool shareTitleScreen; + public string conditionRequired; + public string factRequired; + + public TitleScreenBuilder(IModBehaviour mod, Action builder, bool disableNHPlanets, bool shareTitleScreen, string conditionRequired, string factRequired) + { + this.mod = mod; + this.builder = builder; + this.disableNHPlanets = disableNHPlanets; + this.shareTitleScreen = shareTitleScreen; + this.conditionRequired = conditionRequired; + this.factRequired = factRequired; + } + } } } diff --git a/NewHorizons/INewHorizons.cs b/NewHorizons/INewHorizons.cs index c9c3579e..5a1a9b09 100644 --- a/NewHorizons/INewHorizons.cs +++ b/NewHorizons/INewHorizons.cs @@ -233,7 +233,16 @@ namespace NewHorizons /// void SetNextSpawnID(string id); - - void RegisterTitleScreenHandler(Action builder, bool deleteNHPlanets = true, bool shareTitleScreen = false, string conditionRequired = null, string factRequired = null); + /// + /// Registers a builder for the main menu. + /// Call this once before the main menu finishes loading + /// + /// + /// Builder to run when this title screen is selected. + /// If set to true, NH generated planets will not show on the title screen. If false, this title screen has the same chance as other NH planet title screens to show. + /// If set to true, this custom title screen will merge with all other custom title screens with shareTitleScreen set to true. If false, NH will randomly select between this and other valid title screens that are loaded. + /// Persistent condition required for this title screen to appear. + /// Ship log fact required for this title screen to appear. + void RegisterTitleScreenBuilder(IModBehaviour mod, Action builder, bool disableNHPlanets = true, bool shareTitleScreen = false, string conditionRequired = null, string factRequired = null); } } diff --git a/NewHorizons/NewHorizonsApi.cs b/NewHorizons/NewHorizonsApi.cs index 85e1a1a4..e2407347 100644 --- a/NewHorizons/NewHorizonsApi.cs +++ b/NewHorizons/NewHorizonsApi.cs @@ -363,10 +363,7 @@ namespace NewHorizons public void SetNextSpawnID(string id) => PlayerSpawnHandler.TargetSpawnID = id; - // TODO: Implement - public void RegisterTitleScreenHandler(Action builder, bool deleteNHPlanets = true, bool shareTitleScreen = false, string conditionRequired = null, string factRequired = null) - { - throw new NotImplementedException(); - } + public void RegisterTitleScreenBuilder(IModBehaviour mod, Action builder, bool disableNHPlanets = true, bool shareTitleScreen = false, string conditionRequired = null, string factRequired = null) + => TitleSceneHandler.RegisterBuilder(mod, builder, disableNHPlanets, shareTitleScreen, conditionRequired, factRequired); } } From a2639993fada2f501a5d981dbb272d045eb2a07a Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Fri, 14 Feb 2025 23:58:27 -0500 Subject: [PATCH 31/87] Reset color --- NewHorizons/Handlers/TitleSceneHandler.cs | 1 + .../Handlers/TitleScreen/TitleScreenColourHandler.cs | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index e7062c76..0a47eb3f 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -30,6 +30,7 @@ namespace NewHorizons.Handlers ambientLight.transform.SetParent(planetRoot.transform, true); InitSubtitles(); + TitleScreenColourHandler.ResetColour(); AudioTypeHandler.Init(); // Load player data for fact and persistent condition checking diff --git a/NewHorizons/Handlers/TitleScreen/TitleScreenColourHandler.cs b/NewHorizons/Handlers/TitleScreen/TitleScreenColourHandler.cs index 2b20a410..1fa9e6fb 100644 --- a/NewHorizons/Handlers/TitleScreen/TitleScreenColourHandler.cs +++ b/NewHorizons/Handlers/TitleScreen/TitleScreenColourHandler.cs @@ -1,5 +1,6 @@ using HarmonyLib; using NewHorizons.Utility.Files; +using NewHorizons.Utility.OWML; using System.Linq; using UnityEngine; using UnityEngine.SceneManagement; @@ -12,6 +13,7 @@ namespace NewHorizons.Handlers.TitleScreen { public static void SetColour(Color colour) { + NHLogger.LogVerbose("Setting title screen colour to " + colour.ToString()); colour.a = 1; var buttons = GameObject.FindObjectOfType()._mainMenu.GetComponentsInChildren(); var footer = GameObject.Find("TitleMenu/TitleCanvas/FooterBlock").GetComponentsInChildren(); @@ -25,6 +27,11 @@ namespace NewHorizons.Handlers.TitleScreen GameObject.FindObjectOfType()._logoMaterialClone.mainTexture = logo; } + public static void ResetColour() + { + _mainMenuColour = null; + } + [HarmonyPrefix] [HarmonyPatch(typeof(UIStyleApplier), nameof(UIStyleApplier.ChangeColors))] public static bool UIStyleApplier_ChangeColors(UIStyleApplier __instance, UIElementState state) From 323bf6549ec302ee6f36731cf15c2cb923c1e8e2 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Fri, 14 Feb 2025 22:47:28 -0500 Subject: [PATCH 32/87] add builders, randomization, and sharing --- .../External/Configs/TitleScreenConfig.cs | 4 - NewHorizons/Handlers/TitleSceneHandler.cs | 117 ++++++++++++++++-- 2 files changed, 105 insertions(+), 16 deletions(-) diff --git a/NewHorizons/External/Configs/TitleScreenConfig.cs b/NewHorizons/External/Configs/TitleScreenConfig.cs index 51541721..ea56bc20 100644 --- a/NewHorizons/External/Configs/TitleScreenConfig.cs +++ b/NewHorizons/External/Configs/TitleScreenConfig.cs @@ -87,9 +87,5 @@ namespace NewHorizons.External.Configs /// Extra data that may be used by extension mods /// public object extras; - - public bool KnowsFact() => string.IsNullOrEmpty(factRequiredForTitle) || StandaloneProfileManager.SharedInstance.currentProfile != null && ShipLogHandler.KnowsFact(factRequiredForTitle); - - public bool HasCondition() => string.IsNullOrEmpty(conditionRequiredForTitle) || StandaloneProfileManager.SharedInstance.currentProfile != null && PlayerData.GetPersistentCondition(conditionRequiredForTitle); } } diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 0a47eb3f..6010835f 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -1,3 +1,4 @@ +using Epic.OnlineServices; using NewHorizons.Builder.Body; using NewHorizons.Builder.Props; using NewHorizons.Builder.StarSystem; @@ -43,12 +44,38 @@ namespace NewHorizons.Handlers profileManager.currentProfileGraphicsSettings, profileManager.currentProfileInputJSON); + var validBuilders = Main.TitleScreenConfigs.Select(kvp => (ITitleScreenBuilder)new TitleScreenConfigBuilder(kvp.Key, kvp.Value)) + .Concat(TitleScreenBuilders.Select(kvp => (ITitleScreenBuilder)kvp.Value)) + .Where(builder => builder.KnowsFact() && builder.HasCondition()).ToList(); - // TODO: Implement handlers as well - // TODO: Select one title screen and if it has shareTitleScreen set to true do all the other ones that have it true too. - var (mod, config) = Main.TitleScreenConfigs.FirstOrDefault(kvp => kvp.Value.KnowsFact() && kvp.Value.HasCondition()); - if (config != null) - SetUp(mod, config); + foreach (var builder in validBuilders) + { + NHLogger.LogVerbose("Valid builder: " + builder.Mod.ModHelper.Manifest.UniqueName); + } + + var index = UnityEngine.Random.Range(0, validBuilders.Count()); + var randomBuilder = validBuilders.ElementAtOrDefault(index); + if (randomBuilder != null) + { + validBuilders.RemoveAt(index); + NHLogger.LogVerbose("Building main: " + randomBuilder.Mod.ModHelper.Manifest.UniqueName + " | " + (randomBuilder.CanShare ? "Share" : "Unshare") + " " + (randomBuilder.DisableNHPlanets ? "Disable" : "Enable")); + + if (!randomBuilder.DisableNHPlanets) + { + DisplayBodiesOnTitleScreen(); + } + + randomBuilder.Build(); + + if (randomBuilder.CanShare) + { + foreach (var builder in validBuilders.Where(builder => builder.CanShare && builder.DisableNHPlanets == randomBuilder.DisableNHPlanets)) + { + NHLogger.LogVerbose("Building extra: " + randomBuilder.Mod.ModHelper.Manifest.UniqueName); + builder.Build(); + } + } + } else DisplayBodiesOnTitleScreen(); } @@ -67,13 +94,8 @@ namespace NewHorizons.Handlers subtitleContainer.AddComponent(); } - public static void SetUp(IModBehaviour mod, TitleScreenConfig config) + public static void BuildConfig(IModBehaviour mod, TitleScreenConfig config) { - if (!config.disableNHPlanets) - { - DisplayBodiesOnTitleScreen(); - } - if (config.menuTextTint != null) { TitleScreenColourHandler.SetColour(config.menuTextTint.ToColor()); @@ -379,7 +401,7 @@ namespace NewHorizons.Handlers TitleScreenBuilders.SafeAdd(mod, new TitleScreenBuilder(mod, builder, disableNHPlanets, shareTitleScreen, conditionRequired, factRequired)); } - internal class TitleScreenBuilder + internal class TitleScreenBuilder : ITitleScreenBuilder { public IModBehaviour mod; public Action builder; @@ -397,6 +419,77 @@ namespace NewHorizons.Handlers this.conditionRequired = conditionRequired; this.factRequired = factRequired; } + + public void Build() + { + NHLogger.LogVerbose("Building handler: " + mod.ModHelper.Manifest.UniqueName); + try + { + builder.Invoke(SearchUtilities.Find("Scene")); + } + catch (Exception e) + { + NHLogger.LogError(e); + } + } + + public IModBehaviour Mod => mod; + + public bool DisableNHPlanets => disableNHPlanets; + + public bool CanShare => shareTitleScreen; + + public bool KnowsFact() => string.IsNullOrEmpty(factRequired) || StandaloneProfileManager.SharedInstance.currentProfile != null && ShipLogHandler.KnowsFact(factRequired); + + public bool HasCondition() => string.IsNullOrEmpty(conditionRequired) || StandaloneProfileManager.SharedInstance.currentProfile != null && PlayerData.GetPersistentCondition(conditionRequired); + } + + internal class TitleScreenConfigBuilder : ITitleScreenBuilder + { + public IModBehaviour mod; + public TitleScreenConfig config; + + public TitleScreenConfigBuilder(IModBehaviour mod, TitleScreenConfig config) + { + this.mod = mod; + this.config = config; + } + + public void Build() + { + NHLogger.LogVerbose("Building config: " + mod.ModHelper.Manifest.UniqueName); + try + { + BuildConfig(mod, config); + } + catch (Exception e) + { + NHLogger.LogError(e); + } + } + + public IModBehaviour Mod => mod; + + public bool DisableNHPlanets => config.disableNHPlanets; + + public bool CanShare => config.shareTitleScreen; + + public bool KnowsFact() => string.IsNullOrEmpty(config.factRequiredForTitle) || StandaloneProfileManager.SharedInstance.currentProfile != null && ShipLogHandler.KnowsFact(config.factRequiredForTitle); + + public bool HasCondition() => string.IsNullOrEmpty(config.conditionRequiredForTitle) || StandaloneProfileManager.SharedInstance.currentProfile != null && PlayerData.GetPersistentCondition(config.conditionRequiredForTitle); + } + + internal interface ITitleScreenBuilder + { + IModBehaviour Mod { get; } + + bool DisableNHPlanets { get; } + + bool CanShare { get; } + + void Build(); + bool KnowsFact(); + bool HasCondition(); } } } From 358ea7ce35f81fabf36ecf7e905ea7305bd4a6e3 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 15 Feb 2025 00:03:55 -0500 Subject: [PATCH 33/87] Remove testing logs --- NewHorizons/Handlers/TitleSceneHandler.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 6010835f..5efe6c6a 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -48,17 +48,11 @@ namespace NewHorizons.Handlers .Concat(TitleScreenBuilders.Select(kvp => (ITitleScreenBuilder)kvp.Value)) .Where(builder => builder.KnowsFact() && builder.HasCondition()).ToList(); - foreach (var builder in validBuilders) - { - NHLogger.LogVerbose("Valid builder: " + builder.Mod.ModHelper.Manifest.UniqueName); - } - var index = UnityEngine.Random.Range(0, validBuilders.Count()); var randomBuilder = validBuilders.ElementAtOrDefault(index); if (randomBuilder != null) { validBuilders.RemoveAt(index); - NHLogger.LogVerbose("Building main: " + randomBuilder.Mod.ModHelper.Manifest.UniqueName + " | " + (randomBuilder.CanShare ? "Share" : "Unshare") + " " + (randomBuilder.DisableNHPlanets ? "Disable" : "Enable")); if (!randomBuilder.DisableNHPlanets) { @@ -71,7 +65,6 @@ namespace NewHorizons.Handlers { foreach (var builder in validBuilders.Where(builder => builder.CanShare && builder.DisableNHPlanets == randomBuilder.DisableNHPlanets)) { - NHLogger.LogVerbose("Building extra: " + randomBuilder.Mod.ModHelper.Manifest.UniqueName); builder.Build(); } } From 2de2b0a4f7a8971495f3753801131ba96b0ee427 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 15 Feb 2025 00:04:32 -0500 Subject: [PATCH 34/87] curse vs --- NewHorizons/Handlers/TitleSceneHandler.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 5efe6c6a..3350f2b1 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -1,4 +1,3 @@ -using Epic.OnlineServices; using NewHorizons.Builder.Body; using NewHorizons.Builder.Props; using NewHorizons.Builder.StarSystem; From 8a50834c28227b400d7cf8ef5d27b7b7b3995de8 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 15 Feb 2025 00:14:00 -0500 Subject: [PATCH 35/87] make it a property --- NewHorizons/Handlers/TitleSceneHandler.cs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 3350f2b1..2ec93e82 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -20,6 +20,8 @@ namespace NewHorizons.Handlers public static class TitleSceneHandler { internal static Dictionary TitleScreenBuilders = new(); + internal static NewHorizonsBody[] eligibleBodies => Main.BodyDict.Values.ToList().SelectMany(x => x).ToList() + .Where(b => (b.Config.HeightMap != null || b.Config.Atmosphere?.clouds != null) && b.Config.Star == null && b.Config.canShowOnTitle).ToArray(); public static void Init() { @@ -183,19 +185,8 @@ namespace NewHorizons.Handlers { try { - TitleSceneHandler.DisplayBodyOnTitleScreen(Main.BodyDict.Values.ToList().SelectMany(x => x).ToList()); - } - catch (Exception e) - { - NHLogger.LogError($"Failed to make title screen bodies: {e}"); - } - } - - public static void DisplayBodyOnTitleScreen(List bodies) - { // Try loading one planet why not - // var eligible = BodyDict.Values.ToList().SelectMany(x => x).ToList().Where(b => (b.Config.HeightMap != null || b.Config.Atmosphere?.Cloud != null) && b.Config.Star == null).ToArray(); - var eligible = bodies.Where(b => (b.Config.HeightMap != null || b.Config.Atmosphere?.clouds != null) && b.Config.Star == null && b.Config.canShowOnTitle).ToArray(); + var eligible = eligibleBodies; var eligibleCount = eligible.Count(); if (eligibleCount == 0) return; @@ -258,6 +249,11 @@ namespace NewHorizons.Handlers planet.transform.localScale *= adjustedSize * (multiplePlanets ? 0.3f : 1f); } + } + catch (Exception e) + { + NHLogger.LogError($"Failed to make title screen bodies: {e}"); + } } private static (GameObject planet, float size) LoadTitleScreenBody(NewHorizonsBody body) From be6410c600ebce4b4c1e54e05efb15980cbf8bd5 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 15 Feb 2025 00:14:48 -0500 Subject: [PATCH 36/87] fix formatting --- NewHorizons/Handlers/TitleSceneHandler.cs | 112 +++++++++++----------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 2ec93e82..af80da3f 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -185,70 +185,70 @@ namespace NewHorizons.Handlers { try { - // Try loading one planet why not - var eligible = eligibleBodies; - var eligibleCount = eligible.Count(); - if (eligibleCount == 0) return; + // Try loading one planet why not + var eligible = eligibleBodies; + var eligibleCount = eligible.Count(); + if (eligibleCount == 0) return; - var selectionCount = Mathf.Min(eligibleCount, 3); - var indices = RandomUtility.GetUniqueRandomArray(0, eligible.Count(), selectionCount); + var selectionCount = Mathf.Min(eligibleCount, 3); + var indices = RandomUtility.GetUniqueRandomArray(0, eligible.Count(), selectionCount); - NHLogger.LogVerbose($"Displaying {selectionCount} bodies on the title screen"); + NHLogger.LogVerbose($"Displaying {selectionCount} bodies on the title screen"); - var planetSizes = new List<(GameObject planet, float size)>(); + var planetSizes = new List<(GameObject planet, float size)>(); - var bodyInfo = LoadTitleScreenBody(eligible[indices[0]]); - bodyInfo.planet.transform.localRotation = Quaternion.Euler(15, 0, 0); - planetSizes.Add(bodyInfo); + var bodyInfo = LoadTitleScreenBody(eligible[indices[0]]); + bodyInfo.planet.transform.localRotation = Quaternion.Euler(15, 0, 0); + planetSizes.Add(bodyInfo); - if (selectionCount > 1) - { - bodyInfo.planet.transform.localPosition = new Vector3(0, -15, 0); - bodyInfo.planet.transform.localRotation = Quaternion.Euler(10f, 0f, 0f); - - var bodyInfo2 = LoadTitleScreenBody(eligible[indices[1]]); - bodyInfo2.planet.transform.localPosition = new Vector3(7, 30, 0); - bodyInfo2.planet.transform.localRotation = Quaternion.Euler(10f, 0f, 0f); - planetSizes.Add(bodyInfo2); - } - - if (selectionCount > 2) - { - var bodyInfo3 = LoadTitleScreenBody(eligible[indices[2]]); - bodyInfo3.planet.transform.localPosition = new Vector3(-5, 10, 0); - bodyInfo3.planet.transform.localRotation = Quaternion.Euler(10f, 0f, 0f); - planetSizes.Add(bodyInfo3); - } - - SearchUtilities.Find("Scene/Background/PlanetPivot/PlanetRoot").SetActive(false); - - var lightGO = new GameObject("Light"); - lightGO.transform.parent = SearchUtilities.Find("Scene/Background").transform; - lightGO.transform.localPosition = new Vector3(-47.9203f, 145.7596f, 43.1802f); - lightGO.transform.localRotation = Quaternion.Euler(13.1412f, 122.8785f, 169.4302f); - var light = lightGO.AddComponent(); - light.type = LightType.Directional; - light.color = Color.white; - light.range = float.PositiveInfinity; - light.intensity = 0.8f; - - // Resize planets relative to each other - // If there are multiple planets shrink them down to 30% of the size - var maxSize = planetSizes.Select(x => x.size).Max(); - var minSize = planetSizes.Select(x => x.size).Min(); - var multiplePlanets = planetSizes.Count > 1; - foreach (var (planet, size) in planetSizes) - { - var adjustedSize = size / maxSize; - // If some planets would be too small we'll do a funny thing - if (minSize / maxSize < 0.3f) + if (selectionCount > 1) { - var t = Mathf.InverseLerp(minSize, maxSize, size); - adjustedSize = Mathf.Lerp(0.3f, 1f, t * t); + bodyInfo.planet.transform.localPosition = new Vector3(0, -15, 0); + bodyInfo.planet.transform.localRotation = Quaternion.Euler(10f, 0f, 0f); + + var bodyInfo2 = LoadTitleScreenBody(eligible[indices[1]]); + bodyInfo2.planet.transform.localPosition = new Vector3(7, 30, 0); + bodyInfo2.planet.transform.localRotation = Quaternion.Euler(10f, 0f, 0f); + planetSizes.Add(bodyInfo2); } - planet.transform.localScale *= adjustedSize * (multiplePlanets ? 0.3f : 1f); - } + if (selectionCount > 2) + { + var bodyInfo3 = LoadTitleScreenBody(eligible[indices[2]]); + bodyInfo3.planet.transform.localPosition = new Vector3(-5, 10, 0); + bodyInfo3.planet.transform.localRotation = Quaternion.Euler(10f, 0f, 0f); + planetSizes.Add(bodyInfo3); + } + + SearchUtilities.Find("Scene/Background/PlanetPivot/PlanetRoot").SetActive(false); + + var lightGO = new GameObject("Light"); + lightGO.transform.parent = SearchUtilities.Find("Scene/Background").transform; + lightGO.transform.localPosition = new Vector3(-47.9203f, 145.7596f, 43.1802f); + lightGO.transform.localRotation = Quaternion.Euler(13.1412f, 122.8785f, 169.4302f); + var light = lightGO.AddComponent(); + light.type = LightType.Directional; + light.color = Color.white; + light.range = float.PositiveInfinity; + light.intensity = 0.8f; + + // Resize planets relative to each other + // If there are multiple planets shrink them down to 30% of the size + var maxSize = planetSizes.Select(x => x.size).Max(); + var minSize = planetSizes.Select(x => x.size).Min(); + var multiplePlanets = planetSizes.Count > 1; + foreach (var (planet, size) in planetSizes) + { + var adjustedSize = size / maxSize; + // If some planets would be too small we'll do a funny thing + if (minSize / maxSize < 0.3f) + { + var t = Mathf.InverseLerp(minSize, maxSize, size); + adjustedSize = Mathf.Lerp(0.3f, 1f, t * t); + } + + planet.transform.localScale *= adjustedSize * (multiplePlanets ? 0.3f : 1f); + } } catch (Exception e) { From 840ae1c09f52938a0d8936e21a6a6506593a20e9 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 15 Feb 2025 00:22:03 -0500 Subject: [PATCH 37/87] check if there are any NH planets --- NewHorizons/Handlers/TitleSceneHandler.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index af80da3f..fc020399 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -22,6 +22,7 @@ namespace NewHorizons.Handlers internal static Dictionary TitleScreenBuilders = new(); internal static NewHorizonsBody[] eligibleBodies => Main.BodyDict.Values.ToList().SelectMany(x => x).ToList() .Where(b => (b.Config.HeightMap != null || b.Config.Atmosphere?.clouds != null) && b.Config.Star == null && b.Config.canShowOnTitle).ToArray(); + internal static int eligibleCount => eligibleBodies.Count(); public static void Init() { @@ -49,6 +50,8 @@ namespace NewHorizons.Handlers .Concat(TitleScreenBuilders.Select(kvp => (ITitleScreenBuilder)kvp.Value)) .Where(builder => builder.KnowsFact() && builder.HasCondition()).ToList(); + var hasNHPlanets = eligibleCount != 0; + var index = UnityEngine.Random.Range(0, validBuilders.Count()); var randomBuilder = validBuilders.ElementAtOrDefault(index); if (randomBuilder != null) @@ -64,7 +67,7 @@ namespace NewHorizons.Handlers if (randomBuilder.CanShare) { - foreach (var builder in validBuilders.Where(builder => builder.CanShare && builder.DisableNHPlanets == randomBuilder.DisableNHPlanets)) + foreach (var builder in validBuilders.Where(builder => builder.CanShare && (hasNHPlanets ? builder.DisableNHPlanets == randomBuilder.DisableNHPlanets : true))) { builder.Build(); } From 4c552db70389ec99ec02889ccca83345f0404afa Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 15 Feb 2025 01:00:46 -0500 Subject: [PATCH 38/87] make background module --- .../External/Configs/TitleScreenConfig.cs | 23 +++++++++++++++++-- NewHorizons/Handlers/TitleSceneHandler.cs | 23 +++++++++++++++++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/NewHorizons/External/Configs/TitleScreenConfig.cs b/NewHorizons/External/Configs/TitleScreenConfig.cs index ea56bc20..55c30c8e 100644 --- a/NewHorizons/External/Configs/TitleScreenConfig.cs +++ b/NewHorizons/External/Configs/TitleScreenConfig.cs @@ -50,15 +50,34 @@ namespace NewHorizons.External.Configs public string ambience; /// - /// Changes the speed the skybox rotates (and by extension the main menu planet). This is in degrees per second. + /// Edit properties of the background /// - public float rotationSpeed = 1; + public BackgroundModule Background; /// /// Edit properties of the main menu planet /// public MenuPlanetModule MenuPlanet; + [JsonObject] + public class BackgroundModule + { + /// + /// Changes the speed the background rotates (and by extension the main menu planet). This is in degrees per second. + /// + public float rotationSpeed = 1; + + /// + /// Disables the renderers of objects at the provided paths + /// + public string[] removeChildren; + + /// + /// A list of DetailInfos to populate the background with. + /// + public SimplifiedDetailInfo[] details; + } + [JsonObject] public class MenuPlanetModule { diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index fc020399..4d0fcf4f 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -127,7 +127,26 @@ namespace NewHorizons.Handlers Delay.FireOnNextUpdate(() => ambienceSource.AssignAudioLibraryClip(audioType)); } - SearchUtilities.Find("Scene/Background").GetComponent()._degreesPerSecond = config.rotationSpeed; + if (config.Background != null) + { + var background = SearchUtilities.Find("Scene/Background"); + + if (config.Background.removeChildren != null) + { + RemoveChildren(background, config.Background.removeChildren); + } + + if (config.Background.details != null) + { + foreach (var simplifiedDetail in config.Background.details) + { + DetailBuilder.Make(background, null, mod, new DetailInfo(simplifiedDetail)); + } + } + + var rotator = background.GetComponent(); + rotator._degreesPerSecond = config.Background.rotationSpeed; + } if (config.MenuPlanet != null) { @@ -152,7 +171,7 @@ namespace NewHorizons.Handlers if (config.MenuPlanet.destroyMenuPlanet) { - menuPlanet.SetActive(false); + SearchUtilities.Find("Scene/Background/PlanetPivot/PlanetRoot").SetActive(false); } } } From e38bff6ccaad20d790cce33c8a9715eac61d6509 Mon Sep 17 00:00:00 2001 From: Ben C Date: Sat, 15 Feb 2025 06:04:05 +0000 Subject: [PATCH 39/87] Updated Schemas --- NewHorizons/Schemas/title_screen_schema.json | 52 ++++++++++++++------ 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/NewHorizons/Schemas/title_screen_schema.json b/NewHorizons/Schemas/title_screen_schema.json index 2ea6af14..8226a496 100644 --- a/NewHorizons/Schemas/title_screen_schema.json +++ b/NewHorizons/Schemas/title_screen_schema.json @@ -36,10 +36,9 @@ "type": "string", "description": "The ambience audio that will play on the title screen. Can be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list." }, - "rotationSpeed": { - "type": "number", - "description": "Changes the speed the skybox rotates (and by extension the main menu planet). This is in degrees per second.", - "format": "float" + "Background": { + "description": "Edit properties of the background", + "$ref": "#/definitions/BackgroundModule" }, "MenuPlanet": { "description": "Edit properties of the main menu planet", @@ -131,13 +130,14 @@ } } }, - "MenuPlanetModule": { + "BackgroundModule": { "type": "object", "additionalProperties": false, "properties": { - "destroyMenuPlanet": { - "type": "boolean", - "description": "Disables the renderers of the main menu planet and all objects on it (this is to improve compatibility with other mods that don't use the NH title screen json)." + "rotationSpeed": { + "type": "number", + "description": "Changes the speed the background rotates (and by extension the main menu planet). This is in degrees per second.", + "format": "float" }, "removeChildren": { "type": "array", @@ -148,15 +148,10 @@ }, "details": { "type": "array", - "description": "A list of DetailInfos to populate the main menu planet with.", + "description": "A list of DetailInfos to populate the background with.", "items": { "$ref": "#/definitions/SimplifiedDetailInfo" } - }, - "rotationSpeed": { - "type": "number", - "description": "Changes the speed the main menu planet. This is in degrees per second.", - "format": "float" } } }, @@ -239,6 +234,35 @@ "format": "float" } } + }, + "MenuPlanetModule": { + "type": "object", + "additionalProperties": false, + "properties": { + "destroyMenuPlanet": { + "type": "boolean", + "description": "Disables the renderers of the main menu planet and all objects on it (this is to improve compatibility with other mods that don't use the NH title screen json)." + }, + "removeChildren": { + "type": "array", + "description": "Disables the renderers of objects at the provided paths", + "items": { + "type": "string" + } + }, + "details": { + "type": "array", + "description": "A list of DetailInfos to populate the main menu planet with.", + "items": { + "$ref": "#/definitions/SimplifiedDetailInfo" + } + }, + "rotationSpeed": { + "type": "number", + "description": "Changes the speed the main menu planet. This is in degrees per second.", + "format": "float" + } + } } }, "$docs": { From 02ecb2dd27c9a149edff88ed4d5af49a5eebaaca Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 15 Feb 2025 01:44:13 -0500 Subject: [PATCH 40/87] add a sector for eotp (because water) --- NewHorizons/Handlers/TitleSceneHandler.cs | 24 +++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 4d0fcf4f..db3ffd4e 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -26,6 +26,9 @@ namespace NewHorizons.Handlers public static void Init() { + var scene = SearchUtilities.Find("Scene"); + scene.AddComponent(); + var planetRoot = SearchUtilities.Find("Scene/Background/PlanetPivot/PlanetRoot"); var campfire = SearchUtilities.Find("Scene/Background/PlanetPivot/Prefab_HEA_Campfire"); campfire.transform.SetParent(planetRoot.transform, true); @@ -127,10 +130,12 @@ namespace NewHorizons.Handlers Delay.FireOnNextUpdate(() => ambienceSource.AssignAudioLibraryClip(audioType)); } + var background = SearchUtilities.Find("Scene/Background"); + var menuPlanet = SearchUtilities.Find("Scene/Background/PlanetPivot"); + var sector = background.GetComponentInParent(); + if (config.Background != null) { - var background = SearchUtilities.Find("Scene/Background"); - if (config.Background.removeChildren != null) { RemoveChildren(background, config.Background.removeChildren); @@ -140,7 +145,7 @@ namespace NewHorizons.Handlers { foreach (var simplifiedDetail in config.Background.details) { - DetailBuilder.Make(background, null, mod, new DetailInfo(simplifiedDetail)); + DetailBuilder.Make(background, sector, mod, new DetailInfo(simplifiedDetail)); } } @@ -150,8 +155,6 @@ namespace NewHorizons.Handlers if (config.MenuPlanet != null) { - var menuPlanet = SearchUtilities.Find("Scene/Background/PlanetPivot"); - if (config.MenuPlanet.removeChildren != null) { RemoveChildren(menuPlanet, config.MenuPlanet.removeChildren); @@ -161,7 +164,7 @@ namespace NewHorizons.Handlers { foreach (var simplifiedDetail in config.MenuPlanet.details) { - DetailBuilder.Make(menuPlanet, null, mod, new DetailInfo(simplifiedDetail)); + DetailBuilder.Make(menuPlanet, sector, mod, new DetailInfo(simplifiedDetail)); } } @@ -501,5 +504,14 @@ namespace NewHorizons.Handlers bool KnowsFact(); bool HasCondition(); } + + private class FakeSector : Sector + { + public override void Awake() + { + _occupantMask = DynamicOccupant.Player; + SectorManager.RegisterSector(this); + } + } } } From cdf977d652c4b5fc69c1fede89cb69829d0c04b5 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 15 Feb 2025 02:10:57 -0500 Subject: [PATCH 41/87] keepLoaded and sectorOccupantsUpdated --- .../External/Modules/Props/DetailInfo.cs | 1 + NewHorizons/Handlers/TitleSceneHandler.cs | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/NewHorizons/External/Modules/Props/DetailInfo.cs b/NewHorizons/External/Modules/Props/DetailInfo.cs index 4c4ca70c..6662586d 100644 --- a/NewHorizons/External/Modules/Props/DetailInfo.cs +++ b/NewHorizons/External/Modules/Props/DetailInfo.cs @@ -61,6 +61,7 @@ namespace NewHorizons.External.Modules.Props public DetailInfo(SimplifiedDetailInfo info) { + keepLoaded = true; JsonConvert.PopulateObject(JsonConvert.SerializeObject(info), this); } diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index db3ffd4e..29309224 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -27,7 +27,11 @@ namespace NewHorizons.Handlers public static void Init() { var scene = SearchUtilities.Find("Scene"); + var background = SearchUtilities.Find("Scene/Background"); + var planetPivot = SearchUtilities.Find("Scene/Background/PlanetPivot"); scene.AddComponent(); + background.AddComponent(); + planetPivot.AddComponent(); var planetRoot = SearchUtilities.Find("Scene/Background/PlanetPivot/PlanetRoot"); var campfire = SearchUtilities.Find("Scene/Background/PlanetPivot/Prefab_HEA_Campfire"); @@ -132,7 +136,6 @@ namespace NewHorizons.Handlers var background = SearchUtilities.Find("Scene/Background"); var menuPlanet = SearchUtilities.Find("Scene/Background/PlanetPivot"); - var sector = background.GetComponentInParent(); if (config.Background != null) { @@ -145,7 +148,7 @@ namespace NewHorizons.Handlers { foreach (var simplifiedDetail in config.Background.details) { - DetailBuilder.Make(background, sector, mod, new DetailInfo(simplifiedDetail)); + DetailBuilder.Make(background, background.GetComponentInParent(), mod, new DetailInfo(simplifiedDetail)); } } @@ -164,7 +167,7 @@ namespace NewHorizons.Handlers { foreach (var simplifiedDetail in config.MenuPlanet.details) { - DetailBuilder.Make(menuPlanet, sector, mod, new DetailInfo(simplifiedDetail)); + DetailBuilder.Make(menuPlanet, menuPlanet.GetComponentInParent(), mod, new DetailInfo(simplifiedDetail)); } } @@ -509,8 +512,16 @@ namespace NewHorizons.Handlers { public override void Awake() { + _subsectors = new List(); _occupantMask = DynamicOccupant.Player; SectorManager.RegisterSector(this); + _parentSector = GetComponentInParent(); + if (_parentSector != null && _parentSector != this) _parentSector.AddSubsector(this); + } + + public void Start() + { + OnSectorOccupantsUpdated.Invoke(); } } } From 4ca24054b640a985b3fe91f1f2ba829b0ab00130 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 15 Feb 2025 02:20:56 -0500 Subject: [PATCH 42/87] edit a little --- NewHorizons/Handlers/TitleSceneHandler.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 29309224..315617e1 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -515,8 +515,12 @@ namespace NewHorizons.Handlers _subsectors = new List(); _occupantMask = DynamicOccupant.Player; SectorManager.RegisterSector(this); - _parentSector = GetComponentInParent(); - if (_parentSector != null && _parentSector != this) _parentSector.AddSubsector(this); + var parentSector = GetComponentInParent(); + if (parentSector != null && parentSector != this) + { + _parentSector = parentSector; + _parentSector.AddSubsector(this); + } } public void Start() From e1c4335dc982b3f98cb4bbde6881791fc8562351 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 15 Feb 2025 02:21:45 -0500 Subject: [PATCH 43/87] triggerRoot --- NewHorizons/Handlers/TitleSceneHandler.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 315617e1..b08acaf7 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -512,6 +512,7 @@ namespace NewHorizons.Handlers { public override void Awake() { + _triggerRoot = gameObject; _subsectors = new List(); _occupantMask = DynamicOccupant.Player; SectorManager.RegisterSector(this); From d9b51fa5a84d829bfcc054712205caca758ea167 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 15 Feb 2025 02:23:53 -0500 Subject: [PATCH 44/87] direct add --- NewHorizons/Handlers/TitleSceneHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index b08acaf7..74b90941 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -520,7 +520,7 @@ namespace NewHorizons.Handlers if (parentSector != null && parentSector != this) { _parentSector = parentSector; - _parentSector.AddSubsector(this); + _parentSector._subsectors.SafeAdd(this); } } From c93689037b87f71cde6319d48bbc93bed0816ee3 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 15 Feb 2025 02:27:08 -0500 Subject: [PATCH 45/87] nevermind i have no idea what I'm doing lol --- NewHorizons/Handlers/TitleSceneHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 74b90941..a0575c47 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -515,13 +515,13 @@ namespace NewHorizons.Handlers _triggerRoot = gameObject; _subsectors = new List(); _occupantMask = DynamicOccupant.Player; - SectorManager.RegisterSector(this); var parentSector = GetComponentInParent(); if (parentSector != null && parentSector != this) { _parentSector = parentSector; - _parentSector._subsectors.SafeAdd(this); + _parentSector.AddSubsector(this); } + SectorManager.RegisterSector(this); } public void Start() From e4407995d594a2a85d40ab1118fa433480864ee1 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 15 Feb 2025 02:29:20 -0500 Subject: [PATCH 46/87] right that would make sense lol --- NewHorizons/Handlers/TitleSceneHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index a0575c47..caed9b2a 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -515,8 +515,8 @@ namespace NewHorizons.Handlers _triggerRoot = gameObject; _subsectors = new List(); _occupantMask = DynamicOccupant.Player; - var parentSector = GetComponentInParent(); - if (parentSector != null && parentSector != this) + var parentSector = GetComponentsInParent().FirstOrDefault(parentSector => parentSector != this); + if (parentSector != null) { _parentSector = parentSector; _parentSector.AddSubsector(this); From aa0939631d250011854d49e4c5417a57c4df37c1 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 15 Feb 2025 02:33:15 -0500 Subject: [PATCH 47/87] comment --- NewHorizons/Handlers/TitleSceneHandler.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index caed9b2a..85ce82b2 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -508,6 +508,9 @@ namespace NewHorizons.Handlers bool HasCondition(); } + /// + /// For water and etc (they require a sector or else they will get deleted by detail builder) + /// private class FakeSector : Sector { public override void Awake() From 5f47e3b2ec15e7de8ba9a9feecc492eafa7a8ff4 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 15 Feb 2025 02:53:23 -0500 Subject: [PATCH 48/87] more comments --- NewHorizons/Handlers/TitleSceneHandler.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 85ce82b2..9daf2645 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -29,10 +29,13 @@ namespace NewHorizons.Handlers var scene = SearchUtilities.Find("Scene"); var background = SearchUtilities.Find("Scene/Background"); var planetPivot = SearchUtilities.Find("Scene/Background/PlanetPivot"); + + // Add fake sectors for ocean water component support scene.AddComponent(); background.AddComponent(); planetPivot.AddComponent(); + // parent ambient light and campfire to the root (idk why they aren't parented in the first place mobius) var planetRoot = SearchUtilities.Find("Scene/Background/PlanetPivot/PlanetRoot"); var campfire = SearchUtilities.Find("Scene/Background/PlanetPivot/Prefab_HEA_Campfire"); campfire.transform.SetParent(planetRoot.transform, true); @@ -47,24 +50,27 @@ namespace NewHorizons.Handlers var profileManager = StandaloneProfileManager.SharedInstance; profileManager.PreInitialize(); profileManager.Initialize(); - if (profileManager.currentProfile != null) + if (profileManager.currentProfile != null) // check if there is even a profile made yet PlayerData.Init(profileManager.currentProfileGameSave, profileManager.currentProfileGameSettings, profileManager.currentProfileGraphicsSettings, profileManager.currentProfileInputJSON); + // Grab configs and handlers and merge them into one list var validBuilders = Main.TitleScreenConfigs.Select(kvp => (ITitleScreenBuilder)new TitleScreenConfigBuilder(kvp.Key, kvp.Value)) .Concat(TitleScreenBuilders.Select(kvp => (ITitleScreenBuilder)kvp.Value)) .Where(builder => builder.KnowsFact() && builder.HasCondition()).ToList(); var hasNHPlanets = eligibleCount != 0; + // Get random index for the main builder var index = UnityEngine.Random.Range(0, validBuilders.Count()); var randomBuilder = validBuilders.ElementAtOrDefault(index); if (randomBuilder != null) { validBuilders.RemoveAt(index); + // display nh planets if not disabled if (!randomBuilder.DisableNHPlanets) { DisplayBodiesOnTitleScreen(); @@ -72,14 +78,17 @@ namespace NewHorizons.Handlers randomBuilder.Build(); + // if it can share build extras if (randomBuilder.CanShare) { + // only build the ones that also can share and have the same value for disabling nh planet (if there is any nh planets) foreach (var builder in validBuilders.Where(builder => builder.CanShare && (hasNHPlanets ? builder.DisableNHPlanets == randomBuilder.DisableNHPlanets : true))) { builder.Build(); } } } + // default to displaying nh planets if no title screen builders else DisplayBodiesOnTitleScreen(); } @@ -172,7 +181,7 @@ namespace NewHorizons.Handlers } var rotator = menuPlanet.GetComponent(); - rotator._localAxis = Vector3.up; + rotator._localAxis = Vector3.up; // fix axis (because there is no reason for it to be negative when degrees were also negative) rotator._degreesPerSecond = config.MenuPlanet.rotationSpeed; if (config.MenuPlanet.destroyMenuPlanet) From c493db68834de5de985b7b227507564fcd6bf5d1 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 15 Feb 2025 03:20:35 -0500 Subject: [PATCH 49/87] Start on docs by making the page --- docs/src/content/docs/guides/title-screens.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 docs/src/content/docs/guides/title-screens.md diff --git a/docs/src/content/docs/guides/title-screens.md b/docs/src/content/docs/guides/title-screens.md new file mode 100644 index 00000000..8076f226 --- /dev/null +++ b/docs/src/content/docs/guides/title-screens.md @@ -0,0 +1,6 @@ +--- +title: Title Screens +description: A guide to creating a custom title screens in New Horizons +--- + +Welcome! This page outlines how to edit a custom title screen. \ No newline at end of file From cfaa0dc55adb6288decab0cd00e8581fc2223edc Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 15 Feb 2025 03:31:14 -0500 Subject: [PATCH 50/87] add an event --- NewHorizons/Handlers/TitleSceneHandler.cs | 9 +++++++++ NewHorizons/INewHorizons.cs | 5 +++++ NewHorizons/Main.cs | 1 + NewHorizons/NewHorizonsApi.cs | 1 + 4 files changed, 16 insertions(+) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 9daf2645..4be176c8 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -91,6 +91,15 @@ namespace NewHorizons.Handlers // default to displaying nh planets if no title screen builders else DisplayBodiesOnTitleScreen(); + + try + { + Main.Instance.OnTitleScreenLoaded?.Invoke(); + } + catch (Exception e) + { + NHLogger.LogError($"Error in event handler for OnTitleScreenLoaded: {e}"); + } } public static void InitSubtitles() diff --git a/NewHorizons/INewHorizons.cs b/NewHorizons/INewHorizons.cs index 5a1a9b09..82f7509c 100644 --- a/NewHorizons/INewHorizons.cs +++ b/NewHorizons/INewHorizons.cs @@ -73,6 +73,11 @@ namespace NewHorizons /// Gives the name of the planet that was just loaded. /// UnityEvent GetBodyLoadedEvent(); + + /// + /// An event invoked when NH has finished building the title screen. + /// + UnityEvent GetTitleScreenLoadedEvent(); #endregion #region Querying configs diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index d471f1d4..25e2303d 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -111,6 +111,7 @@ namespace NewHorizons public StarSystemEvent OnChangeStarSystem = new(); public StarSystemEvent OnStarSystemLoaded = new(); public StarSystemEvent OnPlanetLoaded = new(); + public UnityEvent OnTitleScreenLoaded = new(); /// /// Depending on platform, the AsyncOwnershipStatus might not be ready by the time we go to check it. diff --git a/NewHorizons/NewHorizonsApi.cs b/NewHorizons/NewHorizonsApi.cs index e2407347..ee3da69f 100644 --- a/NewHorizons/NewHorizonsApi.cs +++ b/NewHorizons/NewHorizonsApi.cs @@ -90,6 +90,7 @@ namespace NewHorizons public UnityEvent GetChangeStarSystemEvent() => Main.Instance.OnChangeStarSystem; public UnityEvent GetStarSystemLoadedEvent() => Main.Instance.OnStarSystemLoaded; public UnityEvent GetBodyLoadedEvent() => Main.Instance.OnPlanetLoaded; + public UnityEvent GetTitleScreenLoadedEvent() => Main.Instance.OnTitleScreenLoaded; public bool SetDefaultSystem(string name) { From 325180589f647d6bfc064f5d2752e6310d4eea9e Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 15 Feb 2025 22:54:55 -0500 Subject: [PATCH 51/87] change to string event --- NewHorizons/Handlers/TitleSceneHandler.cs | 27 +++++++++++++++-------- NewHorizons/INewHorizons.cs | 5 +++-- NewHorizons/Main.cs | 10 ++++----- NewHorizons/NewHorizonsApi.cs | 2 +- 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 4be176c8..65d3ba30 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -91,15 +91,6 @@ namespace NewHorizons.Handlers // default to displaying nh planets if no title screen builders else DisplayBodiesOnTitleScreen(); - - try - { - Main.Instance.OnTitleScreenLoaded?.Invoke(); - } - catch (Exception e) - { - NHLogger.LogError($"Error in event handler for OnTitleScreenLoaded: {e}"); - } } public static void InitSubtitles() @@ -465,6 +456,15 @@ namespace NewHorizons.Handlers { NHLogger.LogError(e); } + + try + { + Main.Instance.OnTitleScreenLoaded?.Invoke(mod.ModHelper.Manifest.UniqueName); + } + catch (Exception e) + { + NHLogger.LogError($"Error in event handler for OnTitleScreenLoaded on title screen {mod.ModHelper.Manifest.UniqueName}: {e}"); + } } public IModBehaviour Mod => mod; @@ -500,6 +500,15 @@ namespace NewHorizons.Handlers { NHLogger.LogError(e); } + + try + { + Main.Instance.OnTitleScreenLoaded?.Invoke(mod.ModHelper.Manifest.UniqueName); + } + catch (Exception e) + { + NHLogger.LogError($"Error in event handler for OnTitleScreenLoaded on title screen {mod.ModHelper.Manifest.UniqueName}: {e}"); + } } public IModBehaviour Mod => mod; diff --git a/NewHorizons/INewHorizons.cs b/NewHorizons/INewHorizons.cs index 82f7509c..5031fb0f 100644 --- a/NewHorizons/INewHorizons.cs +++ b/NewHorizons/INewHorizons.cs @@ -75,9 +75,10 @@ namespace NewHorizons UnityEvent GetBodyLoadedEvent(); /// - /// An event invoked when NH has finished building the title screen. + /// An event invoked when NH has finished building a title screen. + /// Gives the unique name of the mod the title screen builder was from. /// - UnityEvent GetTitleScreenLoadedEvent(); + UnityEvent GetTitleScreenLoadedEvent(); #endregion #region Querying configs diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 25e2303d..3f25eb1d 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -107,11 +107,11 @@ namespace NewHorizons public ShipWarpController ShipWarpController { get; private set; } // API events - public class StarSystemEvent : UnityEvent { } - public StarSystemEvent OnChangeStarSystem = new(); - public StarSystemEvent OnStarSystemLoaded = new(); - public StarSystemEvent OnPlanetLoaded = new(); - public UnityEvent OnTitleScreenLoaded = new(); + public class StringEvent : UnityEvent { } + public StringEvent OnChangeStarSystem = new(); + public StringEvent OnStarSystemLoaded = new(); + public StringEvent OnPlanetLoaded = new(); + public StringEvent OnTitleScreenLoaded = new(); /// /// Depending on platform, the AsyncOwnershipStatus might not be ready by the time we go to check it. diff --git a/NewHorizons/NewHorizonsApi.cs b/NewHorizons/NewHorizonsApi.cs index ee3da69f..5293c883 100644 --- a/NewHorizons/NewHorizonsApi.cs +++ b/NewHorizons/NewHorizonsApi.cs @@ -90,7 +90,7 @@ namespace NewHorizons public UnityEvent GetChangeStarSystemEvent() => Main.Instance.OnChangeStarSystem; public UnityEvent GetStarSystemLoadedEvent() => Main.Instance.OnStarSystemLoaded; public UnityEvent GetBodyLoadedEvent() => Main.Instance.OnPlanetLoaded; - public UnityEvent GetTitleScreenLoadedEvent() => Main.Instance.OnTitleScreenLoaded; + public UnityEvent GetTitleScreenLoadedEvent() => Main.Instance.OnTitleScreenLoaded; public bool SetDefaultSystem(string name) { From 98861c13d20e424d8860905a282566fad2eaef07 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Sat, 15 Feb 2025 22:57:49 -0500 Subject: [PATCH 52/87] readd the other event but named differently --- NewHorizons/Handlers/TitleSceneHandler.cs | 9 +++++++++ NewHorizons/INewHorizons.cs | 5 +++++ NewHorizons/Main.cs | 1 + NewHorizons/NewHorizonsApi.cs | 1 + 4 files changed, 16 insertions(+) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 65d3ba30..65031fb0 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -91,6 +91,15 @@ namespace NewHorizons.Handlers // default to displaying nh planets if no title screen builders else DisplayBodiesOnTitleScreen(); + + try + { + Main.Instance.OnAllTitleScreensLoaded?.Invoke(); + } + catch (Exception e) + { + NHLogger.LogError($"Error in event handler for OnAllTitleScreensLoaded: {e}"); + } } public static void InitSubtitles() diff --git a/NewHorizons/INewHorizons.cs b/NewHorizons/INewHorizons.cs index 5031fb0f..b696926f 100644 --- a/NewHorizons/INewHorizons.cs +++ b/NewHorizons/INewHorizons.cs @@ -79,6 +79,11 @@ namespace NewHorizons /// Gives the unique name of the mod the title screen builder was from. /// UnityEvent GetTitleScreenLoadedEvent(); + + /// + /// An event invoked when NH has finished building the title screen. + /// + UnityEvent GetAllTitleScreensLoadedEvent(); #endregion #region Querying configs diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 3f25eb1d..3d0e95e9 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -112,6 +112,7 @@ namespace NewHorizons public StringEvent OnStarSystemLoaded = new(); public StringEvent OnPlanetLoaded = new(); public StringEvent OnTitleScreenLoaded = new(); + public UnityEvent OnAllTitleScreensLoaded = new(); /// /// Depending on platform, the AsyncOwnershipStatus might not be ready by the time we go to check it. diff --git a/NewHorizons/NewHorizonsApi.cs b/NewHorizons/NewHorizonsApi.cs index 5293c883..2c3d495b 100644 --- a/NewHorizons/NewHorizonsApi.cs +++ b/NewHorizons/NewHorizonsApi.cs @@ -91,6 +91,7 @@ namespace NewHorizons public UnityEvent GetStarSystemLoadedEvent() => Main.Instance.OnStarSystemLoaded; public UnityEvent GetBodyLoadedEvent() => Main.Instance.OnPlanetLoaded; public UnityEvent GetTitleScreenLoadedEvent() => Main.Instance.OnTitleScreenLoaded; + public UnityEvent GetAllTitleScreensLoadedEvent() => Main.Instance.OnAllTitleScreensLoaded; public bool SetDefaultSystem(string name) { From 899e66e7ed6c497051e1a00084b84257c72c59e9 Mon Sep 17 00:00:00 2001 From: xen-42 Date: Sun, 16 Feb 2025 17:40:41 -0500 Subject: [PATCH 53/87] Comment what SimplifiedDetailInfo is and change title scene handler remove children to use findall --- NewHorizons/Builder/Body/ProxyBuilder.cs | 1 + NewHorizons/External/Modules/Props/DetailInfo.cs | 3 +++ NewHorizons/Handlers/TitleSceneHandler.cs | 7 +------ 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/NewHorizons/Builder/Body/ProxyBuilder.cs b/NewHorizons/Builder/Body/ProxyBuilder.cs index 3520008d..0b4cafc3 100644 --- a/NewHorizons/Builder/Body/ProxyBuilder.cs +++ b/NewHorizons/Builder/Body/ProxyBuilder.cs @@ -210,6 +210,7 @@ namespace NewHorizons.Builder.Body { foreach (var detailInfo in body.Config.Props.proxyDetails) { + // Thought about switching these to SimplifiedDetailInfo but we use AlignRadial with these so we can't DetailBuilder.Make(proxy, null, body.Mod, detailInfo); } } diff --git a/NewHorizons/External/Modules/Props/DetailInfo.cs b/NewHorizons/External/Modules/Props/DetailInfo.cs index 6662586d..f7399e2b 100644 --- a/NewHorizons/External/Modules/Props/DetailInfo.cs +++ b/NewHorizons/External/Modules/Props/DetailInfo.cs @@ -6,6 +6,9 @@ using System.ComponentModel; namespace NewHorizons.External.Modules.Props { + /// + /// A lesser form of DetailInfo used for the title screen since that supports fewer features + /// [JsonObject] public class SimplifiedDetailInfo : GeneralPropInfo { diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 65031fb0..66799f7d 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -202,15 +202,10 @@ namespace NewHorizons.Handlers private static void RemoveChildren(GameObject go, string[] paths) { - var goPath = go.transform.GetPath(); - var transforms = go.GetComponentsInChildren(true); foreach (var childPath in paths) { - // Multiple children can have the same path so we delete all that match - var path = $"{goPath}/{childPath}"; - var flag = true; - foreach (var childObj in transforms.Where(x => x.GetPath() == path)) + foreach (var childObj in go.transform.FindAll(childPath)) { flag = false; // idk why we wait here but we do From 8d1119c62e13f16d422c42072ff3c30938b5dd8a Mon Sep 17 00:00:00 2001 From: Ben C Date: Sun, 16 Feb 2025 22:41:59 +0000 Subject: [PATCH 54/87] Updated Schemas --- NewHorizons/Schemas/title_screen_schema.json | 1 + 1 file changed, 1 insertion(+) diff --git a/NewHorizons/Schemas/title_screen_schema.json b/NewHorizons/Schemas/title_screen_schema.json index 8226a496..e2f92847 100644 --- a/NewHorizons/Schemas/title_screen_schema.json +++ b/NewHorizons/Schemas/title_screen_schema.json @@ -157,6 +157,7 @@ }, "SimplifiedDetailInfo": { "type": "object", + "description": "A lesser form of DetailInfo used for the title screen since that supports fewer features", "additionalProperties": false, "properties": { "rotation": { From 657b19077442d5bdd31e7ab5aad0d5e771d8e872 Mon Sep 17 00:00:00 2001 From: xen-42 Date: Sun, 16 Feb 2025 17:42:16 -0500 Subject: [PATCH 55/87] brackets --- NewHorizons/Handlers/TitleSceneHandler.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 66799f7d..7ccd6cf7 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -90,7 +90,9 @@ namespace NewHorizons.Handlers } // default to displaying nh planets if no title screen builders else + { DisplayBodiesOnTitleScreen(); + } try { From 75b84cb94c222be0e7127de69db2efafa36f1dcf Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 01:03:17 -0500 Subject: [PATCH 56/87] update star system doc a little --- docs/src/content/docs/guides/star-systems.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/src/content/docs/guides/star-systems.md b/docs/src/content/docs/guides/star-systems.md index a7d8f671..8ca4e695 100644 --- a/docs/src/content/docs/guides/star-systems.md +++ b/docs/src/content/docs/guides/star-systems.md @@ -16,7 +16,12 @@ A star system config file will look something like this: ```json title="my_star_system.json" { "$schema": "https://raw.githubusercontent.com/Outer-Wilds-New-Horizons/new-horizons/main/NewHorizons/Schemas/star_system_schema.json", - "travelAudio": "assets/Travel.mp3", + "canEnterViaWarpDrive": true, + "startHere": false, + "respawnHere": true, + "GlobalMusic": { + "travelAudio": "planets/assets/Travel Audio.mp3" + }, "Vessel": { "coords": { "x": [4, 0, 3, 1], From 39cfce0f90c05cafe27ae02c783c7229d6c36eb6 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 01:03:42 -0500 Subject: [PATCH 57/87] flesh out the title screen doc more --- docs/src/content/docs/guides/title-screens.md | 63 ++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/docs/src/content/docs/guides/title-screens.md b/docs/src/content/docs/guides/title-screens.md index 8076f226..97b7fb46 100644 --- a/docs/src/content/docs/guides/title-screens.md +++ b/docs/src/content/docs/guides/title-screens.md @@ -3,4 +3,65 @@ title: Title Screens description: A guide to creating a custom title screens in New Horizons --- -Welcome! This page outlines how to edit a custom title screen. \ No newline at end of file +Welcome! This page outlines how to edit a custom title screen. + +## Getting Started + +Your mod's title screen config is a JSON file named `title-screen.json` that should be placed within your mod folder. + +A title screen config file will look something like this: + +```json title="title-screen.json" +{ + "$schema": "https://raw.githubusercontent.com/Outer-Wilds-New-Horizons/new-horizons/main/NewHorizons/Schemas/title_screen_schema.json", + "disableNHPlanets": true, + "factRequiredForTitle": "EXAMPLES_ARTIFICIAL_GRAVITY", + "shareTitleScreen": true, + "menuTextTint": { + "r": 128, + "g": 128, + "b": 255 + }, + "music": "planets/assets/TitleScreenMusic.mp3", + "ambience": "planets/assets/TitleScreenAmbience.mp3", + "Skybox": { + "destroyStarField": true, + "rightPath": "systems/New System Assets/Skybox/Right_Large.png", + "leftPath": "systems/New System Assets/Skybox/Left_Large.png", + "topPath": "systems/New System Assets/Skybox/Up_Large.png", + "bottomPath": "systems/New System Assets/Skybox/Down_Large.png", + "frontPath": "systems/New System Assets/Skybox/Front_Large.png", + "backPath": "systems/New System Assets/Skybox/Back_Large.png" + }, + "Background": { + "details": [ + { + "assetBundle": "assetbundles/test", + "path": "Assets/Prefabs/Background.prefab", + "position": {"x": 200, "y": 280, "z": -50}, + "rotation": {"x": 310, "y": 0, "z": 310}, + "scale": 0.05 + } + ], + "rotationSpeed": 10 + }, + "MenuPlanet": { + "destroyMenuPlanet": false, + "removeChildren": ["PlanetRoot/Props"], + "details": [ + { + "assetBundle": "assetbundles/test", + "path": "Assets/Prefabs/ArtificialGravity.prefab", + "removeChildren": ["Gravity"], + "parentPath": "PlanetRoot", + "position": {"x": 0, "y": 32, "z": 0}, + "rotation": {"x": 90, "y": 0, "z": 0}, + "scale": 10 + } + ], + "rotationSpeed": 20 + } +} +``` + +To see all the different things you can put into a config file check out the [Title Screen Schema](/schemas/title-screen-schema). \ No newline at end of file From 4ed239de1e161a126ef1760d48c4a1ff6ab2b2e1 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 01:22:11 -0500 Subject: [PATCH 58/87] build last --- NewHorizons/Handlers/TitleSceneHandler.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 7ccd6cf7..a7a9f61b 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -76,8 +76,6 @@ namespace NewHorizons.Handlers DisplayBodiesOnTitleScreen(); } - randomBuilder.Build(); - // if it can share build extras if (randomBuilder.CanShare) { @@ -87,6 +85,9 @@ namespace NewHorizons.Handlers builder.Build(); } } + + // Build main one last so it overrides the extras + randomBuilder.Build(); } // default to displaying nh planets if no title screen builders else From bbafbfbab2bd549349b59ae2d4f2a601bc9b3eb3 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 01:43:44 -0500 Subject: [PATCH 59/87] comment what the object is --- NewHorizons/INewHorizons.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/INewHorizons.cs b/NewHorizons/INewHorizons.cs index b696926f..f5a68ec4 100644 --- a/NewHorizons/INewHorizons.cs +++ b/NewHorizons/INewHorizons.cs @@ -249,7 +249,7 @@ namespace NewHorizons /// Call this once before the main menu finishes loading /// /// - /// Builder to run when this title screen is selected. + /// Builder to run when this title screen is selected. The GameObject passed through it is the main scene object containing both the background and menu planet. /// If set to true, NH generated planets will not show on the title screen. If false, this title screen has the same chance as other NH planet title screens to show. /// If set to true, this custom title screen will merge with all other custom title screens with shareTitleScreen set to true. If false, NH will randomly select between this and other valid title screens that are loaded. /// Persistent condition required for this title screen to appear. From e94fc11bb9854f5255299b60fce07ba43f63dadc Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 01:46:29 -0500 Subject: [PATCH 60/87] more docs --- docs/src/content/docs/guides/title-screens.md | 86 ++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) diff --git a/docs/src/content/docs/guides/title-screens.md b/docs/src/content/docs/guides/title-screens.md index 97b7fb46..8c415471 100644 --- a/docs/src/content/docs/guides/title-screens.md +++ b/docs/src/content/docs/guides/title-screens.md @@ -64,4 +64,88 @@ A title screen config file will look something like this: } ``` -To see all the different things you can put into a config file check out the [Title Screen Schema](/schemas/title-screen-schema). \ No newline at end of file +## Configs + +### `disableNHPlanets` + +If set to `true`, prevents NH-generated planets from appearing on the title screen. Defaults to true. + +### `shareTitleScreen` + +If set to `true`, this title screen will merge with others that have the same setting enabled. For more info head to the [sharing section](#sharing) of this page. Defaults to false. + +### `menuTextTint` + +Defines the color of the menu text and logo. Uses RGB values, where `r`, `g`, and `b` range from `0` to `255`. + +### `factRequiredForTitle` + +Specifies a ship log fact that must be discovered for this title screen to appear. + +### `conditionRequiredForTitle` + +Specifies a persistent condition required for this title screen to appear. + +### `music` and `ambience` + +The audio for background music and ambience. Can be a path to a .wav/.ogg/.mp3 file, or taken from the [AudioClip list](/reference/audio-enum). + +### `Background` and `MenuPlanet` + +A module for the background and main menu planet that include object additions, removal, and rotation speed. + +## Schema + +To see all the different things you can put into a config file check out the [Title Screen Schema](/schemas/title-screen-schema). + +## API + +New Horizons provides an API method to register and build custom title screens dynamically: + +```csharp title="INewHorizons.cs" +/// +/// Registers a builder for the main menu. +/// Call this once before the main menu finishes loading +/// +void RegisterTitleScreenBuilder(IModBehaviour mod, Action builder, bool disableNHPlanets = true, bool shareTitleScreen = false, string conditionRequired = null, string factRequired = null); +``` + +It shares a few values with the configs but also has an exclusive one. + +`builder`: Builder to run when this title screen is selected. The GameObject passed through it is the main scene object containing both the background and menu planet. + +### Example usage + +```csharp title="YourModBehaviour.cs" +NewHorizons = ModHelper.Interaction.TryGetModApi("xen.NewHorizons"); +NewHorizons.RegisterTitleScreenBuilder(this, BuildTitleScreen, disableNHPlanets: true, shareTitleScreen: true); +``` + +```csharp title="YourModBehaviour.cs" +public void BuildTitleScreen(GameObject scene) +{ + ModHelper.Console.WriteLine($"Building title screen", MessageType.Success); + //Add an object to the title screen or do whatever else you want +} +``` + +## Events + +Additionally, New Horizons provides events for tracking title screen loading: + +```csharp title="INewHorizons.cs" +/// +/// An event invoked when NH has finished building a title screen. +/// Gives the unique name of the mod the title screen builder was from. +/// +UnityEvent GetTitleScreenLoadedEvent(); + +/// +/// An event invoked when NH has finished building the title screen. +/// +UnityEvent GetAllTitleScreensLoadedEvent(); +``` + +## Sharing + +New Horizons will randomly select a valid title screen each time the user enters the main menu and then if `shareTitleScreen` is set to `true` it will build all the other shareable title screens (that also have matching `disableNHPlanets` values). If it doesn't have share set to true then it will only show the randomly selected. From 627599b71d44f4236b75fcd3087ba050259e12fc Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 01:49:32 -0500 Subject: [PATCH 61/87] example --- docs/src/content/docs/guides/title-screens.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/src/content/docs/guides/title-screens.md b/docs/src/content/docs/guides/title-screens.md index 8c415471..c0373246 100644 --- a/docs/src/content/docs/guides/title-screens.md +++ b/docs/src/content/docs/guides/title-screens.md @@ -146,6 +146,25 @@ UnityEvent GetTitleScreenLoadedEvent(); UnityEvent GetAllTitleScreensLoadedEvent(); ``` +### Example usage + +```csharp title="YourModBehaviour.cs" +NewHorizons = ModHelper.Interaction.TryGetModApi("xen.NewHorizons"); +NewHorizons.GetTitleScreenLoadedEvent().AddListener(OnTitleScreenLoaded); +NewHorizons.GetAllTitleScreensLoadedEvent().AddListener(OnAllTitleScreensLoaded); +``` + +```csharp title="YourModBehaviour.cs" +public void OnTitleScreenLoaded(string modUniqueName) +{ + ModHelper.Console.WriteLine($"Title screen loaded: " + modUniqueName, MessageType.Success); +} +public void OnAllTitleScreensLoaded() +{ + ModHelper.Console.WriteLine($"All title screens loaded", MessageType.Success); +} +``` + ## Sharing New Horizons will randomly select a valid title screen each time the user enters the main menu and then if `shareTitleScreen` is set to `true` it will build all the other shareable title screens (that also have matching `disableNHPlanets` values). If it doesn't have share set to true then it will only show the randomly selected. From c6d71c0e3f98892dc13841ea2a154b5efd523321 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 01:59:35 -0500 Subject: [PATCH 62/87] make --- docs/src/content/docs/guides/title-screens.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/content/docs/guides/title-screens.md b/docs/src/content/docs/guides/title-screens.md index c0373246..c2a72f36 100644 --- a/docs/src/content/docs/guides/title-screens.md +++ b/docs/src/content/docs/guides/title-screens.md @@ -3,7 +3,7 @@ title: Title Screens description: A guide to creating a custom title screens in New Horizons --- -Welcome! This page outlines how to edit a custom title screen. +Welcome! This page outlines how to make a custom title screen. ## Getting Started From d18d029efdb6e963035491393be733229d0dc19d Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 02:03:35 -0500 Subject: [PATCH 63/87] details --- docs/src/content/docs/guides/title-screens.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/src/content/docs/guides/title-screens.md b/docs/src/content/docs/guides/title-screens.md index c2a72f36..0deb2059 100644 --- a/docs/src/content/docs/guides/title-screens.md +++ b/docs/src/content/docs/guides/title-screens.md @@ -94,6 +94,10 @@ The audio for background music and ambience. Can be a path to a .wav/.ogg/.mp3 f A module for the background and main menu planet that include object additions, removal, and rotation speed. +#### `details` +You can add objects to both the background and menu planet. The menu planet objects spin while the background objects are stationary. +These simplified details are just like the details in planet configs except that they only have the basic features. + ## Schema To see all the different things you can put into a config file check out the [Title Screen Schema](/schemas/title-screen-schema). From 102d5b7256ca75aef3ff5f17190ec6da749e3a1b Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 02:05:23 -0500 Subject: [PATCH 64/87] smaller --- docs/src/content/docs/guides/title-screens.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/src/content/docs/guides/title-screens.md b/docs/src/content/docs/guides/title-screens.md index 0deb2059..f7b2f0f6 100644 --- a/docs/src/content/docs/guides/title-screens.md +++ b/docs/src/content/docs/guides/title-screens.md @@ -94,7 +94,8 @@ The audio for background music and ambience. Can be a path to a .wav/.ogg/.mp3 f A module for the background and main menu planet that include object additions, removal, and rotation speed. -#### `details` +##### `details` + You can add objects to both the background and menu planet. The menu planet objects spin while the background objects are stationary. These simplified details are just like the details in planet configs except that they only have the basic features. From 2c1570287c83fe90de47edd0e31f309af4fc1c4e Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 02:23:12 -0500 Subject: [PATCH 65/87] little comments --- NewHorizons/Handlers/TitleSceneHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index a7a9f61b..37a5706f 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -43,8 +43,8 @@ namespace NewHorizons.Handlers ambientLight.transform.SetParent(planetRoot.transform, true); InitSubtitles(); - TitleScreenColourHandler.ResetColour(); - AudioTypeHandler.Init(); + TitleScreenColourHandler.ResetColour(); // reset color at the start + AudioTypeHandler.Init(); // init audio for custom music // Load player data for fact and persistent condition checking var profileManager = StandaloneProfileManager.SharedInstance; From be3a9f77a5c52fd123415702d51a73a9a28ccb46 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 02:23:24 -0500 Subject: [PATCH 66/87] notice --- docs/src/content/docs/guides/title-screens.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/content/docs/guides/title-screens.md b/docs/src/content/docs/guides/title-screens.md index f7b2f0f6..7e8dda17 100644 --- a/docs/src/content/docs/guides/title-screens.md +++ b/docs/src/content/docs/guides/title-screens.md @@ -105,7 +105,7 @@ To see all the different things you can put into a config file check out the [Ti ## API -New Horizons provides an API method to register and build custom title screens dynamically: +New Horizons provides an API method to register and build custom title screens dynamically. Keep in mind you can only choose configs or api not both. ```csharp title="INewHorizons.cs" /// From 2774f6a68bfd91acb63537b4d12c7cdea72ff69c Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 02:23:52 -0500 Subject: [PATCH 67/87] a little more detailed --- docs/src/content/docs/guides/title-screens.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/content/docs/guides/title-screens.md b/docs/src/content/docs/guides/title-screens.md index 7e8dda17..332b2f76 100644 --- a/docs/src/content/docs/guides/title-screens.md +++ b/docs/src/content/docs/guides/title-screens.md @@ -105,7 +105,7 @@ To see all the different things you can put into a config file check out the [Ti ## API -New Horizons provides an API method to register and build custom title screens dynamically. Keep in mind you can only choose configs or api not both. +New Horizons provides an API method to register and build custom title screens dynamically. Keep in mind you can only choose config or api not both as they don't merge. ```csharp title="INewHorizons.cs" /// From 109a030ab440d49f7c3e4c68d8d1c99a05b5f49e Mon Sep 17 00:00:00 2001 From: xen-42 Date: Mon, 17 Feb 2025 12:33:23 -0500 Subject: [PATCH 68/87] Rename to persistentConditionRequiredForTitle to be more clear --- NewHorizons/External/Configs/TitleScreenConfig.cs | 2 +- NewHorizons/Handlers/TitleSceneHandler.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NewHorizons/External/Configs/TitleScreenConfig.cs b/NewHorizons/External/Configs/TitleScreenConfig.cs index 55c30c8e..5451c003 100644 --- a/NewHorizons/External/Configs/TitleScreenConfig.cs +++ b/NewHorizons/External/Configs/TitleScreenConfig.cs @@ -22,7 +22,7 @@ namespace NewHorizons.External.Configs /// /// Persistent condition required for this title screen to appear. /// - public string conditionRequiredForTitle; + public string persistentConditionRequiredForTitle; /// /// If set to true, NH generated planets will not show on the title screen. If false, this title screen has the same chance as other NH planet title screens to show. diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 37a5706f..ce9c33eb 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -526,7 +526,7 @@ namespace NewHorizons.Handlers public bool KnowsFact() => string.IsNullOrEmpty(config.factRequiredForTitle) || StandaloneProfileManager.SharedInstance.currentProfile != null && ShipLogHandler.KnowsFact(config.factRequiredForTitle); - public bool HasCondition() => string.IsNullOrEmpty(config.conditionRequiredForTitle) || StandaloneProfileManager.SharedInstance.currentProfile != null && PlayerData.GetPersistentCondition(config.conditionRequiredForTitle); + public bool HasCondition() => string.IsNullOrEmpty(config.persistentConditionRequiredForTitle) || StandaloneProfileManager.SharedInstance.currentProfile != null && PlayerData.GetPersistentCondition(config.persistentConditionRequiredForTitle); } internal interface ITitleScreenBuilder From 73831f8ed69d6abec20045e8a962b2256ed6575d Mon Sep 17 00:00:00 2001 From: Ben C Date: Mon, 17 Feb 2025 17:35:38 +0000 Subject: [PATCH 69/87] Updated Schemas --- NewHorizons/Schemas/title_screen_schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/Schemas/title_screen_schema.json b/NewHorizons/Schemas/title_screen_schema.json index e2f92847..e6d16e6e 100644 --- a/NewHorizons/Schemas/title_screen_schema.json +++ b/NewHorizons/Schemas/title_screen_schema.json @@ -12,7 +12,7 @@ "type": "string", "description": "Ship log fact required for this title screen to appear." }, - "conditionRequiredForTitle": { + "persistentConditionRequiredForTitle": { "type": "string", "description": "Persistent condition required for this title screen to appear." }, From 43be182cb13b4e69e9b267cd7d30f1cb5f786fe0 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 14:14:04 -0500 Subject: [PATCH 70/87] rename here as well --- NewHorizons/Handlers/TitleSceneHandler.cs | 12 ++++++------ NewHorizons/INewHorizons.cs | 4 ++-- NewHorizons/NewHorizonsApi.cs | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index ce9c33eb..0be7fe62 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -428,9 +428,9 @@ namespace NewHorizons.Handlers return meshRenderer; } - public static void RegisterBuilder(IModBehaviour mod, Action builder, bool disableNHPlanets, bool shareTitleScreen, string conditionRequired, string factRequired) + public static void RegisterBuilder(IModBehaviour mod, Action builder, bool disableNHPlanets, bool shareTitleScreen, string persistentConditionRequired, string factRequired) { - TitleScreenBuilders.SafeAdd(mod, new TitleScreenBuilder(mod, builder, disableNHPlanets, shareTitleScreen, conditionRequired, factRequired)); + TitleScreenBuilders.SafeAdd(mod, new TitleScreenBuilder(mod, builder, disableNHPlanets, shareTitleScreen, persistentConditionRequired, factRequired)); } internal class TitleScreenBuilder : ITitleScreenBuilder @@ -439,16 +439,16 @@ namespace NewHorizons.Handlers public Action builder; public bool disableNHPlanets; public bool shareTitleScreen; - public string conditionRequired; + public string persistentConditionRequired; public string factRequired; - public TitleScreenBuilder(IModBehaviour mod, Action builder, bool disableNHPlanets, bool shareTitleScreen, string conditionRequired, string factRequired) + public TitleScreenBuilder(IModBehaviour mod, Action builder, bool disableNHPlanets, bool shareTitleScreen, string persistentConditionRequired, string factRequired) { this.mod = mod; this.builder = builder; this.disableNHPlanets = disableNHPlanets; this.shareTitleScreen = shareTitleScreen; - this.conditionRequired = conditionRequired; + this.persistentConditionRequired = persistentConditionRequired; this.factRequired = factRequired; } @@ -482,7 +482,7 @@ namespace NewHorizons.Handlers public bool KnowsFact() => string.IsNullOrEmpty(factRequired) || StandaloneProfileManager.SharedInstance.currentProfile != null && ShipLogHandler.KnowsFact(factRequired); - public bool HasCondition() => string.IsNullOrEmpty(conditionRequired) || StandaloneProfileManager.SharedInstance.currentProfile != null && PlayerData.GetPersistentCondition(conditionRequired); + public bool HasCondition() => string.IsNullOrEmpty(persistentConditionRequired) || StandaloneProfileManager.SharedInstance.currentProfile != null && PlayerData.GetPersistentCondition(persistentConditionRequired); } internal class TitleScreenConfigBuilder : ITitleScreenBuilder diff --git a/NewHorizons/INewHorizons.cs b/NewHorizons/INewHorizons.cs index f5a68ec4..9d85239c 100644 --- a/NewHorizons/INewHorizons.cs +++ b/NewHorizons/INewHorizons.cs @@ -252,8 +252,8 @@ namespace NewHorizons /// Builder to run when this title screen is selected. The GameObject passed through it is the main scene object containing both the background and menu planet. /// If set to true, NH generated planets will not show on the title screen. If false, this title screen has the same chance as other NH planet title screens to show. /// If set to true, this custom title screen will merge with all other custom title screens with shareTitleScreen set to true. If false, NH will randomly select between this and other valid title screens that are loaded. - /// Persistent condition required for this title screen to appear. + /// Persistent condition required for this title screen to appear. /// Ship log fact required for this title screen to appear. - void RegisterTitleScreenBuilder(IModBehaviour mod, Action builder, bool disableNHPlanets = true, bool shareTitleScreen = false, string conditionRequired = null, string factRequired = null); + void RegisterTitleScreenBuilder(IModBehaviour mod, Action builder, bool disableNHPlanets = true, bool shareTitleScreen = false, string persistentConditionRequired = null, string factRequired = null); } } diff --git a/NewHorizons/NewHorizonsApi.cs b/NewHorizons/NewHorizonsApi.cs index 2c3d495b..80a318d1 100644 --- a/NewHorizons/NewHorizonsApi.cs +++ b/NewHorizons/NewHorizonsApi.cs @@ -365,7 +365,7 @@ namespace NewHorizons public void SetNextSpawnID(string id) => PlayerSpawnHandler.TargetSpawnID = id; - public void RegisterTitleScreenBuilder(IModBehaviour mod, Action builder, bool disableNHPlanets = true, bool shareTitleScreen = false, string conditionRequired = null, string factRequired = null) - => TitleSceneHandler.RegisterBuilder(mod, builder, disableNHPlanets, shareTitleScreen, conditionRequired, factRequired); + public void RegisterTitleScreenBuilder(IModBehaviour mod, Action builder, bool disableNHPlanets = true, bool shareTitleScreen = false, string persistentConditionRequired = null, string factRequired = null) + => TitleSceneHandler.RegisterBuilder(mod, builder, disableNHPlanets, shareTitleScreen, persistentConditionRequired, factRequired); } } From fadbfafb404d3b71cca7a6231cffff0a9147919d Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 14:15:08 -0500 Subject: [PATCH 71/87] start on rework --- NewHorizons/Handlers/TitleSceneHandler.cs | 44 +++++++++++++++++++---- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 0be7fe62..e140e962 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -19,7 +19,7 @@ namespace NewHorizons.Handlers { public static class TitleSceneHandler { - internal static Dictionary TitleScreenBuilders = new(); + internal static Dictionary TitleScreenBuilders = new(); internal static NewHorizonsBody[] eligibleBodies => Main.BodyDict.Values.ToList().SelectMany(x => x).ToList() .Where(b => (b.Config.HeightMap != null || b.Config.Atmosphere?.clouds != null) && b.Config.Star == null && b.Config.canShowOnTitle).ToArray(); internal static int eligibleCount => eligibleBodies.Count(); @@ -57,9 +57,9 @@ namespace NewHorizons.Handlers profileManager.currentProfileInputJSON); // Grab configs and handlers and merge them into one list - var validBuilders = Main.TitleScreenConfigs.Select(kvp => (ITitleScreenBuilder)new TitleScreenConfigBuilder(kvp.Key, kvp.Value)) - .Concat(TitleScreenBuilders.Select(kvp => (ITitleScreenBuilder)kvp.Value)) - .Where(builder => builder.KnowsFact() && builder.HasCondition()).ToList(); + var validBuilders = TitleScreenBuilders.Values + .Where(list => list.IsValid) + .Select(list => list.GetRelevantBuilder()).ToList(); var hasNHPlanets = eligibleCount != 0; @@ -428,9 +428,41 @@ namespace NewHorizons.Handlers return meshRenderer; } - public static void RegisterBuilder(IModBehaviour mod, Action builder, bool disableNHPlanets, bool shareTitleScreen, string persistentConditionRequired, string factRequired) + internal static void RegisterBuilder(IModBehaviour mod, ITitleScreenBuilder builder) { - TitleScreenBuilders.SafeAdd(mod, new TitleScreenBuilder(mod, builder, disableNHPlanets, shareTitleScreen, persistentConditionRequired, factRequired)); + if (!TitleScreenBuilders.ContainsKey(mod)) + TitleScreenBuilders.Add(mod, new TitleScreenBuilderList()); + + TitleScreenBuilders[mod].Add(builder); + } + + public static void RegisterBuilder(IModBehaviour mod, TitleScreenConfig config) + => RegisterBuilder(mod, + new TitleScreenConfigBuilder(mod, config)); + + public static void RegisterBuilder(IModBehaviour mod, Action builder, bool disableNHPlanets, bool shareTitleScreen, string persistentConditionRequired, string factRequired) + => RegisterBuilder(mod, + new TitleScreenBuilder(mod, builder, + disableNHPlanets, shareTitleScreen, + persistentConditionRequired, factRequired)); + + internal class TitleScreenBuilderList + { + public List list = new List(); + + public void Add(ITitleScreenBuilder builder) + { + list.Add(builder); + } + + public bool IsValid => GetRelevantBuilder() != null; + + public ITitleScreenBuilder GetRelevantBuilder() + { + if (list.Count <= 1) return list.FirstOrDefault(); + + return list.LastOrDefault(builder => builder.KnowsFact() && builder.HasCondition()); + } } internal class TitleScreenBuilder : ITitleScreenBuilder From 2869544b92ef57c6f700dfadec6f20f9ac17cadd Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 14:16:13 -0500 Subject: [PATCH 72/87] actually i guess I don't need this lol --- NewHorizons/Handlers/TitleSceneHandler.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index e140e962..2a21e6ea 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -459,8 +459,6 @@ namespace NewHorizons.Handlers public ITitleScreenBuilder GetRelevantBuilder() { - if (list.Count <= 1) return list.FirstOrDefault(); - return list.LastOrDefault(builder => builder.KnowsFact() && builder.HasCondition()); } } From d9441f5140d5c3a0b1a78b8b2d5d10c75a5d364f Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 14:20:22 -0500 Subject: [PATCH 73/87] index --- NewHorizons/Handlers/TitleSceneHandler.cs | 25 +++++++++++++++-------- NewHorizons/INewHorizons.cs | 4 ++-- NewHorizons/Main.cs | 3 ++- NewHorizons/NewHorizonsApi.cs | 2 +- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 2a21e6ea..e3fe01a7 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -453,6 +453,7 @@ namespace NewHorizons.Handlers public void Add(ITitleScreenBuilder builder) { list.Add(builder); + builder.Index = list.IndexOf(builder); } public bool IsValid => GetRelevantBuilder() != null; @@ -484,23 +485,23 @@ namespace NewHorizons.Handlers public void Build() { - NHLogger.LogVerbose("Building handler: " + mod.ModHelper.Manifest.UniqueName); + NHLogger.LogVerbose($"Building handler {mod.ModHelper.Manifest.UniqueName} #{index}"); try { builder.Invoke(SearchUtilities.Find("Scene")); } catch (Exception e) { - NHLogger.LogError(e); + NHLogger.LogError($"Error while building title screen handler {mod.ModHelper.Manifest.UniqueName} #{index}: {e}"); } try { - Main.Instance.OnTitleScreenLoaded?.Invoke(mod.ModHelper.Manifest.UniqueName); + Main.Instance.OnTitleScreenLoaded?.Invoke(mod.ModHelper.Manifest.UniqueName, index); } catch (Exception e) { - NHLogger.LogError($"Error in event handler for OnTitleScreenLoaded on title screen {mod.ModHelper.Manifest.UniqueName}: {e}"); + NHLogger.LogError($"Error in event handler for OnTitleScreenLoaded on title screen {mod.ModHelper.Manifest.UniqueName} #{index}: {e}"); } } @@ -513,6 +514,9 @@ namespace NewHorizons.Handlers public bool KnowsFact() => string.IsNullOrEmpty(factRequired) || StandaloneProfileManager.SharedInstance.currentProfile != null && ShipLogHandler.KnowsFact(factRequired); public bool HasCondition() => string.IsNullOrEmpty(persistentConditionRequired) || StandaloneProfileManager.SharedInstance.currentProfile != null && PlayerData.GetPersistentCondition(persistentConditionRequired); + + private int index = -1; + public int Index { get => index; set => index = value; } } internal class TitleScreenConfigBuilder : ITitleScreenBuilder @@ -528,23 +532,23 @@ namespace NewHorizons.Handlers public void Build() { - NHLogger.LogVerbose("Building config: " + mod.ModHelper.Manifest.UniqueName); + NHLogger.LogVerbose($"Building config {mod.ModHelper.Manifest.UniqueName} #{index}"); try { BuildConfig(mod, config); } catch (Exception e) { - NHLogger.LogError(e); + NHLogger.LogError($"Error while building title screen config {mod.ModHelper.Manifest.UniqueName} #{index}: {e}"); } try { - Main.Instance.OnTitleScreenLoaded?.Invoke(mod.ModHelper.Manifest.UniqueName); + Main.Instance.OnTitleScreenLoaded?.Invoke(mod.ModHelper.Manifest.UniqueName, index); } catch (Exception e) { - NHLogger.LogError($"Error in event handler for OnTitleScreenLoaded on title screen {mod.ModHelper.Manifest.UniqueName}: {e}"); + NHLogger.LogError($"Error in event handler for OnTitleScreenLoaded on title screen {mod.ModHelper.Manifest.UniqueName} #{index}: {e}"); } } @@ -557,6 +561,9 @@ namespace NewHorizons.Handlers public bool KnowsFact() => string.IsNullOrEmpty(config.factRequiredForTitle) || StandaloneProfileManager.SharedInstance.currentProfile != null && ShipLogHandler.KnowsFact(config.factRequiredForTitle); public bool HasCondition() => string.IsNullOrEmpty(config.persistentConditionRequiredForTitle) || StandaloneProfileManager.SharedInstance.currentProfile != null && PlayerData.GetPersistentCondition(config.persistentConditionRequiredForTitle); + + private int index = -1; + public int Index { get => index; set => index = value; } } internal interface ITitleScreenBuilder @@ -570,6 +577,8 @@ namespace NewHorizons.Handlers void Build(); bool KnowsFact(); bool HasCondition(); + + int Index { get; set; } } /// diff --git a/NewHorizons/INewHorizons.cs b/NewHorizons/INewHorizons.cs index 9d85239c..07512ad6 100644 --- a/NewHorizons/INewHorizons.cs +++ b/NewHorizons/INewHorizons.cs @@ -76,9 +76,9 @@ namespace NewHorizons /// /// An event invoked when NH has finished building a title screen. - /// Gives the unique name of the mod the title screen builder was from. + /// Gives the unique name of the mod the title screen builder was from and the index for when you have multiple title screens. /// - UnityEvent GetTitleScreenLoadedEvent(); + UnityEvent GetTitleScreenLoadedEvent(); /// /// An event invoked when NH has finished building the title screen. diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 3fc6b689..8569da89 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -112,7 +112,8 @@ namespace NewHorizons public StringEvent OnChangeStarSystem = new(); public StringEvent OnStarSystemLoaded = new(); public StringEvent OnPlanetLoaded = new(); - public StringEvent OnTitleScreenLoaded = new(); + public class StringIndexEvent : UnityEvent { } + public StringIndexEvent OnTitleScreenLoaded = new(); public UnityEvent OnAllTitleScreensLoaded = new(); /// diff --git a/NewHorizons/NewHorizonsApi.cs b/NewHorizons/NewHorizonsApi.cs index 80a318d1..14a4fdcf 100644 --- a/NewHorizons/NewHorizonsApi.cs +++ b/NewHorizons/NewHorizonsApi.cs @@ -90,7 +90,7 @@ namespace NewHorizons public UnityEvent GetChangeStarSystemEvent() => Main.Instance.OnChangeStarSystem; public UnityEvent GetStarSystemLoadedEvent() => Main.Instance.OnStarSystemLoaded; public UnityEvent GetBodyLoadedEvent() => Main.Instance.OnPlanetLoaded; - public UnityEvent GetTitleScreenLoadedEvent() => Main.Instance.OnTitleScreenLoaded; + public UnityEvent GetTitleScreenLoadedEvent() => Main.Instance.OnTitleScreenLoaded; public UnityEvent GetAllTitleScreensLoadedEvent() => Main.Instance.OnAllTitleScreensLoaded; public bool SetDefaultSystem(string name) From d827d6956d93c7afee0eeace382d821bb57b2931 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 15:28:09 -0500 Subject: [PATCH 74/87] Change config to a list of infos --- NewHorizons/External/Configs/TitleScreenConfig.cs | 9 +++++++++ NewHorizons/Handlers/TitleSceneHandler.cs | 8 ++++---- NewHorizons/Main.cs | 4 ++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/NewHorizons/External/Configs/TitleScreenConfig.cs b/NewHorizons/External/Configs/TitleScreenConfig.cs index 5451c003..575b29c6 100644 --- a/NewHorizons/External/Configs/TitleScreenConfig.cs +++ b/NewHorizons/External/Configs/TitleScreenConfig.cs @@ -8,6 +8,15 @@ namespace NewHorizons.External.Configs { [JsonObject] public class TitleScreenConfig + { + /// + /// Create title screens + /// + public TitleScreenInfo[] titleScreens; + } + + [JsonObject] + public class TitleScreenInfo { /// /// Colour of the text on the main menu diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index e3fe01a7..ca8492c7 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -119,7 +119,7 @@ namespace NewHorizons.Handlers subtitleContainer.AddComponent(); } - public static void BuildConfig(IModBehaviour mod, TitleScreenConfig config) + public static void BuildConfig(IModBehaviour mod, TitleScreenInfo config) { if (config.menuTextTint != null) { @@ -436,7 +436,7 @@ namespace NewHorizons.Handlers TitleScreenBuilders[mod].Add(builder); } - public static void RegisterBuilder(IModBehaviour mod, TitleScreenConfig config) + public static void RegisterBuilder(IModBehaviour mod, TitleScreenInfo config) => RegisterBuilder(mod, new TitleScreenConfigBuilder(mod, config)); @@ -522,9 +522,9 @@ namespace NewHorizons.Handlers internal class TitleScreenConfigBuilder : ITitleScreenBuilder { public IModBehaviour mod; - public TitleScreenConfig config; + public TitleScreenInfo config; - public TitleScreenConfigBuilder(IModBehaviour mod, TitleScreenConfig config) + public TitleScreenConfigBuilder(IModBehaviour mod, TitleScreenInfo config) { this.mod = mod; this.config = config; diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 8569da89..c6bf6cd9 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -860,6 +860,10 @@ namespace NewHorizons } TitleScreenConfigs[mod] = titleScreenConfig; + foreach (var info in titleScreenConfig.titleScreens) + { + TitleSceneHandler.RegisterBuilder(mod, info); + } } private void LoadTranslations(string folder, IModBehaviour mod) From a6c0fa562a25c1ca645fd09e20b1fffd312a94bc Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 15:31:44 -0500 Subject: [PATCH 75/87] Reset configs --- NewHorizons/Handlers/TitleSceneHandler.cs | 8 ++++++++ NewHorizons/Main.cs | 3 +++ 2 files changed, 11 insertions(+) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index ca8492c7..d5a9cd50 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -446,6 +446,14 @@ namespace NewHorizons.Handlers disableNHPlanets, shareTitleScreen, persistentConditionRequired, factRequired)); + internal static void ResetConfigs() + { + foreach (var builderList in TitleSceneHandler.TitleScreenBuilders.Values) + { + builderList.list.RemoveAll(builder => builder is TitleScreenConfigBuilder); + } + } + internal class TitleScreenBuilderList { public List list = new List(); diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index c6bf6cd9..54d57707 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -175,6 +175,9 @@ namespace NewHorizons { BodyDict.Clear(); SystemDict.Clear(); + TitleScreenConfigs.Clear(); + + TitleSceneHandler.ResetConfigs(); BodyDict["SolarSystem"] = new List(); BodyDict["EyeOfTheUniverse"] = new List(); // Keep this empty tho fr From 6735c21cc9cf371814f677e3e2431c8facb14011 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 15:43:23 -0500 Subject: [PATCH 76/87] fix this default --- .../External/Modules/Props/EchoesOfTheEye/DreamCandleInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/External/Modules/Props/EchoesOfTheEye/DreamCandleInfo.cs b/NewHorizons/External/Modules/Props/EchoesOfTheEye/DreamCandleInfo.cs index 10106fb8..7f4efb24 100644 --- a/NewHorizons/External/Modules/Props/EchoesOfTheEye/DreamCandleInfo.cs +++ b/NewHorizons/External/Modules/Props/EchoesOfTheEye/DreamCandleInfo.cs @@ -14,7 +14,7 @@ namespace NewHorizons.External.Modules.Props.EchoesOfTheEye /// /// The type of dream candle this is. /// - [DefaultValue(DreamCandleType.Ground)] public DreamCandleType type = DreamCandleType.Ground; + [DefaultValue("ground")] public DreamCandleType type = DreamCandleType.Ground; /// /// Whether the candle should start lit or extinguished. From c6137ff96c893f699a2b8fe1e1691d43c4e4055c Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 15:44:21 -0500 Subject: [PATCH 77/87] make it an empty array as default --- NewHorizons/External/Configs/TitleScreenConfig.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/External/Configs/TitleScreenConfig.cs b/NewHorizons/External/Configs/TitleScreenConfig.cs index 575b29c6..e5a73046 100644 --- a/NewHorizons/External/Configs/TitleScreenConfig.cs +++ b/NewHorizons/External/Configs/TitleScreenConfig.cs @@ -12,7 +12,7 @@ namespace NewHorizons.External.Configs /// /// Create title screens /// - public TitleScreenInfo[] titleScreens; + public TitleScreenInfo[] titleScreens = new TitleScreenInfo[0]; } [JsonObject] From 18fc7f1dde30e97621cd53ccba42185fca821f37 Mon Sep 17 00:00:00 2001 From: Ben C Date: Mon, 17 Feb 2025 20:49:20 +0000 Subject: [PATCH 78/87] Updated Schemas --- NewHorizons/Schemas/body_schema.json | 2 +- NewHorizons/Schemas/title_screen_schema.json | 98 ++++++++++++-------- 2 files changed, 58 insertions(+), 42 deletions(-) diff --git a/NewHorizons/Schemas/body_schema.json b/NewHorizons/Schemas/body_schema.json index 32632247..6075c264 100644 --- a/NewHorizons/Schemas/body_schema.json +++ b/NewHorizons/Schemas/body_schema.json @@ -4507,7 +4507,7 @@ }, "type": { "description": "The type of dream candle this is.", - "default": "Ground", + "default": "ground", "$ref": "#/definitions/DreamCandleType" }, "startLit": { diff --git a/NewHorizons/Schemas/title_screen_schema.json b/NewHorizons/Schemas/title_screen_schema.json index e6d16e6e..a0659c58 100644 --- a/NewHorizons/Schemas/title_screen_schema.json +++ b/NewHorizons/Schemas/title_screen_schema.json @@ -4,45 +4,16 @@ "type": "object", "additionalProperties": false, "properties": { - "menuTextTint": { - "description": "Colour of the text on the main menu", - "$ref": "#/definitions/MColor" + "titleScreens": { + "type": "array", + "description": "Create title screens", + "items": { + "$ref": "#/definitions/TitleScreenInfo" + } }, - "factRequiredForTitle": { + "$schema": { "type": "string", - "description": "Ship log fact required for this title screen to appear." - }, - "persistentConditionRequiredForTitle": { - "type": "string", - "description": "Persistent condition required for this title screen to appear." - }, - "disableNHPlanets": { - "type": "boolean", - "description": "If set to true, NH generated planets will not show on the title screen. If false, this title screen has the same chance as other NH planet title screens to show." - }, - "shareTitleScreen": { - "type": "boolean", - "description": "If set to true, this custom title screen will merge with all other custom title screens with shareTitleScreen set to true. If false, NH will randomly select between this and other valid title screens that are loaded." - }, - "Skybox": { - "description": "Customize the skybox for this title screen", - "$ref": "#/definitions/SkyboxModule" - }, - "music": { - "type": "string", - "description": "The music audio that will play on the title screen. Can be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list." - }, - "ambience": { - "type": "string", - "description": "The ambience audio that will play on the title screen. Can be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list." - }, - "Background": { - "description": "Edit properties of the background", - "$ref": "#/definitions/BackgroundModule" - }, - "MenuPlanet": { - "description": "Edit properties of the main menu planet", - "$ref": "#/definitions/MenuPlanetModule" + "description": "The schema to validate with" }, "extras": { "type": "object", @@ -50,13 +21,58 @@ "additionalProperties": { "type": "object" } - }, - "$schema": { - "type": "string", - "description": "The schema to validate with" } }, "definitions": { + "TitleScreenInfo": { + "type": "object", + "additionalProperties": false, + "properties": { + "menuTextTint": { + "description": "Colour of the text on the main menu", + "$ref": "#/definitions/MColor" + }, + "factRequiredForTitle": { + "type": "string", + "description": "Ship log fact required for this title screen to appear." + }, + "persistentConditionRequiredForTitle": { + "type": "string", + "description": "Persistent condition required for this title screen to appear." + }, + "disableNHPlanets": { + "type": "boolean", + "description": "If set to true, NH generated planets will not show on the title screen. If false, this title screen has the same chance as other NH planet title screens to show." + }, + "shareTitleScreen": { + "type": "boolean", + "description": "If set to true, this custom title screen will merge with all other custom title screens with shareTitleScreen set to true. If false, NH will randomly select between this and other valid title screens that are loaded." + }, + "Skybox": { + "description": "Customize the skybox for this title screen", + "$ref": "#/definitions/SkyboxModule" + }, + "music": { + "type": "string", + "description": "The music audio that will play on the title screen. Can be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list." + }, + "ambience": { + "type": "string", + "description": "The ambience audio that will play on the title screen. Can be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list." + }, + "Background": { + "description": "Edit properties of the background", + "$ref": "#/definitions/BackgroundModule" + }, + "MenuPlanet": { + "description": "Edit properties of the main menu planet", + "$ref": "#/definitions/MenuPlanetModule" + }, + "extras": { + "description": "Extra data that may be used by extension mods" + } + } + }, "MColor": { "type": "object", "additionalProperties": false, From a4a5d53416fd9e38e04f65218f8e37fa933e4699 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 16:12:20 -0500 Subject: [PATCH 79/87] ToString --- NewHorizons/Handlers/TitleSceneHandler.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index d5a9cd50..6a156d40 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -448,7 +448,7 @@ namespace NewHorizons.Handlers internal static void ResetConfigs() { - foreach (var builderList in TitleSceneHandler.TitleScreenBuilders.Values) + foreach (var builderList in TitleScreenBuilders.Values) { builderList.list.RemoveAll(builder => builder is TitleScreenConfigBuilder); } @@ -525,6 +525,8 @@ namespace NewHorizons.Handlers private int index = -1; public int Index { get => index; set => index = value; } + + public override string ToString() => Mod.ModHelper.Manifest.UniqueName + " #" + Index; } internal class TitleScreenConfigBuilder : ITitleScreenBuilder @@ -572,6 +574,8 @@ namespace NewHorizons.Handlers private int index = -1; public int Index { get => index; set => index = value; } + + public override string ToString() => Mod.ModHelper.Manifest.UniqueName + " #" + Index; } internal interface ITitleScreenBuilder From 075dac755ac13e6a5625d759b69540d843a34e50 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 16:27:56 -0500 Subject: [PATCH 80/87] edit for rework --- docs/src/content/docs/guides/title-screens.md | 129 ++++++++++-------- 1 file changed, 74 insertions(+), 55 deletions(-) diff --git a/docs/src/content/docs/guides/title-screens.md b/docs/src/content/docs/guides/title-screens.md index 332b2f76..285a4713 100644 --- a/docs/src/content/docs/guides/title-screens.md +++ b/docs/src/content/docs/guides/title-screens.md @@ -14,58 +14,71 @@ A title screen config file will look something like this: ```json title="title-screen.json" { "$schema": "https://raw.githubusercontent.com/Outer-Wilds-New-Horizons/new-horizons/main/NewHorizons/Schemas/title_screen_schema.json", - "disableNHPlanets": true, - "factRequiredForTitle": "EXAMPLES_ARTIFICIAL_GRAVITY", - "shareTitleScreen": true, - "menuTextTint": { - "r": 128, - "g": 128, - "b": 255 - }, - "music": "planets/assets/TitleScreenMusic.mp3", - "ambience": "planets/assets/TitleScreenAmbience.mp3", - "Skybox": { - "destroyStarField": true, - "rightPath": "systems/New System Assets/Skybox/Right_Large.png", - "leftPath": "systems/New System Assets/Skybox/Left_Large.png", - "topPath": "systems/New System Assets/Skybox/Up_Large.png", - "bottomPath": "systems/New System Assets/Skybox/Down_Large.png", - "frontPath": "systems/New System Assets/Skybox/Front_Large.png", - "backPath": "systems/New System Assets/Skybox/Back_Large.png" - }, - "Background": { - "details": [ - { - "assetBundle": "assetbundles/test", - "path": "Assets/Prefabs/Background.prefab", - "position": {"x": 200, "y": 280, "z": -50}, - "rotation": {"x": 310, "y": 0, "z": 310}, - "scale": 0.05 + "titleScreens": [ + { + "disableNHPlanets": false, + "shareTitleScreen": true, + "music": "planets/assets/TitleScreenMusic.mp3" + }, + { + "disableNHPlanets": true, + "shareTitleScreen": true, + "factRequiredForTitle": "EXAMPLES_ARTIFICIAL_GRAVITY", + "menuTextTint": { + "r": 128, + "g": 128, + "b": 255 + }, + "music": "planets/assets/TitleScreenMusic.mp3", + "ambience": "planets/assets/TitleScreenAmbience.mp3", + "Skybox": { + "destroyStarField": true, + "rightPath": "systems/New System Assets/Skybox/Right_Large.png", + "leftPath": "systems/New System Assets/Skybox/Left_Large.png", + "topPath": "systems/New System Assets/Skybox/Up_Large.png", + "bottomPath": "systems/New System Assets/Skybox/Down_Large.png", + "frontPath": "systems/New System Assets/Skybox/Front_Large.png", + "backPath": "systems/New System Assets/Skybox/Back_Large.png" + }, + "Background": { + "details": [ + { + "assetBundle": "assetbundles/test", + "path": "Assets/Prefabs/Background.prefab", + "position": {"x": 200, "y": 280, "z": -50}, + "rotation": {"x": 310, "y": 0, "z": 310}, + "scale": 0.05 + } + ], + "rotationSpeed": 10 + }, + "MenuPlanet": { + "destroyMenuPlanet": false, + "removeChildren": ["PlanetRoot/Props"], + "details": [ + { + "assetBundle": "assetbundles/test", + "path": "Assets/Prefabs/ArtificialGravity.prefab", + "removeChildren": ["Gravity"], + "parentPath": "PlanetRoot", + "position": {"x": 0, "y": 32, "z": 0}, + "rotation": {"x": 90, "y": 0, "z": 0}, + "scale": 10 + } + ], + "rotationSpeed": 20 } - ], - "rotationSpeed": 10 - }, - "MenuPlanet": { - "destroyMenuPlanet": false, - "removeChildren": ["PlanetRoot/Props"], - "details": [ - { - "assetBundle": "assetbundles/test", - "path": "Assets/Prefabs/ArtificialGravity.prefab", - "removeChildren": ["Gravity"], - "parentPath": "PlanetRoot", - "position": {"x": 0, "y": 32, "z": 0}, - "rotation": {"x": 90, "y": 0, "z": 0}, - "scale": 10 - } - ], - "rotationSpeed": 20 - } + } + ] } ``` +You can have multiple title screens but only one will be selected from the list. The last title screen in the list, that is unlocked, will always be selected. + ## Configs +Title screens from configs are always put first into the list. + ### `disableNHPlanets` If set to `true`, prevents NH-generated planets from appearing on the title screen. Defaults to true. @@ -105,7 +118,11 @@ To see all the different things you can put into a config file check out the [Ti ## API -New Horizons provides an API method to register and build custom title screens dynamically. Keep in mind you can only choose config or api not both as they don't merge. +New Horizons provides an API method to register and build custom title screens dynamically. + +These will be put at the end of the list for the selection of all your mod's title screens. + +You cannot combine configs with API unfortunately as only the API will be selected. ```csharp title="INewHorizons.cs" /// @@ -119,7 +136,9 @@ It shares a few values with the configs but also has an exclusive one. `builder`: Builder to run when this title screen is selected. The GameObject passed through it is the main scene object containing both the background and menu planet. -### Example usage +### Example API usage + +You can run `RegisterTitleScreenBuilder` more than once to add multiple title screen builders. ```csharp title="YourModBehaviour.cs" NewHorizons = ModHelper.Interaction.TryGetModApi("xen.NewHorizons"); @@ -136,14 +155,14 @@ public void BuildTitleScreen(GameObject scene) ## Events -Additionally, New Horizons provides events for tracking title screen loading: +Additionally, New Horizons provides events in the API for tracking title screen loading: ```csharp title="INewHorizons.cs" /// /// An event invoked when NH has finished building a title screen. -/// Gives the unique name of the mod the title screen builder was from. +/// Gives the unique name of the mod the title screen builder was from and the index for when you have multiple title screens. /// -UnityEvent GetTitleScreenLoadedEvent(); +UnityEvent GetTitleScreenLoadedEvent(); /// /// An event invoked when NH has finished building the title screen. @@ -151,7 +170,7 @@ UnityEvent GetTitleScreenLoadedEvent(); UnityEvent GetAllTitleScreensLoadedEvent(); ``` -### Example usage +### Example event usage ```csharp title="YourModBehaviour.cs" NewHorizons = ModHelper.Interaction.TryGetModApi("xen.NewHorizons"); @@ -160,13 +179,13 @@ NewHorizons.GetAllTitleScreensLoadedEvent().AddListener(OnAllTitleScreensLoaded) ``` ```csharp title="YourModBehaviour.cs" -public void OnTitleScreenLoaded(string modUniqueName) +public void OnTitleScreenLoaded(string modUniqueName, int index) { - ModHelper.Console.WriteLine($"Title screen loaded: " + modUniqueName, MessageType.Success); + ModHelper.Console.WriteLine($"Title screen loaded: {modUniqueName} #{index}", MessageType.Success); } public void OnAllTitleScreensLoaded() { - ModHelper.Console.WriteLine($"All title screens loaded", MessageType.Success); + ModHelper.Console.WriteLine("All title screens loaded", MessageType.Success); } ``` From 246e76561d985b68c57b741f22d9568f3dfa7b6e Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 17:05:20 -0500 Subject: [PATCH 81/87] almost forgot to add schema to docs navigation --- docs/astro.config.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 61ba83dc..584dec3e 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -90,6 +90,7 @@ export default defineConfig({ { label: "Addon Manifest Schema", link: "schemas/addon-manifest-schema" }, { label: "Dialogue Schema", link: "schemas/dialogue-schema" }, { label: "Text Schema", link: "schemas/text-schema" }, + { label: "Title Screen Schema", link: "schemas/title-screen-schema" }, { label: "Ship Log Schema", link: "schemas/shiplog-schema" } ] }, From 1763a39fb0ee166406fd4796c9a6f1d344bbd4f6 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 17:07:52 -0500 Subject: [PATCH 82/87] and here too --- docs/astro.config.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 584dec3e..a99b16dc 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -14,6 +14,7 @@ const schemas = [ "addon_manifest_schema.json", "dialogue_schema.xsd", "text_schema.xsd", + "title_screen_schema.json", "shiplog_schema.xsd" ]; From e26a34164022d425688cc296a2764fc6babfbc3d Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 17:11:19 -0500 Subject: [PATCH 83/87] oh and edit exporter since I moved extras --- SchemaExporter/SchemaExporter.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/SchemaExporter/SchemaExporter.cs b/SchemaExporter/SchemaExporter.cs index 5c5aad09..4b15e469 100644 --- a/SchemaExporter/SchemaExporter.cs +++ b/SchemaExporter/SchemaExporter.cs @@ -98,7 +98,7 @@ public static class SchemaExporter break; } - if (_title is "Star System Schema" or "Celestial Body Schema" or "Title Screen Schema") + if (_title is "Star System Schema" or "Celestial Body Schema") { schema.Properties["extras"] = new JsonSchemaProperty { Type = JsonObjectType.Object, @@ -111,6 +111,19 @@ public static class SchemaExporter }; } + if (_title is "Title Screen Schema") + { + schema.Definitions["TitleScreenInfo"].Properties["extras"] = new JsonSchemaProperty { + Type = JsonObjectType.Object, + Description = "Extra data that may be used by extension mods", + AllowAdditionalProperties = true, + AdditionalPropertiesSchema = new JsonSchema + { + Type = JsonObjectType.Object + } + }; + } + return schema; } } From 916befa0ff5c9dd4200e0120b86dd51c29eb281a Mon Sep 17 00:00:00 2001 From: Ben C Date: Mon, 17 Feb 2025 22:13:11 +0000 Subject: [PATCH 84/87] Updated Schemas --- NewHorizons/Schemas/title_screen_schema.json | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/NewHorizons/Schemas/title_screen_schema.json b/NewHorizons/Schemas/title_screen_schema.json index a0659c58..f1c45631 100644 --- a/NewHorizons/Schemas/title_screen_schema.json +++ b/NewHorizons/Schemas/title_screen_schema.json @@ -14,13 +14,6 @@ "$schema": { "type": "string", "description": "The schema to validate with" - }, - "extras": { - "type": "object", - "description": "Extra data that may be used by extension mods", - "additionalProperties": { - "type": "object" - } } }, "definitions": { @@ -69,7 +62,11 @@ "$ref": "#/definitions/MenuPlanetModule" }, "extras": { - "description": "Extra data that may be used by extension mods" + "type": "object", + "description": "Extra data that may be used by extension mods", + "additionalProperties": { + "type": "object" + } } } }, From e07efa9a5cf41814d3d3e579ec669b4d56b22ce7 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 19:15:58 -0500 Subject: [PATCH 85/87] Fix logo still being colored when reloading title screen --- .../Handlers/TitleScreen/TitleScreenColourHandler.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/NewHorizons/Handlers/TitleScreen/TitleScreenColourHandler.cs b/NewHorizons/Handlers/TitleScreen/TitleScreenColourHandler.cs index 1fa9e6fb..ffb30f3f 100644 --- a/NewHorizons/Handlers/TitleScreen/TitleScreenColourHandler.cs +++ b/NewHorizons/Handlers/TitleScreen/TitleScreenColourHandler.cs @@ -1,4 +1,5 @@ using HarmonyLib; +using NewHorizons.Utility; using NewHorizons.Utility.Files; using NewHorizons.Utility.OWML; using System.Linq; @@ -23,8 +24,11 @@ namespace NewHorizons.Handlers.TitleScreen } _mainMenuColour = colour; var logo = ImageUtilities.TintImage(ImageUtilities.GetTexture(Main.Instance, "Assets\\textures\\MENU_OuterWildsLogo_d.png"), (Color)_mainMenuColour); - GameObject.FindObjectOfType()._logoMaterial.mainTexture = logo; - GameObject.FindObjectOfType()._logoMaterialClone.mainTexture = logo; + var animRenderer = GameObject.FindObjectOfType(); + var colouredLogoMaterial = GameObject.Instantiate(animRenderer._logoMaterial).Rename("MENU_OuterWildsLogoANIM_mat_Coloured"); + colouredLogoMaterial.mainTexture = logo; + animRenderer._logoMaterial = colouredLogoMaterial; + animRenderer.Awake(); } public static void ResetColour() From 439093e65d776fd9db5cf9eed83060e5a6cc36da Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 19:17:50 -0500 Subject: [PATCH 86/87] Reload title screen on profile change --- NewHorizons/Handlers/TitleSceneHandler.cs | 13 +++++++++ NewHorizons/Main.cs | 4 ++- NewHorizons/Patches/TitleScenePatches.cs | 34 +++++++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 NewHorizons/Patches/TitleScenePatches.cs diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 6a156d40..14aab01f 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -13,6 +13,7 @@ using System; using System.Collections.Generic; using System.Linq; using UnityEngine; +using UnityEngine.SceneManagement; using Color = UnityEngine.Color; namespace NewHorizons.Handlers @@ -23,6 +24,7 @@ namespace NewHorizons.Handlers internal static NewHorizonsBody[] eligibleBodies => Main.BodyDict.Values.ToList().SelectMany(x => x).ToList() .Where(b => (b.Config.HeightMap != null || b.Config.Atmosphere?.clouds != null) && b.Config.Star == null && b.Config.canShowOnTitle).ToArray(); internal static int eligibleCount => eligibleBodies.Count(); + internal static bool reloaded = false; public static void Init() { @@ -48,6 +50,7 @@ namespace NewHorizons.Handlers // Load player data for fact and persistent condition checking var profileManager = StandaloneProfileManager.SharedInstance; + profileManager.OnProfileSignInComplete += OnProfileSignInComplete; profileManager.PreInitialize(); profileManager.Initialize(); if (profileManager.currentProfile != null) // check if there is even a profile made yet @@ -105,6 +108,16 @@ namespace NewHorizons.Handlers } } + private static void OnProfileSignInComplete(ProfileManagerSignInResult result) + { + NHLogger.LogError($"OnProfileSignInComplete {result}: {StandaloneProfileManager.SharedInstance.currentProfile.profileName}"); + reloaded = true; + + // Taken and modified from SubmitActionLoadScene.ConfirmSubmit + LoadManager.LoadScene(OWScene.TitleScreen); + Locator.GetMenuInputModule().DisableInputs(); + } + public static void InitSubtitles() { GameObject subtitleContainer = SearchUtilities.Find("TitleMenu/TitleCanvas/TitleLayoutGroup/Logo_EchoesOfTheEye"); diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 54d57707..4e48f881 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -165,7 +165,9 @@ namespace NewHorizons if (wasUsingCustomTitleScreen != CustomTitleScreen && SceneManager.GetActiveScene().name == "TitleScreen" && _wasConfigured) { NHLogger.LogVerbose("Reloading"); - SceneManager.LoadScene("TitleScreen", LoadSceneMode.Single); + // Taken and modified from SubmitActionLoadScene.ConfirmSubmit + LoadManager.LoadScene(OWScene.TitleScreen); + Locator.GetMenuInputModule().DisableInputs(); } _wasConfigured = true; diff --git a/NewHorizons/Patches/TitleScenePatches.cs b/NewHorizons/Patches/TitleScenePatches.cs new file mode 100644 index 00000000..1b5607f8 --- /dev/null +++ b/NewHorizons/Patches/TitleScenePatches.cs @@ -0,0 +1,34 @@ +using HarmonyLib; +using NewHorizons.Handlers; +using NewHorizons.Utility.OWML; +using OWML.Utils; +using UnityEngine; + +namespace NewHorizons.Patches; + +[HarmonyPatch] +internal static class TitleScenePatches +{ + [HarmonyPrefix, HarmonyPatch(typeof(TitleScreenAnimation), nameof(TitleScreenAnimation.Awake))] + public static void TitleScreenAnimation_Awake(TitleScreenAnimation __instance) + { + // Skip Splash on title screen reload + if (TitleSceneHandler.reloaded) + { + TitleSceneHandler.reloaded = false; + + TitleScreenAnimation titleScreenAnimation = __instance; + titleScreenAnimation._fadeDuration = 0; + titleScreenAnimation._gamepadSplash = false; + titleScreenAnimation._introPan = false; + + TitleAnimationController titleAnimationController = GameObject.FindObjectOfType(); + titleAnimationController._logoFadeDelay = 0.001f; + titleAnimationController._logoFadeDuration = 0.001f; + titleAnimationController._optionsFadeDelay = 0.001f; + titleAnimationController._optionsFadeDuration = 0.001f; + titleAnimationController._optionsFadeSpacing = 0.001f; + titleAnimationController.FadeInTitleLogo(); + } + } +} From 492c0bf47d8400f09546a6ca465c27150b3308c0 Mon Sep 17 00:00:00 2001 From: Noah Pilarski Date: Mon, 17 Feb 2025 19:37:03 -0500 Subject: [PATCH 87/87] reopen profile menu --- NewHorizons/Handlers/TitleSceneHandler.cs | 4 +++- NewHorizons/Main.cs | 1 + NewHorizons/Patches/TitleScenePatches.cs | 12 +++++++++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/NewHorizons/Handlers/TitleSceneHandler.cs b/NewHorizons/Handlers/TitleSceneHandler.cs index 14aab01f..7183675f 100644 --- a/NewHorizons/Handlers/TitleSceneHandler.cs +++ b/NewHorizons/Handlers/TitleSceneHandler.cs @@ -25,6 +25,7 @@ namespace NewHorizons.Handlers .Where(b => (b.Config.HeightMap != null || b.Config.Atmosphere?.clouds != null) && b.Config.Star == null && b.Config.canShowOnTitle).ToArray(); internal static int eligibleCount => eligibleBodies.Count(); internal static bool reloaded = false; + internal static bool reopenProfile = false; public static void Init() { @@ -110,8 +111,9 @@ namespace NewHorizons.Handlers private static void OnProfileSignInComplete(ProfileManagerSignInResult result) { - NHLogger.LogError($"OnProfileSignInComplete {result}: {StandaloneProfileManager.SharedInstance.currentProfile.profileName}"); + NHLogger.LogVerbose($"OnProfileSignInComplete {result}: {StandaloneProfileManager.SharedInstance.currentProfile.profileName}"); reloaded = true; + reopenProfile = true; // Taken and modified from SubmitActionLoadScene.ConfirmSubmit LoadManager.LoadScene(OWScene.TitleScreen); diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 4e48f881..01e1f089 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -165,6 +165,7 @@ namespace NewHorizons if (wasUsingCustomTitleScreen != CustomTitleScreen && SceneManager.GetActiveScene().name == "TitleScreen" && _wasConfigured) { NHLogger.LogVerbose("Reloading"); + TitleSceneHandler.reloaded = true; // Taken and modified from SubmitActionLoadScene.ConfirmSubmit LoadManager.LoadScene(OWScene.TitleScreen); Locator.GetMenuInputModule().DisableInputs(); diff --git a/NewHorizons/Patches/TitleScenePatches.cs b/NewHorizons/Patches/TitleScenePatches.cs index 1b5607f8..a0705c53 100644 --- a/NewHorizons/Patches/TitleScenePatches.cs +++ b/NewHorizons/Patches/TitleScenePatches.cs @@ -1,5 +1,6 @@ using HarmonyLib; using NewHorizons.Handlers; +using NewHorizons.Utility; using NewHorizons.Utility.OWML; using OWML.Utils; using UnityEngine; @@ -12,11 +13,11 @@ internal static class TitleScenePatches [HarmonyPrefix, HarmonyPatch(typeof(TitleScreenAnimation), nameof(TitleScreenAnimation.Awake))] public static void TitleScreenAnimation_Awake(TitleScreenAnimation __instance) { - // Skip Splash on title screen reload if (TitleSceneHandler.reloaded) { TitleSceneHandler.reloaded = false; + // Skip Splash on title screen reload TitleScreenAnimation titleScreenAnimation = __instance; titleScreenAnimation._fadeDuration = 0; titleScreenAnimation._gamepadSplash = false; @@ -29,6 +30,15 @@ internal static class TitleScenePatches titleAnimationController._optionsFadeDuration = 0.001f; titleAnimationController._optionsFadeSpacing = 0.001f; titleAnimationController.FadeInTitleLogo(); + + // Reopen profile + if (TitleSceneHandler.reopenProfile) + { + TitleSceneHandler.reopenProfile = false; + Delay.FireOnNextUpdate(() => + SearchUtilities.Find("TitleMenu/TitleCanvas/TitleLayoutGroup/MainMenuBlock/MainMenuLayoutGroup/Button-Profile") + .GetComponent().Submit()); + } } } }