From c1074c1159bd0e6e4e0dde5107156d8b866b5904 Mon Sep 17 00:00:00 2001 From: MrPurple6411 Date: Sun, 16 May 2021 13:19:49 -0600 Subject: [PATCH 01/10] Dialog popup bug fix. --- QModManager/Patching/GameDetector.cs | 2 +- QModManager/Patching/Patcher.cs | 19 +-- QModManager/Utility/Dialog.cs | 151 +++++++++++----------- QModManager/Utility/SummaryLogger.cs | 8 +- QModPluginEmulator/QModPluginGenerator.cs | 15 +++ 5 files changed, 109 insertions(+), 86 deletions(-) diff --git a/QModManager/Patching/GameDetector.cs b/QModManager/Patching/GameDetector.cs index c2d75a13..50c13681 100644 --- a/QModManager/Patching/GameDetector.cs +++ b/QModManager/Patching/GameDetector.cs @@ -19,7 +19,7 @@ internal class GameDetector private static readonly Dictionary SupportedGameVersions = new Dictionary { #if SUBNAUTICA_STABLE - { QModGame.Subnautica, 67816 } + { QModGame.Subnautica, 65786 } #elif BELOWZERO_STABLE { QModGame.BelowZero, 44290 } #elif SUBNAUTICA_EXP diff --git a/QModManager/Patching/Patcher.cs b/QModManager/Patching/Patcher.cs index 490a7ecc..88211da6 100644 --- a/QModManager/Patching/Patcher.cs +++ b/QModManager/Patching/Patcher.cs @@ -1,6 +1,7 @@ namespace QModManager.Patching { using System; + using System.Collections.Generic; using System.IO; using System.Reflection; using API; @@ -18,6 +19,8 @@ internal static class Patcher internal static QModGame CurrentlyRunningGame { get; private set; } = QModGame.None; internal static int ErrorModCount { get; private set; } + internal static List Dialogs { get; } = new List(); + internal static void Patch() { try @@ -43,13 +46,13 @@ internal static void Patch() Logger.Fatal("There was an error with the QMods directory"); Logger.Fatal("Please make sure that you ran Subnautica from Steam/Epic/Discord, and not from the executable file!"); - new Dialog() + Dialogs.Add(new Dialog() { message = "A fatal error has occurred. QModManager could not be initialized.", color = Dialog.DialogColor.Red, leftButton = Dialog.Button.SeeLog, rightButton = Dialog.Button.Close, - }.Show(); + }); return; } @@ -74,13 +77,13 @@ internal static void Patch() { Logger.Fatal($"Nitrox was detected!"); - new Dialog() + Dialogs.Add(new Dialog() { message = "Both QModManager and Nitrox detected. QModManager is not compatible with Nitrox. Please uninstall one of them.", leftButton = Dialog.Button.Disabled, rightButton = Dialog.Button.Disabled, color = Dialog.DialogColor.Red, - }.Show(); + }); return; } @@ -95,24 +98,24 @@ internal static void Patch() Logger.Fatal($"A fatal patching exception has been caught! Patching ended prematurely!"); Logger.Exception(pEx); - new Dialog() + Dialogs.Add(new Dialog() { message = "A fatal patching exception has been caught. QModManager could not be initialized.", color = Dialog.DialogColor.Red, leftButton = Dialog.Button.SeeLog, - }.Show(); + }); } catch (Exception e) { Logger.Fatal("An unhandled exception has been caught! Patching ended prematurely!"); Logger.Exception(e); - new Dialog() + Dialogs.Add(new Dialog() { message = "An unhandled exception has been caught. QModManager could not be initialized.", color = Dialog.DialogColor.Red, leftButton = Dialog.Button.SeeLog, - }.Show(); + }); } } diff --git a/QModManager/Utility/Dialog.cs b/QModManager/Utility/Dialog.cs index 23ada2d8..be2b2085 100644 --- a/QModManager/Utility/Dialog.cs +++ b/QModManager/Utility/Dialog.cs @@ -71,39 +71,62 @@ internal enum DialogColor internal Button rightButton = Button.Disabled; private GameObject coroutineHandler; + private float pos = 0; + private Sprite Sprite; internal void Show() { - coroutineHandler = new GameObject("QModManager Dialog Coroutine"); - coroutineHandler.AddComponent().StartCoroutine(ShowDialogEnumerator()); + if(coroutineHandler is null) + { + coroutineHandler = new GameObject("QModManager Dialog Coroutine"); + coroutineHandler.AddComponent().StartCoroutine(ShowDialogEnumerator()); + } + else if(coroutineHandler.TryGetComponent(out DummyBehaviour dummyBehaviour)) + { + dummyBehaviour.StartCoroutine(ShowDialogEnumerator()); + } + else + { + coroutineHandler.AddComponent().StartCoroutine(ShowDialogEnumerator()); + } } private IEnumerator ShowDialogEnumerator() { - while (uGUI._main == null) + //Must have at least one button with an action + if(leftButton.Action is null && rightButton.Action is null) + { + UnityEngine.Object.Destroy(coroutineHandler); + yield break; + } + + //Ensures a new dialog is not created until the main menu has fully loaded or it will break; + while(uGUI_MainMenu.main is null || FPSInputModule.current is null || FPSInputModule.current.lastGroup != uGUI_MainMenu.main) yield return null; uGUI_SceneConfirmation confirmation = uGUI.main.confirmation; - // Disable buttons if their action is null - if (leftButton.Action == null) - confirmation.yes.gameObject.SetActive(false); - if (rightButton.Action == null) - confirmation.no.gameObject.SetActive(false); + // Show dialog + //Had to move this before the code to change its values as the values are reset during the showing in BelowZero. + confirmation.Show(message, OnCallBack); - // Disable buttons if their text is null, otherwise set their button text - if (string.IsNullOrEmpty(leftButton.Text)) + // Disable left button if its text or action is null, otherwise set their button text + if(leftButton.Action == null || string.IsNullOrEmpty(leftButton.Text)) confirmation.yes.gameObject.SetActive(false); else SetText(confirmation.yes.gameObject, leftButton.Text); - if (string.IsNullOrEmpty(rightButton.Text)) + + // Disable right button if its text or action is null, otherwise set their button text + if(rightButton.Action == null || string.IsNullOrEmpty(rightButton.Text)) confirmation.no.gameObject.SetActive(false); else SetText(confirmation.no.gameObject, rightButton.Text); + // Reduce the text size on the buttons + ChangeAllFontSizes(confirmation.gameObject, -4f); + // If one button is disabled, center the other - float pos = 0; - if (confirmation.yes.gameObject.activeSelf && !confirmation.no.gameObject.activeSelf) + if(confirmation.yes.gameObject.activeSelf && !confirmation.no.gameObject.activeSelf) { pos = confirmation.yes.transform.localPosition.x; confirmation.yes.transform.localPosition = new Vector3( @@ -111,7 +134,7 @@ private IEnumerator ShowDialogEnumerator() confirmation.yes.transform.localPosition.y, confirmation.yes.transform.localPosition.z); } - if (!confirmation.yes.gameObject.activeSelf && confirmation.no.gameObject.activeSelf) + else if(!confirmation.yes.gameObject.activeSelf && confirmation.no.gameObject.activeSelf) { pos = confirmation.no.transform.localPosition.x; confirmation.no.transform.localPosition = new Vector3( @@ -121,61 +144,54 @@ private IEnumerator ShowDialogEnumerator() } // Turn the dialog blue if the blue parameter is true - Sprite sprite = confirmation.gameObject.GetComponentInChildren().sprite; - if (color == DialogColor.Blue) + Sprite = confirmation.gameObject.GetComponentInChildren().sprite; + if(color == DialogColor.Blue) confirmation.gameObject.GetComponentInChildren().sprite = confirmation.gameObject.GetComponentsInChildren()[1].sprite; - // Reduce the text size on the buttons - object[] texts = ChangeAllFontSizes(confirmation.gameObject, -4f); - - // Show dialog - confirmation.Show(message, delegate (bool leftButtonClicked) - { - // Run actions based on which button was pressed - if (leftButtonClicked) - leftButton.Action?.Invoke(); - else - rightButton.Action?.Invoke(); - - // Revert everything to its original state - if (confirmation.yes.gameObject.activeSelf && !confirmation.no.gameObject.activeSelf) - { - confirmation.yes.transform.localPosition = new Vector3( - pos, - confirmation.yes.transform.localPosition.y, - confirmation.yes.transform.localPosition.z); - } - if (!confirmation.yes.gameObject.activeSelf && confirmation.no.gameObject.activeSelf) - { - confirmation.no.transform.localPosition = new Vector3( - pos, - confirmation.no.transform.localPosition.y, - confirmation.no.transform.localPosition.z); - } + } - confirmation.yes.gameObject.SetActive(true); - confirmation.no.gameObject.SetActive(true); + internal void OnCallBack(bool leftButtonClicked) + { + uGUI_SceneConfirmation confirmation = uGUI.main.confirmation; - SetText(confirmation.yes.gameObject, "Yes"); - SetText(confirmation.no.gameObject, "No"); + // Run actions based on which button was pressed + if(leftButtonClicked) + leftButton.Action?.Invoke(); + else + rightButton.Action?.Invoke(); - confirmation.gameObject.GetComponentInChildren().sprite = sprite; + // Revert everything to its original state + if(confirmation.yes.gameObject.activeSelf && !confirmation.no.gameObject.activeSelf) + { + confirmation.yes.transform.localPosition = new Vector3( + pos, + confirmation.yes.transform.localPosition.y, + confirmation.yes.transform.localPosition.z); + } + if(!confirmation.yes.gameObject.activeSelf && confirmation.no.gameObject.activeSelf) + { + confirmation.no.transform.localPosition = new Vector3( + pos, + confirmation.no.transform.localPosition.y, + confirmation.no.transform.localPosition.z); + } - ChangeAllFontSizes(texts, 4f); + confirmation.yes.gameObject.SetActive(true); + confirmation.no.gameObject.SetActive(true); - UnityEngine.Object.Destroy(coroutineHandler); + SetText(confirmation.yes.gameObject, "Yes"); + SetText(confirmation.no.gameObject, "No"); - // Re-open the dialog if the button pressed was not close - bool closeButtonClicked = (leftButtonClicked && leftButton == Button.Close) || (!leftButtonClicked && rightButton == Button.Close); - if (!closeButtonClicked) - Show(); - }); + confirmation.gameObject.GetComponentInChildren().sprite = Sprite; - // Focus popup - while (confirmation.selected) - yield return new WaitForSecondsRealtime(0.25f); + ChangeAllFontSizes(confirmation.gameObject, 4f); - confirmation.Select(); + // Re-open the dialog if the button pressed was not close + bool closeButtonClicked = (leftButtonClicked && leftButton == Button.Close) || (!leftButtonClicked && rightButton == Button.Close); + if(!closeButtonClicked) + Show(); + else + UnityEngine.Object.Destroy(coroutineHandler); } private static void SetText(GameObject obj, string text) @@ -204,29 +220,18 @@ private static void SetText(GameObject obj, string text) } object txt = obj.GetComponentInChildren(SelectedTextType); - textProperty.SetValue(txt, text, null); } - private static object[] ChangeAllFontSizes(GameObject obj, float change) + private static void ChangeAllFontSizes(GameObject obj, float change) { if (fontSizeProperty == null) - return null; + return; object[] textComponents = obj.GetComponentsInChildren(SelectedTextType); - ChangeAllFontSizes(textComponents, change); - - return textComponents; - } - - private static void ChangeAllFontSizes(object[] textComponents, float change) - { - if (fontSizeProperty == null) - return; - // Loop starts at 1 because text 0 is the main dialog text, which shouldn't be changed - for (int i = 1; i < textComponents.Length; i++) + for(int i = 1; i < textComponents.Length; i++) { object t = textComponents[i]; float originalSize = (float)fontSizeProperty.GetValue(t, null); diff --git a/QModManager/Utility/SummaryLogger.cs b/QModManager/Utility/SummaryLogger.cs index e9d92671..3148723f 100644 --- a/QModManager/Utility/SummaryLogger.cs +++ b/QModManager/Utility/SummaryLogger.cs @@ -141,23 +141,23 @@ internal static void ReportIssues(List mods) message += " Check the log for more information."; - new Dialog() + Patcher.Dialogs.Add(new Dialog() { message = message, leftButton = Dialog.Button.SeeLog, rightButton = Dialog.Button.Close, color = Dialog.DialogColor.Red - }.Show(); + }); } else if (VersionCheck.result != null) { - new Dialog() + Patcher.Dialogs.Add(new Dialog() { message = $"There is a newer version of QModManager available: {VersionCheck.result.ToStringParsed()} (current version: {Assembly.GetExecutingAssembly().GetName().Version.ToStringParsed()})", leftButton = Dialog.Button.Download, rightButton = Dialog.Button.Close, color = Dialog.DialogColor.Blue - }.Show(); + }); } } } diff --git a/QModPluginEmulator/QModPluginGenerator.cs b/QModPluginEmulator/QModPluginGenerator.cs index dbbfff35..ebb5bcb4 100644 --- a/QModPluginEmulator/QModPluginGenerator.cs +++ b/QModPluginEmulator/QModPluginGenerator.cs @@ -108,6 +108,13 @@ private static IEnumerator InitializeQMM(IEnumerator result) SummaryLogger.ReportIssues(ModsToLoad); SummaryLogger.LogSummaries(ModsToLoad); + if(Patcher.Dialogs.Count > 0) + { + foreach(Dialog dialog in Patcher.Dialogs) + { + dialog.Show(); + } + } } yield break; } @@ -122,6 +129,14 @@ private static void InitializeQMM() SummaryLogger.ReportIssues(ModsToLoad); SummaryLogger.LogSummaries(ModsToLoad); + + if(Patcher.Dialogs.Count > 0) + { + foreach(Dialog dialog in Patcher.Dialogs) + { + dialog.Show(); + } + } } } #endif From 831dce9fd24bee33f37b6237aa2d4e5349a36d96 Mon Sep 17 00:00:00 2001 From: MrPurple6411 Date: Sun, 16 May 2021 14:06:37 -0600 Subject: [PATCH 02/10] Version Bump --- Data/latest-version.txt | 2 +- Executable/Properties/AssemblyInfo.cs | 4 ++-- Installer/BZ.EXP.iss | 2 +- Installer/BZ.STABLE.iss | 2 +- Installer/Properties/AssemblyInfo.cs | 4 ++-- Installer/SN.EXP.iss | 2 +- Installer/SN.STABLE.iss | 2 +- OculusNewtonsoftRedirect/Properties/AssemblyInfo.cs | 4 ++-- QModManager/Properties/AssemblyInfo.cs | 4 ++-- QModPluginEmulator/Properties/AssemblyInfo.cs | 4 ++-- UnityAudioFixer/Properties/AssemblyInfo.cs | 4 ++-- 11 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Data/latest-version.txt b/Data/latest-version.txt index cd9b8f55..8c7fafd3 100644 --- a/Data/latest-version.txt +++ b/Data/latest-version.txt @@ -1 +1 @@ -4.1.2 \ No newline at end of file +4.1.3 \ No newline at end of file diff --git a/Executable/Properties/AssemblyInfo.cs b/Executable/Properties/AssemblyInfo.cs index 353511da..c2b60ce8 100644 --- a/Executable/Properties/AssemblyInfo.cs +++ b/Executable/Properties/AssemblyInfo.cs @@ -12,5 +12,5 @@ [assembly: ComVisible(false)] -[assembly: AssemblyVersion("4.1.2")] -[assembly: AssemblyFileVersion("4.1.2")] +[assembly: AssemblyVersion("4.1.3")] +[assembly: AssemblyFileVersion("4.1.3")] diff --git a/Installer/BZ.EXP.iss b/Installer/BZ.EXP.iss index ca3f817e..03dbb674 100644 --- a/Installer/BZ.EXP.iss +++ b/Installer/BZ.EXP.iss @@ -5,7 +5,7 @@ #endif #define Name "QModManager" ; The name of the game will be added after it -#define Version "4.1.2" +#define Version "4.1.3" #define Author "QModManager" #define URL "https://github.com/QModManager/QModManager" #define SupportURL "https://discord.gg/UpWuWwq" diff --git a/Installer/BZ.STABLE.iss b/Installer/BZ.STABLE.iss index b3d8b30e..f59e0d01 100644 --- a/Installer/BZ.STABLE.iss +++ b/Installer/BZ.STABLE.iss @@ -5,7 +5,7 @@ #endif #define Name "QModManager" ; The name of the game will be added after it -#define Version "4.1.2" +#define Version "4.1.3" #define Author "QModManager" #define URL "https://github.com/QModManager/QModManager" #define SupportURL "https://discord.gg/UpWuWwq" diff --git a/Installer/Properties/AssemblyInfo.cs b/Installer/Properties/AssemblyInfo.cs index f7cc9bfd..2d945d7d 100644 --- a/Installer/Properties/AssemblyInfo.cs +++ b/Installer/Properties/AssemblyInfo.cs @@ -14,5 +14,5 @@ [assembly: Guid("8c6c9a0b-80c4-43d2-89f2-749e6f09fdda")] -[assembly: AssemblyVersion("4.1.2")] -[assembly: AssemblyFileVersion("4.1.2")] +[assembly: AssemblyVersion("4.1.3")] +[assembly: AssemblyFileVersion("4.1.3")] diff --git a/Installer/SN.EXP.iss b/Installer/SN.EXP.iss index 511307c6..e428a780 100644 --- a/Installer/SN.EXP.iss +++ b/Installer/SN.EXP.iss @@ -5,7 +5,7 @@ #endif #define Name "QModManager" ; The name of the game will be added after it -#define Version "4.1.2" +#define Version "4.1.3" #define Author "QModManager" #define URL "https://github.com/QModManager/QModManager" #define SupportURL "https://discord.gg/UpWuWwq" diff --git a/Installer/SN.STABLE.iss b/Installer/SN.STABLE.iss index c4e33c83..d52d8c27 100644 --- a/Installer/SN.STABLE.iss +++ b/Installer/SN.STABLE.iss @@ -5,7 +5,7 @@ #endif #define Name "QModManager" ; The name of the game will be added after it -#define Version "4.1.2" +#define Version "4.1.3" #define Author "QModManager" #define URL "https://github.com/QModManager/QModManager" #define SupportURL "https://discord.gg/UpWuWwq" diff --git a/OculusNewtonsoftRedirect/Properties/AssemblyInfo.cs b/OculusNewtonsoftRedirect/Properties/AssemblyInfo.cs index 0946c77c..8c614c95 100644 --- a/OculusNewtonsoftRedirect/Properties/AssemblyInfo.cs +++ b/OculusNewtonsoftRedirect/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("4.1.2")] -[assembly: AssemblyFileVersion("4.1.2")] +[assembly: AssemblyVersion("4.1.3")] +[assembly: AssemblyFileVersion("4.1.3")] diff --git a/QModManager/Properties/AssemblyInfo.cs b/QModManager/Properties/AssemblyInfo.cs index afff034a..dc6cd653 100644 --- a/QModManager/Properties/AssemblyInfo.cs +++ b/QModManager/Properties/AssemblyInfo.cs @@ -13,8 +13,8 @@ [assembly: ComVisible(false)] -[assembly: AssemblyVersion("4.1.2")] -[assembly: AssemblyFileVersion("4.1.2")] +[assembly: AssemblyVersion("4.1.3")] +[assembly: AssemblyFileVersion("4.1.3")] [assembly: InternalsVisibleTo("QMMTests")] [assembly: InternalsVisibleTo("QModManager")] diff --git a/QModPluginEmulator/Properties/AssemblyInfo.cs b/QModPluginEmulator/Properties/AssemblyInfo.cs index d36927e8..3f88e19e 100644 --- a/QModPluginEmulator/Properties/AssemblyInfo.cs +++ b/QModPluginEmulator/Properties/AssemblyInfo.cs @@ -33,8 +33,8 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("4.1.2")] -[assembly: AssemblyFileVersion("4.1.2")] +[assembly: AssemblyVersion("4.1.3")] +[assembly: AssemblyFileVersion("4.1.3")] [assembly: NeutralResourcesLanguage("en")] [assembly: InternalsVisibleTo("QModManager.QMMLoader")] diff --git a/UnityAudioFixer/Properties/AssemblyInfo.cs b/UnityAudioFixer/Properties/AssemblyInfo.cs index bdc33326..8edab69c 100644 --- a/UnityAudioFixer/Properties/AssemblyInfo.cs +++ b/UnityAudioFixer/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("4.1.2")] -[assembly: AssemblyFileVersion("4.1.2")] +[assembly: AssemblyVersion("4.1.3")] +[assembly: AssemblyFileVersion("4.1.3")] From 76b16dac4c4f0609e56950c87f432208686a335d Mon Sep 17 00:00:00 2001 From: MrPurple6411 Date: Sun, 16 May 2021 15:37:23 -0600 Subject: [PATCH 03/10] Ensure Component --- QModManager/Utility/Dialog.cs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/QModManager/Utility/Dialog.cs b/QModManager/Utility/Dialog.cs index be2b2085..4322ea0b 100644 --- a/QModManager/Utility/Dialog.cs +++ b/QModManager/Utility/Dialog.cs @@ -79,16 +79,9 @@ internal void Show() if(coroutineHandler is null) { coroutineHandler = new GameObject("QModManager Dialog Coroutine"); - coroutineHandler.AddComponent().StartCoroutine(ShowDialogEnumerator()); - } - else if(coroutineHandler.TryGetComponent(out DummyBehaviour dummyBehaviour)) - { - dummyBehaviour.StartCoroutine(ShowDialogEnumerator()); - } - else - { - coroutineHandler.AddComponent().StartCoroutine(ShowDialogEnumerator()); } + var dummyBehaviour = coroutineHandler.EnsureComponent(); + dummyBehaviour.StartCoroutine(ShowDialogEnumerator()); } private IEnumerator ShowDialogEnumerator() From bb148d0c8501aedf0ab514765fb34d5e1c9f63f9 Mon Sep 17 00:00:00 2001 From: MrPurple6411 Date: Sun, 16 May 2021 15:40:46 -0600 Subject: [PATCH 04/10] Remove count check --- QModPluginEmulator/QModPluginGenerator.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/QModPluginEmulator/QModPluginGenerator.cs b/QModPluginEmulator/QModPluginGenerator.cs index ebb5bcb4..49d4b2ea 100644 --- a/QModPluginEmulator/QModPluginGenerator.cs +++ b/QModPluginEmulator/QModPluginGenerator.cs @@ -108,12 +108,9 @@ private static IEnumerator InitializeQMM(IEnumerator result) SummaryLogger.ReportIssues(ModsToLoad); SummaryLogger.LogSummaries(ModsToLoad); - if(Patcher.Dialogs.Count > 0) + foreach(Dialog dialog in Patcher.Dialogs) { - foreach(Dialog dialog in Patcher.Dialogs) - { - dialog.Show(); - } + dialog.Show(); } } yield break; @@ -130,12 +127,9 @@ private static void InitializeQMM() SummaryLogger.ReportIssues(ModsToLoad); SummaryLogger.LogSummaries(ModsToLoad); - if(Patcher.Dialogs.Count > 0) + foreach(Dialog dialog in Patcher.Dialogs) { - foreach(Dialog dialog in Patcher.Dialogs) - { - dialog.Show(); - } + dialog.Show(); } } } From eae7ba20e0c8a6204e9a8b38cbf97364150b197b Mon Sep 17 00:00:00 2001 From: MrPurple6411 Date: Mon, 17 May 2021 05:40:58 -0600 Subject: [PATCH 05/10] Fix Null ref we caused by destroying sentry --- .../HarmonyPatches/DisableDevErrorReporting.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/QModManager/HarmonyPatches/DisableDevErrorReporting.cs b/QModManager/HarmonyPatches/DisableDevErrorReporting.cs index bcb6c925..5b53594a 100644 --- a/QModManager/HarmonyPatches/DisableDevErrorReporting.cs +++ b/QModManager/HarmonyPatches/DisableDevErrorReporting.cs @@ -1,6 +1,7 @@ namespace QModManager.HarmonyPatches.DisableDevErrorReporting { using HarmonyLib; + using System.Collections; using UnityEngine; [HarmonyPatch] @@ -16,5 +17,15 @@ internal static bool Prefix(SentrySdk __instance) GameObject.Destroy(__instance); return false; } + +#if !SUBNAUTICA_STABLE + [HarmonyPostfix] + [HarmonyPatch(typeof(SystemsSpawner), nameof(SystemsSpawner.SetupSingleton))] + internal static IEnumerator Postfix(IEnumerator enumerator) + { + yield return null; + yield break; + } +#endif } } From 2e4d87285faa577d1dd0cbc6f599e535cb15f344 Mon Sep 17 00:00:00 2001 From: MrPurple6411 Date: Mon, 17 May 2021 05:41:18 -0600 Subject: [PATCH 06/10] Fix datetime to Now instead of Today --- QModManager/Patching/GameDetector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QModManager/Patching/GameDetector.cs b/QModManager/Patching/GameDetector.cs index 50c13681..8d1eb109 100644 --- a/QModManager/Patching/GameDetector.cs +++ b/QModManager/Patching/GameDetector.cs @@ -65,7 +65,7 @@ internal GameDetector() Logger.Info($"Game Version: {CurrentGameVersion} Build Date: {SNUtils.GetDateTimeOfBuild():dd-MMMM-yyyy}"); Logger.Info($"Loading QModManager v{Assembly.GetExecutingAssembly().GetName().Version.ToStringParsed()}{(IsValidGameRunning && MinimumBuildVersion != 0 ? $" built for {CurrentlyRunningGame} v{MinimumBuildVersion}" : string.Empty)}..."); - Logger.Info($"Today is {DateTime.Today:dd-MMMM-yyyy_HH:mm:ss}"); + Logger.Info($"Today is {DateTime.Now:dd-MMMM-yyyy_HH:mm:ss}"); if (!IsValidGameVersion) { From 7446525374e91081cfaadf6c6dedae696f95c8d3 Mon Sep 17 00:00:00 2001 From: MrPurple6411 Date: Mon, 17 May 2021 05:42:13 -0600 Subject: [PATCH 07/10] Patch Mirror Internal log with a filter to remove useless strings from being logged. --- QModPluginEmulator/QModPluginGenerator.cs | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/QModPluginEmulator/QModPluginGenerator.cs b/QModPluginEmulator/QModPluginGenerator.cs index 49d4b2ea..6fe35ae0 100644 --- a/QModPluginEmulator/QModPluginGenerator.cs +++ b/QModPluginEmulator/QModPluginGenerator.cs @@ -57,6 +57,18 @@ public static void Finish() { PluginCache = GetPluginCache(); Harmony = new Harmony("QModManager.QModPluginGenerator"); + foreach(Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + if(assembly?.GetName()?.Name?.Contains("MirrorInternalLogs") ?? false) + { + Type type = AccessTools.TypeByName("MirrorInternalLogs.Util.LibcHelper"); + var method = type?.GetMethod("Format"); + + if(method != null) + Harmony.Patch(method, postfix: new HarmonyMethod(typeof(QModPluginGenerator), nameof(QModPluginGenerator.LibcHelper_Format_Postfix))); + break; + } + } Harmony.Patch( typeof(TypeLoader).GetMethod(nameof(TypeLoader.FindPluginTypes)).MakeGenericMethod(typeof(PluginInfo)), postfix: new HarmonyMethod(typeof(QModPluginGenerator).GetMethod(nameof(TypeLoaderFindPluginTypesPostfix)))); @@ -70,6 +82,21 @@ public static void Finish() } } + public static List DirtyLogStrings = new List() + { + "(Filename", "Resetting cell with", "Replacing cell", + "PerformGarbage", "Fallback handler could not load" + }; + + private static void LibcHelper_Format_Postfix(ref string __result) + { + foreach(string dirtyString in DirtyLogStrings) + { + if(__result.Contains(dirtyString)) + __result = __result.Remove(__result.IndexOf(dirtyString)); + } + } + #if SUBNAUTICA_STABLE [HarmonyPatch(typeof(SystemsSpawner), nameof(SystemsSpawner.Awake))] #else @@ -78,6 +105,8 @@ public static void Finish() [HarmonyPrefix] private static void PreInitializeQMM() { + + Patcher.Patch(); // Run QModManager patch ModsToLoad = QModsToLoad.ToList(); From 83ae57c3611107f198051e2ee60257603a5213f0 Mon Sep 17 00:00:00 2001 From: MrPurple6411 Date: Tue, 18 May 2021 00:21:12 -0600 Subject: [PATCH 08/10] Split string cleaning. --- QModPluginEmulator/QModPluginGenerator.cs | 28 +++++++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/QModPluginEmulator/QModPluginGenerator.cs b/QModPluginEmulator/QModPluginGenerator.cs index 6fe35ae0..da803e2f 100644 --- a/QModPluginEmulator/QModPluginGenerator.cs +++ b/QModPluginEmulator/QModPluginGenerator.cs @@ -82,18 +82,36 @@ public static void Finish() } } - public static List DirtyLogStrings = new List() + public static List DirtyStartStrings = new List() { - "(Filename", "Resetting cell with", "Replacing cell", + "Resetting cell with", "Replacing cell", "PerformGarbage", "Fallback handler could not load" }; + public static List DirtyMidStrings = new List() + { + "\n(Filename", + }; + private static void LibcHelper_Format_Postfix(ref string __result) { - foreach(string dirtyString in DirtyLogStrings) + foreach(string dirtyString in DirtyStartStrings) + { + if(__result.StartsWith(dirtyString)) + { + __result = ""; + return; + } + } + + foreach(string dirtyString in DirtyMidStrings) { - if(__result.Contains(dirtyString)) - __result = __result.Remove(__result.IndexOf(dirtyString)); + int i = __result.IndexOf(dirtyString); + if(i >= 0) + { + __result = __result.Remove(i); + return; + } } } From 1adf8619902bb01949bf489ad4393e6a71f8bfbc Mon Sep 17 00:00:00 2001 From: Tobias Strebitzer Date: Thu, 20 May 2021 11:39:46 +0800 Subject: [PATCH 09/10] Implement OSX Build Flow --- MacOSX/README.md | 22 +++++ MacOSX/build.sh | 74 +++++++++++++++ MacOSX/dist/Distribution | 38 ++++++++ MacOSX/dist/QModManager.sh | 35 +++++++ MacOSX/dist/Resources/banner.png | Bin 0 -> 61220 bytes MacOSX/dist/Resources/conclusion.html | 27 ++++++ MacOSX/dist/Resources/license.html | 127 ++++++++++++++++++++++++++ MacOSX/dist/Resources/welcome.html | 12 +++ 8 files changed, 335 insertions(+) create mode 100644 MacOSX/README.md create mode 100755 MacOSX/build.sh create mode 100755 MacOSX/dist/Distribution create mode 100755 MacOSX/dist/QModManager.sh create mode 100644 MacOSX/dist/Resources/banner.png create mode 100644 MacOSX/dist/Resources/conclusion.html create mode 100644 MacOSX/dist/Resources/license.html create mode 100644 MacOSX/dist/Resources/welcome.html diff --git a/MacOSX/README.md b/MacOSX/README.md new file mode 100644 index 00000000..8effc400 --- /dev/null +++ b/MacOSX/README.md @@ -0,0 +1,22 @@ +# Building on OSX + +## Preparation + +### Prepare Solution +* Open `QModManager.sln` with Visual Code to initialize packages + +### Create Publicized Assemblies +* Follow instructions at the [SMLHelper GitHub page](https://github.com/SubnauticaModding/SMLHelper) +* Download [AssemblyPublicizer.zip](https://github.com/CabbageCrow/AssemblyPublicizer/releases/download/v1.1.0/AssemblyPublicizer.zip) and extract to `~/AssemblyPublicizer.exe` +* Create publizised assemblies: + * `cd "~/Library/Application Support/Steam/steamapps/common/SubnauticaZero/SubnauticaZero.app/Contents/Resources/Data/Managed"` + * `mono ~/AssemblyPublicizer.exe -i Assembly-CSharp.dll` + * `mono ~/AssemblyPublicizer.exe -i Assembly-CSharp-firstpass.dll` + * Copy the dlls from `publicized_assemblies/` to `Dependencies/BZ.STABLE/` + +## Build +* Create distribution package by running `MacOSX/build.sh` + +## Installation +* Copy distribution package contents to `~/Library/Application Support/Steam/steamapps/common/SubnauticaZero` +* Update Steam Launch options to `"/Users/username/Library/Application Support/Steam/steamapps/common/SubnauticaZero/QModManager.sh" %command%` diff --git a/MacOSX/build.sh b/MacOSX/build.sh new file mode 100755 index 00000000..d53fcef5 --- /dev/null +++ b/MacOSX/build.sh @@ -0,0 +1,74 @@ +#!/bin/bash + +# Variables +CONFIGURATION="BZ.STABLE" +VERSION="4.0.2.3" +echo "[$CONFIGURATION]" + +# Clean up build and dist folder +DEPS="./Dependencies" +BUILD="./Build/$CONFIGURATION" +DIST="./Build/MacOSX/$CONFIGURATION" +rm -rf ./Build +rm -rf $DIST +mkdir -p $DIST +mkdir -p "./$DIST/BepInEx/patchers/QModManager/" +mkdir -p "./$DIST/BepInEx/plugins/QModManager/" +mkdir -p "./$DIST/doorstop_libs" + +# Download QModManager.exe +echo "~> downloading QModManager.exe" +wget -q -O "$DIST/QModManager.zip" "https://github.com/SubnauticaModding/QModManager/archive/refs/tags/v$VERSION.zip" +unzip -qq "$DIST/QModManager.zip" -d "$DIST/QModManager" +cp "$DIST/QModManager/QModManager-$VERSION/Build/QModManager.exe" "./$DIST/BepInEx/patchers/QModManager/QModManager.exe" +cp "$DIST/QModManager/QModManager-$VERSION/Build/QModManager.exe.config" "./$DIST/BepInEx/patchers/QModManager/QModManager.exe.config" +rm "$DIST/QModManager.zip" +rm -rf "$DIST/QModManager" + +# Download doorstop libs +echo "~> downloading doorstop libs" +wget -q -O "./$DIST/doorstop_libs/libdoorstop_x64.dylib" https://github.com/SphereII/DMTBridgeLoaderPlugin/raw/main/doorstop_libs/libdoorstop_x64.dylib +wget -q -O "./$DIST/doorstop_libs/libdoorstop_x86.dylib" https://github.com/SphereII/DMTBridgeLoaderPlugin/raw/main/doorstop_libs/libdoorstop_x86.dylib + +# Build projects +echo "~> building OculusNewtonsoftRedirect" +msbuild ./OculusNewtonsoftRedirect/QModManager.OculusNewtonsoftRedirect.csproj -property:Configuration=$CONFIGURATION -verbosity:quiet 2>&1 > /dev/null +echo "~> building QModManager" +msbuild ./QModManager/QModManager.csproj -property:Configuration=$CONFIGURATION -verbosity:quiet 2>&1 > /dev/null +echo "~> building UnityAudioFixer" +msbuild ./UnityAudioFixer/QModManager.UnityAudioFixer.csproj -property:Configuration=$CONFIGURATION -verbosity:quiet 2>&1 > /dev/null +echo "~> building QModPluginGenerator" +msbuild ./QModPluginEmulator/QModManager.QModPluginGenerator.csproj -property:Configuration=$CONFIGURATION -property:PostBuildEvent= -verbosity:quiet 2>&1 > /dev/null + +# Copy Build Files +echo "~> creating distribution package" +cp -r "$DEPS/BepInEx/BepInEx" "./$DIST" +cp "$DEPS/BepInEx/doorstop_config.ini" "./$DIST" +cp "$DEPS/BepInEx/winhttp.dll" "./$DIST" +cp "$DEPS/cldb.dat" "./$DIST/BepInEx/patchers/QModManager/" +cp "./packages/AssetsTools.NET.2.0.3/lib/net35/AssetsTools.NET.dll" "./$DIST/BepInEx/patchers/QModManager/" +cp "$BUILD/QModManager.QModPluginGenerator.dll" "./$DIST/BepInEx/patchers/QModManager/" +cp "$BUILD/QModManager.UnityAudioFixer.dll" "./$DIST/BepInEx/patchers/QModManager/" +cp "$BUILD/QModManager.UnityAudioFixer.xml" "./$DIST/BepInEx/patchers/QModManager/" +cp "$BUILD/QModInstaller.dll" "./$DIST/BepInEx/plugins/QModManager/" +cp "$BUILD/QModInstaller.xml" "./$DIST/BepInEx/plugins/QModManager/" + +# Copy Build Files for SN.SABLE +if [ "$CONFIGURATION" != "SN.STABLE" ]; then + cp "$DEPS/Oculus.Newtonsoft.Json.dll" "./$DIST/BepInEx/patchers/QModManager/" + cp "$BUILD/QModManager.OculusNewtonsoftRedirect.dll" "./$DIST/BepInEx/patchers/QModManager/" +fi + +# Copy Launcher +cp "./MacOSX/dist/QModManager.sh" "./$DIST/QModManager.sh" +chmod +x "./$DIST/QModManager.sh" +echo "~> distribution package created at $DIST" + +# Build Installer Package +chmod -R 755 $DIST +PKG_BUILD="./MacOSX/PKG.$CONFIGURATION" +mkdir -p $PKG_BUILD +pkgbuild --identifier org.QModManager.$VERSION --version $VERSION --install-location "/Library/Application Support/Steam/steamapps/common/SubnauticaZero" --root "$DIST" $PKG_BUILD/QModManager.pkg > /dev/null 2>&1 +productbuild --distribution ./MacOSX/dist/Distribution --resources ./MacOSX/dist/Resources --package-path $PKG_BUILD "./Build/MacOSX/QModManager-$VERSION.$CONFIGURATION.pkg" > /dev/null 2>&1 +rm -rf $PKG_BUILD +echo "~> installer package created at Build/MacOSX/QModManager-$VERSION.$CONFIGURATION.pkg" diff --git a/MacOSX/dist/Distribution b/MacOSX/dist/Distribution new file mode 100755 index 00000000..4a077ec2 --- /dev/null +++ b/MacOSX/dist/Distribution @@ -0,0 +1,38 @@ + + + QModManager + + + + + + + + + + + + + + + + + + QModManager.pkg + diff --git a/MacOSX/dist/QModManager.sh b/MacOSX/dist/QModManager.sh new file mode 100755 index 00000000..c9993067 --- /dev/null +++ b/MacOSX/dist/QModManager.sh @@ -0,0 +1,35 @@ +#!/bin/sh +EXECUTABLE_NAME="SubnauticaZero.app" + +export DOORSTOP_ENABLE=TRUE +export DOORSTOP_INVOKE_DLL_PATH="${PWD}/BepInEx/core/BepInEx.Preloader.dll" + +ARCH="" +EXECUTABLE_NAME=`basename "${EXECUTABLE_NAME}" .app` +REAL_EXECUTABLE_NAME=`defaults read "${PWD}/${EXECUTABLE_NAME}.app/Contents/Info" CFBundleExecutable` +EXECUTABLE_PATH="${PWD}/${EXECUTABLE_NAME}.app/Contents/MacOS/${REAL_EXECUTABLE_NAME}" +EXECUTABLE_TYPE=`LD_PRELOAD="" file -b "${EXECUTABLE_PATH}"`; + +case $EXECUTABLE_TYPE in + *64-bit*) + arch="x64" + ;; + *32-bit*|*i386*) + arch="x86" + ;; + *) + echo "Cannot identify executable type (got ${EXECUTABLE_TYPE})!" + echo "Please create an issue at https://github.com/BepInEx/BepInEx/issues." + exit 1 + ;; +esac + +DOORSTOP_LIBS="${PWD}/doorstop_libs" +DOORSTOP_LIBNAME=libdoorstop_${arch}.dylib + +export LD_LIBRARY_PATH="${DOORSTOP_LIBS}":${LD_LIBRARY_PATH} +export LD_PRELOAD=$DOORSTOP_LIBNAME:$LD_PRELOAD +export DYLD_LIBRARY_PATH="${DOORSTOP_LIBS}" +export DYLD_INSERT_LIBRARIES="${DOORSTOP_LIBS}/$DOORSTOP_LIBNAME" + +"${EXECUTABLE_PATH}" diff --git a/MacOSX/dist/Resources/banner.png b/MacOSX/dist/Resources/banner.png new file mode 100644 index 0000000000000000000000000000000000000000..de5b6cee9672ca821261d83813ea2fa811390db6 GIT binary patch literal 61220 zcmeEN_cxpW+i$BysiLJeMO9I&W{qggmfFrC;-_e{S-{4!f`7 zAD4$=G^u_%feUiU;Ihg!aPVI`UVOuzY6?Uf&VJ-Uj_cF zz<(9^uLA#7;J*s|SAqX3@LvV~{|adQNx65!^4onDsmTnU{ifaWuGv*x=*47~#6^R! zO)vA{CoA^lV|%g9QE8OS=6TvBB{joakoHxY;l2V(wq2%OIrd#6bR(&M*aoJJVO+{gP?RQvrS) zGz?o?Gt=al>^b~;3{qQhQRz)HN}sNo7*9_sGJ-jnARhXbk_90omr|3aoQx7r(;pUN zgcNTFYN+}m{2a86IZl-5)6-9HuaPQK-{XsljO^v!;Ns%4>*?uP8-GCC{Tz?YB6@3J zVBnxq4P0tF`$9swxgtpUmT97z=TcgKS~@(3kyRi2gi=19e3#YgS;bs(QetAFfu3GM z9E)`Q6S!R2R!S#|b)g*snF}dDOG-*|{MB9EPdW7Dipq!gb5TMg=9HDK!9e@b^;KNUGoFj7=&533Nk6 z<7?V0*FVbz+nxj}b~$>%P4KZFgvYUbXRp(Vys9&)Xt3&f``@fHj! z(5z&IrwY?V- zIuGF|4QKgwZv>xjdmld*Z9NcUd`3Ga^i$MHM_*lC{Zwq)R0O$GQjyvEVWo56t+$__ z-&^N2=7l9(m710Zr=63np7q?>bxUa=bahUsUxVOY&@JWykkIn)-}$FXJ6M zPsNPN+H+uv`t!i0Rs_#%(xgFxK3tDh|9wJI0?etn5a433zKF{oZ2GF7w^pG39I9n1 zx>@+SDzB`>W~h8rmdU3MX;fA2y`=zio16T7^{Njs>WYem$HJ4q8Po@y!zwl$qtF=( z>XTzIEk*EmvIkWZ9&J5mD*ez0<5dEJ{QNOtiz$vXd121lWN&)5F>H~&W-GpwN_>Kh zMbf_e3sZA*#(IY6q|WK@tg8q4AdGMgBp9V>ee9Y;VSkzUe}ID<@&UWSEneh4A-X)m3xAE5Gnrb5>59Q34{!`E_e=>6oCj~8hAm(3u70NETHIb=*F z1bcc9(ysNM41DHsiB?-_54t$n_U6IC@EaDF8)noASKH9b?Zg6T(8VcDdX6U}U3_Gx z&W}!fSZ(cntA1D)ey>w}vcS?p*n4O4t_O9?<;CvSbF-$8o6!s+JGyt;ZQnsD-pCoG zGYXAG6sgWj9_OdIOMz#r?U=5ROP6lm&XuJ`zdbjSXfQ`%s;rpl0_DzFJ%-(3Ws8s& z!*)_QI6$DOvU$4JYH$dy))$Q1`>%h;~Dm)WK-+7`n$i_Ja6u|k%+XoJW5Um@0u({ zDy!|m%#1WqifZE3`Zy43U15DkN80WPg&Reg2JZjf66cyKs?wp^@{}qVT5X99bDqn@ zd-xZ)E+sO~@yE#=_3vl~9mU6;%(7Jh7c9>=X}1)ayMBCRrQ4dYJyW?Tje8!Q5Q|Zpz*^O4~C( zTuGz(S#@PftOCK$4WMI^kcslxq(1Y7`m?O9`cl8uL}Ud&q|8p&s`ZE|%?8@juA~(! zB%3~kn-TPg^$!148{K>~$fv3Plnoiq$Hx~np)-eGdi31zZ(|VtBDRkW5(wTI`0DHn znB)mQd~>>>NFQZh(bDn$Cu4CzF7dxrLXVnaMbc##6r&)p3~65-QTrck_N^USl>uH+ z$JqfbU_keWPkKnJ6jDq&jdfBwcE4G$(;#G(6hpo5qQe!m8V)$gI_6j?cr45={hG%% zP7|_rqW3c6D6t}Nut$A6n~|NTe(lxp{e*fC zmAU%wZ8vLB>bYY!)O`ZH7%?uJsN&H~{rQiJzjZahyFcT%(g7v;RUci)D#80SbaqO* zyQ(h0R**At%0YA(KQ<%{55j+q5tKU_&QGiWx(or=M}TLGhKAXxa_NNOulL9f-~Jg> zN$B&m1 zG4&C;*rH}B0kj3sR%fa@_PyLnpE#V<)uaHqdKpjupxNh~+-#+!C@Qd8t+?E&$i#l8 z3|wBA)G9(s(`+erR}`FLTe^=^_RS-&EfpH||gqlpJKFgW5aua{iWu|drWp3mw0~a)|Ej+|7U0tTa;qZT7`%w-N z#M^I5eNX(?(b{^stVQ`W2TV2*W3SAgooXc5$+Q2de0ad%&GW3=kKT&wmS;%B4vpn5 z1ceSlRYS4Ap(Zp_yRH$6{h2T9R8OxFXH9cc(|z#17Zf`dM!|F+25a@)7^E*@SxdvR zr0%z(5vzK6ai?(~m}vLHXl$Kz8|ARmLC9$VNzcMg%O0xO-STF4b3ecH8H7HOUk=}5LD>timS5W~d^09GLKV{0QG&L}g_*LxtjE|4W z_jJkt7P$PG#9TvG!Xwsa>0{=ps8(2j;d{WeUkJ9ivFI#2N+9(m5Yh5=_D0Xh!Ou^W zLVLsuX7?0$iqS>Ztop4o3)8tct@9O12xuTi0wF2aJLaJ9oOgwSf`XQCa{6Y05bQi% z{-1OMMec^$T17#5Jzp%Xyft19I}1}b9CmQsW`(B1@d_v z5%678LTX``8P!qTxx@rz{C1jb?!P_BiK6`%_YuLEL?m?UcA&C8*}O*wN_zblZZi#N z4%#hi5GXDylieSw{X)GK4#7`D@GTP>()_$IYD`6*g}(#d=T?4>G|04 z3qGc-Z%a_7(zvGx%7#Us`GrZM#HDBHa$|my0oFEV$J~Oxa!we+;dPTiwH)VX_D9ro zs@JQuwf&(K>L%Q(NeCve4Vy|+&$L8g$i#MhD zWDNN-aZE9BuAuH+<>fSU!>5Uf(Pgcddjno5{1vP@ud2MXxbWXP-t{d-TotMfH1`v7 z);3XLD%2|83Er!ji4EM$$tsOh!2o1Tbj3+M+S-tAz%)6xx!V0OTX?{POQ4)7RvKbx z@|<=XIBg0(othw5a3kh~g1P)}4(Ag6?-q4UXE^nIVey%r9zFU7W@6}J5t!?+^51Km z3p`xyi7Bd1m3t{soJ~t$I$Od-M(nS)rm!<%k$UG)Ph{P+z^Jm;0ticZ?=gF|SJ_oG z9enWir(%GxoM2Y$le3B3PMze=z^N$*4d=^aG}I57aMw;j{K@v8jy+40tqwdgG_PjY za=IfY;gjZM%$A1HNxQqrhuPYT$bIv;Qin$E%iP(lIbUi^8)!Fx$-vlHst~q73YS>; z(6u)>I0zac0GV9?vp%lHABv`lhD!UocO@E_&sLByu&AGy=VnICa92T&kG&OvZNwO( z<)sF3Mh!BAT)QHHcJ8a4mBp$32I=7u$% zZ<4Ct-g#)5HYM77 zPkwsToNBS|w%nY@=Z+T_7Y}l&CB0K`HRF~sa})hA9?-IqwuG~PcWCte6!DB1JJ?lz zBP`+*%#k6!6U@rW@hz!GC|>U^G$AH9Pc3;=V`?mt=HR$s;eEj;i=gyR>2fng1oZ** zV%u*kLxS^`uXwPv{V$rPV(X+tnu7-0){Y{M(2f)a`@+p07@Inq&2-M3nRH2(=Qt4Y zVem)I)}(l5|43~SE5wmNYw9;DkO*9NaR!q?DR8mHe+Yq;^Y`0IIvXwLByvGB@6sczR-{SS6e8j(P0_Ck@wlAaV3ofPPf-2eG9JF?AjEIVu^)q4}9BUvF!0J}`)gj1Jd z{UTUBBvm4vD_6)DqP^nK6wYk=q2o?`fkuY0tbHSpRWdSV%yy+SRK3VUdwh2GCrJ%` zI2-$iLV1gp{q;^A0|TS?*vz~MIt%ZM^_Sca%55+sHhexUXUif?23Oc4{t}D1N?#YU zQ|jWJ9|&`dzilIHv;A@Ac&+Pb=4`cd;J{3E$!H<;_s5mo&4vt-Jiq;f!LZfr&&Vr7 z^wQPuJIO6gMc_WP#ayc9OGYa{Un^N+oM{Na+UzJ?D&yY-0HS((k22`si$mV0D;>DV za9(kxVw{4BxM*YzqF2H0-jx)g#Xs%Ss&{ofSrl}yzC&+)3y{OZyG+g4CoU?gm-k85 z?%7rgTLg_|z&L8M|i2xL+kuR zev|s{3l${^MlA(>mKazhz3P-K3}SqZAZ6F!QK^qKOL-X%Twj~`_|^xlNS8n_dLO2} zFEw1M_Ol2uxcAkG@A)AV^?j}$rlE0LXb^?>rxSDIp{PhYH%EXs3}7& zdvA_-U_GKp+-OBY==I%wpL+}Hya?Le^LK1pqLMgUCyox0Y^78UB zlW`Mg;_})WEgQPHeYQ6vk=56vk^qG7&bts^f;|?wmqwrQ- z^fj+J=Phr&dd`LE(Nxo^57>MhPg0Mn@NIO~rXJdd zT;x0Ui?z8<2n#ukGY(JMKoAl{RTON5^l@Eb#l8ilrLKF|eedxd9EA}|@|^zCYaJj> zT@||#I=$D{{^az&Sjz@K@Ff>h?&LRC5yBwS-p(V!7+F7JQJz?FCICCXfj3L00l60! z7eNNu6^*NrAk;@Rz*ZKOBTSIH?8Y8`i}?Ync3UA{5>|Qsg?2s#R%MY^U%A?{nYs;> zF7ODtz4p09OS2KO*#VSm-R>cv?Z15^S-a!ay!^uJ>pitC=}C1?v#F=IuL8e97gLf9 z#*gA_Wh^im1{2jQ%N?$}#p-3dmwjMCnTxtUbBjk3NPD8cT4wJL_oMQmKE1Umf zJw+MC&H*f?!tvaitkn*jrUA&hC^F5S5$IKHu)8g-CRZ&kQ70WSHysJZP{T#^2v&u)SauAg|X@O6DbYYAQfay+cSv(P??n5EUn zl4ATCEq*3Vk3Xm>>88pc-4dQ$*Mf3gO7m_bjZn`eDrkdz^;fX`OupW(mzb;b0dyOF zJ)ag!$-IZglL#}xwnbc?TKK{f&W$uRJ63p1YqA)2MD5S^X1}xzh)>VV7#?P#Tec?m z3ZSk`yRs=>kDMc)Xs}@4%A!boT2=P1L0hmzl<1Z{(h?LoY`~ zD)#3jKTQuk)r)3=j0HC_jKuThctT+!Y_xcGzhckYn>FkY&?O5WC)6EsGt+RHA%Xsr z9rs2Cq0eQj4(f0@Z1{iK`T6lF|C@5Zt7&?|<;7FNoIrrP9FBUwJuU;~wJaC4bN3)y*fgj`D z1`kPe*kAAt_~k5XxwyEfi0bLk$}&;7xw(<}>@Un_;y+FWR8qvw5E#3#ZC*=pZSCq- zvPPPLRC(bNl;!Y4F$r`LcQnlg0V|Oq&JD4J3l%(pi_-n4(Z|oA_eJ4+ouJuzGi)FD zh|L^>hFoCopvsx$>TBBteJ&T~dP_zfQ;v6hO&VBaW>}7ni%dzR?KZzfvZnbRZ>oc) zn-OALnF0G>@r=8vOA=Huc@K@IB@yQf7y3oi!k0-V?k_o++ zv46|f?!a5D7`7Bd->>12yw4RD|FCNKb>%l6fN#&>Sd$NDtDtRxLc4DFlI*#G{iuM_ zW2;1u^yAZg*zXiNuhomnf&(%C2W!Wh2U`$gZibuCF&eg5YQ-iWLF7c(@O)9jDNSb!c#3Y%0jfS$j38IQu4Q2TxFk=in64M6I%zY$yK0^*H5x za>M0V;?+{$2wi}fJLFc-WpoHG>|k;Bis@3Lw-T!9N@WG8ml#cy+1u1dV$g?1D5Cz@ zr}cseubxn-?9WWQzY>#Zij(uIQ6}MYS-rk^iGOF0k}&CC*U}{pj%M35HrGaBj|tU$ zKo=gU+8wK&CXVzY$k5_u1n^PtUSB`vU%aJ)9s+{tVpF~`B3HOZgnt#?(SAHCz4UMT z$YZ67*|5sG2i_Wh_PO6P5ceOm|P$3sE z-V(Mm9yEe@U~`z9ZY*sVWMij5h8g=e#K!#Id?xJSdo#1e3NL9!*CL7hvbMI%l(HUz z?dIW-;r)JsAUgrh36k;aQj<&D4Nzv+D<+VKY=3}D6WUDX=gYEVkAk2Wv?hdcb8MGN zBFBM~iQq3mp+myBXZ~c|G?!(lzv*2PBMx${vEdhiF~`pV+;ik=tS3hdzkF!hHm$B~ z3->p(08n{}B}%_9LKXH~?Cno>%l6ocP+N$sQeW|^_}8T>L6mRR;q#wf25LCS&ObtJ zaE321BSGOfkS|RV?j?)I0{Zkk$iRwWZ%g3bUBct=EG#c~*CfmJV0Trc#erdRS2#EU z(d;qAe1bC4H$wxD22$#{DEkgS9%Z_x8Td5ytrie>Zc;Fb6aFpStmoiY?Ui`1 zRzc}j@C1vb&f5APVa8{D@doEdA54x$xnhnj~f`kUgi$yjd& z7IuLJ>g6usD`^@ArArM+7db<8JY{>`dGKZ1o8$Gti{HAu+<>#yGciIBCdr`C}g+uGqfTX(zD_X*FeF_^WspID? z`c5?_+=-`=O`?ULAZ2-7%x3wM!nFnps*wR*A1?#Hbcx)~%X@O#6rq9>BuCMnALM}26R(NtIRSCwP)lXYMTDeYVkh{l0L(ml}RP(>QIdemeus?Lu z=eR7p^TUxVY05UgUxJw;4jSGvl0X7f6jMp7mqbRDPhu7t2n`Oree4dLyK@-S&xVsQ zUNzk68d{a?YZdWZUzPAkX7euEW0IA9Q~ae%q2-INoEShVs# z-I#I z(IWZL>wy>#8&s3`?pffL^wL*ezon||0A0%Nuf#ac@U4WAG-HvKgxWHQsV~MRHXbIbO&GHck3SP~vD_ly=B?#4HU;*~-!xK2f(c4D{$J}-* zDRFLtB~yNd{F>M@g63V39yG{PKzKoNn`-q4OrX0xS<$eptc*YEXVo~2HImq1Cu29_ zPeTBDKla3kx@*N)_wP~_!8nVdlsR~HqUvqi%HC97skj`4NRSlZG#i1j-J{!5U`~4* z>OI7?H};K3b6$3(lU&d>l|cLzoG112EG>+*wS~p=MPjxdF`s99RA{QHsi}|=G9GPt{ZP;xC(}SXEPEJ)Eps z`%c0A)(ezLfVTVjYv5=8N)y7UchIVU2@l|GqsQ7lK_YW<;r-{Tx}^l5dBNy66?)nq z4$Ra;?;X^r{Bf9+Ii1v{{>CYzL{(%`=R9@R#~QGAsuz3!ejkbm&UHqH6CiB~T( zTY{I&@J;)rZzqO&Y0+2_8($Lxte1_18=vWkjoRAgB;%{74Nr19D6vZlsKk~_hTUYe_OLFd61 zM&jfyF>?ec4>FV5_oIAeJ}i0kc0nkcAQ$SI{yP$y`w{G{Uo2k{NbubJ2Tc%1NiR9| zdm#U^!p$|ToNab~jD**J^erh^_8d;jBbz$JoHv40dJ2zb9iWStYZnZ2iEf9y6_?kM z@EanO5dV&h`5bppb=iy}=;!!`1y41f;G?S2b3M>nxs03j@hfx7-ThejmW9jL{hioO z{|%AY=x%jK79$`^6o+A;J`slZ*nSHFoyR7Ak-Q$#YWM-a^ET3dS=F; z{bGu?j~v6!nBV{f`%E;notEv$i-`sM-^L^HhSQ{9{7wPE2bhxbCg;)MJLFG$Q_gMh z)_NlCm!}mK8m%7q)Vyb5fudq!JxlcE627ea4!L$d@Q3cr;ZC`O9~ZF*blU{5aV6~B z3Cx{KWdKOY`Z)GD;xWCN^RsvFu&$eK1aY?4pzSEpVZtMTo%WtJwEO&roapn>ERfti zUpt9<9zfg?u?E02uezn^KN64mXGFhu`ebyGzKLcifk(HPPS89ZIo|*@-q|)z0DLi- z@PJ$#L$7e?Y6Mn#wUv8W#CiA&%rS~r<@P#8XrU(X{7C%@2fM-rehjteT&|lopTEo# z1UvbW@oF25ZaFM@5Cl=yhVe&JhcpMAdMdwSmw@VtrS(hr#U*@462FO$1Lr!q1*VhI zBItZ$Cj4CTFD6K{>EPbeH+@QSQ15K))20b~xW+C@uK`*C)RRXZ^W4vS{n1-n**f$? zaS+^EOp$8iDM*fOg;PJbfG%vHyGhwHj?5hr_O9FeFlH@SK3C6$q!;x7S$KT_VQv-ClZZ})Cv{5YVZ`LLIX?y^e`*CkExYasznbM^W3 z0kR3`f$kLijK$dQ;VdlZtev10o$1NO5-aab$b1r~gS$yOP)AP3*f2l>G~l{ZnLm>5 zCY$-prnh68+nWz3pqD55!Y6$D67;T(Y)VxbW1k}3(h^TYu#WwD?RX>*nq1D_kZ+z? zqnlGM9)`GQQ1#5b`ER3pG{bT=!pL8v{%0tL;mNW{vCjSIKXf-=20Psj1z*daP&K-> zE%e^3NT~w*YHyL;MULEs_KvYd#-%%;OHFU49&qr72%l;#RE*h{XRreF&MB|`5);$# zx$FhvdWo8Skj}6$?T-wQQBqz@jIuw z&b@S7HNbTXO;P^nZIl)`-KekDoCB>Z6L{u@O zya4TY>jHNE@Rc`O+dDshCyNL?71lVfxVor-R1?@zhj?!|2Y5q4$KFo%wbU&OJR#rk z6nqp9Z4m`$w(y0bjK=;jjxsIh^l|zVuMV^qNo>F^a6J|>5@Js|K!lf$A=Eof-*7ss z?XvfePI_+l*Lr=GU9 zw(qo=uUUeBf_oZaFyr4KNN5%6biO}Bkes_JDXR$WTpLLtfAzG7N-)Cql3_c0_+x^T z&xYG=zuZ;R?imgNd7wRP4hUqS17$Bud*o=V*tnD~;NE=g%yf({|MiU+ZR9F| zizUYJ?f5Dc*VU99hkEl@0nQV0&J%(;{U(fXi-8xNXGngQGCp|2K4U+*=v1P9!6?2> zm-K!u@3h3b`;sR4e=E@|;cVuR+VDyio?Cu9bxs=Wa-FszXEU*&U^&b*OR)m(Ge1q%kxIau5Epu!DIW>qYXnzP1l(+De z)L3~6w|T`jN}aE3@BwG8ceTc@F>h>Q;+r=Ok>Zz&p7pjiKX#4ic4hUb=mcJF0)u>a z;bn^yk);J_OI-zpE_foJ!Tp}gLAGs#thc%DA|`b;`%?4E^f-L#x9doG;M^EElnWv` z`bG*Tl&ao5ZwxhV^$Kv9?g&D2h-#Ln8@@Ll_eGp#mtH~B&J{w5b%g;Z@lc$tjelGz z3PxFQ?CY#|q}w>ehgs}$ua>y~x5|xrvw157Dgi`vs|ozhJp@g`K$`hvrzIr@6|v~i ztZ-I;Lgr0VIGs!X_c00IMk@ukl%DOo6)}!~N>hMaCn1Ea$^Zlt4gsA@FP)E0sH&+pkduEJpS2pm(j+~s_ts?AH3dt({KPS=(J~9L=g(uD*ro*t;iC6Di_IL!FQGZ7 z2Y;*{#MA{2PR!NDmAJQ_!b97S_}Z&;QST%Tzg1 zM*1*|xl4StL(POt1bff$;sYv0+|5|@fjM6b{EVip0epE3h2S(V*ELze*8!khUf8d& z0!27bLJcGb=}J-$u+a;^lt_R$Km+spR+=3L9QO! z?Et}XE2&yP11!P;z88Bs7{0YWaXU75hSI~lj`s5Gvl-GXprP*LJ`zPfsh_A9%_n90 z8^(5PvVuvq2EpxgfAjULa1KSevl*LR?8M&~hc~7KbD+kC_fM(sqeN196>@-w>v5Wk zOC%v%DQMo(D4g#ni&*j_BxA)3yrlB)4#T#Cpk7Waefj2LxE0lNg>H?HZxmSFIiL4Y z)KTvj1a68zjr`YQBm@REZc!h}9es~8O-MRUO-(&w`e|ckBi9#1Kl~wfwR2bL3p*Q- zZ6)Z;jBo|BdCBHd+}H{(z?baTDKL!QIb>d%QmDDO7?0X+O@5beHy%LAPUZiPDv~BI z!c6hCwjv;rS6mSv6~xB-nD_DHtTzuy`CpNK4mmOB9!RkDM{TqtywIruFW&w3wSOV< z8I6|N`f0m~&^?>o+Vd@IJu@D+Pzl2CT0r^0Z5F#W7i5SbEE-i|USm&zxJtGE*;C&C ztxHn)#dE`YSEDEp8=s|Fif85xB0US2EgvY2~5FKXe?Vw((;l(iFlKq z8@-_VLN;nf-X%HpJl;AuM+t%bI9kSWpyrac{L+^f#|Zl+p~tgk9Nn;LAK+%DW}^=F z`tomI(xQ#|0S%QX59d>#wYK8FN%i6p-XrY$YE4~QYrIbql9C=FOx~x)#y|Ra#j$5X zaC)jB*fZoqLO3jAY~GiS-&j=nVx=iK_|^%<$WZKT!YI2A=&ElHrf6qt+s%0i;NdCi z>!~YDz4t{SbKt=Qi6Gb94O&o40no`#J7fF60m4{(Q#-0M7gXxexSgLC+xjm%D*xxr zR|>bW&GfV!R~Ne#7N79=LjtU#DtZ*t@Gq%c{jh;wY+9~dZs;=FqVdB@;Wg$c5Fi8u z63$Pu$U8G+&>kKh2MA4Cor|XWTX+WHll}nIrR-UFRer-PrLbq3)xn_QhV9-9L}V`w z#`aCtAMP$=x?UdGxGE!7f=p>#dG&8b# zQO$CMN8HMxx?C6TtE3S8ZR5@=tG)#`u}xd44c8rggZNI%vi8jykL~e1 z?`B_=fFB|Ef+i5Vmp1ECFO)*KPJd|Uve42>xXpc}BIoZB8c=Esiy%_xC;J?_`?*o@ zwd3fGGPaPE&mV$8q!|gcEKn+1#+}_v6O;M5`!v%EruEJBZKNqT3v%;+`&by+oQ6cx zL&<&A-^9hPo4FEm-%$vCPs&sSQHx}yt9kq@D$th zuJ30PRa&)riBQ@bXM2LO7?ez;L>Mw)CN35|--D3A8??>x! zpKg~L)r@Nb&exf9%TFA*4Zm=qSC+3Sq?Wz>(8{armTxT6Q9Jd|f}Y0a<&Nd3^bLvp zc#J9M2wl3wn>wl!MLMgf1>WGMVdrkU>;(b;O3*i$6~_ z(!}|V%nt@Q5^TQ17*^jZf=fu93ldu1{Y^B8|e@8-~If-F}-t-nO;<0Uj9I){%fV9 z{2?;~NOhxzgphL|)aD-_m9kv^d#ClznG~;5iYR4BW3pFYW7x5l6=Ny`8w7DqAqtB17mMNpvTQqSJs>!iwB2MOE4bMRXSmh^isdnX{378J-2 z)+p^Mef#8U#oANJn$I6@M{xY4_+nKm!imqS$ar6~`D#Y~N#Awjve{@V;O6GW(iY#O z+#}>ellf`_Ol*^Ka~m5QAHbj#U&qnG@kD0!Fl*||C&9qn;ePe7KQv#43NAm9sAZmZ z0|VEXyw)Y3S%>+4c|SYlFh6~!N2IP$Y5jfaq?ZYp4j~BevEtwx*#_y4v6=omJbwB} zfq1k!KO*m1{~|00{ENH!jP&WRKR~K`kDTI3LBBU-lLF6X9paMC`Xz&lB*ZA3RYK>s zCkhIpwAXa)c`f4~?lqwi0n>xB<&vNS%TV0j+h}RDS+qUPKxC3jOr`|Te9);NBZ*5R z|K4-c-o0u`3#|desBJz5`?oZC zIKHhal}-=7e@@(gNoNjXmv6DM>i?9jJNyR1V=lUd)3%!iDVP@T{Vws)@q9A61Zst8 zG&SU6e)WHQyd?5Zw7$09eWc_h@6Wj9C$Cr7EH+WLV%H+RXC-L98tp(^N5fZ^;SIA; zrJ9>yjD|xk#XKVLcm#i~IU3p9+nWNj01vq}-cffXa%Izk?_|H>n_rz{w|{)!d(0sL z#Ir^iZ7o%;BSI0FvU7s4;#sA&2$CJeXh`34Iy^Yzt^Yf{LMw(R3VUC@xLWz?^xD9Y z@;h3mvFQ4BqxvEKv;u;ssuQw>=bGOBWgj3fowf9lG|-Q=t2^H8sfi@Ky}zb;m*AEC zqa)M@o*&^D`whj4>k$m{c%az!^2IV} zr#0@C{@mS%PoG>E+mf#mWTGp4TglRt) zG3T^>TJqlhr#pE*uVj8zVl`Lx&G=hdByfAI ztXXbx*w^@%Bx1LTEnmAO7oemHKGkCS|5a)&-2sfY)wj6`6}Mj88qMO=xA${XP;l~| zpf0QUOM$1x#P)aJauFswCPbpYjhVc;)q=TBtrv9ixyjsOlV_FJYK=PZlqLr#P3Bb6 zKAJw`9af~*zYgw`s{B1EaK2a1ssHQnCg>AEV7$=X8)%iBDQe+EV8w`BuI))!om_pr*5@dg%fy)h}z(Rvo1*+rz;ti={3(#5u+i?6UHo zHN*Jdw^)DZAg^)nj-cLnkx|Sl=l;!s=UsI311pLkf!lhVFlu#vetx&B zi|KZ8e)AU43z?}_@Ht`OC+!IspnV~8L7hn#@!E`@$)%xxW@aXZpyD;x_#Y!UL)NaP zH20FHE@|0jkKy>Ee(ahZYG=1MK(^{d&iBWwK{Bg3;KiGd-e2b}D&&rbMdqVb{_glc zGBpXsvt*iNAUjSwo^{r(vV@$mv3J&=*3Y|}u)EP;WS{~avIL{H#_n80L;h1n#FLYSG#YG0KlR>IfPca!4w`E9I zvb*YN%8h6xm1DNM$lRQ?nEXTfL%eS|9(I@R5|4tQLa1$I(2rJPsJ0rnKz*wh(iNYz zzHkhJO8iS^47k-p@aDe{!`{7+3BO1F>|kK*)}x@QOwU1{m^2As`SVB7TcJ^ag{fcp zQ6F8DZcJ`&Y=}kvWl*h9jUs)bQX2J-EYYju)y=A342n`;yh0zBeTPkV2z^I2*xWpN zOp5Iy74G;(0br~B{ksgA)4D;$N0l!{0ia>{nDBIMFkg3mVcc+OVUC7@ab5SB0?1H{ zbeMTUvwJ9&iji?gm#U3aV% zefydqD!r3H~zy>er=Rt-wh%Ut+5F)$3cyA zoK_~}m8a>4kB*kV*rHsC=7xCFP8r2o9G@xp+?RF-gI#nLbX}qf<8>f{IF2J(N7yO!h(-e-49~3$nVJ z65VEi5AKPuQo3qJb?KkDsFP3_-7PCFj%*|(J^<+e@WmSoo6hesD$#A!F7VO;x*Q_3 zvIAFu6p3m3BcZ5=oPw&+k<7E26(Ulqgy4#FaY$4n1ZEx;|8)p7*I`r(3>@;$BmSpF zQ>hS^CS)OgxGuX_rDNo zTULt}bHEFAyhP_LGv4CplJ5-u0)BVpDM>F`_k*7<6mvT`b0sfW~`qvahk{p|BAqD5bg$wOY8u%eqiU2bL)K{j!ne*egJW~BwZVI}4%XG73@{$^^(-kR_td!GUJ07wVn zKzgjB%HniuoCF7xAHN|8IsbfUzaHG!*F;v9_(2c!>o6Ll%N|HbSKal5aM(VjLEj^0 z=OtTf4FUXOhz}HYjy{aUkG6B$&iqlW5BbI!Dosv8mvKtbKxaWGCl0ulL%`?N6nB0; zMg-CJq)H&(#__B|jv}Zztpny^`RZw8+6#lA+rI?lz5AkUzS|`p-uyX0nsmIq%P~(H zz@h<)-Q&LA4g&;Ku;*I%Z|BJ#O&CpE%Va<5jS~zVT5wEU*J+*_9DcPS0+Xp3GEg94 z4%n-5vd(=~X(N7jI^QaMF)Qo6#ybolGp!Qw{jbZ0)ty~QR=@S{6mKS+T3jeCmucpA zUmAC+%~8ACOblFf6ZT<5e1=nmsm`b{|3paDm|P$`(eHiPQ&@?3udRS4j`WqcnxeYoBFnR+MHinUL`cgp z&-)69ZSCxOus`hX+$JV&a*+F&#jnWFts-w^WOSMaZ2P@??V(T1xBd9>gF{mqS?jTC zhOlV~=K3&}t@IO~Gs_upw#Rdcf?P#W-H)*5e?Ve&&q^u%ewW_rulN+Io_p-B=rx8dA^w{kxo- zE}FSpB5t;2H|;!VRTy4LSa<#2_FjdU3jHkAp#?o&L}DF#AJ*E7Q<#*=yhlz>-a^BgmYLeEaK!jHhEl9NBM7GOK++vHm1unB~_CIxw5UNd< z-elppcWa4f|KvK^zPQ>GRS?15))yMqPXQsU=h#Kk$>B465wAC?PIA6o8=d)rQ8ZTs z4&e4}>zz_*q%}R0c0MI|yr$(B?4#bp*oX*HsHoEqnEtz-XT|fsy&QgnD(X@a!x&Fh z7V78luc+Y32?>+#GnHBQj0gejfwop2TLaA%Byb!QBq|R9)To(^P6kKE@a!??1L`l*F$E3$+d=H-My{-uxX)yCx8j^41$#D1()N>WlzVE;wm5Q_7 z{d_C;40C5GhxNf$-A*5IWfx551aOx-uF5HSYAat=(wyWR6|yqsi`q-M^P(s~UMexX zGPPa4seM!4Hg@uk`k^@6U1qk$N4zso7$depJBgOJ6IZt$WWpAfE`vHn1qB697?SOu zry}P0Cf*BcHZEH=Z#4UWyoD=KG^EpEvSHRDHsCzf*mGU*vPK-KwpxNKq5UDErL>^1 zP>Qr3qwj{SWAVkzPl7D#PvEp7kj_Nu4lEUpan&)_(7?N;O~%XU-Yc?SAMQIO66i&Y zCVAE^50W2xjKYHU%fHK&nwc{fW@{~w{qNIazH?~Ib37ahaCr2hreowZlyX+r^2AY@T=99iK;xLR$T_AAmzveFIWXDWkts<$ruf z#vm|_q7W65!weufxmO_)bTs{VQ?`Tz}*1B213KF)`^_?UH96K0p7GHiZ&F z!pE#HG62K=q7i+#nWbYo@U;c5@5gz*xOol&eX+V9!aVX<88tVzPnK9dcVs^n*DTG^ z(s=E|@5``Bu&WU;=PlDf?#H@IT?!|UL2&)}(^On=-(BnmnM1QZK5fyN5o}v zw*zqMsS&I6q+V00wS29$E-o##`;o?VnZy;E@9@mefMzSI;NsH_>?~Hu#{{)FH`jOS zl7AVM^Bn_%A41e|t1qcdJ%=1Wk>%2to-<++5;C%v3y0H#W)7N89~G<(TTJ3*1BKfs zqD%A33)kK?b!{W!|7}@^9yNieu&0~WANTp${n-k2xS06vsQKPj#2 z*@%^|o<{H1-Kp$ORoU9JB<#qTJ5O0UM2pJnTD4!IUc12BVH4?#9NeA+Wfbcl{4=t< zMo>UN2On}Tg!k|4V!-hQPPN@RQi%c2LEy^LSEEtuOIq2bueQInikYh}pp~j0-a9;Y zkQ14aFi`p&ue622rz#$9H0mr>0~R_H@}BHBaevFaE`A$`5>$|vHs9{DyM-Km|4_tS zm-n4J*OI=FZrzK}M6$}no|K@LrUMhGQmo}`6#hi*$m+S!+Njsz(b3Uw6%@i%-o6d% zqWT#ZhZ~oW04b-W)5(@?)OZ2({@*`-idQq^P#kyHDntltipbJYetXfCyNmjl^mEf? z#!mxp!KeVJf9z#mTmuO|8bR+WNm;Kl%Jn4V2RqE;N zF0Yq1x~&0UUPr0Z^;i=b#vWaMu0G%>EH1M9^yy?fe92D}cqzFzjUgmMBK~Zwd_s)e zv|RnA$I0EBQv^Pk$%jx5_jn@52U}dogk!^h;g-doH~)URj)3zw>lH`ydCd$lkGZKi zIO~;?1@TFh^2>>JX;Za<_hzYH9rrT3 zX@IJ#9hJWVW=EM z6#{W*b_5v)4FI`c!)MXj2%ny;L&13vuzR8IAKE=A+e}vD@JzPZ{I@-l!aHYR>M8h+ z*al>3&oZqNT?dD^hWLJIY<}|&2dBUx!yD}$(d=SUDfgq(%@tn}?X#;{!V_w*$~@*w z0c;2w18x|k28`RV_12#)_y79$_xCAeh1&(;nj+c0ZbT%-@0GP1x6?ib*VbBIic+rv zQSY-<}Bic}aZiaH_Gdi#XwQoj;E?Vf-7bMY}eMXzR2Eol_#`PhhY>9^vpT`RIr7jP+9rW-wb-Ut_ zPp;OE)1T?Iugn+jAi$;nQIPptL5^IbJzk1#)#mqkypK2=5%>86i7)T<9aYEV2*k`i zEbki-!)JP4W4G-6I#;)*1yCvT{GS&fb{P7-L{wDl{xS=+4X;~ri>ME~gwYY6JEWO3 zA_ryu6Om&D3eY#b4j9h$4v~QSOAi`vDbsKj6_seXNtOWj;LqV;EbVleY(yF&ckPM* zN%R7JkEj4N)$`5^qIhA?f52K;Txj>{L@=3}aTF;c6k}XUuHGtPSQUmD@FhG76HO%o z>qM{!5ig#9qO!&{(4G8*m1OPvQ32&A{K=?^h`PGEuD`DwTR_dh`R?~LP9v#OE3P)6 zai9YXz_YBN0Ig^AOW5@e!HR8ew492KjZG*_Hw%=XeD&JZNm^>x(6~l! z09Ue9{4h`M4fs)pD00Q_5dDG}V@0{H66sI%$;9jg#;}v(CAd=^)WH?f z+U)FXMxS*V97^U2{DR}rerHpW$LsYy*=;+5qrwVHjcP5y5@Np!W=IvUVj{Gs$i8vkxwq)}bsejI$f~udR z#U_s$E!Y9GL1PKFujLnWcW?#w^mf@0l%r3v$GJ|rd^xg)^Xnw`Lz9b!L)FtHw9=1v zA{o6SHyVRIPbH0lK~6KjvMHE)H7{7&xywF*ob>H+lvJ9Ad^D~*-BDNMsfb26t=Zb- zdjrwQG*;@9# zf5HMsPk&l3&0s-werjs9X_}R;=_1z9W1sWx$QMD;p>XFpwf(m))yUaOEA-HjokSh{e#bXD*g@zv8YxUo+tm789a)Eps9kBYmC)mhqyB| z1uYRfP>*me8bTxRE8WAn{brW0+dnX{NG+6x@`WCwqMXDf$fEK9aN>50;AY*oJNf&p z<+_VQ88>g3$frHg6X7fQu+Uynxs{bwY{J*?iK{8yx&g8yTb6pAiej?hC0Lb+3H5+^ z;(QyYJ_JM~CC5ELN?jL#4B|OVFh+VD9A0Cy0onw{aaShqfG^S{DdKT_YWeo^Dr0*%fBWsZR_0%wp--D?Hh6lgl z1-K7?DBG0QXrR8pon`B3pKtd)>6@`s$EI?Gf}6=lE*XRDMc(j1 zLo9dbS?Ko{(U{m+O3~q=Vd0QVL7BXw!h+oL;z=B=?q6PAgtW*gK_zjJUqa5G^b{2b zB{qkHwI^$@I{}IMlhvTP5nQx`1hwfbZy}8fps#Me1$fv}>q=t@jhZ5&a7_Z8Cd7@;3V*M!IF)jR)~QBD8#p?)lR=0l&YCV>=|$mA)@ANVYp0G+&j= z$$0z0=G9B5EEE4^|$pBP!uBw7laA3b91p0YTq9lcT2J2^z`UPGssX$1weVyM9li} zT0{=CHCQ-crhSt8qUO|@PL7V>o|d2Pd@N|pozgp-NMYH{AV|ep3rJE6(rDkHSbwM2 zF~rfw2*(7!U-i#cZ@kCntGZ6b5PREs9)Au?j^1R)ezk<25+Lg< z>f^Yw^^;G7pTA0qH-AOVq_AdPYS49%;P+GSq5a@WT zBrb8^0$V#%c>9(&x3Qff@3-|-S+&-9jqw}rAodGXkpRv^VRAdF=t!}{60=o87Of)2 z4%UDZh!$TG3Z}z18LIIF0Cuc?PZ;X|Zu`>)lGqnF8}r{h#Zt#i`lZmG>$PS=$=0M;p) z0*3mYfmcDn!IvyD_6b?DIhVcFveiR>GM+n?h+yAvORG^GU3dW)et_HIP=s;mz6U@@ zf4rX_A2dOrNU7w4*c-9q>$JaV~8aC#R*&~^MawaQ_2iQ2+O6?|)<3r_-$a)s%1+TrZ z^(M81kACwUW{PJT6)!`o-=n4J{W(k*|Ji)pj-kuZa(}u-$gX$o>h`|*aV?zVvupzC zl+}5cgxqPMy0V~Igwoj8W@LwGSMHAVz8IkK2EW7qhXTULVi1ld*yfE# z3%t&80o;*F8n+pG<3a4D9@TM{$Jv@L!i$qIYkL&e_>`yJ_bo!pm^5&~tjCyp9sinB z&G>ewtEaLCUB{yQpuXw5+vC2W##__DH*xBm!kPZe-H&7uS6ERQU2QaLneDXEX$hR% z)ZCpGtIlPAGMHN$n{_-rpx<}dj+iR?3=z5V!)+ZtzfkzezSsbY0o8nD(UEc?cicNy zb=|lWnL)*ck3+V=h_k%y12eC>o|Qnm z=WJMpp5V)bX0@l0T}1wMIZVvZw_sA;%c`rJ-E!v7$M<)JY#vWkrA?hsKHz&1N%^GN zXg|Zqz;46FZV7wHY;0^qgxmP!rp2r|LHrRd)u{u34!-hmHNq~zq}W+SNj34u$1 z3@hllX)xF@0_~w)*~!Vt2ued!qzT>zjj)sW%1YjgwJg!quA`CoMs_0WGVx!J4Vx?a zJ}xmYNeTEoZ1l`+O!El{#@{vu;4r7tU>)GZl2MYl4)5cb+|RaM-tVq`>n9j0LNY=t z-+PZh8(skse$9y(9;OfZm~7z%kfR*f3AO5de}bBU!SX$zwzj;$fYH16(XJ5#*=v{? zd5o#zS=DB5I{4A{@DOwB0D*(Bb+CuEw!Yr6LF{^(OBzkp!>^ip5T%0wqEI-FEnwEp z$;siPIes{qq5a43_uK8ll(t^j8TZl!byEH1I3_05Iq{&3ky%CVABrinS2Di)RsTiRON88lZ_a+WqCP;)ZFsE_aP zgklpDiP?f@ViUf%-)NB9E&6u@{ljgmEdbS8%Mdat43(x?p!74)*VhMq05j?r#$DFgwAs4A3RlIU3aD@wplR>upruz#i1`*9 zi(?o3jLZWhMMJY(L*l+PKt|BF4A+@|va44ztu?8Ly!_zgj=0nZ&Qxctkgo(|%kL4g zmW*B~SQQo76&f^Ud8UaAC(^Awc7A;$xSHX&+otkoK9<|x-oRe`<$;5YT(HbXuhV=c zBWgb}%8JVR0&^#Q&39%>0b1vpemT_wsknWbNOYOyeT)y%*p_$i&6PtuijriXab#hC$Yg z%}MBbLQfd(rc*^d`pxK{2P=g59&KjTLkPb+{zAvVu#SkHId4TXUJNN`s|-R>hx2h=&mj-?G;8pBf(ozS6bOV2EerH8A|%iv8P z&6Ia+Ri?vw(t`sR=Dm()Wl7a=qp~Mm%ycCBJ zMn3S&PZVpHXLeq@)|_Hmzb98jcFa04}N*!h!k$YOi>e($m2M@r7WpApGve4CM^Y32`?KN#Mvci~3K*T$3zTiIAye`v1Cw!drB zfiObYLzxFn&+}jjBO00@qHuWkd>G>j6$R~3^8oHtzV9qmSw#k=M1v%PNCp=cPOc<6R5|9^8 zs)LM>-HJ3`g$~HK6f&{1mv{m&-!rueZ=Gu<*z&KnN-!DtqQ>WkVnswmVE)`0O2`=8 zqAX!dU;V1`sjDgmDaVK681 zRqYSUdJpY|?c|U9bo?{|_qR^ngGs6QAyVd0ywIQ!dC_^yPXZjc_G^a?0wf`eJ}x}&<`?#7V}8%PxR41Y+=dy*i)rvs_@T0m)|7-&ve_# z`B_aw34>=MR?fPeBI~hz{`v`3R##WIY9Ft&JTAE=V@E(OGKyhMq-NDwnMFl|TR|gh zUCN|f#z+M2){MWjNDmb#F}EwDIdQJPI%1~X{R%xt$BEShg0Id7`t;PtTzbCe$+Aal zU8Q{k11vmZ{>a_$L1QbCoBVb?HBpCr`>2@CyV7Pc#0vmbDWPIh6p4M=R;?Nl-tmc* zltMw;wEVB*IcvQ%^DCaf+P}Rw{#wk=NMeDa?WR$tM!%P!*kiby(ST+v}ud@SZ0(HyCqPj}HprHdYASS{^_Vf=xyuC3=o zCPfV)+5xJ>Y`Q;ej?=r7d1%e{u{lyQKs>QAv#nrV15FoVTkauI$tF+qTBafDvgRF{>NtpPdpeiSxt zOTqn+Pz;sah_!PpvQgi+%NCB#q;O$z6Wi6%7Xtnfq)95 zcQ$^Jg0oMz_;K^=%Dd1X{855;`xO;kzQ;_D6fO(kygx&hS0st9oi0-P=-maA?k17_ zqE%wh(rgJ-b>e0Lx#L8jLz>RPFSKmX;%@Z>Y%ffM;OV)o`1~}!IWN8PsOX#e(c~Cf zU{(_ogkF_4iBBS-Zj*^Qc#;Mzr^r_gJ$^yIU%8)ucmn|JmC>Q0Aw)0Fi#6#$iD&ei z@A-d-HhVthrs;FE^H5zbJblJ4J>d7C3UTuDJl7{ z^+KIcutOKyC|b6g=1}Q;|J})s>qo(h%D`U3mMNKi;R)5px!VBYLhB^nLyBok$=S5# zSwdO`lOeC-)Zc3=vh@|d7w~+N+InK&4w+-_10hOs@DqX0ZJJJ_9 z_Qqo%2c{d0-uyp7(%In-n12F?U4#Y;Of-~tZAnm~LQXR1w|@$uv6rI7tto-%xw!Pe zF9B*LJqe{GZ1``E!Wk&M$xBSCWOi`1UH;sNVjO80C&j)tC+@IoIH)#( zU-jb$Y!tS(SVv$l4p!OK_@Z0PrP`mIWB-`b?JA7%iLju#gvZ>G0LtNIkd#*QemaQx zqJ_5%9ovbY68lmMnKF+3H1tqcS646y3&*6>)YKHiAU%2hX_wD4PZr6Wlw0>a2YpR~ z+ID6)Y}v)`0U41VNeoHV%uGr8AB#2C;jCl&+}5>)?{2lYHV`+D(!>uFHUc@xWpIXl z3tQGB85+$4ADV)3wxuLs3e*rjWJVdU+y@GNn0;J80HR40@vr!YUmQvwd7U&CLM6nF zn@N)9la}Xo8lNH~|MQ64T5{3&$``Obi+5D$(e@u^Bt2zIp}r@iN^kw7f0H!&;%XkKZ*V>u8Wp5l_aU zmPQf12LCgJhQA==_23rsmY7N&Q!^nPvwF9{+3q8aeh2?p6fD+6Xt8hCFL@!KeKuq? zz&ju@03PC6TU*mvzqr3`(5{$YB#mB?Wkf`>TNus^mR9jmE&EUSKW=L3{;SPKBhF>9`teJFb-_FP3Ky~!wT zHEkLbovC!3Q(jx>L`?4)d~Ph@3VF`fIVrj@duHFoY`yJ#HMu(|7rYuu;$vA1Cc1nJ!q}tmx-G+zR8c+j98$?>Cy}7yJ3&A2Un zlJ-6-4K(vrd1E2&t{nZZT1S)vIQb}tj|*Idaij-uE_1-W8?rhIw%-_ zhqzK87Lh2<>>lu?N0vXmZZPug@jVRnJeiYM9*TI=0Q27LREQ=OG;@?wEZi1pL6ZNd zZhdBQv{CHis$SkrBW+5Hq4b^DmtO`Fly-q*ujnOqkF!Wp7;x58w@y+&u?Ip6@_b{RUpZ#lG*3yz^h2d5SDg4Hs~ikp6m_XD+tGoBx%1q$)Tcl~Bh!Q6T- zPF|u?!cv8OsY3pBa@8d9`{RxPM{;NB*cXtx!B_$u|1KC|h!zOvo3SbUVC6#e?Ou}> z5Yit=xxtr>4kh#k5X$KU>+WLBmK}4L4o7Q@JFEH*c%fuKblQrzs(N_|8Y|>LmbFFaJRD^6nx^$VUI>nAuI%z0 z3_@q3t{xJ~b@8%K;5 zKvwN^8MYp|2=XTrLPTPIh0TtKPQY+VJq0M9NBE%me)%540?jO;QG^S|DW8Idc-zUB zOQi233@ILmb#b5selO?6WuI^vrY0z^TFkK4cHdnW@|bWiz-f1ehg3mCp!@YYZBS5< zCe1N+zYTAypzDP-n4#(5FKy<>M%zi6(3Jb#*SIy{i~rJwQO*Q~IFVVLYDvCkE9b3< z|3#CjjH(JvHH`IozR~SW60p8Dq(_%_@77!#3a<( ziU-H;GxMUTsFTm>i>*k5n3uS_<5IlHv$k?MGW6LD=H00Rf@Txn8BD()Fcz`*u@!PG zmX+R*wiRwBIeYX|3nY8Q5D^mai}5kL-1lw=a?xhSb?3_FDh`DyQ1H-jH z;dDFK4B0FadMThEyLg*4yM^28AuhvY7*bpd9gJgO-`j=o&pWhIfP}`KmaaFGLt|Ky9^~Qg+aAIg@ z3#jDR`};O&(Wu~624HI>kc~bcdDWdXm1$Qvu(=bii|u}8NS*P7BYI!)EkERiE8@^tSXo(-oFzP8;O^1_fa8kO zCi#w?r+K~Qs_BR=hInuagl03}n#(bR9yJd`@L3N6@47>|K*WT{^0+&l1sejla*E5G z)hxV8hi=yH$HM!x--RXz-^tEKQ7Juromt6ELQfVgX-!+@OG>mjQ zQU6p3(n=T$K9|&;9PJq_SGK&Yctw&FP-_{QN2}FW#Sqob>)|D4P^aY@8YS*bs_GZF=ARUIbaZtVCpr+BE*iD7i$>z@{Gb712U1{`KU{6mfxt4mKa&2_A5 zA{F7c0oK0c_K%DKXz>kxsaFvh!vtl=i=cuHkyoWURd3Zh3fm&K`ll0<_?>F~a4W$1 zEe*h%l|ryC;J?+z2uj0lS{@!AEZO?b*S#RN+ae&}I2Ls#OGXf~f=|3&uz1_S=gd*{*KM{838tLS1x zKaYSbj_zP;w-D%axHjhR_cm`1cO!?4X?)6qy>`XlVePBJtAId72TB-txGx7Ja#QUX zMlQi~KAUA<2a2rcB3^Y-HNwVdj$M5~15rP&%A5etYYotKFM8TbYuy=_7p|7l){)4@El(BIrI|&uq18bvG!tmSWNZG>gR=e{d`y_sj-Ac5*s``Y?jN zIaBb&p)`4v*bPg{2Vh~vzQ+No7tZBkVjs1{62b5gz1W}vOG@qpK_cutItrppOnzHNN+9E#7jl%)3*R~G4AJw2SIe(u_N z0s2Th4an#?T}H8HWcKM>S>UY($}*(A4P#aqm56f+CE^lKkw-7uG4WlZ?l1#TQZHU} znX8#46RnD|A1VL_nvOrQ&(FdOX^wo_|L$wrp-0$Rk5|{tdIN%2Eo9#Sv)v!wko0Tc zfSk2H*Z;$p-v9GDuKc+a8@l0ZWYQFW+Tmiq^A``Fx(!o|n+8|QmXB=e4J3%+PE7DF zlw!q`OUC0BD}0< zU~S-$Q(dimZ)A<6FWt<*@W|=En%sm{$sC>|wi4PBWzeddbAkNvV@d(nD zc0%nL6i}C13!+~8gUSE!hw$G&o@8xN8l<+AG?vW%>`DnxROd80Lmv9+O+->XAf5~nRv-cLW@l$7AoYV4bTsHxImaMT@)Hack9n0u z#(*0Z*E4EzSa;=L?pu?gLe1Z&ppvUpjHCUxDdV0RHrn~+)@hV{GoX2`BN>WT#2Dp7^-Q*TiJ86FQ9H}QBndn0sjz%}sVM+7yA zW6+)7ov%e^%Mp&$EixDr)yg0fuqFzapmB!A2?(U-VS_%!xM@x2S-)qAtepeR51<)E zM^{z#nbAt9$L!ng2;y}o7>dj}Tg}4r^55l^%9xvQ%PJaJB6UOZY8yvOO${>U7)zCz zk`*m@;aAPK5cebe7b=-arzrH|0!n0!YBL=XgmK% zqDOnUnBfTBt49!?Dv`8}T{Yamd{(d3(U*=-Nl6)Ciee6lbtpWC*P}J40L_|z9p}6j zTSq%;$>V=$7B%u*kNe4qqeh0dAF={`zm+g(lMypSAqqWwwe0D%1!$fI4GKueIKZ=yFQ?WgcP1~X{O%#X5AQtd0yo?{-ny8Zlo6S)w52Y=xG2d zL~}GMBEUO%+&L{4K+M@=_=62%Wl_#Kg^7^xfdG;F2qZB*_5hcrZQZ!0e@B@ta=sKt z9l~{O+WP_YE$)GBJ8E?{v)q`T zAEP2KRrr2B%Ryh1OX$q8nz3zyF9-+gAs>>@4 zS@hOIoZvSWvNY5FVmjrTw@Y$(qi{r{x(?jmfpgG1y&uGZe!0=i8UrYktOP;my7$0( zw0QFyb4W_!n{_wk<76qMHCIHwhAo1dx4zdzb7j~1OK<*z$I#-zMmblJKmV>j*dK%% zSrE7vlYAB#!6iTt&@B4*7zFHJZf<5~=0QwuxKjKwz+oDUQsv$^r~hiBnGdgKm6n47 zF$LkVZ(l!c8SgqJg<0wtK(|Jw(72Oy4Tv9vv6LjNsYoUc+ss!Vtian}Pe4iP>>sZ? zmq?$k5xv<{upwo5uGzi$KvAX%GZ#8f6d`5$%o=BP`MzQKp#-Nq$?=h=jI)R%e3_HT z*xv2&W~=7wd;6?G?pBtNHsqcFLid(In)u$65M%qX2nzCWwv&b*{BdQ}HGjlfzF6G+ zjSRU=6{R&B%(N;H@kB&ssTQ8=KgSMTFuoG( zbBZeio_{c0^!?r&e*xZo?|x9eC`vH-2DP439mGgHfbofJeh{PX1H{oAAU1NgPC}+- ztIWDvb~~F_2yW(n{!;z&#{A~fzs2`-SO^T##Dz;?qtRD<1EUiD5j<CkMLkqs->7sr&o;u*%BH8Cu)2l|@|u7+^?7E6Q>=G+wp(A)1|f3?{b= zKFd&XPzfdn|64PoZ#EEngc(yW`Q0+K45{Nnx4(kMu2ajCmCl>BuN}Vr69LAI`?p)- zPj$rY`ubCctORvnWUw~f``Oy6*a;v378y@eV!MCS@eg-buSCI3-`Vjas@PTCNF?0; zr^`M)%lX6fhnK2{`|sXY`FdQVh&9Jun45EJjH>)UpQ&+{e<7*raC z6H`!}rmDtHvF0rW7LN8REzSSTR+8$(Al<(en=5LWE=={TBuz!l!~XH}=QJ3-Dy34N zq_|>U894U+x4t3D{nmW(HYKVC5Cdjl3FHl2M5DkNzjNK6p{~A`v}kKOIp<2omU0~3 z8hwh=sKuO9?jXN-Sl0tj>4YIY0`dbWYAqk)u^1+!)_*twhJ%8FqN2#Ry1f?>sUSV_ z_hN6FFvFK1>|LL5@mue$KsDlMgbCfQ_X`R=epC~1Qo6zQU``XbtoxN9HPD^n{U3r51@nkunz1Rd? z5!d~Sv)rcA)q&b>Zu0*zF!V%&F24_AaSngqFqlP>3u}3QkMQRiHkP9klDmZ9S^52h zWa@~x-f$}!1P{T&V+==~+jUT+7F?yq>5OrRkYozW-A)}Ixzp);>nuVU9L|9lrM{|! zSB{IKf;W{d#TkmD#uo5KurZ285z8<=*1FLC-)@M#>Jg4NR$d$O4v)h_ZAh&v`F94h z@GvawNaZNBNQF?esMJ{Uv@iXYf#*!b4h6GJv0vYCWxQ)9DE(w;U|QTC*I$qvQdfrX~cd5!^WW9%>zbZImCPq(}&%8l(<1heQOn|QY zNb+Pm6Ps2K>jHADh$RzBoGMAy;zSuJNz67vHjLKw?ORt?iXccQ#KKAeIDMW(iK~n_ zSh=DvdEQsFqJQIalOY{aSa#VByZvr%@weS-cagk^I59P~&5~-Ggu#nPZYje7WZtBb zD%&7n`52+TQF5=&(p@bK{`Ltz~9nuc{f|KoisxRoisPV@Mc?{c%TT8_h2G`9p8IcRgHJqLS z!O71=*~e}@Ras0U zy`o=`yLtqIE39gIOk=)=*m{^~%(Mf*ckn^zd@KfYC)z3LNOFNzQ+vemh!bnIoDcr5iZfRM>pnk zQ!Ph|{b}7uV@EYDC6S+5nz3w!uW>(*b9?$28sEc-`K$5$F*{n^hguj;%SU=8Lc|>N zgSjeYE^ariu3#H08KQ_2*f1ZGB8I9J4vXHFDr^1u0dZ#}I$G?sm3F=Wak7*?O;U%< zdEPm{LfBP2tR~z+#pv47=SP~-X$A3-QQa2o$3)DO%U|y(k7zM{BX|D&%29kWv4TsT zS z=6A*lq|$8J#%JPv$eQZj|G8X(jP;N zeVK3r(xoto@4aiW*xG= zvHzfFYN_!?R(dG)Tm4$Gn`YNM#;5*N{SOK6m+4$2oOG>0oKD?I!ox{gT0QIfa`IQ0 zR{^R)(-pJKgvoomSCDU??m*s%*T4vr1g>`Mn_KMC5 zTX1hkYY)#ZYbbA8W5`^~SSpNuQg!mViM+92?Ip`O-vVyUC|LMc*g>*Yd=xkQ#k)qp zS}9`MasoXUCdaaW#Md#Z`ghtwby;CCldHr3i+OFgO)v=6r=;}-I+1<{$7>Bxp0NvA(7n%T|FL3OI z5DKEuW2#-(s5kwE>F-1Pw?|+*g;Y)+lgWRMx&Jd@SR!$SbmO2d-K(pJ^5vJ6aY_Yx zH=bbq8U9jtf>l<(qKYav#8o0&+uv284PS_hQuLlvo^V&GOSFTp0oCFv9kU$Y%7@TK z>?TUB++|el(0;IGkAzy98r84?o>uF@QRu@@OTMZicPz(IChxaPgdC$LsHwT3Vm^ z^wXll#wRFNPZciW1?KY_qX>%(r|VesjZb&3_YGYaZdaH(1|`yIY(qM^)0szVqFbql zR$IrSt}y-Zli^*f8O_K&Aqep$(ABe00uMmAl0i}ANa#Ahw&z*U@@h`0v7)H7vdsnP zHBi3-X?)BAL;q3GBdTu?)BPJr?kh$Tg^deO5KU(VHJ0=~sx7KkIQVFu z$O|ikV{7vBO}yfNr7=}Ap*dZ{FHnB(tTep#ZhhxHH0yAb*nm4DpU8nU({D45!t>(O zbYffNB*klcrCPBUzeewNyV)=oKm0_gP-zGf3;g^#@2PF-e6^*(y8DDI+n2A9567Uw;)FI z<^}#me8E+|Y@V=!$2$%ek*Vz@Z#=_DO z%6OH92j_h5Z?WllQNB(40QGU_>bl3x$2Yz2fI=d;>t{hGepJ6#;tRm<4mV;-HvP|6 zb$drq)gUMO-2FyeN+PD*EZN2igW*3Vy~ne-7SkvwTr2%orR3bDsWi#secUbG9oOUe z(?)l2Rj{WoFJM@zeDUIGBy45xfcT3OZ{-`6tBD66v4IVBSyhnS}w+VSk@RBH*fRcigzfYcF(vG*`-4)V?!Vcr(6~7mJI7ti8@R8K@`~yW93{T&R zRp&RsSSdLEWo=GQPA0)9=L{;4K0iiuZz4ARObTf9`tnKR8!=M#rY7xDb49sqKsZ#Y zw+#F)WcV}vWjemHXB4i(Zu@fKs8$FhdD{{DdA6L$e?;w)X=OZq)m^lTQuNy-er9&J%kAsRxfF+W_ZuU}k0(>Fn&RG&wnW(bd&839QOV zK&nB%>ui!w`xX{LNSVH^^LYl#h+)zYDVms)nu#0~YBE=GAPot*lT~$wkMKlf!%s|p-%Bt^G7y4UZ7(Am_CSmqKJ8Ma~zA> z(hVM3>JBKFNLX<=JbFRf6s8J4Kz2@Gt<*8(rCvbE*8oL6`*5f+D=Vv`qrH9QAGR-Q zBlr#Kz*?c^^z?LQP$8h!`6swhWA?=w5zW)e|JS1aAh3vj?h?g}=3U3R+^vfy#P*s9 zM8o}NssKI!>vF@tUU7h|6pMbze=oNv@$m2%m+gL@*#TlRUCR466NS0nMNVZD`IV1!b)!SIh>85&Zk#MQuRNUr*tY9~lk>#UbQ=YHF%FI5^lGc+l{ay5}eFK|(-MIweP%A>MnQ>-~JL^Wku=`QLl5 zz1D95CQQuB=g$L6DbQ`&%WEc7F-9^lB=e%-00#=>N*86i(|q6C4TD&=ddyM;o}t?P z6L7i+XFajMt9#%5Hl=d#jveA2N5JUl=xzaNH3sba_tP#)fe*+7eyj{Q8>>yg{P?;X ze^~FdY85qBA;@6c!v15Ixr(-?3C;i-ZbMu)0PknxI zM&8q=>S=VCe#SiY(jNGOK_BB6ptdkiv?Vwb3W&Xt=HuhLEbHU@{I-kEGJ`*Z?#Az2#0NZrTl3U36j&0jAOVWJdAeaGQ={?)^d#jlhEQKopm_Ew4a zwr#nl^x^1mqLbej+IBXh$b@Q80Vx!?2&}xKl@%4n*9C}t1lrtK_Es8xnZWR*e&x$q z?!~4(yasm;m`HDKQOZW#M*m|)v5N0!efSZjG%+mDxt;fNR~oekI}+^T*~7a3e36yr zbK#wM5jpYVo;VjbFH%?(#dlW{B`JesM@n*YZhauXTYp45Zo{xElJ=-dpg2)EbWbp9Oj8-R(=?c%G{)Z15o4u|wQ3BT25j}^-%1z*% znInnv0s}-4#50hxc7&gRqq`oK0-XOmI1R~-tk|*=aK5*OodHa$C=kPa#qbpT-98zX zf2?Axa>rot-bzRcn;O*N{^_T2^*gNm@9;~f5(1;f)05`uKFU_+oio`XyC(vW{SVy% zQR(Et_(v`qjCdygA8NZ7A41I0&8(ly@S=VSI9#l4acN~|u|T^I2(e`h@KN%<1pdKz z?a0AUwD{(f|>)k&6q0?0t#tLhK_y#3fO)`5|C!ZWJ2A7Q6< zxp;XCVGbxFPkXzy>XKqGJM za|{^m=K#`9|=%n<^qT&>w$!vFh` z-xx9f$lA^Kq;pX>usVxjvsM`-}^3tl20GWNVedPG`tgP7htwceS!J1 z@=voxM{D!u_IGN`V~i(8oulX;4SAo>UqA%VsRIPGn@QB-s~~-p7&e-WXPvrqeNJ!W z0-uOHVL`=VE1BtaX*rOL4Q*|C zEXYK5jI{VxS3pD&eCcjaG&6p@O88P5kA?i8cos^B0de(D;Ey8J48HTO|GV+`JyKUE zzoq!Cw6<1PdQ|*aGD+7;r_B7uQb)atR^HblkyLKf{hWu-7gf+x>4wX{(mOXf zDCT@9%IRIqrN+~iK9v2rEHJvT(FJd|A}C_L04|FQhtogyN8)RJV$Z77rkhluTXT&` z@}``Tr`AFC66fN#j?Hq@v=w@Wh6*sO%W6m_NAv*eUd)bwn2e0fDv#0Wk3u|42+7|d z@!t3f-x;tfIg7o)|QDpWN-sceh zJQ-Zdx4n|$Tiz*6?YAcT0X3XCR4mXWpz^w)^OfoA@N$MJP1>>}^M-@?NL~r&LWJj& zBC9*5HQ7DPLock#IXx-O?Dde(H>}A1K-Wz-`;LR@Qv%9Q^maqBfg9F0Cz`f2$N#-O zEVQ}n`1hKEOweBIJ;mTdq)D_tB8c+?XoUN_RX)fRB@$x+g9RXOg`0GSN4-sfb@${k z@e?qwjctE%7-U>SI5bm9fTcRFGn`hFoRX5#XEn)E3||W^6~R$KNbu)IA3Vw{sd+;j z`!4C39GWtMczH(^@=zV5NaE4hIn}gt{AbC~bxb>!kdV+x12!p;yx0Mu>k&YG(C)ra zQ2WI`ncXMW{$?b?a+Rgehh$CgX`7zQ+>(q5>;7%et-LO+F`8~N;oGN8U%Y9%w#0!k zb*8zuD|V6EJLe^#JHoH2Xpnc7`Qhqb9Yp$PWJXCxO;gAkngv(TJfB!Y6Npn6NVB|g z!7zwOFk*&q^N{6MU`Ly}k&A%RX1nI5&QDO+o75zeJ5t;SB&4Jqtg=^lb|fHQrL?|;R#k!JDA}Oi zZQ=ZFt4-h^(uj|j`mzy3`YtN3UQLM$THI5;dA|*efNmvv)f8(Oy9bp=;^`}$rLTUz zoMyU!*#|@mRJZ(05woAVy-|Kc=e{9$C8_~Dz9B!K`+{P}q?rfBeBF`U#!ga{Bcgla zH}R_Yt^!Vi*RaIJ`z7vK)rCxi3aU>>uIQrj&!uN+G2>e3vDzy&HMOdKB8})Z6lrj6 z12Ydk_iPWG%QofX!+K#as%uoIBO)*uHG1F${0Lj|dGRcS?ZE@u@KeD)%w}i3LupB) z)Y~qN_Sn5AOJ}k?%IA=c2jG~N+cF>I4Zq|J-nbjD)A#{_IlUQdB z#zmb#vl?ibYwCWl?a>`GEu9}UVlJ!w&&^k?L5|h)U|6-9F3Q+Xt!-ZSZh%`R#B0O| zR2KX}b_Wv#T))1=X#rYpzLimHq{~QqgZLtwLJ(*ejuiQ9ijZ?W7Ol(-^W@NqMkp>7 zH~jl?iY(3fy8hzHlP8ce+_fy$B2X4O)#&Ly2^NSWK=+De1{7d{OV3Xc za8DkZ)DH$TYz2r>p#^)AJ6qnpB=TvxzzxG*IkOMrf|6p1a8ej?jzU0dHB#*R=zCP2 zZoqpiNO$bGHjo+u66;312F*UwJJe@lQw^<9S+g4#*LOo>0CLd`f258bX2w1>#WtWU zc{;_7{JDR3?L!wi&X@wfvSq#QLxIt36$fpi;7DsHG+C4Z6(*hHO%@GIHhhD zy7LF1|3KN~JBdm9>cC2uX%JYo!9OH`XO3^;S=`3WFywvH=OV=bRpkKgO%jVS>hVd@ zC&1rr{3Wt2YsnB++;hoDKmqQV@F{Mu*@kx# zU;_AF7qGs*u7;~#pvhlQ8QMaGCKG1>IGqi8T}zCvzezuV|Kj%?F3MdazmYEkC9JD%KEg2qFK4d=}$ol>Fjzq!Il%*qYo~crRnWgW1EGGjrE(YbFi<%txP$+Xr7@@3=Yt`U#B`>THhqUdKwk7 z+xkTTE%)to`4xc|6G?hDmn&Jc7;w3&RK!X}iVyk7w4xPFr|QK&@vXb%vri9NKXI$Q zxZzLgz|ofLjOPVO0OOgFjPHp01L@-qD$SblyB*VJlDhdFItKTH?LQq%9)TPE+StH^xLsM^MctCcgEj!01< zbD*_ywFxWsbJw2jgzmV!Tv<#G(X&H};eddrg-nNO&s+0PIbA9a^@d=FW2&~TDkNAb<7cJx zpX27?Dms~{H46JEnUwp-0+!$*8}R{u5k8f~Uw{C&|N6s+4`)x7Ce)<#w<=bjDV95+S2n=%F6`KQLo7tw$-k zrM(|^i;8MLbZO3Y+yD_>cZ-qH@G}O3F~)eI+qrpo1O=d7j~N5311=^>qH3XjKao!r zmc2;08wdgzNSYB?x5!xB60gsvr3w_#hNb~jp1I*o13{B^gP+OO`I_v$d3(1&4=W!N zl6gCj_ydgP29PrZpPCA?(b`^EY|v-oqvXo``%{v`JKf&1H_sFTq}@WLql7$}o*hYT zxG^sr?Ryk@d0s9QUvNz9+f>>Yk|n3w4E-W59|VV&KVi&JLbdX)Sv>~_?{#G7|&88n;eB*KgEyelJOu4i>jcmQ^o_2XYs#a9CoktyT zaZ6bzItuz^s#xb74sClu|EKz#ZWv%cI{dkDG5QF!}pN z3sejkhHSa-)k5jWRMb-?UBkqM1|+sCM!FoPtH{e^>)xy-tqF)kBW4D_7`m5V_+V^hPc&)^7!MMMQ)RSl2DiUp5yiJp&DFrAsGYz)x8v;2UKI-(4uF<(Gxk6})22iH70G~=*&nZe z*R@ly#EBf3W!+&@p5mq6WHP^EBxnW`}aHLP;Jc>p|# z?AEGA?P8;_0C|k70^4#T*RS9Ow^r}Z`l?AYOA4Nv!xk_!EZ}FccP)9Hh;<*k#GukU zcGGWz!9SYbFQ?4&u7_u4F6qYm{4&`C9c@VATSOH&UDvblKYNAw&lq^T1(hwXYYp)) zr%bIdX{#BH4(7>c>n4`1&Oss+#Y2gd>ZOSYX604PiKRtS4iqJCvK;v82q=Y zSQk5=+7%v1Z4D;1Mh|B7mOr@En>+i>1(u~FbBQRqcYJMGgPjj$Z+=?p0L)~iUQb2g zdwEX6ZL{gOlR|&S>5k~6P_+%vgQ|IW5Lx zl77VXYSbFM{*1-3+e@=S7r8vBMSm2{EoB_fQ`Q&C- zxh)PO45JsY|9#?g#6@TbYiJkKqa=BGTpCz#D6pz!Tp0N7yQ)IKB${7S@=oFu)$Jj|xu5SEx)W!y@DmY#;as5I~W zc;A^XC{yLbqi9b-(qo0eN`Smo+3B7F;|jBaT6=<{k#Wk0RIrz3fz80}YlV817jyh) zskVnVZ{Ezu8~q!vaLre^d@PDVgONmHZBhs)tV-ni7YLyr52TP;#$QGYUsdMASdsXQ zrUhI>{>WoNxA=kgHS1TbJ27WRU&Hy5vB0l0oxQs#()(R{ z9XA&^CNou|m^{H^WLzYdJ#)<7Pq5hji{yUs#hGGvxsCpyOfl*4#9<)`!|oZ2x^(ES zc$x!d41Z!Eiy4N_B{b=A&tB0+tkI1HU2ylr;%Q|Mfl&8y)r^q{s+%-9%{e&DbVm_N z&AZ4%$lq}A`RztE_g?{9#^v2%00WR7ES{Z*~1MzTh&EFI9dNAf`7*5MP3r`L-! zhfn>*!Hd#77ulzHcIz1!y4I(d4p(y?Gk<39{_H&aZtX*YrNG0eySvd-_&3z=pnMxx z;%9jWJxc8}Njw?z{tYB~wi46!x2>h)>m!~2jFqK_{(Is+V=1VX{|O{z6)&6MyELPW zy1s^6>{d*I?I2YvVRL4l5vOT(Z2FW@Eofj#3VnEun$}1FiUx}p6m@biR z;dHv$*O!Y#WXT3>8>6-%n+3t{x0^ehSaLhVjSlb{eH<=3gOvM`Hbf3>Ljo)Ot_EwB zpyI;KD}OpFzAc}ZD zjr~h-1k0$LCa}6qfO)|F_lM5TI?(Ca`*%N>T*QGd)R z*FPK-8(ED(*b5p4kSK7T0Kgp)CgTzDX&DPEj%3rwcN=_ko#DaJLGy)1rL zq5m=h@#f(#{(I6O*(X4gvd0HRZlF?p&gf67LbfCT&eS5?%OxUa%(JpFJElz0=rdry)KX29Syr>AUkqot zkTxZVMRz07q9Vj|BfMtM@ZsQ5+u~XanaH3sTI7yNiUe`3l7MEsOs!nnTK~Y{-RLG0 zrR7~!14{S_WH{oZr_(t;Ir45t7b>W)YTDlHG`KuV9M&>t-moAT1F-3<`lquG|GC_> zD3WA;eAdA(*p`iHrR6xDQIj1RVm}zm1>Jv9!<#MrP>bL!@-FwL!GFbcY-yKh>%p*H z?_JORZ~PyeuMBp!b!tnNgoT8@Uj0jGuJ}=}GoHL2!ND3p0xrOhBo})Yq~j92Lor2L zX+jlu9y)q0QFs0cGt<+iAjbBKR!3R#WV`;2VNvl5eyu?WL&y{`%A8>UyW|m zq>=y6s$t>gfX~1E{Q@kbotiynx6Lz(_ntxxI!;l^OEX%`mg>4=3;K-Y>}6ol`c`%U zFO&aHG{SiLu9}5_LZ=*p2kE7tIY@!}QYJCTKx6Tl?<`0<*y3|*rE;Hi+Ub7!mDhLl zp74Q-&d>+-D_PSHNT9}O-M}1{CcGuDd+QS<`$YxWU!|5Bs+ikBZI7*t;14IA9WvpT{uX{B^&y9!G<@7ErC-K4y9eVG$001$d1f%< zj@$Z6;8Mtp`FO<0@j$JMb;&jEX=QmpjRJtUDOiyA>4= z`;{tU9(`(1HJaYPy4Q$u&zsqlU97gGH*wX{V%&T8tRAjyD<4QZz+qL z+yIwb2DaetVmvGE^Gt%!68Xy!Njh?!XrA3x1?!wU7`sW;2|N;JBMR_#eU=2#A{TsT zYBdNkGe^fPqp5OB&G>#9lOxhyw*E*)Hd*2Cpe=}m@V|&No5B_N^*bCS+P81o_x2Oa zRf0+|-53$isT4wY#u!G=MVBX&eJ`f>pky`=qPKO`;_i{@kL zasXAvE_;PxtY0^YMa*7xm){kpSaOuLFS<69@B)#G?lu-%2CWuHUiwk}4V|p)RD;yX za%3W5<#!EbTs~GDUq;EC<*J-D{C@_w|;i-H9!uhDxh={WsN zXk5T7zu?pG5HjpXdXJ^$#9eOR#tTNnsXESbx-=KK_~D}HliM-OJX$pv9=EbcOo)&L zurt+JeK(Rj2h*udHl^yk*_ii8I|nj;~%cY2Gws;v-3y8IxgzcUj%NNuK5iJ zqhRxkCcHR&wu3|qdy;|~h6A#X`)YW#C>`=Yl*1CJx}~CIf<`+oiALXH37r2)WAd9* zYpdRz-pBIc!-oMFY=4Q@3XjWES30D;QU_X)Q>9l_k}Q0CoB@BoFG;}7A?=?AotSnU zETLelY_k`-5L6rdKoqtA_i41k-L|5qyZ?Tv@3M5&D5J)|mK=?SiuZo<6e4dU z@ofOP%ugkNv-VU;vp`>OrOJMqWt3Zaz4C{vG|yM|1wa#OnD~3nVYOf;N=h+(AKBvEGV!=IOg^H#Jm?~vu%dDdKeI_pZkEg%&92jBz zj$vq>@1I(eQe&D*Uv=obtmJ#Ea?|&*oYlvE!<4U!KH#BIrbO+v(8J45kq589k>+CX z>Uqz0|wdo7lAUY!yDJOJQeA|L2NRFTwxZ`i5S4UsGYxj z*jAMF+O8ZwGR>wL^hY$})6dQy7>`N!u5?skAp_Bms>(4y1az1{e2 zX9tF?MuugV6V&X8$=+G`Gf`$?VM&*}yZ%utQ&qido6EC-y-(VRCU>ETIA;xOQ>7Gk zZ}W7lMbWQ4Y0?Arb1yLQ{|1Co-|67T(YmlLGszwPK>H)6rhW>IkH<>I5U+z3HL3ka{+cA@_@7`!I7@C!LcJE`QJ|u9Hv07!9$J4{ z*vM}mU}7i(edI5AO2pnC>TZTQeE044`_0?76OB2i4@~cw7uSfOhN!Ct(Q**#$73?i zEXH&OuZC^iLr1ocb(f&%fa=Z`2;2UanNKQ^U|9q3zWX- zML^X^X{G&2%OnK#K;{dtx5o{=oOx|x)?oORv(Drg)&@y89YdzyolV__S}#iOulIMS3P z@K#{CzGW43raqz@(|V{K3U|L|qExoqUdCtQraYC)s2vGErhp>}uh4J=j0^T$-XMto zdEJt_e@#k$zLS?%Jvvr=%qp1i4V-WIV^2#a2$D&LF7F6ea zE-gHPg=v)+BLnY}aHcd{mRWy4y(6TG-@$ z|BGl-Leavy_6VB6$ZG~Jd4%ez7zK|drQ4cAbgW7C6I`?B z%wEj9{N`^$8^Az2t1>Z<&-J4e;`gqj6P1@a9(`uVSPe?<_X~6MZFS-B0`>G!n*R%g zqJW0+-eQy7ZML`nSu}HRS?=j~BRe4F)F;GcA-&LkpJ^ul#Ejuefq4*SpG9^NMP>{H zSAl=OS^12CW@zbHeUU1U`nx`d;gukslq-Hwe5YDz%BG;=`;n3QYX%N)4#slK-@^pm zBtlcAMh~EyNfAqLC>siFl#$j`zDq)D> zO6NjzZyLXu-AZ?`c27gR+mXKSnCLmcjr_|d?bEkUBXd~8Mqil^Z49<3s5M6?l!jT` zsUxGqloJ_mvkI;oQo!A&W8^!~C|yJkw^HsgkSgx8RK22W_@T7CVpeB>iq&Ds*Oi+8 z@Ps-_H{yQum?cZooBC}rD5BS`d5<&L2V9BMi83LEa&#ha!h(0{tSvS;ljrNaWJ=RM zf-Lj3-Y-!{S9m15Q8Z2)Q;P6{eI?G|#7olkE1&cR;3nRo=aSuM8qT(!8{2Ug+0`!p zHc|u``P14>;W4(#GfPu0uctYV%bud%G1%37bn!vjnS!7#0X7RDn_skD4>x%oyvUd| zHOC(yT3oB3^q)i^qG8!h)*mx0YPj1hJRLAZ3qP(?)3+pTTlQ@I^&sE;!3U2!JSqy? zmhUAkiT}mBY5uqeu|v4jXp&=s9p@YZMG#Re+?Dp_237WD@)6cME)VE^cg%SufeY$h z0VbC2!>f&UTk}s=Q5BR^^eO`u_4Y*t1=BWB85_@RV=mMJ9W$wqB?|(G(_4QTF=Q2q z7Lv}Q1IrF|%!|Xt))R;Q)l}BuP?@BlNz-GxFj1Ocmcq24qxd>MpU)M@TG_|pwC{V@ zEuFDm8VevCiak}Nn-_3aV|5SI-bni8TfY2whF#(DdxIot3_rIBqa-b)Q)iCe7+otn z?YSD}Lyt3+rgyq0!+x_dT`65OpqhDBrv3=aZkvja_VT{qJ0te-*Zm0UTCa~6?D}i6 ztDO7+g}yNdnvERs&fd!Z?j&r^nLL^G!EN)Hr=vAl`g8SXuilxS*o;{P{_Xf$^?t)h z`j)~OwCIsgobk1m$5d%KMA&4NA90s&ct0v8%L=RY%zHt!>V&Lp&r4!s^*WwZ6X%;h zX=izEBAd<`Aa?-z*yep_N3sc-)q zc+h5n~9jcdA0$AfgA*r*ix+_2FhW;;S(ZH zyGgvKi{%bx>-&IS8;zY{MVfH3^jm_A*SjtTLJE0;UArQ^LPW{6h*F$?^{wy}Dswk8 z8k#y&)jlu^CS~Ii#8n}(Wb3UT}*wsSHjcf(3Oq%kQyW^hEm1Pb$9SGFKRE?pD?bkuMjPR?d zyBGgpzl+uMzVd^s2<4~UBaR5l<6FTgTIQNeWAy!Dmw>f1!Lf~PrL#;CR7o2<1+98k zgc(t2tb_Na9tWt)9>riUzyDE{f_}lDvT_5%={`Cpog(h0&)IBp6NSkQ+;VUgDyH6q zclduN-7xsjJp_emp7FiA%vlt-auIy9if^DU6K6RB1{+%`7+dT8Jwd%3)@Y3?fp?m5p$osizfpqH7y5qzL^={FX1YgvZQ6oi zwANer7Ejd%WlubiO2?q$ExY^{=gn5kxT={CqY3Y9o(Ek;9rYsYzr}9_vDa@CilANz z_OM)cD1n5c>4qZlG5X^$4(NMQf>yeQWzW;a+Je|ge=(z=OW=hICH}N0*18#IhHB#l z#TmZ1>A5t&4NHju`Omrp?-hBtUg#=z00u(wt7{L#8?$=+nDCC%Pd!x^A0P82;faIk z?;XjYXF75BkjDQMDW!?pZ;a2@HZ<@{^mxh&CT+*aYb)Lr*-oeFasE&7uO;hq1E#6= zBTCI`1NQv!+&n40X<6MFIWk*$MwLF9Oy!0F8YlPcgHU+t;P=l0(f$g;x#D9I)Af8E zU$o;te|Vsz&^$771_f=9L7hV~I?uVcHv+xsG}TDcbW8 zymmR9D*SQ1zXkrq8_1I@$b0T)Cc2CkoLTaXcXqB4ag;8KA zt}tj+gqMe|c0+lnt#lF@JjjbGSiEo(8o~5LQMF1f^m3%nn2@hrOVZ`+vLjabHIJq7 zPv;}CEljBvrg8zWnW$mAM`gPfyk*th&NN#;q%u_QFoxpSH4QpxkGD4!PCM2^@t7ma zp28s!ac%S8_J_@vhb7v-O7?t)lvkvskCV%r$KGlkp5XU$>n>7#@7+?5d)G+Fe!oCC zWT5Vsjh*Tax4qDaHwygQQ#lI66eKJ@zx!_x0zVO8QRyY2WI<)#z>Hnsd0FZteH%Ud z_X$@ducx)xc*@*etSx59?U(NQOn-ZUXwP^j+CJyv*vGnk%(>CQG=@zE8WW|z0aUew zGdROmVXkXJ+Ai$o&WW2>f5;wxwee2b)npO`Ld4O0g?GXKi1?{1Bqc!5EvNPa@D(Y5 z1;;KO&FvDSF`DhWwO!LrqjZMZd*<{leCW@3*4iBF-pXv0{3@N`LFqLiNG0E%9cFK~ z8Te}(g{I%aGAOc{bux>1RONU;CLNMQz@`l932jd*t^d9>YO&mY68VN(M6Z4-0a42e zJ3VSn4KJ^(KN_(jshZ+C`WBys_1Y1cwLJ6_7x`Ziy~BEllfzz$X(|S5(PHBPuzgjV zmZhKMEm-z;V?T!n?0gf-JS=SZ{M*z%dS+9y0=_ee zuU7sck>Z5E#;^wyEKV&{IOa1RSFW?}h|>75o%e>QQ^Bp$cV;NxrfSFjnR+rlm^&+L zdH<8i*ejukFQn;EE~M!~?+bn!lnERe;k*mDMq`W8VO7|8LOu!;6lT1B&-d!s_hsLF zz=qqQTYRYT{zC+t!74t|$P>U2LDd~jIs6ZQZ<3zeJr$x7+yUFJ(@zlOC|77OIk`#V z2@QhstS|Xb>q)yz~cmx!u@YP>M^Vbn|j*yeW8Q9dhMZ zR@2f$m7(XNX(0!r!Jt6gO63J3+0Gm%~rl^<}3B z?KjOUK3+1t-ya_AD>TmBs_%BEfJrM@ww*R!WQV+g^{prFf*9F^3$}BSBt@P!q1Lb&*uz&h` zAM6Cvnjp3-*qD#Xx$n?;Nb~!{^BSK&FHLsDM$gVQfa@FYv%3wkhG&qM$(yTA-rvFx zS{7KppgHHh`(!cSI-xAEW3YG1yagGJqPV>E#zpP_oQ!yph58M}GM1?lpz`&z^1RuX z7M8!}SJ8BspPZ-zpg#FtrGBk7|Y}<8iwOu4R_N?ac(5aR9_t;Ng`D2n|ULjbreXZ<7iPXZRIm{a9 zJW^&ByM)(Cy1Tmaa~=J10~X8D+Z%WG;x-gym*B{gNt*_z8Sm?JigORkaS_UTp`05q zcQsG0;}+c%%fU>&rFPOg-vynQd#vD6Y$7Rk?ZMvuE zt@Y3|5mK?eNE4&+YS0H!*V@Hk@kQmegXtWcXVJANXq@`kwgUryre=VlyRl?#`P8-{ zPqcFGUid;1%iu4_eaE00i;bv0_>qZSJ;uZ!Y&68e&o4x0N|&cXtgmT7ZsH38^Z0w4 za#D&rEvHM9iigi~1a5cS`&Z6Z^c8nz&oH`_CU>px!tE^Hi*!&a8;kjMJJ7n7Zb3{; zM7HkFR7XwWFxu%|jG?4F5?gOYcZ*Mfs|+>SvnN07Ry*m_4;d!p`deSQ3B()!{TeQL3)z8AN2Cs6XSo} zrtSO8<@iJiiD+zlS)xh#>(QU0dFa}7Xn)i6`E9<`Ase`e)6y8;qSjC$p8RX>;W2h~ zF?Ut;o)gzb+vKMppA(kgQwEJwm=9F;(BP0qnE*!F$nXzt{X4o<>LMxLlc zO^`nFDjjt6QRQf)N-A_*T;jjm4w+}U*bYV7$s&cz*}2ZjYqN5Y;AclDj>-LG<16XO zG`6;=#m?Nsd@c>Rm=~- zBWqo$#`QKHUDT#aObAoDKg3UGve{Rb=-wGU$?0WPj8^Qmc*{dtn3K+)od*qcXX}A0 z#7Qoj@*)!v!lvw(VIY8uHZ9qt$~&){+%=idF|)JM;~f|fOuM{oU3ZMIJ$WcxmiJ|Q z@3Fc3DgK@}l16n#baw4*Q)FqIVSR)PIb#~bpzjXBei*vDWS?;4W8U}I`2``#w;{OH zePq4P9pX(q*-aF*piSJ}jg9KiYEYNSQBJcd8s50Z_S0itJ5GvK-1H0M=pY86oUau4 zqgAe3Gt1=;7lG`-h|+Zzgi!vozX8p)Bmp1c*sb7&=9MM$1myNxnb0V z!iF`lg2<;dScAyDSPo6mi8o3up*2z3w&wcHLH%B8!u zD?LlT_e&mTZU7=`9QddlZLe!TZ3!=l4uk=6;Upm;LFG`lk*(ze7;mYVzZoY&O2r5! z(k#Zeup*!k=;%WPA;EZ*ssYHFlq&@;A_TkytQ5sh;*i6{GEuF}?~#hApPBfardFp` z%{4<^uWMXPcmlFI@`d(H-pSv=mRY{9xf*BB0M2^@uG}DBvC&WR?~2sTq#_qqB+rmx z@YI~lH+nznw3X7wv2e!y;KOrIgW(?IU!6WPrWIp+u&tVV&jm%(#5!e$N{plB*SkL# zcV^KuYxD#i2%|V66Bu>_caD&`wxn)+Ql8yK+oi1LHP1%^InATfVj$? zn>Df?QC%OHWqp2uu5*v%2144u2`iVsd&`sgRS*N^GgXwcL83y0Ws10Os5LAn{avPu z=S7JT$Ib=@sV@#y(z_bzVq#*z#vI^eDzcE)-sARPUl<|Fe-VLipI?kEJ(g-kvC|MYjnP+Dx$=0K>i(LNP#30yW}H%)l7cImeF7R1SPjeDlN$BnVRcMLaKgJKoRx zA43ffL6@Y7rHP42Ey#IC3-l~-QBtD z+)PfG*VM-_Dx8TGX!^^Vqjveg(ch`7#I2VPsi!iZTf#?1RXQ};DilzbV``zHmA8;O zUj_V-afD3rw++sKSEuO*dgP0w(?3kFG;lfIljCh;^Xg`FPr29C{#Ku?Y@5Y??)-GW z+zwS5U<Aa8cylbVaY%QVlq|db?V%~<4_0CV^Qsm%Js9ruA9?WI0~)p zCRIKcWzo)noUm6kLvlHW`JDOnzRe|kZAL-~ndZO@MrrvdeeOmS&lGV`Tvk*L!<9ce zJjRpp?l_%`PNqi$1IC3TJWibW$I7MEq3LN?~UDEgk zHwU?rjcUgg6cjK#yGx^-K6Hgut~H{@gEq7OyvHKW(N$)p%+}S`WVC!KessJWYjnWb zKX-~OrhGF|nsJQ+lJ!Cwn5D`heAl=G! ze@roEG?TVlLTTyInuOpjnYdO`ZZ}p|8!r06PgRvfK2C@q->OmFcTMUAN|cHvSY*(7 z&0F4FLI2B19Mo{yJpUbKzIxb1f!Hi@CAzoW#n-bZp=`>9;Z-S8gUk4q1F z-rZ5ka|slG0&wNT3VV24TG-9#+&YX)5Nz!IGvu-WLN%O|%)c5c*odrf3#0Wt1dmX) zCeiaseY5yRl8%(sutWx!lY`67=KEe9xGP}qxw4DFA4K*9C$^p1yw*^T`2L@D$kmT| za{tVX$0twv@VdpAX)Y^n@D4<`L!{m8{#VP}N1<~jF56TbOUv`s_VnggyE8mqG_Itj zOxLeeU$*Sdcq;^sbu$U;P?UJqxv1dH)H&UtR_P;1LH)4C_;IpKI?hi*(0rjHf&Lrr^L{ks z)>>JkWw|&ZM%ggC$@h6~0`1F!3*SC)PyOk)P%-F3^OfnC;k|}SW&89Wn{duroPY48 z)xG3okhL?m4zTRZy=*{yOu~#LcnUuXw7j>as9$dwQX&5nA3!?JN^fTCQZB|G`08t> zY;}9#;mZrds>~Mzzz=g{foo6>`b)#q=t!oXn1hK--DS$)Cjo+IAepi7LVlegkWUQZ zVddbNPNCNlIcGmrkv9*` z!#bU|?yG*JkIcGSQS#%8>Z&K0Yp;KT6Zoxkem36hV-#3JQ>&03{wXP4&M9## zh?RIa@+lII%Zvm{9j_NH_6)f<*Xm?~z_c&jha8uHTp~wJS}HH%DcWt15ohRBY;+WV zch}6E+8HW7(g@mlSLZH$f}>ge@tyQ`Ru3zoF!Du-_b08!0j-3!DNE*(RsV^Z=bu8z z8aoO;u>`!jh0;QpFA!5XJo^BZSpk>=e^U6OYRP%0frp!X$NU#L9fmaQ z`b<+|rs(?20D7~eLBD`cNJZ8L9;4+7mM~~glx9?uyoC{cFUOCDl@rntR<^9jvk3V zk0d_@_oaUyy&lLlBx$` zJ(-MBVBlx1Nt(=1uvkcr&Oqfr)#FTk%i4po7XJ1VnZJG= z1S0xM;o}lLRf_Qy?n?l}p@)|}g7LTNwNS@9A(iCZ2&YT6fSa0!pp>)pNgDRSiYKfe zXFu0{+Oag-+pn>S*S)xeJ;IkI5<`y)}o1-Y!O4nSn{YOL&(w-vW#MkB@7ZnLxaiWp<t*1p_U!ag9W(u-X1uM=`msnyqESEJdoF=Ea=wm--{H z4^rT|!Wn7ShfZDISd|8}D!LL`ykYrUftXb8CWS4zRL$`W0a4?mgNUYm$XVYjuZBL` zb_Qh~G&hm>pve0cTzIsHqG9kI5SLBp@K#;jKvjM%P^q6s$0NATdHSwFk)M0LFv)9Hbc7!W<%Mv1O?JPcI?`Z^*>Pn( z#twbpvdi0-QJ;7sB%l$6c>9&m?7s`jq2GxPlVF=W9ZkG#g*ZlH3LUHV)6B>06;1t8 zpN6pDzn;HvG4e6bRHU*wqIw^rzYqp`N;fVDuhO~E%LZl*r$T{)@Ay!ESN~kSMZO1J z_gQ0K8T@oetCoJ+v-N?%kuotf=2QUB)Np~ZWPQ8)wsY<3SV$+4sr6&_Ibje&$dJdV z+Qmo?pRdJxPrC-o)lv*#@j=wrx%Zh@C{ebx)K4%ka_)Jo=T59BJ8q~H5rAm(N zKPc6gHktv`9d6Dh+373g9w&|km*Y_WPs6Ib07K(VT3;9-&C#l#e}0o~`{=9J+b9+NPjnJg#buJX?g^dShhnDIY}i?kJDiv1U@p#<7WOAC z6bt}%P^6}1YUF};T^r9TPn}oWbSYXJRbt$BGHl^~EW=Iu>7Y=D^??9$K~FwmZ;2{h z2`i}+>N2HQ(Rt^{E$I|T5otuU+qyyM%X}aeO&;3a>6%41H)8ENc&ArPci%<$9-y?~ z11=fHm^c?P$zLh^?BshM>uM1oYLcezE#qPCw@$H0o-+spBy^@)PV(E}8LIcprc&xW zI8Ia?q?jSnRhD)>-<*7c3~REkmHj>NZeAKn{i zBWh&=5Q}`Hk zW|oTT4n*Es zg1OEtP4U;H(R|6d6TOBls1{br1vrvDrno$7=Z$Eh0iy_8e3iuEe1=(z@W!7UL)yqR z$tI^Y1y_0EI6fJxf=<8v5Jw-!kiTI$ixEn$xM4nZgPuDlR|e@YoRID4@=UxCnp_1w z1FZN6H?XwH6}QzJbYN2+Y~VZUb)(GNwBX^B7mQDQqPvB{_gye(qw_TI@O4Og^iX3(|s;QW~oBOxub;nuGt#f*> zfpu;f$03d$Hw%Pk3AXP3VcVSh9cHEa;IMGgB7-4_IMJa&zY*37FbDWeF;|4{&@ych zga>&8y+~95A~@i%&cfJuTt7YsJF0xJdy%*`R>+joOq+s(u^l9=;&Vvj8tl&ME8j}f zp$g0u1i4(@gIJ9%gbTt|>Tof%2#aZ~^Sn{ip_4sG)R8~baM6x*r*Ypo5%ki>W2EI) zSU!(w(M1IDbzMSV0@_4KmfqS9A}7X{!7U6b<`bpD+iYK$_;uhIu@^gD=jW_L5bHZj ziUN4KcEz(mHH+by2!buF=7mC9XJ=;>z%5Uh1(s2fy4H<3j71>alS2eLY-=~6 zPz~#sIp^)Wo#XM%%<;wFYu~8@f|Lq ziM>+5gpj9U30oKo_QG=FRNU6r+~Bq3)}wwbQ*q9U1J%!OgTsMBbgP2fm_Jvt4XpRY(3^QW*X$9T(Ue`!+VBwmhi^nw@fK>)&IUky zo;nAx-oR>3GEsBqtzIkmt8Pj_>spquqW1YT6HN=X>(4C3AY4F|G?Jdnye#x9)EAijAa$f-N-S+;$-Z + + + +
+

QModManager

+

Thank you for installing QModManager.

+
Configure Steam
+

Set the Launch Options for Subnautica Below Zero to:

+ + "/Users/{USERNAME}/Library/Application Support/Steam/steamapps/common/SubnauticaZero/QModManager.sh" %command% + +
+
+
+
Resources
+

Go through following links for additional information.

+ +
+

+

Copyright © 2021 QModManager Inc. All rights reserved.

+
+ + diff --git a/MacOSX/dist/Resources/license.html b/MacOSX/dist/Resources/license.html new file mode 100644 index 00000000..0d656739 --- /dev/null +++ b/MacOSX/dist/Resources/license.html @@ -0,0 +1,127 @@ + + + + +
+

+ NOTE: + This license does not apply to the contents of the QMMHarmonyShimmer folder. The contents of the QMMHarmonyShimmer folder are licensed under GPL-3.0 (view LICENSE). +

+ +

Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License

+

By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions.

+

Section 1 – Definitions.

+
    +
  1. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image.
  2. +
  3. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights.
  4. +
  5. Effective Technological Measures means those measures that, in the absence of proper authority, may not + be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar + international agreements.
  6. +
  7. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material.
  8. +
  9. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License.
  10. +
  11. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license.
  12. +
  13. Licensor means the individual(s) or entity(ies) granting rights under this Public License.
  14. +
  15. NonCommercial means not primarily intended for or directed towards commercial advantage or monetary compensation. For purposes of this Public License, the exchange of the Licensed Material for other material subject to Copyright and Similar Rights by digital file-sharing or similar means is NonCommercial provided there is no payment of monetary compensation in connection with the exchange.
  16. +
  17. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them.
  18. +
  19. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world.
  20. +
  21. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning.
  22. +
+

Section 2 – Scope.

+
    +
  1. License grant. +
      +
    1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: +
        +
      1. reproduce and Share the Licensed Material, in whole or in part, for NonCommercial purposes only; and
      2. +
      3. produce and reproduce, but not Share, Adapted Material for NonCommercial purposes only.
      4. +
      +
    2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions.
    3. +
    4. Term. The term of this Public License is specified in Section 6(a).
    5. +
    6. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material.
    7. +
    8. Downstream recipients. +
      +
        +
      1. Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License.
      2. +
      3. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material.
      4. +
      +
      +
    9. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i).
    10. +
    +
  2. Other rights.

    +
      +
    1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise.
    2. +
    3. Patent and trademark rights are not licensed under this Public License.
    4. +
    5. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties, including when the Licensed Material is used other than for NonCommercial purposes.
    6. +
    +
  3. +
