From 23d847a4ac087f7867a349b53f09fcfaff3c4e74 Mon Sep 17 00:00:00 2001 From: Regalis Date: Thu, 30 Jul 2015 23:28:15 +0300 Subject: [PATCH] Better UI scaling, quest tweaking, contentpackage hash bugfix, misc bugfixes --- Subsurface/Characters/Character.cs | 95 ++++++++++------- Subsurface/Characters/Ragdoll.cs | 9 +- Subsurface/Content/Items/Engine/engine.xml | 3 +- Subsurface/Content/Items/Pump/pump.png | Bin 882 -> 13480 bytes Subsurface/Content/Quests.xml | 13 ++- Subsurface/ContentPackage.cs | 34 ++++-- Subsurface/DebugConsole.cs | 4 +- Subsurface/Events/Quests/MonsterQuest.cs | 15 +-- Subsurface/Events/Quests/Quest.cs | 10 +- Subsurface/Events/Quests/SalvageQuest.cs | 15 +-- Subsurface/GUI/GUI.cs | 3 + Subsurface/GUI/GUIComponent.cs | 22 ++++ Subsurface/GUI/GUIListBox.cs | 8 +- Subsurface/GUI/GUITextBox.cs | 1 + Subsurface/GUI/TitleScreen.cs | 12 ++- Subsurface/Game1.cs | 3 +- .../Items/Components/Holdable/Holdable.cs | 2 +- Subsurface/Items/Components/Label.cs | 2 - Subsurface/Items/Components/Machines/Radar.cs | 11 +- .../Items/Components/Machines/Steering.cs | 1 - .../Items/Components/Signal/Connection.cs | 2 +- .../Components/Signal/ConnectionPanel.cs | 5 + Subsurface/Items/Components/Signal/Wire.cs | 5 +- Subsurface/Items/Inventory.cs | 15 ++- Subsurface/Items/Item.cs | 10 +- Subsurface/Map/Md5Hash.cs | 24 ++++- Subsurface/Screens/MainMenu.cs | 3 +- Subsurface/Screens/NetLobbyScreen.cs | 98 +++++++++++------- Subsurface_Solution.v12.suo | Bin 485888 -> 485888 bytes 29 files changed, 287 insertions(+), 138 deletions(-) diff --git a/Subsurface/Characters/Character.cs b/Subsurface/Characters/Character.cs index 9c810492a..c8c669313 100644 --- a/Subsurface/Characters/Character.cs +++ b/Subsurface/Characters/Character.cs @@ -38,7 +38,7 @@ namespace Subsurface public double LastNetworkUpdate; - public float LargeUpdateTimer; + public int LargeUpdateTimer; public readonly Dictionary Properties; public Dictionary ObjectProperties @@ -898,6 +898,19 @@ namespace Subsurface { if (isDead) return; + //if the game is run by a client, characters are only killed when the server says so + if (Game1.Client != null) + { + if (networkMessage) + { + new NetworkEvent(NetworkEventType.KillCharacter, ID, true); + } + else + { + return; + } + } + isDead = true; AnimController.movement = Vector2.Zero; AnimController.TargetMovement = Vector2.Zero; @@ -923,20 +936,6 @@ namespace Subsurface joint.MaxMotorTorque = 0.0f; } - - //if the game is run by a client, characters are only killed when the server says so - if (Game1.Client != null) - { - if (networkMessage) - { - new NetworkEvent(NetworkEventType.KillCharacter, ID, true); - } - else - { - return; - } - } - if (Game1.Server != null) { new NetworkEvent(NetworkEventType.KillCharacter, ID, false); @@ -999,6 +998,7 @@ namespace Subsurface } message.Write(AnimController.StunTimer); + message.Write((byte)health); LargeUpdateTimer = 5; } @@ -1021,18 +1021,23 @@ namespace Subsurface { if (type == NetworkEventType.PickItem) { - int itemId = message.ReadInt32(); + int itemId = -1; + + try + { + itemId = message.ReadInt32(); + } + catch + { + return; + } + Item item = FindEntityByID(itemId) as Item; if (item != null) { Debug.WriteLine("pickitem "+itemId ); item.Pick(this); } - else - { - } - - //DebugConsole.ThrowError("pickitem"); return; } @@ -1088,21 +1093,25 @@ namespace Subsurface { foreach (Limb limb in AnimController.limbs) { - Vector2 pos = Vector2.Zero; - pos.X = message.ReadFloat(); - pos.Y = message.ReadFloat(); + Vector2 pos = Vector2.Zero, vel = Vector2.Zero; + float rotation = 0.0f, angularVel = 0.0f; - Vector2 vel = Vector2.Zero; - vel.X = message.ReadFloat(); - vel.Y = message.ReadFloat(); + try + { + pos.X = message.ReadFloat(); + pos.Y = message.ReadFloat(); - float rotation = message.ReadFloat(); - float angularVel = message.ReadFloat(); + vel.X = message.ReadFloat(); + vel.Y = message.ReadFloat(); - //if (vel != Vector2.Zero && vel.Length() > 100.0f) { } + rotation = message.ReadFloat(); + angularVel = message.ReadFloat(); + } + catch + { + return; + } - //if (pos != Vector2.Zero && pos.Length() > 100.0f) { } - if (limb.body != null) { limb.body.TargetVelocity = vel; @@ -1113,15 +1122,31 @@ namespace Subsurface } - AnimController.StunTimer = message.ReadFloat(); + float newStunTimer = 0.0f, newHealth = 0.0f; + + try + { + newStunTimer = message.ReadFloat(); + newHealth = message.ReadByte(); + } + catch { return; } + + AnimController.StunTimer = newStunTimer; + Health = newHealth; LargeUpdateTimer = 1; } else { Vector2 pos = Vector2.Zero; - pos.X = message.ReadFloat(); - pos.Y = message.ReadFloat(); + try + { + pos.X = message.ReadFloat(); + pos.Y = message.ReadFloat(); + } + + catch { return; } + Limb torso = AnimController.GetLimb(LimbType.Torso); torso.body.TargetPosition = pos; diff --git a/Subsurface/Characters/Ragdoll.cs b/Subsurface/Characters/Ragdoll.cs index 6f764c0e7..5d1c09d1a 100644 --- a/Subsurface/Characters/Ragdoll.cs +++ b/Subsurface/Characters/Ragdoll.cs @@ -320,10 +320,11 @@ namespace Subsurface } avgVelocity = avgVelocity / limbs.Count(); - - + float impact = Vector2.Dot((f1.Body.LinearVelocity + avgVelocity) / 2.0f, -normal); + if (Game1.Server != null) impact = impact / 2.0f; + Limb l = (Limb)f1.Body.UserData; if (impact > 1.0f && l.HitSound != null && l.soundTimer <= 0.0f) l.HitSound.Play(Math.Min(impact / 5.0f, 1.0f), impact * 100.0f, l.body.FarseerBody); @@ -335,10 +336,8 @@ namespace Subsurface } } - public virtual void Draw(SpriteBatch spriteBatch) - { - + { foreach (Limb limb in limbs) { limb.Draw(spriteBatch); diff --git a/Subsurface/Content/Items/Engine/engine.xml b/Subsurface/Content/Items/Engine/engine.xml index 1cf0af13f..3ae2f1d81 100644 --- a/Subsurface/Content/Items/Engine/engine.xml +++ b/Subsurface/Content/Items/Engine/engine.xml @@ -31,7 +31,7 @@ - + @@ -40,6 +40,7 @@ + diff --git a/Subsurface/Content/Items/Pump/pump.png b/Subsurface/Content/Items/Pump/pump.png index 30a17346557683524c5dd4c46ad5255076a6c068..8fe06b478739b199df3eabcb2df54063a0f479a6 100644 GIT binary patch literal 13480 zcmV;ZG*`=sP)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRabE=fc|RCwC#eM^s}Ns`que|+~wW>wdtySl3S1rq!V!~y{lJH&cmxj{;NjyP{wQC^ixQF8pAZqGl;Bs*`v3lS|9Afy z|GrWRdhhZ7FZfx=Ib)0gA_6lb=L``6Gso*Q^9x_+dGA3)=wSoA!N-rj|0#$FfG%Xt z2}B9Z137095DP_#u+?e{IFM38vc;;kfKmdF5gW%B+!qZXq?{qb=zV}d*xL@G1R{W0 zz$_pFF8dCE009OMFf*71AONBp=>Puo=MPuFn|}DhQc9pib_xedDf+CTr=JM1*etB4 zkoC`P+W;aEfKrNm{XCeZR^(EUl5QL#0*?WKpw7|!7#Mx%sU|(;9tDU9qjx|A0$}uk z);a*#bpRxL554#J*?RK*I+)i2+oCh`LlSsTc>n+)XFa)N=!0d^KT9qU5wyL5i1fdd zVgY;;q@3Z0-tTd?2$3kE+a|~*Lzt0EK`j-+64!-p8rY`l`foHhlHdJADe{4b4e*8^ zqYqmI1_;PGf$f1OTWCGidJW_yF%%I%1f^uKC3meg4ez$7zL}~;kTsF>s{{ag@0M&@ zf|xW{@M}qgArNGHPw!d;ps(Y;yRHJ(?E86t_h{jNdiL%ay`OkkF5v$!%ZBo--xI{N zL=*q}db-!|U;oYD2QxoZ0dMm0H~+?8LrMv?7W}vW{=f0}{_fwgM2@g+o1I+2fBNJ9 zjDPZv{{c$LNGYR~jP0}m0Jd$zzx{Xr0srb>{xh7m%@$d3KA&*8?C`igc;H|En}3gg z@z4J$SoAcv-ZA>X7>qtT{^KA0G5*m%{QKy=0RUR-=)Gf%f&cPf{|El|-}>ti77S+m z&;Rv*9Iz;B_27p|OmSRKzG+eiR*V9adebGw*)6T(_6dh3BEjxkVj)^*JZ z!@_&YIVu9*agM#>2Qp+{Dq;LEc<{N5Uv8MSC6 z00H~HN20evx4wDCP$V!ViqbGyB=Lli?6i-;@tz0-5j>MDK5T&B_Zk4e5&BbrE&gzO zZ?nD^Mxr$o3kHwK(#gI*5goC8EA4vMs(>tt^wE)0MsFP~0_JhZ@_pg`YS1cS0HpcE zyHpB(eNeE4SCB83o;ETrEh7{`t=(%NvqK zp`5bcQF;a0Yx%~=OX>Kq0p2hP45DYb+mkIoDH#c~=6875PkL|N?(+%yz`!BD^Ghia z`g2b4b6f9VmdN~_C0xNH!Awg1eJ%;i!v?sI4`$XVkZ1T7$KZJ`q!T=T(gm6m^f6GY zRtvcl6oZr<+U=I{`w7*l&G=N&og)D589=HMMJn&1^WTXW7|+<_q%e9mWdF7#mFd1$VE30 zkD+AJA@f(D>0txh69A<5@CwN;Kns!9@kB^bpU;x5lpG6GPgRo&!Xc!yX##RiQTKyH z2`C~AOa8J^$%9Aa6Ji9CZ`gpPfrkxn9}ysXc*k6HS~7Ue-n;%?^whdYWQ;M%qNFu_ zA3bQ~loDEN5aR|MY+~WaGg>pCNfa2GxruHL2Y!H~5{VwzzV$GTB+$!Kl2GEFi4RTo%FIb`gw0R5R5G?Eic#Xtx_vOC8*bpa zfs#xKiIQ;-6D6#rf^rH-*rNs;Wc{w)|6eZ<#0K`HN$9wcQw5r{cIRQ7fkC#Ov3pp~ zB~Oi@T`{$4Vo0{p6dR}kCy&T2aL@*@fl#3}SVDfc4g0VG?x6}ucG6@KZ}?)Ak|QVZ zQ&@{Kd|Encg6L#WK)PK+erpZAcWkE(+qOZ(D+|O)E&=e&bIq;z#cYk7{m|8`i#-c8 zr;lCO;h@mk43dZ-(RCyiJvL(qIfR}LJf%b-Oi`HFu8yqqaOe*nHo%)jfO)6dsXH`@ zN|bv3k#jbQmJ�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 @@ -14,7 +16,9 @@ description="A particularly aggressive Moloch has been terrorizing vessels traveling between [location1] and [location2]. A reward of 1000 credits has been promised to those who kill the creature." commonness="10" reward="1000" - successmessage="You have successfully killed the Moloch." + radarlabel="Moloch" + failuremessage="fail" + successmessage="The Moloch has been killed." monsterfile="Content/Characters/Moloch/moloch.xml"> @@ -23,7 +27,9 @@ description="A particularly aggressive Tiger Thresher has been terrorizing vessels traveling between [location1] and [location2]. A reward of 800 credits has been promised to those who kill the creature." commonness="10" reward="800" - successmessage="You have successfully killed the Tiger Thresher." + radarlabel="Tiger Thresher" + failuremessage="fail" + successmessage="The Tiger Thresher has been killed." monsterfile="Content/Characters/TigerThresher/tigerthresher.xml"> @@ -32,6 +38,7 @@ description="Researchers of [location1] have picked up an infrasonic signal highly similar to those emitted by alien artifacts previously discovered on Europa. Investigate the signal and retrieve the potential artifact." commonness="5" reward="1000" + radarlabel="Infrasonic signal" failuremessage="It turns out the signal picked up by [location1] was emitted by a Moloch." successmessage="It turns out the signal was emitted by a Moloch. The researchers of [location1] have agreed to pay you the reward nevertheless for killing the Moloch." monsterfile="Content/Characters/Moloch/moloch.xml"> diff --git a/Subsurface/ContentPackage.cs b/Subsurface/ContentPackage.cs index 18054e039..1fddd191e 100644 --- a/Subsurface/ContentPackage.cs +++ b/Subsurface/ContentPackage.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Security.Cryptography; using System.Text; using System.Xml.Linq; @@ -120,17 +121,36 @@ namespace Subsurface { StringBuilder sb = new StringBuilder(); + List hashes = new List(); + + //foreach (ContentFile file in files) + //{ + // if (file.path.EndsWith(".xml", true, System.Globalization.CultureInfo.InvariantCulture)) + // { + // XDocument doc = ToolBox.TryLoadXml(file.path); + // sb.Append(doc.ToString()); + // } + //} + var md5 = MD5.Create(); foreach (ContentFile file in files) { - XDocument doc = ToolBox.TryLoadXml(file.path); - - sb.Append(doc.ToString()); + using (var stream = File.OpenRead(file.path)) + { + hashes.Add(md5.ComputeHash(stream)); + } } - string str = sb.ToString(); - byte[] bytes = new byte[str.Length * sizeof(char)]; - System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length); - md5Hash = new Md5Hash(bytes); + + + //string str = sb.ToString(); + byte[] bytes = new byte[hashes.Count()*16]; + for (int i = 0; i < hashes.Count; i++ ) + { + hashes[i].CopyTo(bytes, i*16); + } + //System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length); + + md5Hash = new Md5Hash(bytes); } public List GetFilesOfType(ContentType type) diff --git a/Subsurface/DebugConsole.cs b/Subsurface/DebugConsole.cs index 3a326162f..0844322dc 100644 --- a/Subsurface/DebugConsole.cs +++ b/Subsurface/DebugConsole.cs @@ -246,12 +246,12 @@ namespace Subsurface break; case "savemap": if (commands.Length < 2) break; - Submarine.SaveCurrent("Content/SavedMaps/" + commands[1]); + Submarine.SaveCurrent("Content/SavedMaps/" + string.Join(" ", commands.Skip(1))); NewMessage("map saved", Color.Green); break; case "loadmap": if (commands.Length < 2) break; - Submarine.Load("Content/SavedMaps/" + commands[1]); + Submarine.Load("Content/SavedMaps/" + string.Join(" ", commands.Skip(1))); break; case "savegame": SaveUtil.SaveGame(SaveUtil.SaveFolder+"save"); diff --git a/Subsurface/Events/Quests/MonsterQuest.cs b/Subsurface/Events/Quests/MonsterQuest.cs index 1a0b8ec85..37f049dc1 100644 --- a/Subsurface/Events/Quests/MonsterQuest.cs +++ b/Subsurface/Events/Quests/MonsterQuest.cs @@ -16,14 +16,6 @@ namespace Subsurface Character monster; - public override string RadarLabel - { - get - { - return monster.SpeciesName; - } - } - public override Vector2 RadarPosition { get @@ -35,7 +27,6 @@ namespace Subsurface public MonsterQuest(XElement element) : base(element) { - //monsterName = ToolBox.GetAttributeString(element, "monstername", ""); monsterFile = ToolBox.GetAttributeString(element, "monsterfile", ""); } @@ -48,7 +39,11 @@ namespace Subsurface public override void End() { - if (!monster.IsDead) return; + if (!monster.IsDead) + { + new GUIMessageBox("Quest failed", failureMessage); + return; + } GiveReward(); diff --git a/Subsurface/Events/Quests/Quest.cs b/Subsurface/Events/Quests/Quest.cs index f7789789d..2296522b8 100644 --- a/Subsurface/Events/Quests/Quest.cs +++ b/Subsurface/Events/Quests/Quest.cs @@ -20,8 +20,10 @@ namespace Subsurface protected bool completed; - private string successMessage; - private string failureMessage; + protected string successMessage; + protected string failureMessage; + + protected string radarLabel; private int reward; @@ -47,7 +49,7 @@ namespace Subsurface public virtual string RadarLabel { - get { return ""; } + get { return radarLabel; } } public virtual Vector2 RadarPosition @@ -65,6 +67,8 @@ namespace Subsurface successMessage = ToolBox.GetAttributeString(element, "successmessage", ""); failureMessage = ToolBox.GetAttributeString(element, "failuremessage", ""); + + radarLabel = ToolBox.GetAttributeString(element, "radarlabel", ""); } public static Quest LoadRandom(Location[] locations, Random rand) diff --git a/Subsurface/Events/Quests/SalvageQuest.cs b/Subsurface/Events/Quests/SalvageQuest.cs index ac8afc1ec..7b4456dd6 100644 --- a/Subsurface/Events/Quests/SalvageQuest.cs +++ b/Subsurface/Events/Quests/SalvageQuest.cs @@ -13,14 +13,6 @@ namespace Subsurface Item item; - public override string RadarLabel - { - get - { - return "Infrasonic signal"; - } - } - public override Vector2 RadarPosition { get @@ -52,8 +44,11 @@ namespace Subsurface public override void End() { - if (item.CurrentHull == null) return; - + if (item.CurrentHull == null) + { + new GUIMessageBox("Quest failed", failureMessage); + return; + } item.Remove(); GiveReward(); diff --git a/Subsurface/GUI/GUI.cs b/Subsurface/GUI/GUI.cs index 386c642d3..5adb10e2f 100644 --- a/Subsurface/GUI/GUI.cs +++ b/Subsurface/GUI/GUI.cs @@ -297,6 +297,9 @@ namespace Subsurface } DebugConsole.Draw(spriteBatch); + + + if (GUIComponent.MouseOn != null && !string.IsNullOrWhiteSpace(GUIComponent.MouseOn.ToolTip)) GUIComponent.MouseOn.DrawToolTip(spriteBatch); } public static void Update(float deltaTime) diff --git a/Subsurface/GUI/GUIComponent.cs b/Subsurface/GUI/GUIComponent.cs index c89948873..fec02c78a 100644 --- a/Subsurface/GUI/GUIComponent.cs +++ b/Subsurface/GUI/GUIComponent.cs @@ -42,6 +42,14 @@ namespace Subsurface set; } + public string ToolTip + { + get; + set; + } + + private GUITextBlock toolTipBlock; + //protected float alpha; public GUIComponent Parent @@ -222,6 +230,20 @@ namespace Subsurface //DrawChildren(spriteBatch); } + public void DrawToolTip(SpriteBatch spriteBatch) + { + int width = 200; + if (toolTipBlock==null || (string)toolTipBlock.userData != ToolTip) + { + string wrappedText = ToolBox.WrapText(ToolTip, width, GUI.SmallFont); + toolTipBlock = new GUITextBlock(new Rectangle(0,0,width, wrappedText.Split('\n').Length*15), ToolTip, GUI.style, null, true); + toolTipBlock.userData = ToolTip; + } + + toolTipBlock.rect = new Rectangle((int)PlayerInput.MousePosition.X, (int)PlayerInput.MousePosition.Y, toolTipBlock.rect.Width, toolTipBlock.rect.Height); + toolTipBlock.Draw(spriteBatch); + } + public virtual void Update(float deltaTime) { if (CanBeFocused) diff --git a/Subsurface/GUI/GUIListBox.cs b/Subsurface/GUI/GUIListBox.cs index ffaf15f1e..39af7f1a2 100644 --- a/Subsurface/GUI/GUIListBox.cs +++ b/Subsurface/GUI/GUIListBox.cs @@ -111,9 +111,10 @@ namespace Subsurface if (parent != null) parent.AddChild(this); + scrollBarHidden = true; scrollBar = new GUIScrollBar( - new Rectangle(this.rect.X + this.rect.Width, this.rect.Y, 20, this.rect.Height), color, 1.0f, style); + new Rectangle(this.rect.X + this.rect.Width-20, this.rect.Y, 20, this.rect.Height), color, 1.0f, style); frame = new GUIFrame(Rectangle.Empty, style, this); if (style != null) style.Apply(frame, this); @@ -214,14 +215,15 @@ namespace Subsurface private void ShowScrollBar() { + if (scrollBarHidden) Rect = new Rectangle(rect.X, rect.Y, rect.Width - scrollBar.Rect.Width, rect.Height); scrollBarHidden = false; - Rect = new Rectangle(rect.X, rect.Y, rect.Width - scrollBar.Rect.Width, rect.Height); + } private void HideScrollBar() { + if (!scrollBarHidden) Rect = new Rectangle(rect.X, rect.Y, rect.Width + scrollBar.Rect.Width, rect.Height); scrollBarHidden = true; - Rect = new Rectangle(rect.X, rect.Y, rect.Width + scrollBar.Rect.Width, rect.Height); } public override void Draw(SpriteBatch spriteBatch) diff --git a/Subsurface/GUI/GUITextBox.cs b/Subsurface/GUI/GUITextBox.cs index 514a68165..bb5516663 100644 --- a/Subsurface/GUI/GUITextBox.cs +++ b/Subsurface/GUI/GUITextBox.cs @@ -193,6 +193,7 @@ namespace Subsurface new Vector2((int)caretPos.X + 2, caretPos.Y + Font.MeasureString("I").Y - 3), textBlock.TextColor * (textBlock.TextColor.A / 255.0f)); } + } public void ReceiveTextInput(char inputChar) diff --git a/Subsurface/GUI/TitleScreen.cs b/Subsurface/GUI/TitleScreen.cs index 277030099..7379d5fb3 100644 --- a/Subsurface/GUI/TitleScreen.cs +++ b/Subsurface/GUI/TitleScreen.cs @@ -81,7 +81,17 @@ namespace Subsurface titlePos, null, Color.White * Math.Min((state - 3.0f) / 5.0f, 1.0f), 0.0f, new Vector2(titleTexture.Width / 2.0f, titleTexture.Height / 2.0f), scale, SpriteEffects.None, 0.0f); - string loadText = (loadState<100.0f) ? "Loading... "+(int)loadState+" %" : "Press any key to continue"; + string loadText = ""; + if (loadState == 100.0f) + { + loadText = "Press any key to continue"; + + } + else if (loadState > 0.0f) + { + loadText = "Loading... " + (int)loadState + " %"; + } + spriteBatch.DrawString(GUI.Font, loadText, new Vector2(Game1.GraphicsWidth/2.0f - 50.0f, Game1.GraphicsHeight*0.8f), Color.White); spriteBatch.End(); diff --git a/Subsurface/Game1.cs b/Subsurface/Game1.cs index 3ffe5a805..be882f75e 100644 --- a/Subsurface/Game1.cs +++ b/Subsurface/Game1.cs @@ -196,6 +196,8 @@ namespace Subsurface loadState = 70.0f; yield return Status.Running; + GameMode.Init(); + Submarine.Preload("Content/SavedMaps"); loadState = 80.0f; yield return Status.Running; @@ -214,7 +216,6 @@ namespace Subsurface ParticleManager = new ParticleManager("Content/Particles/prefabs.xml", Cam); yield return Status.Running; - GameMode.Init(); GUIComponent.Init(Window); DebugConsole.Init(Window); yield return Status.Running; diff --git a/Subsurface/Items/Components/Holdable/Holdable.cs b/Subsurface/Items/Components/Holdable/Holdable.cs index dd5048d39..a06616106 100644 --- a/Subsurface/Items/Components/Holdable/Holdable.cs +++ b/Subsurface/Items/Components/Holdable/Holdable.cs @@ -204,7 +204,7 @@ namespace Subsurface.Items.Components AnimController ac = picker.AnimController; - item.sprite.Depth = picker.AnimController.GetLimb(LimbType.RightHand).sprite.Depth + 0.01f; + //item.sprite.Depth = picker.AnimController.GetLimb(LimbType.RightHand).sprite.Depth + 0.01f; ac.HoldItem(deltaTime, cam, item, handlePos, holdPos, aimPos, holdAngle); } diff --git a/Subsurface/Items/Components/Label.cs b/Subsurface/Items/Components/Label.cs index 9d57c5f4d..411fbdeee 100644 --- a/Subsurface/Items/Components/Label.cs +++ b/Subsurface/Items/Components/Label.cs @@ -24,8 +24,6 @@ namespace Subsurface.Items.Components } } - - public Label(Item item, XElement element) : base(item, element) { diff --git a/Subsurface/Items/Components/Machines/Radar.cs b/Subsurface/Items/Components/Machines/Radar.cs index 8333ea1f2..89a995781 100644 --- a/Subsurface/Items/Components/Machines/Radar.cs +++ b/Subsurface/Items/Components/Machines/Radar.cs @@ -59,9 +59,7 @@ namespace Subsurface.Items.Components else { pingState = 0.0f; - } - - + } } public override bool Use(float deltaTime, Character character = null) @@ -84,7 +82,7 @@ namespace Subsurface.Items.Components int radius = GuiFrame.Rect.Height / 2 - 10; DrawRadar(spriteBatch, new Rectangle((int)GuiFrame.Center.X - radius, (int)GuiFrame.Center.Y - radius, radius * 2, radius * 2)); - voltage = 0.0f; + //voltage = 0.0f; } private void DrawRadar(SpriteBatch spriteBatch, Rectangle rect) @@ -198,8 +196,6 @@ namespace Subsurface.Items.Components quest.RadarLabel, quest.RadarPosition, displayScale, center, (rect.Width * 0.55f)); } - - } } @@ -218,8 +214,7 @@ namespace Subsurface.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 / 80.0f) + " m", new Vector2(markerPos.X + 10, markerPos.Y + 15), Color.LightGreen); } } diff --git a/Subsurface/Items/Components/Machines/Steering.cs b/Subsurface/Items/Components/Machines/Steering.cs index 7a2c6cb70..f61e7c734 100644 --- a/Subsurface/Items/Components/Machines/Steering.cs +++ b/Subsurface/Items/Components/Machines/Steering.cs @@ -47,7 +47,6 @@ namespace Subsurface.Items.Components { if (float.IsNaN(value.X) || float.IsNaN(value.Y)) { - targetVelocity = Vector2.Zero; return; } targetVelocity.X = MathHelper.Clamp(value.X, -100.0f, 100.0f); diff --git a/Subsurface/Items/Components/Signal/Connection.cs b/Subsurface/Items/Components/Signal/Connection.cs index 43589f7d0..234f86d50 100644 --- a/Subsurface/Items/Components/Signal/Connection.cs +++ b/Subsurface/Items/Components/Signal/Connection.cs @@ -459,7 +459,7 @@ namespace Subsurface.Items.Components if (Wires[i]!=null) { Wires[i].Item.body.Enabled = false; - Wires[i].Connect(this, false); + Wires[i].Connect(this, false, true); } } diff --git a/Subsurface/Items/Components/Signal/ConnectionPanel.cs b/Subsurface/Items/Components/Signal/ConnectionPanel.cs index 50cbd499f..18b743e89 100644 --- a/Subsurface/Items/Components/Signal/ConnectionPanel.cs +++ b/Subsurface/Items/Components/Signal/ConnectionPanel.cs @@ -91,6 +91,11 @@ namespace Subsurface.Items.Components } } + public override void Remove() + { + base.Remove(); + } + public override void FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetOutgoingMessage message) { foreach (Connection c in connections) diff --git a/Subsurface/Items/Components/Signal/Wire.cs b/Subsurface/Items/Components/Signal/Wire.cs index aaa2245ef..65b8344b4 100644 --- a/Subsurface/Items/Components/Signal/Wire.cs +++ b/Subsurface/Items/Components/Signal/Wire.cs @@ -61,7 +61,7 @@ namespace Subsurface.Items.Components if (connection == connections[1]) connections[1] = null; } - public void Connect(Connection newConnection, bool addNode = true) + public void Connect(Connection newConnection, bool addNode = true, bool loading = false) { for (int i = 0; i < 2; i++) { @@ -85,7 +85,6 @@ namespace Subsurface.Items.Components Nodes.Add(newConnection.Item.Position); } - break; } @@ -110,7 +109,7 @@ namespace Subsurface.Items.Components CleanNodes(); } - Item.NewComponentEvent(this, true); + if (!loading) Item.NewComponentEvent(this, true); } public override void Equip(Character character) diff --git a/Subsurface/Items/Inventory.cs b/Subsurface/Items/Inventory.cs index f0516245c..75db0a607 100644 --- a/Subsurface/Items/Inventory.cs +++ b/Subsurface/Items/Inventory.cs @@ -287,10 +287,19 @@ namespace Subsurface public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message) { - int itemId = message.ReadInt32(); - if (itemId == -1) return; + int itemId=-1, slotIndex = -1; - int slotIndex = message.ReadInt32(); + try + { + itemId = message.ReadInt32(); + slotIndex = message.ReadInt32(); + } + catch + { + return; + } + + if (itemId == -1) return; Item item = FindEntityByID(itemId) as Item; if (item == null) return; diff --git a/Subsurface/Items/Item.cs b/Subsurface/Items/Item.cs index 04937ab11..6474c6bb4 100644 --- a/Subsurface/Items/Item.cs +++ b/Subsurface/Items/Item.cs @@ -1184,7 +1184,7 @@ namespace Subsurface public override void Remove() { base.Remove(); - + //sprite.Remove(); if (body != null) body.Remove(); @@ -1194,6 +1194,14 @@ namespace Subsurface } itemList.Remove(this); + + foreach (Item it in itemList) + { + if (it.linkedTo.Contains(this)) + { + it.linkedTo.Remove(this); + } + } } } diff --git a/Subsurface/Map/Md5Hash.cs b/Subsurface/Map/Md5Hash.cs index 93e03c935..d13aa078c 100644 --- a/Subsurface/Map/Md5Hash.cs +++ b/Subsurface/Map/Md5Hash.cs @@ -1,4 +1,5 @@ -using System.Security.Cryptography; +using System.IO; +using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Xml.Linq; @@ -40,6 +41,13 @@ namespace Subsurface shortHash = GetShortHash(hash); } + public Md5Hash(FileStream fileStream) + { + hash = CalculateHash(fileStream); + + shortHash = GetShortHash(hash); + } + public Md5Hash(XDocument doc) { string docString = Regex.Replace(doc.ToString(), @"\s+", ""); @@ -51,6 +59,20 @@ namespace Subsurface shortHash = GetShortHash(hash); } + private string CalculateHash(FileStream stream) + { + MD5 md5 = MD5.Create(); + byte[] byteHash = md5.ComputeHash(stream); + // step 2, convert byte array to hex string + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < byteHash.Length; i++) + { + sb.Append(byteHash[i].ToString("X2")); + } + + return sb.ToString(); + } + private string CalculateHash(byte[] bytes) { MD5 md5 = MD5.Create(); diff --git a/Subsurface/Screens/MainMenu.cs b/Subsurface/Screens/MainMenu.cs index b83d0ff7c..0bd277acc 100644 --- a/Subsurface/Screens/MainMenu.cs +++ b/Subsurface/Screens/MainMenu.cs @@ -162,12 +162,13 @@ namespace Subsurface new GUITextBlock(new Rectangle(0, 100, 0, 30), "Server port:", GUI.style, Alignment.CenterX, Alignment.CenterX, menuTabs[(int)Tabs.HostServer]); portBox = new GUITextBox(new Rectangle(0, 130, 200, 30), Color.White, Color.Black, Alignment.CenterX, Alignment.CenterX, null, menuTabs[(int)Tabs.HostServer]); portBox.Text = NetworkMember.DefaultPort.ToString(); + portBox.ToolTip = "Server port"; GUIButton hostButton = new GUIButton(new Rectangle(0, 0, 200, 30), "Start", Alignment.BottomCenter, GUI.style, menuTabs[(int)Tabs.HostServer]); hostButton.OnClicked = HostServerClicked; //---------------------------------------------------------------------- - for (int i = 1; i < 4; i++ ) + for (int i = 1; i < 5; i++ ) { button = new GUIButton(new Rectangle(-20, -20, 100, 30), "Back", Alignment.TopLeft, GUI.style, menuTabs[i]); button.OnClicked = PreviousTab; diff --git a/Subsurface/Screens/NetLobbyScreen.cs b/Subsurface/Screens/NetLobbyScreen.cs index 1d0c86ead..d757a2466 100644 --- a/Subsurface/Screens/NetLobbyScreen.cs +++ b/Subsurface/Screens/NetLobbyScreen.cs @@ -34,6 +34,8 @@ namespace Subsurface public bool IsServer; public string ServerName, ServerMessage; + private GUITextBox serverMessage; + public Submarine SelectedMap { get { return subList.SelectedData as Submarine; } @@ -101,10 +103,12 @@ namespace Subsurface public NetLobbyScreen() { - Rectangle panelRect = new Rectangle( - 40, 40, Game1.GraphicsWidth - 80, Game1.GraphicsHeight - 80); + int width = Math.Min(Game1.GraphicsWidth - 80, 1500); + int height = Math.Min(Game1.GraphicsHeight - 80, 800); - menu = new GUIFrame(panelRect, Color.Transparent); + Rectangle panelRect = new Rectangle(0,0,width,height); + + menu = new GUIFrame(panelRect, Color.Transparent, Alignment.Center); //menu.Padding = GUI.style.smallPadding; //server info panel ------------------------------------------------------------ @@ -139,28 +143,15 @@ namespace Subsurface GUI.style, menu); playerList = new GUIListBox(new Rectangle(0,0,0,0), null, GUI.style, playerListFrame); - } - public override void Deselect() - { - textBox.Deselect(); - } + //submarine list ------------------------------------------------------------------ - public override void Select() - { - Game1.LightManager.LosEnabled = false; + int columnWidth = infoFrame.Rect.Width / 3 - 30; + int columnX = 0; - infoFrame.ClearChildren(); - - textBox.Select(); - - Character.Controlled = null; - Game1.GameScreen.Cam.TargetPos = Vector2.Zero; - - new GUITextBlock(new Rectangle(0, 110, 0, 30), "Selected submarine:", GUI.style, infoFrame); - subList = new GUIListBox(new Rectangle(0, 140, 200, 200), Color.White, GUI.style, infoFrame); + new GUITextBlock(new Rectangle(columnX, 120, columnWidth, 30), "Selected submarine:", GUI.style, infoFrame); + subList = new GUIListBox(new Rectangle(columnX, 150, columnWidth, 200), Color.White, GUI.style, infoFrame); subList.OnSelected = SelectMap; - subList.Enabled = (Game1.Server != null); if (Submarine.SavedSubmarines.Count > 0) { @@ -181,10 +172,13 @@ namespace Subsurface return; } - new GUITextBlock(new Rectangle(220, 110, 0, 30), "Selected game mode: ", GUI.style, infoFrame); - modeList = new GUIListBox(new Rectangle(220, 140, 200, 200), GUI.style, infoFrame); - modeList.Enabled = (Game1.Server != null); + columnX += columnWidth + 20; + //gamemode ------------------------------------------------------------------ + + new GUITextBlock(new Rectangle(columnX, 120, 0, 30), "Selected game mode: ", GUI.style, infoFrame); + modeList = new GUIListBox(new Rectangle(columnX, 150, columnWidth, 200), GUI.style, infoFrame); + foreach (GameModePreset mode in GameModePreset.list) { if (mode.IsSinglePlayer) continue; @@ -198,40 +192,72 @@ namespace Subsurface textBlock.UserData = mode; } - GUITextBlock durationText = new GUITextBlock(new Rectangle((int)(modeList.Rect.Right + 20 - 80), 110, 100, 20), + columnX += columnWidth + 20; + + //duration ------------------------------------------------------------------ + + GUITextBlock durationText = new GUITextBlock(new Rectangle(columnX, 120, columnWidth, 20), "Game duration: ", GUI.style, Alignment.Left, Alignment.TopLeft, infoFrame); durationText.TextGetter = DurationText; - durationBar = new GUIScrollBar(new Rectangle((int)(modeList.Rect.Right + 20 - 80), 140, 180, 20), + durationBar = new GUIScrollBar(new Rectangle(columnX, 150, columnWidth, 20), GUI.style, 0.1f, infoFrame); durationBar.BarSize = 0.1f; - durationBar.Enabled = (Game1.Server != null); - new GUITextBlock(new Rectangle((int)(modeList.Rect.Right + 20 - 80), 180, 100, 20), + //seed ------------------------------------------------------------------ + + new GUITextBlock(new Rectangle(columnX, 190, columnWidth, 20), "Level Seed: ", GUI.style, Alignment.Left, Alignment.TopLeft, infoFrame); - seedBox = new GUITextBox(new Rectangle((int)(modeList.Rect.Right + 20 - 80), 210, 180, 20), + seedBox = new GUITextBox(new Rectangle(columnX, 220, columnWidth, 20), Alignment.TopLeft, GUI.style, infoFrame); - seedBox.OnEnter = SelectSeed; - seedBox.Enabled = (Game1.Server != null); + seedBox.OnTextChanged = SelectSeed; LevelSeed = ToolBox.RandomSeed(8); + //server info ------------------------------------------------------------------ + var serverName = new GUITextBox(new Rectangle(0, 0, 200, 20), null, null, Alignment.TopLeft, Alignment.TopLeft, GUI.style, infoFrame); serverName.TextGetter = GetServerName; serverName.Enabled = Game1.Server != null; serverName.OnTextChanged = ChangeServerName; - ServerName = (Game1.Server==null) ? "Server" : Game1.Server.Name; - var serverMessage = new GUITextBox(new Rectangle(0, 30, 360, 70), null, null, Alignment.TopLeft, Alignment.TopLeft, GUI.style, infoFrame); - serverMessage.Enabled = Game1.Server != null; + + serverMessage = new GUITextBox(new Rectangle(0, 30, 360, 70), null, null, Alignment.TopLeft, Alignment.TopLeft, GUI.style, infoFrame); serverMessage.Wrap = true; serverMessage.TextGetter = GetServerMessage; serverMessage.OnTextChanged = UpdateServerMessage; + } + + public override void Deselect() + { + textBox.Deselect(); + } + + public override void Select() + { + Game1.LightManager.LosEnabled = false; + + //infoFrame.ClearChildren(); + + textBox.Select(); + + Character.Controlled = null; + Game1.GameScreen.Cam.TargetPos = Vector2.Zero; + + subList.Enabled = Game1.Server != null; + modeList.Enabled = Game1.Server != null; + durationBar.Enabled = Game1.Server != null; + seedBox.Enabled = Game1.Server != null; + serverMessage.Enabled = Game1.Server != null; + ServerName = (Game1.Server==null) ? "Server" : Game1.Server.Name; + + infoFrame.RemoveChild(infoFrame.children.Find(c => c.UserData as string == "startButton")); if (IsServer && Game1.Server != null) { GUIButton startButton = new GUIButton(new Rectangle(0, 0, 200, 30), "Start", Alignment.TopRight, GUI.style, infoFrame); startButton.OnClicked = Game1.Server.StartGame; + startButton.UserData = "startButton"; //mapList.OnSelected = new GUIListBox.OnSelectedHandler(Game1.server.UpdateNetLobby); modeList.OnSelected = Game1.Server.UpdateNetLobby; @@ -244,6 +270,8 @@ namespace Subsurface { int x = playerFrame.Rect.Width / 2; + playerFrame.ClearChildren(); + new GUITextBlock(new Rectangle(x, 0, 200, 30), "Name: ", GUI.style, playerFrame); GUITextBox playerName = new GUITextBox(new Rectangle(x, 30, 0, 20), @@ -462,7 +490,7 @@ namespace Subsurface } //textBox.Text = LevelSeed; - textBox.Selected = false; + //textBox.Selected = false; if (Game1.Server != null) Game1.Server.UpdateNetLobby(null); diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index ae2eb7bcb721cbfb11e979365e0613dbf5f7df70..d1ca1d9c2538e8b05b1a3e53f0fb7306c90d055f 100644 GIT binary patch delta 5609 zcmdUzd0bRSw#WNa-)@@KmQ6*3rfI<_3b>A_fKhP`w2IOA6a*LIhN6ual3=T&CdjyO z31yU#MbbfniP$rJBcdbfM2tp=nn)(Z7_vN(8tw^>}Ev+uMQTH59Ex@fl%QuYTxD05f3O1>{zlCJ$#g#k2GY!|{+O5E39j8u8`Z$(valmL}H<;Z>%dii3TshWCqFLDtH47fqgsV1E7YU1u45< z3;8vu1Nm&3$Go0{|EJKnQog3U^W*4aR7qY?9uMnew0 zLo_7&T(*-YE_6~T7J)SIB3KOMFf4^!29|?#umY?E8DJGy4NM>t$n78Q%m`g~4@1lZ zQCNW2Ag_ZN(5C<+hy{V*S+D|ie+6OCDFzzeJe zz91IW&q1c4ud$H(AzNUpfb@kN4cj5e9+1C45@a$s8;*ho%6~%2YvK*v1YHM-qJ1&s zd@v9;xhz)woM=m8JO0J9UwQ@}kK4bvo9mqD& zg~W$$eN#6;?GE$zkS~L?;37B;x`R@%7g)e7@D4Z!7J)ax0Wbx;1tx>P0ULN7G=M=0 zG1qi=&smRIW^i}B{)6k~ZD#~3GJl8<97*ZsB_$NW<<#^Zs;sD|@^IJK`e-gv=X)Kv&p z!*|VeXr7))`pvAAoJo$3eAx23G0aDt=j)~V5sUP`_1^qRA>v6EDVlN<#FO5U>K}2m z)VquK2lf%m&IdUwf*4M9EX0!=)eG^#M zQ0~=gDzBn_x+0CJ+ucVv;5fc$+HDk1u?VqkccZ2XHSa!E+qNf6)Wr*up$`>PhhyX5 zZ>B=b-rskhp@MOPiHxGj6HdeVHqQiS`Uqai3I4=W(d3oK^REe0xbdD!!;>xKVoj2Jdqi#rqnzV z&82#={Jg&u9Y7~gnrpBc?jmZ-9d8s(_wovF6C$doFG!-XWGBAruxc$g?@@(Gvwxb_%0G@GUmkW*eaZ4Xd03_q9(?6X zG*X(eh|ao8I)8Q*y$8UNMXZE0^5R~Q)9dlRbUlgi$mh9itUip59i>-#NO5baMpahB zc>WmGP~Nyo=q|;Fu`Q%6c>YSpsrb)g23tQ{W&7}BJ0HD>eALsiRZvf8385lSisz zxBhwQ$LhS$5l272e~y>VB5!F~1Qn32gmf-QPeC+P8U*?A_hfQbQ>BqKAHvk+XjXY+ zZ|||*yXVAg?~+~+^*5%8reBcz2hpt7v8lD~moSoaf1;~O(VSr5<;zK@`3@~w9b0kJ zA?nz{yzLM*I4izH<-a>NaMNN$`L$ZUc-M=n5z>en`YRR2lg_F;gw0AOb)Xb@jJ|Rz z>_d7{Ult-9lG{FBr#DQjLEd*9M_!(2euxFFr{*4odeVs{qcL}zPV*ijTJ0EB$uyhg zk>wjKO9*3+4xo`pL!KI-^ppG^kXjH+8n9c>2X>r#qNyQ|2T96MDU`9#h^Fv56^rHv ziv$fXc}-Aj|9I((mhuBJQNvBSE-h}8>N=KRS{1>z5%*00@uU=YvPPySNF z6c+jDV2J0fXH{Wh>y_S8$xt>=8JD6+S1eF0bLja^`}N`3YyVbR5u38!HDbvK*&BIR z%a^Rb2jnTqZS}OZ_LXi%O(1 zj%`abS>h4%C^m|;>K3m}52K^*o8mH7oNDoT(2+bmVm1l?6_$5gUgAmS(!fwN)ZL(m7^CDMh6@``XePc zD*|9ELqML`U9aJYd9;w+euM(FKOA}Y+FPch?OoF{r=6>tbBhNBvu@JZTB_|hnYq4_ zN;@Bn@(b~kj(A%oB?`BmGMU~%;^jCT@@e(#SQn>Ov3l-Tdq%8@uqC%NwTl@!K78V3 zCgEhp6Fe!1#4(y)bhw(8b?ld=0qR;UDj7}^t(%e>6ox>4ts&Ly|(9kf9@M&+@!|d{nVkaes-Z$wTzL)!kAcU_LY2hu^VKmWFEHnX&q^IwV#%{cubC~ zO5a5rUDn%VAA9hM!!*lMgW&Fl8yzn$&wfg&{Mc${&~Ds)|CKcHha*crpBY(VZ>w{7 z!t%Q7s$ePj1iPZNjxJbEdVB0}{Evd;@XW~0Pt{MZB@FX??!nUSGbg-#R#Ll-<5ORt zVBT7-bmzy{u~5_*akDHsD#}JjMQY0i2nyN-TG7TRhjMAz{=v67orPCtP zlAKPq5|T#dBBO>x@1auT(W+uRO6N}}C5*PF=HH^x5wFZ|C&Ja5PR-{t=kxhyt+V#y z?7jBdd#@Y&i4gmVkmVWe^*WvIWiX9&y6NCWkPfDhn7*I=w%F~Y-lA!~8Dr}X{q?|6 zdJJ`wPN}nbHjS^o${ncPBdC3=@!m5WHM)b()L$t*LjDX*L5)nv6+qUTiT4QTgVa}) z4$4VrYKamYXoQjsR)KVI1#Hl%hm}WYw0cYFqVI}!v1+{Duk#5MMS&S$2&~zVkAq2I zI~Wa)ft8?Mov!z5lLajX^acTFF-xZw>pLdJKphCi!fXd)KpprUcntPAkaBWQLAJyD zpCD_%-@tBA#FKqZdEehUb;mWkPDt1Aw}$E;*prHkK_1IcOZG5a4L9};(W4JncLd@6 zq1_QM8m-!+-{~L{SU{uNTHoP+;i6Q0>_53kuIj&Ykt2b5^phCj1TYG`4t|YJ!ywm! zTi^|_32X$Xz+mti@C35+Ymf^;DHsYYXg>_{32;yy-7C8DPH671hJZM*4ezq$9>}?1 zHuwazM_IJGrI#O1a#Q#93T^KOLqAZ2!cfTXAr(-lQ*Za`IPMFmePI3vWGbiy$HB)S z2t0|hHIQ*24f-D-4}l@zZSXFLg#GuB7s2Pi36_8(z>n1Y-rbXKK>Yx$2RFexU=o_; zfIR3+K}YCI-Jn1og?JUZC-g_5I}>;t(e1+Ne&SFfcl)m$9*n+j{}PAydyvCr%Lh6f zqs#{XMDHJh>)>bHZ$R+_+%K2&=iD#L|2y|5KFIyQ!GM2}`_)&1BUMX-MWl}9IMr4; z*n{Ly4r3N#cM1onb^d;8edS5nsgGJ#sc6<54kOvQu#M${svHZeb@s+`ebHRAYF+^+)le;!Z#6jP5ev&KeQ0%P&AC=Zb1kanT9k76zQNh9 z4ffD|1JgfT&DHhSV(C3IN8Ir>ae-JEW#}W~ex;bJvybixs5WQUk?7Y`pH!W6VVBqZ z28_ucUGxHrq5mDoW$ujk43GrEKo218AE8_YmEcj>IzT>$>E%Oy3A|xz1qOj<@GjfL zLzj`30d{}^c%KL9OS<{GOHd+U_$%bIkW;}E;40p`Lr#Ny1$+f$XWo$KfZWI9P(BlS z2gpYt4}fPuI}i-p7RYZvYv?7A(V#!{v7jgL#rJi27=2q5_<>zOeq<;LyMbXK0SMTi zf}AMpLXH6P#>|840(`*JAQMag8&IziZPr5uLMFpjb*JwiAd~Lsja|@*5ru6)IFKK= zq0kIn&hU9i0$pKy0aD%QGhEoKWJG^sHp(ugL+?hQuvJmhw$bXVC>GIbrWjJBOI@mj zQ-Q;mxHyxo)z+J}tyOy=l&@;ZX`&QvJ{ZdGZ_kZ znH_1VUX&*)kBg&Wim6q&z2Cm$-R6$^Zo~NN_F+0PWGx41lh@E&~2E9g(@!0Kh zNrg3+%}Nbs&~hXSTP_b4Dc7m1xSGpHL~1U_d97uc8a6#zV5^$0$J}_hm}ZGAGbMpS9){teWE$)q2}(WGs`{{Yy0z2d}8wu76zgvbgzb1M=v7 zy(5jdyowzQ$=?yoOwXywhlY#X)8wx`zk)P3&76f}#zPl^;h2F-fQ?{WFQKrNW0ZI8 z`U^P8*NTQN^r3R%xL=l7Fo6=prB(W1(Jr2%eTsZ<^xF_v5wbdZ)(szZ!JqxbqI7O0 za^q>avy9B1!aR!CHeDh0qjsEQ^xY%k>}gnhrfh4)i!yF$B9wa=mPWU6VE zw+uPo;>G93{xIZk4cVwX-*KM&1+AgB!oF7V7oCcEvgzvO$YoW|n#isGZw*LnedSfz zskWn-`&02GK4LPho3(4Uc|}Uw)7$g+3@v|6jxR*JIf)f=-jtDF7KXqn3~Ro<_esBO zhEHTBc+X$9kEuX}Yi`k6H1jEh++|i!dVZ&(<%0|aE$QV}C zT}!%)qcfBsE!|Fw$n?pVH8DXeADMd+(=Ty#a`qoa)h_uB*k{k~3;3*u2=B%VO}YPfJMLse=N|9Aarwo_NBuq((>GACcBC7} z6O9weD|w*yR64&$&Q$&@3E9Qx7ML-h@|{W4K6%W=92xlSMbh_}NpsHV zG#lTAhqt(TS+kwPnc_HU;407Mq@MJODYU0KAK~3t=udd8W*Nt)-HHz5<1bMe8D&QD zsq5(Udl95_w1$c7jwru|RV^X2@ghEP#q~47Rzex-ha4yBOX!61|E^{FcpRit)P`<2 zgC=t=xnItIsc2iLU^)IEEo=p!C7L02kL120>2;oNy0B^S_d#A?UY-2P;^8ZM9s5Ar z{W|w0#|&maEX=UkJ08FFV#uiw>yYHcDO*2l4#JqJe3Be5vC-MJX=)#H-y%1&X0~&k zzIZ4hUl>;k=gVKSfv#io{uT$M{9P*_$71GUJDb(AIz_Vv$zKriR`}^^ISQDo-cKXt zJJ-Hc+YaP1{_);DG2cbaUFyVTPeZsCzMRjvIa6s5i9H=DSj4SxvrxWDAIucyG=ouW zPE&lff_a=trW^H-Rd)RCu2~<1&paA<*0N4)N#RH>a6NxRjvDOm5(Kx6OUPHw<2Jq` za}h)Hzm^K^5u$D;n;m7?_)RgFPN&J?Kof6%hD;m%o;(w@?&Y5Omka}w2d&nN_`Td# z%=6)ej!O1@U~cWe7dqohKhCWO!}hSbwfrsrP`Py}7RNQWmQ!uXtxscMExEO{|4(vj znauyv+`1EH_v74J4(#9M)-oS&$*pDTd}}`bxaQVtF#DF=8b$Zz*799GZ{7(2sml)K z^J8g6KQCi&&83Zvv!TxcbHM@^yCN&7Nry5;+-7Q{O?;o~i=G^4|rVE36w0ZjG3(KBK zTX#@1c=wlAmsQjU;Xd%j&XWJ^`O!I8%cH_qV8Cw!nf0xLECJF(^0C4u1kL0Kt*n-F zNF;S)4{_k{`u1AH9vo$2+zutdbUw3#e%ZIt{l7ZDVCf6fziic%LX3TjONr(+=d;Vb zIY>;*=AEX*{7pGM68qn%{CwKG&-K|;D{uM$F>nlb|LO3Ljc}i)&X0-ItOsyZJMx)+ nTE{eo10K3l(m9T@;UNa+6!xW@wJ7T(12>=my_R*-u)gqLf)<-?