From 241c9ee605995a407a481202abdefb7907adacb3 Mon Sep 17 00:00:00 2001 From: Soar Qin Date: Wed, 4 Sep 2024 03:49:24 +0800 Subject: [PATCH] work in progress --- UXAssist/LogisticsPatch.cs | 373 ++++++++++++++++++++-------------- UXAssist/assets/icon/keep.png | Bin 1245 -> 5696 bytes 2 files changed, 225 insertions(+), 148 deletions(-) diff --git a/UXAssist/LogisticsPatch.cs b/UXAssist/LogisticsPatch.cs index d7ef208..7bd3361 100644 --- a/UXAssist/LogisticsPatch.cs +++ b/UXAssist/LogisticsPatch.cs @@ -13,6 +13,8 @@ using UXAssist.Common; namespace UXAssist; +using StorageItemData = (int, int, ELogisticStorage, ELogisticStorage); + public static class LogisticsPatch { public static ConfigEntry LogisticsCapacityTweaksEnabled; @@ -484,11 +486,14 @@ public static class LogisticsPatch private static int _stationTipsRecycleCount; private static GameObject _stationTipRoot; private static GameObject _tipPrefab; - private static readonly Color DemandColor = new(223.7f / 255, 139.6f / 255, 94f / 255); - private static readonly Color SupplyColor = new(90f / 255, 208.5f / 255, 249f / 255); + private static readonly Color DemandColor = new(253f / 255, 150f / 255, 94f / 255); + private static readonly Color SupplyColor = new(97f / 255, 216f / 255, 255f / 255); private static PlanetData _lastPlanet; + private const int StorageSlotCount = 5; + private const int CarrierSlotCount = 3; + private static readonly Sprite[] LogisticsExtraItemSprites = [ Resources.Load("Icons/ItemRecipe/logistic-drone"), @@ -514,34 +519,21 @@ public static class LogisticsPatch UnityEngine.Object.Destroy(_stationTipRoot.GetComponent()); _tipPrefab = UnityEngine.Object.Instantiate(GameObject.Find("UI Root/Overlay Canvas/In Game/Scene UIs/Vein Marks/vein-tip-prefab"), _stationTipRoot.transform); _tipPrefab.name = "tipPrefab"; + var sliderBgPrefab = GameObject.Find("UI Root/Overlay Canvas/In Game/Windows/Station Window/storage-box-0/slider-bg"); var image = _tipPrefab.GetComponent(); image.sprite = GameObject.Find("UI Root/Overlay Canvas/In Game/Windows/Key Tips/tip-prefab").GetComponent().sprite; image.color = new Color(0, 0, 0, 0.8f); image.enabled = true; var rectTrans = (RectTransform)_tipPrefab.transform; rectTrans.localPosition = new Vector3(200f, 800f, 0); - rectTrans.sizeDelta = new Vector2(150, 160f); + rectTrans.sizeDelta = new Vector2(150f, 160f); rectTrans.pivot = new Vector2(0.5f, 0.5f); UnityEngine.Object.Destroy(_tipPrefab.GetComponent()); var infoText = _tipPrefab.transform.Find("info-text").gameObject; - for (var index = 0; index < 5; ++index) + for (var index = 0; index < StorageSlotCount; ++index) { - var countText = UnityEngine.Object.Instantiate(infoText, Vector3.zero, Quaternion.identity, _tipPrefab.transform); - countText.name = "countText" + index; var y = -5f - 35f * index; - var text = countText.GetComponent(); - text.fontSize = 20; - text.text = "99999"; - text.alignment = TextAnchor.MiddleRight; - rectTrans = (RectTransform)countText.transform; - rectTrans.sizeDelta = new Vector2(70f, 30f); - rectTrans.anchorMax = new Vector2(0f, 1f); - rectTrans.anchorMin = new Vector2(0f, 1f); - rectTrans.pivot = new Vector2(0f, 1f); - rectTrans.anchoredPosition3D = new Vector3(30f, y, 0); - UnityEngine.Object.Destroy(countText.GetComponent()); - var iconTrans = _tipPrefab.transform.Find("icon"); var itemIcon = UnityEngine.Object.Instantiate(iconTrans.gameObject, new Vector3(0, 0, 0), Quaternion.identity, _tipPrefab.transform); itemIcon.name = "icon" + index; @@ -551,6 +543,52 @@ public static class LogisticsPatch rectTrans.anchorMin = new Vector2(0f, 1f); rectTrans.pivot = new Vector2(0f, 1f); rectTrans.anchoredPosition3D = new Vector3(0, y, 0); + + var sliderBg = UnityEngine.Object.Instantiate(sliderBgPrefab.gameObject, new Vector3(0, 0, 0), Quaternion.identity, _tipPrefab.transform); + sliderBg.name = "sliderBg" + index; + rectTrans = (RectTransform)sliderBg.transform; + rectTrans.sizeDelta = new Vector2(66f, 6f); + rectTrans.anchorMax = new Vector2(0f, 1f); + rectTrans.anchorMin = new Vector2(0f, 1f); + rectTrans.pivot = new Vector2(0f, 1f); + rectTrans.anchoredPosition3D = new Vector3(34f, y - 18f, 0f); + rectTrans = (RectTransform)sliderBg.transform.Find("current-fg").transform; + rectTrans.sizeDelta = new Vector2(32f, 4f); + rectTrans.anchorMax = new Vector2(0f, 1f); + rectTrans.anchorMin = new Vector2(0f, 1f); + rectTrans.pivot = new Vector2(0f, 1f); + rectTrans.localPosition = new Vector3(1f, -1f, 0f); + rectTrans = (RectTransform)sliderBg.transform.Find("ordered-fg").transform; + rectTrans.sizeDelta = new Vector2(32f, 4f); + rectTrans.anchorMax = new Vector2(0f, 1f); + rectTrans.anchorMin = new Vector2(0f, 1f); + rectTrans.pivot = new Vector2(0f, 1f); + rectTrans.localPosition = new Vector3(33f, -1f, 0f); + rectTrans = (RectTransform)sliderBg.transform.Find("max-fg").transform; + rectTrans.sizeDelta = new Vector2(64f, 4f); + rectTrans.anchorMax = new Vector2(0f, 1f); + rectTrans.anchorMin = new Vector2(0f, 1f); + rectTrans.pivot = new Vector2(0f, 1f); + rectTrans.localPosition = new Vector3(1f, -1f, 0f); + UnityEngine.Object.Destroy(sliderBg.GetComponent()); + UnityEngine.Object.Destroy(sliderBg.transform.Find("thumb").gameObject); + UnityEngine.Object.Destroy(sliderBg.transform.Find("speed-text").gameObject); + sliderBg.gameObject.SetActive(true); + + var countText = UnityEngine.Object.Instantiate(infoText, Vector3.zero, Quaternion.identity, _tipPrefab.transform); + countText.name = "countText" + index; + var text = countText.GetComponent(); + text.fontSize = 16; + text.text = ""; + text.alignment = TextAnchor.UpperRight; + rectTrans = (RectTransform)countText.transform; + rectTrans.sizeDelta = new Vector2(70f, 20f); + rectTrans.anchorMax = new Vector2(0f, 1f); + rectTrans.anchorMin = new Vector2(0f, 1f); + rectTrans.pivot = new Vector2(0f, 1f); + rectTrans.anchoredPosition3D = new Vector3(30f, y, 0); + UnityEngine.Object.Destroy(countText.GetComponent()); + var stateLocal = UnityEngine.Object.Instantiate(iconTrans.gameObject, new Vector3(0, 0, 0), Quaternion.identity, _tipPrefab.transform); stateLocal.name = "iconLocal" + index; stateLocal.GetComponent().material = null; @@ -571,7 +609,7 @@ public static class LogisticsPatch rectTrans.anchoredPosition3D = new Vector3(115f, y, 0); } - for (var i = 0; i < 3; i++) + for (var i = 0; i < CarrierSlotCount; i++) { var iconObj = UnityEngine.Object.Instantiate(GameObject.Find("UI Root/Overlay Canvas/In Game/Top Tips/Entity Briefs/brief-info-top/brief-info/content/icons/icon"), new Vector3(0, 0, 0), Quaternion.identity, _tipPrefab.transform); @@ -587,7 +625,7 @@ public static class LogisticsPatch rectTrans.anchorMax = new Vector2(0f, 1f); rectTrans.anchorMin = new Vector2(0f, 1f); rectTrans.pivot = new Vector2(0f, 1f); - rectTrans.anchoredPosition3D = new Vector3(17f + i * 40f, -180f, 0); + rectTrans.anchoredPosition3D = new Vector3(0f, -180f, 0); var countText = UnityEngine.Object.Instantiate(infoText, Vector3.zero, Quaternion.identity, iconObj.transform); UnityEngine.Object.Destroy(countText.GetComponent()); @@ -604,7 +642,7 @@ public static class LogisticsPatch rectTrans.pivot = new Vector2(0f, 1f); rectTrans.localPosition = new Vector3(0f, -18f, 0f); - if (i >= 2) continue; + if (i >= CarrierSlotCount - 1) continue; countText = UnityEngine.Object.Instantiate(infoText, Vector3.zero, Quaternion.identity, iconObj.transform); UnityEngine.Object.Destroy(countText.GetComponent()); @@ -647,10 +685,12 @@ public static class LogisticsPatch private Text[] _carrierIdleCountText; private GameObject _infoText; + private StationComponent _currentStation; private EStationTipLayout _layout = EStationTipLayout.None; private int _storageNum; - private static readonly Dictionary ItemSprites = new(); + private readonly StorageItemData[] _storageItems = new StorageItemData[5]; + private static readonly Dictionary ItemSprites = new(); private static readonly Color[] StateColor = [Color.gray, SupplyColor, DemandColor]; private static readonly Sprite[] StateSprite = @@ -672,28 +712,29 @@ public static class LogisticsPatch public void InitStationTip() { rectTransform = (RectTransform)transform; - _icons = new Transform[5]; - _iconLocals = new Transform[5]; - _iconRemotes = new Transform[5]; - _iconsImage = new Image[5]; - _iconLocalsImage = new Image[5]; - _iconRemotesImage = new Image[5]; - _countTexts = new Transform[5]; - _countTextsText = new Text[5]; + _icons = new Transform[StorageSlotCount]; + _iconLocals = new Transform[StorageSlotCount]; + _iconRemotes = new Transform[StorageSlotCount]; + _iconsImage = new Image[StorageSlotCount]; + _iconLocalsImage = new Image[StorageSlotCount]; + _iconRemotesImage = new Image[StorageSlotCount]; + _countTexts = new Transform[StorageSlotCount]; + _countTextsText = new Text[StorageSlotCount]; _carrierIcons = new Transform[3]; _carrierTotalCountText = new Text[3]; _carrierIdleCountText = new Text[2]; _infoText = transform.Find("info-text").gameObject; - for (var i = 0; i < 3; i++) + for (var i = CarrierSlotCount - 1; i >= 0; i--) { _carrierIcons[i] = transform.Find("carrierIcon" + i); + _carrierIcons[i].gameObject.SetActive(false); _carrierTotalCountText[i] = _carrierIcons[i].Find("carrierTotalCountText").GetComponent(); - if (i >= 2) continue; + if (i >= CarrierSlotCount - 1) continue; _carrierIdleCountText[i] = _carrierIcons[i].Find("carrierIdleCountText").GetComponent(); } - for (var i = 0; i < 5; i++) + for (var i = StorageSlotCount - 1; i >= 0; i--) { _countTexts[i] = transform.Find("countText" + i); _countTextsText[i] = _countTexts[i].GetComponent(); @@ -707,11 +748,34 @@ public static class LogisticsPatch _icons[i].gameObject.SetActive(false); _iconLocals[i].gameObject.SetActive(false); _iconRemotes[i].gameObject.SetActive(false); + _storageItems[i] = (-1, -1, ELogisticStorage.None, ELogisticStorage.None); } _infoText.SetActive(false); } + public void ResetStationTip() + { + _currentStation = null; + _layout = EStationTipLayout.None; + for (var i = StorageSlotCount - 1; i >= 0; i--) + { + _countTexts[i].gameObject.SetActive(false); + _icons[i].gameObject.SetActive(false); + _iconLocals[i].gameObject.SetActive(false); + _iconRemotes[i].gameObject.SetActive(false); + _storageItems[i] = (-1, -1, ELogisticStorage.None, ELogisticStorage.None); + _countTextsText[i].color = StateColor[0]; + _iconLocalsImage[i].color = StateColor[0]; + _iconRemotesImage[i].color = StateColor[0]; + } + + for (var i = CarrierSlotCount - 1; i >= 0; i--) + { + _carrierIcons[i].gameObject.SetActive(false); + } + } + private static Sprite GetItemSprite(int itemId) { if (ItemSprites.TryGetValue(itemId, out var sprite)) @@ -721,142 +785,143 @@ public static class LogisticsPatch return sprite; } - public void SetItem(int i, StationStore storage, bool isStellar, bool isCollector) + public void SetItem(int i, StationStore storage) { + var (oldItemId, oldItemCount, oldLocalState, oldRemoteState) = _storageItems[i]; var itemId = storage.itemId; + var itemCount = storage.count; var icon = _icons[i]; var iconLocal = _iconLocals[i]; var iconRemote = _iconRemotes[i]; var countUIText = _countTextsText[i]; - if (itemId <= 0) + if (oldItemCount != itemCount) { - icon.gameObject.SetActive(false); - iconLocal.gameObject.SetActive(false); - iconRemote.gameObject.SetActive(false); - countUIText.color = Color.gray; - countUIText.text = "— "; - return; + _storageItems[i].Item2 = itemCount; + countUIText.text = itemCount.ToString(); + } + if (itemId != oldItemId) + { + _storageItems[i].Item1 = itemId; + if (itemId <= 0) + { + icon.gameObject.SetActive(false); + iconLocal.gameObject.SetActive(false); + iconRemote.gameObject.SetActive(false); + countUIText.color = StateColor[0]; + countUIText.text = "— "; + return; + } + _iconsImage[i].sprite = GetItemSprite(itemId); + icon.gameObject.SetActive(true); } - _iconsImage[i].sprite = GetItemSprite(itemId); - icon.gameObject.SetActive(true); - countUIText.text = storage.count.ToString(CultureInfo.CurrentCulture); - if (isCollector) return; - var iconLocalImage = _iconLocalsImage[i]; - var localLogic = storage.localLogic; - iconLocalImage.sprite = StateSprite[(int)localLogic]; - iconLocalImage.color = StateColor[(int)localLogic]; - iconLocal.gameObject.SetActive(true); - if (isStellar) + switch (_layout) { - var iconRemoteImage = _iconRemotesImage[i]; - var remoteLogic = storage.remoteLogic; - iconRemoteImage.sprite = StateSprite[(int)remoteLogic]; - iconRemoteImage.color = StateColor[(int)remoteLogic]; - iconRemote.gameObject.SetActive(true); - countUIText.color = iconRemoteImage.color; - } - else - { - iconRemote.gameObject.SetActive(false); - countUIText.color = iconLocalImage.color; + case EStationTipLayout.InterstellarLogistics: + { + var localLogic = storage.localLogic; + if (oldLocalState != localLogic) + { + _storageItems[i].Item3 = localLogic; + var iconLocalImage = _iconLocalsImage[i]; + iconLocalImage.sprite = StateSprite[(int)localLogic]; + iconLocalImage.color = StateColor[(int)localLogic]; + iconLocal.gameObject.SetActive(true); + } + var remoteLogic = storage.remoteLogic; + if (oldRemoteState != remoteLogic) + { + _storageItems[i].Item4 = remoteLogic; + var iconRemoteImage = _iconRemotesImage[i]; + iconRemoteImage.sprite = StateSprite[(int)remoteLogic]; + iconRemoteImage.color = StateColor[(int)remoteLogic]; + iconRemote.gameObject.SetActive(true); + countUIText.color = iconRemoteImage.color; + } + + break; + } + case EStationTipLayout.VeinCollector: + case EStationTipLayout.PlanetaryLogistics: + { + var localLogic = storage.localLogic; + if (oldLocalState != localLogic) + { + _storageItems[i].Item3 = localLogic; + var iconLocalImage = _iconLocalsImage[i]; + iconLocalImage.sprite = StateSprite[(int)localLogic]; + iconLocalImage.color = StateColor[(int)localLogic]; + iconLocal.gameObject.SetActive(true); + countUIText.color = iconLocalImage.color; + } + iconRemote.gameObject.SetActive(false); + break; + } + case EStationTipLayout.None: + case EStationTipLayout.Collector: + default: + break; } } + private static readonly bool[][] CarrierEnabled = [ + [false, false, false], + [false, false, false], + [false, false, false], + [true, false, false], + [true, true, true], + ]; + private static readonly int[] StorageNums = [0, 2, 1, 4, 5]; + private static readonly float[] TipWindowWidths = [0f, 100f, 120f, 120f, 143f]; + private static readonly float[] TipWindowExtraHeights = [0f, 5f, 5f, 40f, 40f]; + private static readonly float[] CarrierPositionX = [5f, 45f, 108f]; + public void UpdateStationInfo(StationComponent stationComponent, PlanetFactory factory) { + if (_currentStation != stationComponent) + { + _currentStation = stationComponent; + var layout = stationComponent.isCollector ? EStationTipLayout.Collector : + stationComponent.isVeinCollector ? EStationTipLayout.VeinCollector : + stationComponent.isStellar ? EStationTipLayout.InterstellarLogistics : EStationTipLayout.PlanetaryLogistics; + + if (_layout != layout) + { + _layout = layout; + for (var i = StorageSlotCount - 1; i >= 0; i--) + { + _iconLocals[i].gameObject.SetActive(false); + _iconRemotes[i].gameObject.SetActive(false); + _icons[i].gameObject.SetActive(false); + } + + _storageNum = Math.Min(StorageNums[(int)layout], stationComponent.storage.Length); + rectTransform.sizeDelta = new Vector2(TipWindowWidths[(int)layout], TipWindowExtraHeights[(int)layout] + 35f * _storageNum); + for (var i = StorageSlotCount - 1; i >= 0; i--) + { + _countTexts[i].gameObject.SetActive(i < _storageNum); + } + + for (var i = CarrierSlotCount - 1; i >= 0; i--) + { + var active = CarrierEnabled[(int)layout][i]; + _carrierIcons[i].gameObject.SetActive(active); + if (!active) continue; + var rectTrans = (RectTransform)_carrierIcons[i].transform; + rectTrans.anchoredPosition3D = new Vector3(CarrierPositionX[i], -5f - 35f * _storageNum, 0); + } + } + } + var storageArray = stationComponent.storage; - EStationTipLayout layout; - if (stationComponent.isCollector) - { - layout = EStationTipLayout.Collector; - } - else if (!stationComponent.isStellar) - { - layout = stationComponent.isVeinCollector ? EStationTipLayout.VeinCollector : EStationTipLayout.PlanetaryLogistics; - } - else - { - layout = EStationTipLayout.InterstellarLogistics; - } - - if (layout != _layout) - { - _layout = layout; - for (var i = 5 - 1; i >= 0; i--) - { - _countTexts[i].gameObject.SetActive(false); - _iconLocals[i].gameObject.SetActive(false); - _iconRemotes[i].gameObject.SetActive(false); - _icons[i].gameObject.SetActive(false); - } - - for (var i = 2; i >= 0; i--) - { - _carrierIcons[i].gameObject.SetActive(false); - _carrierTotalCountText[i].text = ""; - if (i < 2) _carrierIdleCountText[i].text = ""; - } - - var tipWindowWidth = 143f; - var tipWindowHeight = 5f; - switch (layout) - { - case EStationTipLayout.Collector: - _storageNum = 2; - tipWindowWidth = 100f; - _carrierIcons[0].gameObject.SetActive(false); - _carrierIcons[1].gameObject.SetActive(false); - _carrierIcons[2].gameObject.SetActive(false); - break; - case EStationTipLayout.VeinCollector: - _storageNum = 1; - tipWindowWidth = 120f; - _carrierIcons[0].gameObject.SetActive(false); - _carrierIcons[1].gameObject.SetActive(false); - _carrierIcons[2].gameObject.SetActive(false); - break; - case EStationTipLayout.PlanetaryLogistics: - _storageNum = Math.Min(storageArray.Length, 4); - tipWindowHeight += 35f; - tipWindowWidth = 120f; - _carrierIcons[0].gameObject.SetActive(true); - _carrierIcons[1].gameObject.SetActive(false); - _carrierIcons[2].gameObject.SetActive(false); - break; - case EStationTipLayout.InterstellarLogistics: - _storageNum = Math.Min(storageArray.Length, 5); - tipWindowHeight += 35f; - _carrierIcons[0].gameObject.SetActive(true); - _carrierIcons[1].gameObject.SetActive(true); - _carrierIcons[2].gameObject.SetActive(true); - break; - } - - for (var i = _storageNum - 1; i >= 0; i--) - { - _countTexts[i].gameObject.SetActive(true); - } - - rectTransform.sizeDelta = new Vector2(tipWindowWidth, tipWindowHeight + 35f * _storageNum); - - for (var i = 0; i < 3; i++) - { - var rectTrans = (RectTransform)_carrierIcons[i].transform; - rectTrans.anchoredPosition3D = new Vector3(rectTrans.anchoredPosition3D.x, -5f - 35f * _storageNum, 0); - } - } - - var isStellar = stationComponent.isStellar; - var isCollector = stationComponent.isCollector; for (var j = _storageNum - 1; j >= 0; j--) { var storage = storageArray[j]; - SetItem(j, storage, isStellar, isCollector); + SetItem(j, storage); } int currentCount, totalCount; - switch (layout) + switch (_layout) { case EStationTipLayout.PlanetaryLogistics: totalCount = stationComponent.idleDroneCount + stationComponent.workDroneCount; @@ -876,6 +941,11 @@ public static class LogisticsPatch currentCount = stationComponent.warperCount; _carrierTotalCountText[2].text = currentCount.ToString(); break; + case EStationTipLayout.None: + case EStationTipLayout.Collector: + case EStationTipLayout.VeinCollector: + default: + break; } } } @@ -885,9 +955,16 @@ public static class LogisticsPatch foreach (var stationTip in _stationTips) { if (!stationTip) continue; - stationTip.gameObject.SetActive(false); if (_stationTipsRecycleCount < 128) + { + stationTip.ResetStationTip(); + stationTip.gameObject.SetActive(false); StationTipsRecycle[_stationTipsRecycleCount++] = stationTip; + } + else + { + UnityEngine.Object.Destroy(stationTip); + } } Array.Clear(_stationTips, 0, _stationTips.Length); diff --git a/UXAssist/assets/icon/keep.png b/UXAssist/assets/icon/keep.png index c7f76cdce7a6f714d42945bdd5021ddb2f77b552..39460065b77d6d12b9fa81ed397bf0a69c3d92c0 100644 GIT binary patch literal 5696 zcmeHL`Ck*~)_;;1kU&8+$Rb-4P$VQuzH$A6rbhz+e6h`q>kR-IF3Di261=>RdHfMxNRi&ITfwz<{V^yk3Etwd1%T>o z)rGxOD61TC+Z_pj`X7oP>5PT?Dgd;)w{f@pGbUhSP}muDe7EwEq5VVqqbXV>QtJlq zyE60Ozi#eWqU~)F>FNLLqsP)i>mK}Gcz*o@wXSWa255TwE}!4Nit6H?x^mf4udkFT~O_+?FnzifrKuF_97ZNuue2^}dOgDBA#gVn)VPOLr;PQy8iytUk z23@1U!;~5SckzD+!qeL7YFoW~{x#bp`u7%1-l49Jo@y69n9zvoz2{E{zg7>K#ktO8 zv)OnW>dZ`aQP0q)3px9*qY=m+W*j&EAz!fj+*I0tLA`|_4$DU~%l(b&R||O99i)gs z$OrT!a*fUAAnb1$!gP^P7Iz@!%xt}cd{gi$l|2_|SZ^ZeGxKq&F~(*}mM%Eafc@sL z@yBQ$^MMP_k)v+1*UBj)afl^#H?aE2e;E;C(qSwjd-<0H#q+Vka`x)nOSr+?z2lOt zNA_U%P`h$$Aok=1x+pg4l>SOPM}fdZV`1LK@^SKJ!GqF*FPij;?U)5}m0_htzW^R1 z&96N(Fp|6vX<-6$?d2s}#5_tMs~BNNY2u!OOLKubLKn;&Nnil`$Y7HvwDYTo{n+cJ zey7P*$44fF)|uz^BtOR2|7OJZ_Tjc?#jnpzU)uLQT~xW|a97;7m=8l4QwEV}uv)yO zAQtN&JjLNcQ47?p}-o%Q9 z4y5EUrhd|YA_X5UhPZS2=xC8{<3;e^@7h~=C0fL|_JQL3ZV{blOl1$8H|lhvags(T z3Am5kyiJWCgJ&i;YgTirQt6_^*zYh3ViXz#TF#7<0*r{%AeX~tU~#$uHR7osg4+d$ zwd41gXsbM0VQAQ8M3l%jadF!sb(wgV;E2hP)!ew|cwy{T(yP=#hHzYJl<_C<^N^tu z-ii9_{SHq2Mt`zz^FnIQ)dSP-dutZ}KfSf}yfC_JCg{)a%)s~=Wx0kc-naA+{4iZp0PJqc10H{y$= zX1d*t!s=r*@oVg5!nCN(##MJd*nA zg@XJk65{`EYFMLlZQ#k7Nw+5TVpDIpyA}zqa|WxA2ux;+EfIIndM5CNrz_s$1Xf2! zV+3;JoUZC6VA)ZP++b#h1cB}2FWgGD{BFosff34zzj?s1_ugG2eiY&S)$GL*`mH52 zu>fnV5L&2$Y2jY%{zMK>pu&F#b7+S!i*&*C?e+MyW&wF6sw=u5=l2KHJ(`t;HJzaf zl=#(xZh0^xAcR!qOI#ivbrBrhpjrkj+Y=FMUP-SM_})x9weU|YKj=??X#ISA>(Gj) zUjp~HbLiFnFQ>i1%9poLcLwpDJIH5d@3zjwCQeAVk$f`(({7C#@dOuuS);^H zBo0VJ;;))hr@W3C4E~<|D=pbc{F=QUuZcn{&Xdl1KAVzfqOvwM(YN)s zf_Ut&pg$kO?T)K3%iwCX7p66lv)c^Zh;uVBTA+wyF?%0Dpj3@6>Kkb_H|$d<`6jz^ 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