From cd4e3a3d2a670d882962d060edb286b21f9e9909 Mon Sep 17 00:00:00 2001 From: Regalis Date: Thu, 18 Feb 2016 21:09:10 +0200 Subject: [PATCH] Fixed password box not working, connecting powered items with multiple parallel wires works, velocity/depth indicators on nav, stuff --- .../Data/ContentPackages/Vanilla 0.3.xml | 75 +++++++++--------- Subsurface/Properties/AssemblyInfo.cs | 4 +- Subsurface/Source/GUI/GUIMessageBox.cs | 6 +- .../GameModes/Tutorials/BasicTutorial.cs | 23 +++++- .../Source/Items/Components/Machines/Radar.cs | 3 +- .../Items/Components/Machines/Steering.cs | 15 ++++ .../Items/Components/Power/PowerTransfer.cs | 13 ++- .../Components/Signal/ConnectionPanel.cs | 2 +- Subsurface/Source/Map/Explosion.cs | 48 ++++++----- Subsurface/Source/Map/Gap.cs | 6 +- Subsurface/Source/Map/Structure.cs | 6 +- Subsurface/Source/Networking/GameClient.cs | 3 + Subsurface/Source/Networking/GameServer.cs | 6 +- Subsurface/Source/Networking/NetConfig.cs | 2 + Subsurface/Source/Physics/Physics.cs | 2 + Subsurface/Source/Program.cs | 20 ++--- Subsurface/Source/Screens/MainMenuScreen.cs | 4 +- Subsurface/Source/Sounds/SoundManager.cs | 10 ++- Subsurface/changelog.txt | 16 ++++ Subsurface_Solution.v12.suo | Bin 930304 -> 930304 bytes 20 files changed, 182 insertions(+), 82 deletions(-) diff --git a/Subsurface/Data/ContentPackages/Vanilla 0.3.xml b/Subsurface/Data/ContentPackages/Vanilla 0.3.xml index 226776875..9348a625f 100644 --- a/Subsurface/Data/ContentPackages/Vanilla 0.3.xml +++ b/Subsurface/Data/ContentPackages/Vanilla 0.3.xml @@ -1,40 +1,41 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + diff --git a/Subsurface/Properties/AssemblyInfo.cs b/Subsurface/Properties/AssemblyInfo.cs index f40f11617..63dd17eb2 100644 --- a/Subsurface/Properties/AssemblyInfo.cs +++ b/Subsurface/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; // 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("0.3.2.4")] -[assembly: AssemblyFileVersion("0.3.2.4")] +[assembly: AssemblyVersion("0.3.2.5")] +[assembly: AssemblyFileVersion("0.3.2.5")] diff --git a/Subsurface/Source/GUI/GUIMessageBox.cs b/Subsurface/Source/GUI/GUIMessageBox.cs index 545eb9409..5d25a0f2c 100644 --- a/Subsurface/Source/GUI/GUIMessageBox.cs +++ b/Subsurface/Source/GUI/GUIMessageBox.cs @@ -45,7 +45,11 @@ namespace Barotrauma var frame = new GUIFrame(new Rectangle(0,0,width,height), null, Alignment.Center, GUI.Style, this); new GUITextBlock(new Rectangle(0, 0, 0, 30), header, Color.Transparent, Color.White, textAlignment, GUI.Style, frame, true); - new GUITextBlock(new Rectangle(0, 30, 0, height - 70), text, Color.Transparent, Color.White, textAlignment, GUI.Style, frame, true); + if (!string.IsNullOrWhiteSpace(text)) + { + new GUITextBlock(new Rectangle(0, 30, 0, height - 70), text, + Color.Transparent, Color.White, textAlignment, GUI.Style, frame, true); + } int x = 0; this.Buttons = new GUIButton[buttons.Length]; diff --git a/Subsurface/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs b/Subsurface/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs index 65fe392fb..e0883ab83 100644 --- a/Subsurface/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs +++ b/Subsurface/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs @@ -333,13 +333,21 @@ namespace Barotrauma.Tutorials //fix everything except the command windows foreach (Structure w in Structure.WallList) { - if (windows.Contains(w)) continue; + bool isWindow = windows.Contains(w); for (int i = 0; i < w.SectionCount; i++) { if (!w.SectionIsLeaking(i)) continue; - w.AddDamage(i, -100000.0f); + if (isWindow) + { + w.AddDamage(i, -w.SectionDamage(i) * 0.2f); + } + else + { + w.AddDamage(i, -100000.0f); + } + } } @@ -365,8 +373,19 @@ namespace Barotrauma.Tutorials infoBox = CreateInfoFrame("You should quickly find yourself a diving mask or a diving suit. " + "There are some in the room next to the airlock."); + bool divingMaskSelected = false; + while (!HasItem("Diving Mask") && !HasItem("Diving Suit")) { + if (!divingMaskSelected && + Character.Controlled.ClosestItem != null && Character.Controlled.ClosestItem.Name == "Diving Suit") + { + infoBox = CreateInfoFrame("The can only be one item in each inventory slot, so you need to take off " + +"the jumpsuit if you wish to wear a diving suit."); + + divingMaskSelected = true; + } + yield return CoroutineStatus.Running; } diff --git a/Subsurface/Source/Items/Components/Machines/Radar.cs b/Subsurface/Source/Items/Components/Machines/Radar.cs index 6ef73dd3c..a2fe024df 100644 --- a/Subsurface/Source/Items/Components/Machines/Radar.cs +++ b/Subsurface/Source/Items/Components/Machines/Radar.cs @@ -317,7 +317,8 @@ namespace Barotrauma.Items.Components GUI.DrawRectangle(spriteBatch, new Rectangle((int)markerPos.X, (int)markerPos.Y, 5, 5), Color.LightGreen); spriteBatch.DrawString(GUI.SmallFont, label, new Vector2(markerPos.X + 10, markerPos.Y), Color.LightGreen); - spriteBatch.DrawString(GUI.SmallFont, (int)(dist / 80.0f) + " m", new Vector2(markerPos.X + 10, markerPos.Y + 15), Color.LightGreen); + spriteBatch.DrawString(GUI.SmallFont, (int)(dist * Physics.DisplayToRealWorldRatio) + " m", + new Vector2(markerPos.X + 10, markerPos.Y + 15), Color.LightGreen); } public override bool FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message) diff --git a/Subsurface/Source/Items/Components/Machines/Steering.cs b/Subsurface/Source/Items/Components/Machines/Steering.cs index 5781a17db..9bc6e3bc1 100644 --- a/Subsurface/Source/Items/Components/Machines/Steering.cs +++ b/Subsurface/Source/Items/Components/Machines/Steering.cs @@ -164,7 +164,22 @@ namespace Barotrauma.Items.Components Rectangle velRect = new Rectangle(x + 20, y + 20, width - 40, height - 40); //GUI.DrawRectangle(spriteBatch, velRect, Color.White, false); + + if (Submarine.Loaded != null && Level.Loaded != null) + { + Vector2 realWorldVelocity = ConvertUnits.ToDisplayUnits(Submarine.Loaded.Velocity * Physics.DisplayToRealWorldRatio) * 3.6f; + float realWorldDepth = (Submarine.Loaded.Position.Y - Level.Loaded.Size.Y) *Physics.DisplayToRealWorldRatio; + GUI.DrawString(spriteBatch, new Vector2(x + 20, y + height - 65), + "Velocity: " + (int)realWorldVelocity.X + " km/h", Color.LightGreen, null, 0, GUI.SmallFont); + GUI.DrawString(spriteBatch, new Vector2(x + 20, y + height - 50), + "Descent velocity: " + -(int)realWorldVelocity.Y + " km/h", Color.LightGreen, null, 0, GUI.SmallFont); + + GUI.DrawString(spriteBatch, new Vector2(x + 20, y + height - 30), + "Depth: " + (int)realWorldDepth + " m", Color.LightGreen, null, 0, GUI.SmallFont); + } + + GUI.DrawLine(spriteBatch, new Vector2(velRect.Center.X,velRect.Center.Y), new Vector2(velRect.Center.X + currVelocity.X, velRect.Center.Y - currVelocity.Y), diff --git a/Subsurface/Source/Items/Components/Power/PowerTransfer.cs b/Subsurface/Source/Items/Components/Power/PowerTransfer.cs index b39f610a6..824ed435f 100644 --- a/Subsurface/Source/Items/Components/Power/PowerTransfer.cs +++ b/Subsurface/Source/Items/Components/Power/PowerTransfer.cs @@ -4,6 +4,7 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; using System.Globalization; +using System.Linq; namespace Barotrauma.Items.Components { @@ -105,13 +106,19 @@ namespace Barotrauma.Items.Components ApplyStatusEffects(ActionType.OnActive, deltaTime, null); + List alreadyChecked = new List(); + List connections = item.Connections; if (connections == null) return; foreach (Connection c in connections) { if (!c.IsPower) continue; - foreach (Connection recipient in c.Recipients) + + + var recipients = c.Recipients; + + foreach (Connection recipient in recipients) { if (recipient == null || !c.IsPower) continue; @@ -123,6 +130,8 @@ namespace Barotrauma.Items.Components Powered powered = it.GetComponent(); if (powered == null) continue; + if (connectedList.Contains(powered)) continue; + PowerTransfer powerTransfer = powered as PowerTransfer; PowerContainer powerContainer = powered as PowerContainer; if (powerTransfer != null) @@ -140,6 +149,8 @@ namespace Barotrauma.Items.Components { fullPower += powerContainer.CurrPowerOutput; } + + alreadyChecked.Add(recipient); } else { diff --git a/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs b/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs index 5e675e31f..bc4cb8490 100644 --- a/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs +++ b/Subsurface/Source/Items/Components/Signal/ConnectionPanel.cs @@ -174,7 +174,7 @@ namespace Barotrauma.Items.Components var otherConnection = c.Wires[i].OtherConnection(c); Networking.GameServer.Log( item.Name+" ("+ c.Name + ") -> " + - otherConnection.Item.Name+" ("+(otherConnection == null ? "none" : otherConnection.Name)+")", Color.Orange); + (otherConnection == null ? "none" : otherConnection.Item.Name+" ("+(otherConnection.Name)+")"), Color.Orange); } c.UpdateRecipients(); } diff --git a/Subsurface/Source/Map/Explosion.cs b/Subsurface/Source/Map/Explosion.cs index 9e5d4d8cc..ed6ae9701 100644 --- a/Subsurface/Source/Map/Explosion.cs +++ b/Subsurface/Source/Map/Explosion.cs @@ -79,28 +79,8 @@ namespace Barotrauma if (force == 0.0f && attack.Stun == 0.0f && attack.GetDamage(1.0f) == 0.0f) return; - foreach (Character c in Character.CharacterList) - { + ApplyExplosionForces(worldPosition, attack.Range, force, attack.GetDamage(1.0f), attack.Stun); - - foreach (Limb limb in c.AnimController.Limbs) - { - float dist = Vector2.Distance(limb.WorldPosition, worldPosition); - - if (dist > attack.Range) continue; - - float distFactor = 1.0f - dist / attack.Range; - - if (limb.WorldPosition == worldPosition) continue; - - c.AddDamage(limb.SimPosition, DamageType.None, - attack.GetDamage(1.0f) / c.AnimController.Limbs.Length * distFactor, 0.0f, attack.Stun * distFactor, false); - if (force > 0.0f) - { - limb.body.ApplyLinearImpulse(Vector2.Normalize(limb.WorldPosition - worldPosition) * distFactor * force); - } - } - } } private IEnumerable DimLight() @@ -123,6 +103,32 @@ namespace Barotrauma yield return CoroutineStatus.Success; } + public static void ApplyExplosionForces(Vector2 worldPosition, float range, float force, float damage = 0.0f, float stun = 0.0f) + { + if (range <= 0.0f) return; + + foreach (Character c in Character.CharacterList) + { + foreach (Limb limb in c.AnimController.Limbs) + { + float dist = Vector2.Distance(limb.WorldPosition, worldPosition); + + if (dist > range) continue; + + float distFactor = 1.0f - dist / range; + + if (limb.WorldPosition == worldPosition) continue; + + c.AddDamage(limb.SimPosition, DamageType.None, + damage / c.AnimController.Limbs.Length * distFactor, 0.0f, stun * distFactor, false); + if (force > 0.0f) + { + limb.body.ApplyLinearImpulse(Vector2.Normalize(limb.WorldPosition - worldPosition) * distFactor * force); + } + } + } + } + public static void RangedStructureDamage(Vector2 worldPosition, float worldRange, float damage) { List structureList = new List(); diff --git a/Subsurface/Source/Map/Gap.cs b/Subsurface/Source/Map/Gap.cs index c082f435d..d483046d2 100644 --- a/Subsurface/Source/Map/Gap.cs +++ b/Subsurface/Source/Map/Gap.cs @@ -208,7 +208,11 @@ namespace Barotrauma { flowForce = Vector2.Zero; - if (open == 0.0f) return; + if (open == 0.0f) + { + lerpedFlowForce = Vector2.Zero; + return; + } UpdateOxygen(); diff --git a/Subsurface/Source/Map/Structure.cs b/Subsurface/Source/Map/Structure.cs index 66b18e72e..4811dc103 100644 --- a/Subsurface/Source/Map/Structure.cs +++ b/Subsurface/Source/Map/Structure.cs @@ -518,7 +518,11 @@ namespace Barotrauma bool hasHole = SectionHasHole(sectionIndex); - if (hadHole != hasHole) UpdateSections(); + if (hadHole != hasHole) + { + if (hasHole) Explosion.ApplyExplosionForces(sections[sectionIndex].gap.WorldPosition, 500.0f, 5.0f, 0.0f, 0.0f); + UpdateSections(); + } } diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index e523df138..3dfda2449 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -41,6 +41,9 @@ namespace Barotrauma.Networking endRoundButton.OnSelected = ToggleEndRoundVote; endRoundButton.Visible = false; + newName = newName.Replace(":", ""); + newName = newName.Replace(";", ""); + GameMain.DebugDraw = false; Hull.EditFire = false; Hull.EditWater = false; diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index cb15fecec..3719f4b10 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -39,6 +39,9 @@ namespace Barotrauma.Networking public GameServer(string name, int port, bool isPublic = false, string password = "", bool attemptUPnP = false, int maxPlayers = 10) { + name = name.Replace(":", ""); + name = name.Replace(";", ""); + this.name = name; this.password = password; @@ -1121,12 +1124,11 @@ namespace Barotrauma.Networking int traitorIndex = Rand.Range(0, characters.Count); int targetIndex = Rand.Range(0, characters.Count); - while (targetIndex==traitorIndex) + while (targetIndex == traitorIndex) { targetIndex = Rand.Range(0, characters.Count); } - traitor = characters[traitorIndex]; target = characters[targetIndex]; diff --git a/Subsurface/Source/Networking/NetConfig.cs b/Subsurface/Source/Networking/NetConfig.cs index 9e1940093..871360a5d 100644 --- a/Subsurface/Source/Networking/NetConfig.cs +++ b/Subsurface/Source/Networking/NetConfig.cs @@ -12,6 +12,8 @@ namespace Barotrauma.Networking //UpdateEntity networkevents aren't sent to clients if they're further than this from the entity public const float UpdateEntityDistance = 2500.0f; + public const int MaxPlayers = 16; + public static string MasterServerUrl = GameMain.Config.MasterServerUrl; //if a Character is further than this from the sub, the server will ignore it diff --git a/Subsurface/Source/Physics/Physics.cs b/Subsurface/Source/Physics/Physics.cs index 2196f0d79..41dfe29b3 100644 --- a/Subsurface/Source/Physics/Physics.cs +++ b/Subsurface/Source/Physics/Physics.cs @@ -18,6 +18,8 @@ namespace Barotrauma public const Category CollisionProjectile = Category.Cat6; public const Category CollisionLevel = Category.Cat7; + public static float DisplayToRealWorldRatio = 1.0f / 80.0f; + public static double accumulator; public static double step = 1.0/60.0; diff --git a/Subsurface/Source/Program.cs b/Subsurface/Source/Program.cs index 33441588a..d330ef949 100644 --- a/Subsurface/Source/Program.cs +++ b/Subsurface/Source/Program.cs @@ -43,6 +43,15 @@ namespace Barotrauma } } + public static void CrashMessageBox(string message) + { +#if WINDOWS + MessageBox.Show(message, "Oops! Barotrauma just crashed.", MessageBoxButtons.OK, MessageBoxIcon.Error); +#endif + + Sounds.SoundManager.Dispose(); + } + static void CrashDump(GameMain game, string filePath, Exception exception) { StreamWriter sw = new StreamWriter(filePath); @@ -88,15 +97,8 @@ namespace Barotrauma sw.WriteLine(sb.ToString()); sw.Close(); - #if WINDOWS - MessageBox.Show( "A crash report (''crashreport.txt'') was saved in the root folder of the game."+ - " If you'd like to help fix this bug, please post the report on the Undertow Games forums.", - "Oops! Barotrauma just crashed.", MessageBoxButtons.OK, MessageBoxIcon.Error); - #endif - - Sounds.SoundManager.Dispose(); - - + CrashMessageBox( "A crash report (''crashreport.txt'') was saved in the root folder of the game."+ + " If you'd like to help fix this bug, please post the report on the Undertow Games forums."); } } #endif diff --git a/Subsurface/Source/Screens/MainMenuScreen.cs b/Subsurface/Source/Screens/MainMenuScreen.cs index c0beadcad..8c6b02cd8 100644 --- a/Subsurface/Source/Screens/MainMenuScreen.cs +++ b/Subsurface/Source/Screens/MainMenuScreen.cs @@ -288,10 +288,10 @@ namespace Barotrauma private bool ChangeMaxPlayers(GUIButton button, object obj) { - int currMaxPlayers = 10; + int currMaxPlayers = 8; int.TryParse(maxPlayersBox.Text, out currMaxPlayers); - currMaxPlayers = (int)MathHelper.Clamp(currMaxPlayers+(int)button.UserData, 1, 10); + currMaxPlayers = (int)MathHelper.Clamp(currMaxPlayers + (int)button.UserData, 1, NetConfig.MaxPlayers); maxPlayersBox.Text = currMaxPlayers.ToString(); diff --git a/Subsurface/Source/Sounds/SoundManager.cs b/Subsurface/Source/Sounds/SoundManager.cs index 93416efd6..11a18e4ea 100644 --- a/Subsurface/Source/Sounds/SoundManager.cs +++ b/Subsurface/Source/Sounds/SoundManager.cs @@ -33,7 +33,15 @@ namespace Barotrauma.Sounds public static void Init() { - AC = new AudioContext(); + try + { + AC = new AudioContext(); + } + catch (DllNotFoundException e) + { + Program.CrashMessageBox("OpenAL32.dll not found"); + throw e; + } for (int i = 0 ; i < DefaultSourceCount; i++) { diff --git a/Subsurface/changelog.txt b/Subsurface/changelog.txt index cb0a0da81..2f7e64523 100644 --- a/Subsurface/changelog.txt +++ b/Subsurface/changelog.txt @@ -1,3 +1,19 @@ +--------------------------------------------------------------------------------------------------------- +v0.3.2.5 +--------------------------------------------------------------------------------------------------------- + +- fixed null reference exception when starting a client + +--------------------------------------------------------------------------------------------------------- +v0.3.2.4 +--------------------------------------------------------------------------------------------------------- + +- fixed crashing when highlighting a dead husk +- fixed the unclickable checkboxes in server settings +- sending messages to specific players using ''d; [message]'' and ''name; [message]'' (messages can be +sent to players with spaces in their names now) +- more descriptive log messages when taking items from cabinets or other players + --------------------------------------------------------------------------------------------------------- v0.3.2.3 --------------------------------------------------------------------------------------------------------- diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index bca48bc5a451f60ed9f08f405c8027b92d36dabf..1da1054f47164f3dd4eb702039aa9a977b0a4634 100644 GIT binary patch delta 12272 zcmc(F3tZJzw*T3`$2q^}@$e9l0FQ`>NCs#|gm@4&Ekq>qnnMQoHZ(LcE0Uv;l~Ezb z&N4MabB^{he8jeL>_}e6F-OfD#xX4{bIhp*9c`>k|KA_@z)V6%0$*=!dsUc3lmW58p8#XE}3D3q@TT?x7hc-hJW0l*L3 z3QSl(?@!F$991>;foZ;3!hH7O#teQ%$KqQ4+1Cm7)<%R=j00pD&pp1tNfB|l=XDSKp3bCZ9m^4{k~dl$-mO7Z+O(xSj(MQe+1wGx&Q-#PR!T4Z||7jVov>#tpHsE>^S}QO`(@E#BQ@KMul4EAf+2B_X22Jj?mFp)FsSU?#x$i04JqA zmu>Q$b>1OaTGy^-2XFM#=6?i^#+Q=TPt#@DdcfU?{O(4F^gp0HdOPKzQ)xyR1^23P8~bK{6+&)>y=;kz&L|M=gV%~swM6>>c#pK_ z>r=6crvd!vs6)G%>aRB6DAE~=9MNp}{nvJ0MOIRA6t!8&fi`$P$<o(=%8<6`6wm>v(*pQVHWxGpyfL8n zfSzKuJln14Fa((mU|NkV;n@LePzwuDJ{0+>z)qyCI=3U;^HTjnq%B@52DqK(EtSHw z&rx(6s_tWy+DVF9R44fpnR|_U6BDRTW0Ei7^C+J6I%{O)ecLkc&Ft_1pZAt{TAeE8 z^YZOtHS<3yy2Ast_mn+zIF+OE}DGMQC)o@QEBK6@`FDF#IXvovxd{5+3=c`?{67wz<#bBOlD9 zc|oHSuSgNA7~4eIk&=(HdMa_eAy1f=O?48JC|+Xml6CdFVhdC*vArT&-rg_Cth#m? z)>bPVcCaF1DdJFH%7>91=05&n zF05Ar=On?m(i_1e)(R)(K!hX&>V<^M_Ij8FmNOx6NJtC3E(vVH^Vz}x?s1C2F!H7f z81*0)9EcZ-wa>bsV`JnyFQ|9Q~2vNVG4SS4k!MRn0BzrUmd8v3>b{~2_k61-aEtufpG zp0dU-YZAh*x403g`99FTM)jpuhrqwAeLvEoCLxUVpstFK+m8!8T5W23GEY*FF<-C zXg26d&pk9*oV9ev;?q3{0hoG0B<1j{eT;h|10n;cz?mf zHlAZ4g)f64qHq`JaKMA~8PH;&5O^1;0s5fPO`r_r(?M0xAHeGdIt&Zx4_*Q=3HT6v zYXao%CT6O+sPQXshtkCFSeI4>xdW^@z^7mj2h9ad1pQAm+yyv+naFpi_203u&N=A+ z9k8|n89)(=Ist>|NH?*!FSox!o_S26U*!m$dEZ*m6Dud8$yj=*Ufe4sp~aOgq4M?O zC>mNQr3W^Mq5o|=rlHq=bvveE5&tXOVVTuGyB$`WpWF^>pMGjPtOo!5c6`UWu}PHO zPs(q-0rJT^#1|Y5^Tk(~Yui`P<}c}9cl4e2YWAhfD}9TOzRNn&p2x(rz&UIc5Pmz5Y9WC6i>yFw^8(v=Y&|@;pFz1$6x=k%jv2kXQw~&rzRRX z6F#=(gxHaBS(AQ{1Nk_KM)uJ=`J3b@o*F9c6&sSIa%P`~Th5q~^l&d}0jp{Cg4`1+ z1w(2-hY6pT;+bSwUOQF!QK}9kO9^ypp*_`=IBxEA>ARy@J(5RXKPT<+_jvYf@jVt8 zB`M^Mk%v4fvi&j9lU36ON$f|S7<(uUJs|CL9h?)=W7@p8hE2cc{z*3<3f)KR za|AbeekTRV`@GVR&ga@Acy5uj$w8~u*>idBVre3C?Us`xH+(cY{=hHdKS@}5*C^T+ zB4x2V0@I}Mh6-^9bBzo8bDxhF{OZ03U+S7&zApY3H1ib}L0>&8hPR#{9-i%$-edlq zVl2h(lB!(V;i;qF-PrKmmhXjvb3eXNPN|DoNB-+w(#r@fmvb;9r1M2;2>f1MUHefMTEouzc=qVz1e;Uwvo=RW0m&tnE5#m zJ^UtnSYCsxy5f82>7G1pwe$&VC>5E&*;?u1&)fdTdwV&z9m~{-QT(;--k}EWljgZd`sSg`qsg3-JXB`mOMp*1A9c8Nrw+B zT8B}~G9!-`E|9yYe$=q+?Y*>qm({%}{eljdaz!yKtNano$^^x-CZN6P=TK19ui zOPpYvYP*ltKP`6bH!%KsIZN34Uaxl+XKtPK-6kyh%7x2HKMJ$}mJ_!Q^a-GI1YhdG zF1*V+>1fBxcb~(I($27G9=$_4CeE0LWy}X21FC?>fd#-5z>~mJfMwpxK&ydgfM7v4q^qr1C{|J9*)5X|;^kk#&QZ4R;+6 z$$luK8_-vA@&6k1I28Q12q%Sx;{gTUDZH*Hp}s!`^|8=z5kQ@T{PHev6`)D(w(C<9 z=t|^Qb!`g)4v)jF1^umyx7i*7|JLq^hoSw_>;(84FuK9$hoHhUF#Iae)MT6OE>zfl zJ>-J?RK)3apx)is_g6vtBN{duv>}ZLpEW%U^RS|6u{f*m0DS`VPS7);qd>{MNpgpl z+fIzQDRlVxd!PG{p=&zPe^ynk5;pkvLiMd*scnr@(gll}8@YnmkS++45rpFCPdeu$5l|CxJU5 z!S)A2`@_I`_x=TS&H!hDF?MRomXm6G$N5%AM*FfvyK)mGh+0>VYhL~;+-*ay9LZWE z5EMOJK8DvRm-6LPOoK9A1Z)y+;&;f*9+-kBSey_+>i6N2SZhWq$!~30d?&fpk&W z;-J}gNO_7C7QdzaFb+$Fpmo;Wq~oGGqtbdNS)S$}eI{9Nd8@u96N_4~e%7OD8Op4X z>WiT7gI0rDW!F5KkiXmplwN8QQ`Q2rH(aW4<3c+~uotrEjcul{5bi z>oqRO`w(qUCF05${C~^+EXP^ADw zS?;>1u8Ja;NfnFgO08%HM_3FYs}xA)-?<2dT-N(57a^KCSPo+gY2IMDll*^t)oE~F z4zc{8wmIYL6N#pN-diCkaB} zHd*)wjF=Ww3NBu@TdF}ILZP*N{QKBLA(awgBrlee=# zZ&?Tw0HYCRtQ{gFzA{6e^s+Ey9L)`}A0VkpUO``#IimTbGW*hrfp|4GumK_Vl-J~_ zh7$WK#M>H9H@>PzkWWN!dvQ z9cDr8LoT{4UJK>r)k-xwdDPKBMuQy9zd0grktt=TtZ@GYd0L0Svx-1*ugJZ5Z>K#^ z{Ap>N5h$%Qo*y-TKsannjj~pxfz|eK3eMG%{0r<7_e9vYG7=W3X*_MQvWHRVMJ0`= zMB4Yn(7>@OOvbM?Gx}_^Fo?W;(O^hF`(`>8!qszvf~Ta{H%gg2E$s=paMCFR)PwIJ8KMR{tw9Asa zYosobd#Y-1*B+&XQB7B6EY*mLi%&bC_!%{qD0ZrGX;IvL&{~^kpnU?>{Rehp+F`{n zQ_B!$r|M!Yk@x;e*^eOmCQYNFS(?P1Ey`(;JfErIy zAFF=FXmt|?$e#;w=GNnVS+rKiLH-<$v$6tvt;ol1w4ZkbO4KNpOCMIr!>IIayUV}9 zq0oh2*z>uu#eSx9L%cdxrdjJW5BF54L6d5luqf{qJ(9=Ps-Nk!p~Sx1(#!9;`#wj8 z6j-5#^7?)D`HZs8%5!N$m{vuuLzv>~dbNWq8E*w!5zPnNFE3Ogl!oCd3Qo?!o4r@iiFYGDQeAcm<%FfHKHhrEk$MKaw zB_&3w6;p`hRXf!ReCcR%L@}E2YkMBKB*zkp%T)5L_@6>GbL}oZX_vZ`tvUSz96`y~ zS}8BxtuB`7^pEl!YaL0f%|4|5>UpWX3-CaT{;X}~TlcF28UO5KJEXquyzHiegW?b> z`az536C`ap^QFv>k=won(B&A$c0(Sf3xWd{D$=zf{8~=v7~^FlqHr!Q1@JGeAk!$+ZGUy0DH4VGpF7s+XqtSHHR+-7wZqZN_RQukK1StQpB zN&*Gzu){+RsPDwktUNi1iZbOyUNA>n$Ec)A&*OQg)eZ1Lh7L7)SPQ~CbhN|YoKg38 zpyjL7+sLcw8NAA_Rj@#XCQxI88rA9o2`*6LnTmEm=B~LKOrhSVAr!Pg`-D-^L2(A3 zvCxv*jJp)$Ekj52HlJw`MdMjct~6k)jNV(M4gD2peWX^;XqKoz z28H^5a2vG*o)E1a5(7ngD3uIg$yBySbJE@~#aKSZt*w=P!OUsYycot^mZ;VA43z6Q z%QT!k=k;`|`4syxW|D@b7I?HmdhVBEI4^rruVJ+RF?9mf_t#SR;wf4wBlq`8C=Z>X zeZwgCDV$@Nn?ZGzc6iBI+A5LiwrH?6uLf(|kf(*yiqo=_$1T($@7e@w|K@8!G4P}& z1gf=uv?|i5<8{?~5jHvnW27`{`$Q_4tf1nvdXNP+W12fqIjG|Vxeoq3Z&Hd%p&) zoRy2n}Gh2T$#8)%C zA5}za3eT$18)GOgRmmb(M#_VI_AvAi<*3UJ3v1F8n^q6ETwv9)%Lfe0B zJPX`XpxAc5Z6ZDQf>FW7kg?Plh%Z0Zis%iuc_-yRrPtHUJj6;mE;nA&pTxt-dXO+% zfI@CI@1`_arK8-NbBcp1kPKZ#US*WU+O}~|13mV|EXjBX#F93cM9$>!dZd!QPJOE z1S!12L|m!@f}ADVleu??;boK*FGbQ8Kdu{royJ)D<_jtGDvzi8rJc-w0FAw?lqux- z23OL4Pnow-9Z4SlDKVSe!(f{&Z`$MO!Cx6qk>`-%<=(A^S0FFKU~C#j_t3m;#(NY* zevP-$5PhLZmkZbqqmt4pHK^b|(M>I7Y6B(SgX3@Xv*t8^p6Rtd8#t}O$5H-FtY(U} z8uI+c*g^KAMg}Ws{US^5CH5%(@^0gZKsA^d1!tN;Y8+sslXs@7@ZdgcsqivK{o@d$3?-@_eFm|?ih&PBi&8}jvf6x`wI{qCKPwV=#h73c` zusl%)Z;mm02|r=dzNC9X+w`(kIp<}WIEQz@?_IHSZ7klamX+fX|4OD=%9dERK7rov zZ{EmWwbC~<#F=Sf6djL`I9If}P4{WhP38^M@~L6cp$0?OCKpeiIKFi1#2Mvn{vqcU zbE11fad~m!`1@v*gIxyKQ9OC#{e`oOXG|?EEq15$?n8&N%mgKUP?fu-$nQ9NY)x}ZjF1Zt}Yf)X49D^HD ztIM&hvV#cs@P^Qb_C+YpR>#8xUsnPD_C^wXULzdA<$pWfxLljS8n#=m!BV$NzN*b7 z$?$45ezdr-11IiPkJ##ETOCt@Uz(%dkN?FS4-Id1OKaekV5NTepIJ@#H>aA8c*XA7 zWu&2hFn_{V1+BW4ukyobSzgM+0^3a`u-XtBcAMiQ^NULYuxL+Obk^v_{qfEcJ3m)% zD6F9g4RlLDm)yROCEe&~$$_!p2$;D-Pvx6`ZzzK6zXqPEjHDF*ewdgC1GAs>gK^<_ z!MkRve#`Ym(U^~n&6c}^W1qhat}FH_vt&*1_c#j$kCDP#o;GWQHQvJzz`mgFVWWvD z_`eKoFaCp~(j~XZFdX#%OA> zq~l!xBl3Q345F&fjjKL++W_Nc|8XPXZ@FB*85Kf1k6~shhm3u?Z)BG^^8CdZLYW?O z25(wxKH1}M3YY5tY%HYt zjwjU_XRSPzyk8hq>>f(}%|B9#pnUHr?7@LX;APmh@K z6x5x=t!xS(E;%XQ$G(NT-K>{2IqaEOX)+l_NN*^ixx%48^&PoTtnJs{GPK z&?v$g&U>oP5Js=HnB!^uw`K;-J#J?4Ihu25D>DicGdoc7CuRmW4d)oqDvu-gr>325 zxM&*WJz>7Z(OW9s!GAP|T^UiKm_M1l+s0`*gTdBDI%BB*q*C?-+ldf0w0} zmN;uV;>G0MW!Yz8l(QSX_%V8Ne{1G&2nw%f^n9E3Cy|oEP(A-+^CmLSn%`Md&!@ls U(Y%wtxDR_4IA=1OF86lDxDH$p%nh_eB8tK-ozhhR& zw*3@iiKbigmRDAp+19Mg8Z&duF>T1ov2u(I%e?-73&_ElIcLs%&dfQVvp=6N&sxt~ z@47u}J!`$|#rtJ%@0YzR(r=k3IUKDV4#$h~EINBEB26q#>JGOUaaI;%3&9eL~ANv&eQ2 zAV(2M0xu$09AplpXwf;8avS}AGiyJaL46MDcQl9NN5}}!AIY;p8p2Mb?}Ho<-UUOD z@3)X*tSTWVAbmOVj)vR~xd4B`cRpy>i=SAVI6uP`doSLVvqMVYSVTDHx1&UL5Ky}8a;7VdSPMh!2- zIp|^w^&V25vO6uRcJYPLY8i9ghRi#`R5V~Qq|X)6DRwg=3E(^w+rUz=7V%{cUtYw3 zkdp{*1EK@*zLgPeTeUt;}Nan(~)`;I$jOU9E6?VX~aK4Je&EV zBjcr24qwm6_zq~NqZ3j-fSie3&qKZd`5O2GxE=8$z8R5&SqI;Hk?kXd3D!Yx0XG<~ z(X0+E$rt!-?3RqE-K^4luG!r7$FoFV;726I9Bv)^5bC)L&qMNQ9?@i@*b&3f(Or3-R@ci#mJ-VV#EL zLD>n)C~zBCgv7@oPlGWa7l;8%h7=F2ge(Pbf+^rDPzHkFVepdg_hIeXs4YL==u|4# zCh&wJ_8FtI`Bnr4|EMQy>5+aq+~-bGcw#O)#%Obq(VI5jWkqkv$=&?y|FRzu4&(3m z5z*~`#*c{nl^6=)M@0A+KO(~a<9$cX+-l zX^E>6hB6l=%$Jjt+pg<-*?hTSD0%&S*=GJTGFI_8cBQ4y9i6CGA?vc{*?ncvLzS1V z)6_>dJnt)OIap@PB^uma=^#vO`E-ZlH)uS5v}vZ%i(Eal7@p&0o1HaFm@08~0c$P! z+#MBKF`DI4nZgD)T7Pl#3aDOTLzQQ*QMXdhtqoHvo=M#ODy!}5uaKjp9S(}FkmF~MM2UZb7pO-$!T=8; z+!;-N3~@1+$3pglZYy}WDNh>oI}rZ?JPq9|kZ*uk=no+7g8Uui8t7gI?<1TET~BZ$ z;y;1U!4DYUEfsQjVJ;HxhvLu3cn9QJ$a=_8pa8rM_5-o|_k!F29smZOTLIY~vIrd! z9Y{ia9QX)%BcK;LN?ar-w-BLKNErZaSC9e5(AY(C+pclQd?%vQ!5@+34#=a>ZAW+u z*oSZ^m<&D9rbTjOtNT#jcBpco>H}E_*%B1e@kMfb@(!1=Y%j25Z32B{DG)0~W1FFb za%oxPOcA@>H9x`Y%O#uDq)Be&CHDoGskcaZ2S{DzC|rCibK1^-Q6}b*#xJ4QpN()vv>>9CDqiY&~1Y-IY?U zv$A`_mV}e-n8B7H$BWH#`O5yZkQEclmpqi3sD<*uOQcOkWx1QXJF%h6K7sit4pZXi zpT!br`3-EOZ<#lmN3WK?Q7c2E{?V~S80bGemPqp@pFi{o&wuAgA^aSU6xmwialyAC zES?2@zYFVPjDkfM!`L%v*JpA8xi9PS{E>~);~m0Oss99@|>U^PX>zQ1idjVfSK)NQ={p?`#g zoayp0E6_uh{8iE@*M$2cYj-~JoADi9PdK#jyRlvQW7-<;H$ANO*UkH42jy(hKc-|I>go+qhYdnq=sOkp(SaigVw zhZ@VfMJON2fel!(F-k;Dv{J^jwJ31&2AbJYc_NUkB>7!<)6b)+F7>K3L#JusYL4C! zo&9z54qH2L;nZ|i;#cofnC`DqvS?40QcUZrl$M606S8-1{s`4qDNTnuaWU1b3%^ws z1}0%kFI4n^u1ah)?Rrq^%RLj7U}R0X+<}F?^HSkWU1K_&i|%_kt8Du{)NP2;f{wp{ zQ$cCH8AaYlWiKnDIpgGhJkzV}WTKeLa~QUH$}x+iN1R!dRV?33yAqXrpSLiMpDUIv z7N}G(757Lz$+b|A=Gn!{Smx@tdI+`o98EgSt!8Wi{JldXp)ldS(bWzLiISKWj zz$x%G_y&9n#JS|pkY~VmpbmTw&VnC6Jvaw`1V4fE;Ae0Fh-W>%a0QclqTHXVJw_?R*VE%#fGS@4Kt?&8mh8Guovf$ALAK%*jCcbH)JQ#;)=JvUl zU`4M`jxqllc|_Q+qJPNwuJwcWUs>D!txE8%h>7!M z$eNxC(__B<#r(YNlCqEmY+3SkJJOc7-JpEl!k?rLRC+bfMP*6qVCvsVz1iPUeam34 zAn{ktGgzXlP>3IOt7mO^+&jvbGHp)M;wgTvGS79q*PwFg?!!Y0%Df}aMVH1?}2fwCG{UtYf?o)z(Q^pZ48P8L~5icnceMh>e|YaB}~yRW|A0waPBRq~aP$*z=d4KU%?l5Y>(4 z(9~#UHp`}S5L(qWe>=+<*wp7~)US`6&+j>-ysL6|4@{lwFCzm1cg)Y(8T@YJ()leiFtKs{tpg_Sa>Ye1ms%vvwP>14{axc*RSI%n zo12msNn$@phBl^oiaJ}oJ7fR9K^XTSQyUEG`}qXU1NCqe`W&Q-CF;}73SE3a5HH)l zYBSm1ioiDTrcfL)6QhC%>;k*NTVN0HxvW(CBLohD&x9h|N>&Wa8Y+Lvo`=PirFTVx zlA1S4D?qF?jAq8Ew;4=KuMW+VsXk6^xUXOpG_{R7SQk#^x+`)@jkOgvjQ@P2>XiQ0 zDRDTZh0K3Snb-L8IRBJVEH%AHexulOgCik0l0r6wrbel=akFtwh`}_qg*w|_kGuOO z=OW(k`t$zD>Kn{op?EvBZ#I<@5$@D1E~Z!KrZ}yxP~y}y#Jbaa6-vi$HzSw<`T`H= z2Qoo_kOgi51Hi3dAeh;(5j9=&m&cStCCYykau%2kygnb|u47B%0ms9u&ya}>2NWArG5 zGyg+z$>|`cs?PAMYNwbldagHD4si}zTUfAQ+#9{Q@be{j%^|Oh#71Ww5#j!M7>=qVibgNd*4{PJyq%H{e@v8vGfY0pEc-@I5#S zegO609QaYC!xxp#)UFoi+6%fJ&6C~gpOzjdIKrCGwLYJ1S>9k|G=Ax7V znntVBwLCHhYX_-rEOJi#jpnA{Em|i^-lry0U7e&+;cU&tk$J9sT^+@Pw1LeF<(ao@ zF823I;0Lm`vpUs{({^(EXSHf9RVJvoC>n~F2%1u&E$6{mnp>vWhqR19zM4b_GxZo= z`jB>t@!e;%j23}nRie}ls?G;It8UMwgj=;Zs#vX>RQiQ_fj>7?>&!TcuL+~XDAmPX zC)K(T+Pzm@!*d_jhT*95jGDqz>eU?iACGE{i&C9xZ>l?wSCaG7wGC{QWNJEPKA?8u z`)6uL2(UGp?j*S5%riRr`@jt5k(oKc;DnOT9Ho z`CqZvy(CS?o%YUoT9rw;qYSq@w`xRRx@&M(nEP@iSuk2ZH~eOt-h=#G`7h* z*%?E7BeiI8Nf}M92uq_}2}N9Jq4l7OXK``4;IbOmmX^;m`_R4HlvpZ#)zJ9xS-X+YBav{S?6Jcp6Vyr6#KFq zK{Z#^WL_7i)u@y?)fq>1%gi|5`;v2SI7yjSJnerDV|^?^+lTw$VR||h_R&mA{n?1& zBSZD&j27;aFwGxpxjL0b_cDB1>Cwsqtnev zbSfGN!FgsfAKFpNlPO`1K3t5Gi%(3@{mgk6wwMWyNwlknc2mQpDE-(L581C!{40oy~CDVZ$G=&fAs^v1u?4%V@wPk92Vv_DxY55{O zk?%{;%1ims3+(dx;M_0jgJzR|s-$diie z*|ao$ze;&;sipo6s*7e-sfpyhSNoEuWNOpVzhv`i{&a7B3X^*|9wjzd`?SHS@#JD@w(R!7?nxPM5eB=nM z6;aW?fCpv#vhJUAHCsxQm!#vpEK@(t0;Zu*MUI7QDVMQ_1#>*UIF`Xvh&DZ0+}HTwB*3jXMvN3Kdtsuer+0`Z!rCGn&<<0uC72P2s$ z2lYcT%}rF(D7i{Y<|E?`Oo%-iswwQK^yImF^vyCIiq&IzoZAquna6cFzrFfFnd)9L zV|dJd{S>3%1*3qf@3K1ad583JMzuq%9I9K4Yo>2sz}y;lM6Y7BV!qLX3STgyY28XR ze$p|0u}Y;gu^>*bG8glmr}a!mqZeyQ6wE|}2P7KX+fZqDD~IP~8JiiEe!?PX{`*=2 z?=jH$AdC*J*9K7G7R;rhI(-SFgDyLtYD>|pdHDt!aiGY+U}51C7QVvM3yec5cP%jL zoaBl!V5`jrY?WQ04{KP<9Ba9P(V_FsSRQ*;KZ#HG<4g?JPUEOd=4(cBvvr$)$XE@Z z{ECT}lncV*rDu%{8hnqEM71?ejh7xZDsBj9W&~~SYGl%tAFxD9F6osR^`M?i-iI+# zLu1T!j0R0NW5^Y47t)nuRxGcKGfNol-Y7=)iWu3#udPXZl42}ofq4A0P{h;bP&)sX zIe=G%8spH!WF0fDE9P^N+gu_CVhzdvnvRRWZ0x^75SPBHh$LZOlJbj+AN2OrB6DFE(xOsM^v9&FEpEU=P+plAH`ViiB ze~LAbyl&g3*-uGP{NPq2MJ7*(fn~AXz_M_MTP8Pm8$X6q-g2umxwgR{_StW~gBCw- zB~aEhv-sKwh4N~}EQIrWQ!nI&2h3_bbQWvrnU!)BFO4-ZAq$_yWa*S-9$}O|&Wxpv z0b?}YUva@zyUH2CmlT;rFyhB7m*-A2H^P3V)q}iVG=Jy`b6uNfgG}+SG$!#<$*N!h z&623%0L)W+1&%RigRzevHm%NTV3H{XT$U1uwxmEQhN-$5PIcC5E1G+znL&eUU3L=f ze^ZO)o+nJqppBbwOsVLL>+L=Z%)Qv2rW>ggTxTV28)mIxv}TP}jlNmvTkw4ihSV(> zGIfiJX%}T-+8wAgbxJkl;ZRx{FOIREi=@^ON;J*7jCfp{bux^4ybWu5lC7Xhr_aN2 zR7iF*)xKxM@`5SW3QXg-^)lgS+e}=vOz}q&`E36f8Y%V*CXJuMDT9DKo zPsJ{_u&yH_49sQx!;VIIkKrSMw~gfHlZIJXV}Li>zl@;6+QJe&exvUE{2e7~L|}>P}%(Ef@cMyme3xEXRp~%jZ7Bl*&*z!W$gon! zD7@y4#n-G9#~8;$bYZ?Vj5dw5dy!{^y@<+s;IP$Vfwk6JYBXL5sE(yH=Sk~+I@L#x zq5I11Hf&v^BE8(U;!DPsJ^bL5`^QcjTT+%X=ArWPNBZ^b->XNDe!aV<-qIsbY-@oP zwp0_euGk?h@LH0Ex<})C+IR~4oz>BZ#518{JFwFG+j6YDogQ>Tm@g`sL1v8IP6l#DO9?)iphv=#sU(ew)*N1y}1oms>E3IrdS z6|!9NpRpA2U!)HD{7b7Xz4D~hYL(~K5XNxv7bf?m;8A=ln0L&&B;jAP+DVbL`1X*~ z-1Cv;Wo$UjX{}^ZE_@TE>{lab#0jed9ZZx`=*&SYkG#jF?qWj>S>^HBSg{{l9_~#I z@gnF~u-}w~c;JpcveMO2I24x>J7A5Zwx_HywA-&_@L4qi6$@jhjqvz|?Qjq%^Vs-O z5ob#@_lO)%OJ9&<+$)^fVrF5!pc?ap|ySZ<@2+4gzHduQ8w znJz|OTr-hgX!WisMEfZ?%JMwxmBJ`&fz=Iz-fw}`mplvLlfu1rXR9=<(FqxjWsOVq z!Ss+`>^Tw6V-~SIyWM~2g=fmwyWO@X&6;dIL=}bhK|Xi1-9=){8~h|2+2AIvqF-DS zzGt`VVMo%%`PN;OIo584e}0MfUSG#dcaGrM++Mr%gA9+)De# z*^?SwV-dZP5z?QYnP+RP!8eU;?wiI;3&~}#H+i0%kQnmhhTQavVq#fHG