+

Section 3 – License Conditions.

+

Your exercise of the Licensed Rights is expressly made subject to the following conditions.

+
    +
  1. Attribution.

    +
      +
    1. If You Share the Licensed Material, You must:

      +
        +
      1. retain the following if it is supplied by the Licensor with the Licensed Material: +
          +
        1. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated);
        2. +
        3. a copyright notice;
        4. +
        5. a notice that refers to this Public License;
        6. +
        7. a notice that refers to the disclaimer of warranties;
        8. +
        9. a URI or hyperlink to the Licensed Material to the extent reasonably practicable;
        10. +
        +
      2. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and
      3. +
      4. indicate the Licensed Material is licensed under this Public License, + and include the text of, or the URI or hyperlink to, this Public + License.
      5. +
      + For the avoidance of doubt, You do not have permission under this Public License to Share Adapted Material. +
    2. +
    3. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information.
    4. +
    5. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable.
    6. +
    +
  2. +
+

Section 4 – Sui Generis Database Rights.

+

Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material:

+
    +
  1. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database for NonCommercial purposes only and provided You do not Share Adapted Material;
  2. +
  3. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and
  4. +
  5. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database.
  6. +
+ For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. +

Section 5 – Disclaimer of Warranties and Limitation of Liability.

+
    +
  1. Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.
  2. +
  3. To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.
  4. +
+
    +
  1. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability.
  2. +
+

Section 6 – Term and Termination.

+
    +
  1. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically.
  2. +
  3. +

    Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates:

    +
      +
    1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or
    2. +
    3. upon express reinstatement by the Licensor.
    4. +
    + For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License.
  4. +
  5. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License.
  6. +
  7. Sections 1, 5, 6, 7, and 8 survive termination of this Public License.
  8. +
+

Section 7 – Other Terms and Conditions.

+
    +
  1. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed.
  2. +
  3. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License.
  4. +
+

Section 8 – Interpretation.

+
    +
  1. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License.
  2. +
  3. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions.
  4. +
  5. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor.
  6. +
  7. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority.
  8. +
+
+ diff --git a/MacOSX/dist/Resources/welcome.html b/MacOSX/dist/Resources/welcome.html new file mode 100644 index 00000000..22550135 --- /dev/null +++ b/MacOSX/dist/Resources/welcome.html @@ -0,0 +1,12 @@ + + + + +
+
+

This will install QModManager 4.0.2.3 on your computer. You will be guided through the steps necessary to install this software.

+
+

Click “Continue" to continue the setup

+
+ + From c13167694c2506679aa2430f303284b8e0863ec3 Mon Sep 17 00:00:00 2001 From: MrPurple6411 Date: Thu, 20 May 2021 06:32:52 -0600 Subject: [PATCH 10/10] Update Patcher.cs --- QModManager/Patching/Patcher.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/QModManager/Patching/Patcher.cs b/QModManager/Patching/Patcher.cs index 88211da6..158939ba 100644 --- a/QModManager/Patching/Patcher.cs +++ b/QModManager/Patching/Patcher.cs @@ -26,10 +26,7 @@ internal static void Patch() try { if (Patched) - { - Logger.Warn("Patch method was called multiple times!"); return; // Halt patching - } Patched = true;