From d8904eaa56aea16e10a1bffa74c2dbb43b909a32 Mon Sep 17 00:00:00 2001 From: Regalis Date: Fri, 21 Aug 2015 20:21:22 +0300 Subject: [PATCH] Launcher bugfixes, fixed submarine position syncing, previewing the sub after round ends, wiring bugfix, slower reactor overheat, itemlabel, wifi components --- Launcher/Form1.cs | 3 +- Launcher/PackageManager.Designer.cs | 3 + Launcher/PackageManager.cs | 4 +- .../Content/Items/Electricity/regex.png | Bin 0 -> 231 bytes .../Content/Items/Electricity/signalitems.xml | 27 +- Subsurface/Content/Items/Electricity/wifi.png | Bin 0 -> 225 bytes .../Items/Ladder/{item.xml => ladder.xml} | 0 Subsurface/Content/Items/Reactor/reactor.xml | 2 + Subsurface/Content/Items/blank.png | Bin 0 -> 1631 bytes Subsurface/Content/Items/itemlabel.xml | 14 + Subsurface/Source/Camera.cs | 42 ++- Subsurface/Source/Characters/Character.cs | 8 +- Subsurface/Source/ContentPackage.cs | 4 + Subsurface/Source/DebugConsole.cs | 2 + Subsurface/Source/GUI/GUI.cs | 10 +- Subsurface/Source/GUI/GUIMessageBox.cs | 6 + Subsurface/Source/GUI/GUITextBlock.cs | 8 +- Subsurface/Source/GUI/GUITextBox.cs | 1 + Subsurface/Source/Game1.cs | 2 +- Subsurface/Source/GameSession/GameSession.cs | 2 +- Subsurface/Source/Items/Components/Door.cs | 1 - .../Items/Components/Holdable/Holdable.cs | 2 +- .../Source/Items/Components/ItemLabel.cs | 66 +++++ .../Items/Components/Machines/Reactor.cs | 20 +- .../Items/Components/Signal/Connection.cs | 9 +- .../Components/Signal/RegExFindComponent.cs | 40 +-- .../Items/Components/Signal/WifiComponent.cs | 56 ++++ Subsurface/Source/Items/Item.cs | 30 ++- Subsurface/Source/Items/ItemPrefab.cs | 2 +- Subsurface/Source/Map/Submarine.cs | 10 +- Subsurface/Source/Networking/GameClient.cs | 39 ++- Subsurface/Source/Networking/GameServer.cs | 34 ++- Subsurface/Source/Networking/NetworkMember.cs | 5 + Subsurface/Source/PlayerInput.cs | 252 +++++++++--------- Subsurface/Source/Properties.cs | 6 + Subsurface/Source/Screens/EditMapScreen.cs | 2 +- Subsurface/Source/Screens/GameScreen.cs | 3 +- Subsurface/Source/Screens/Screen.cs | 2 +- Subsurface/Source/Utils/MathUtils.cs | 8 +- Subsurface/Source/Utils/ToolBox.cs | 4 +- Subsurface/StyleCop.Cache | 29 +- Subsurface/Subsurface.csproj | 16 +- Subsurface_Solution.v12.suo | Bin 655872 -> 655872 bytes 43 files changed, 546 insertions(+), 228 deletions(-) create mode 100644 Subsurface/Content/Items/Electricity/regex.png create mode 100644 Subsurface/Content/Items/Electricity/wifi.png rename Subsurface/Content/Items/Ladder/{item.xml => ladder.xml} (100%) create mode 100644 Subsurface/Content/Items/blank.png create mode 100644 Subsurface/Content/Items/itemlabel.xml create mode 100644 Subsurface/Source/Items/Components/ItemLabel.cs create mode 100644 Subsurface/Source/Items/Components/Signal/WifiComponent.cs diff --git a/Launcher/Form1.cs b/Launcher/Form1.cs index d80ed81b5..9a92d6ccc 100644 --- a/Launcher/Form1.cs +++ b/Launcher/Form1.cs @@ -17,7 +17,6 @@ namespace Launcher { public partial class LauncherMain : Form { - public static string ContentPackageFolder = "Data/ContentPackages/"; private const string configPath = "config.xml"; private Subsurface.GameSettings settings; @@ -42,7 +41,7 @@ namespace Launcher { InitializeComponent(); - ContentPackage.LoadAll(LauncherMain.ContentPackageFolder); + ContentPackage.LoadAll(ContentPackage.Folder); contentPackageBox.DataSource = ContentPackage.list; supportedModes = new List(); diff --git a/Launcher/PackageManager.Designer.cs b/Launcher/PackageManager.Designer.cs index 9cfc78428..7584ed37e 100644 --- a/Launcher/PackageManager.Designer.cs +++ b/Launcher/PackageManager.Designer.cs @@ -102,6 +102,7 @@ this.itemList.Name = "itemList"; this.itemList.Size = new System.Drawing.Size(255, 134); this.itemList.TabIndex = 8; + this.itemList.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.fileList_KeyPress); // // itemButton // @@ -161,6 +162,7 @@ this.structureList.Name = "structureList"; this.structureList.Size = new System.Drawing.Size(255, 121); this.structureList.TabIndex = 8; + this.structureList.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.fileList_KeyPress); // // structureButton // @@ -189,6 +191,7 @@ this.jobList.Name = "jobList"; this.jobList.Size = new System.Drawing.Size(255, 134); this.jobList.TabIndex = 11; + this.jobList.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.fileList_KeyPress); // // label4 // diff --git a/Launcher/PackageManager.cs b/Launcher/PackageManager.cs index b1270721f..420b1fdd6 100644 --- a/Launcher/PackageManager.cs +++ b/Launcher/PackageManager.cs @@ -142,7 +142,7 @@ namespace Launcher OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "XML files (*.xml)|*.xml;*.XML"; - //ofd.RestoreDirectory? + ofd.RestoreDirectory = true; if (ofd.ShowDialog() == DialogResult.OK) { @@ -253,7 +253,7 @@ namespace Launcher private void okButton_Click(object sender, EventArgs e) { - if (selectedPackage!=null) selectedPackage.Save(LauncherMain.ContentPackageFolder); + if (selectedPackage!=null) selectedPackage.Save(ContentPackage.Folder); this.Close(); } diff --git a/Subsurface/Content/Items/Electricity/regex.png b/Subsurface/Content/Items/Electricity/regex.png new file mode 100644 index 0000000000000000000000000000000000000000..52a4c0295d745d63f2d599d6a6bfd00be6a11dc3 GIT binary patch literal 231 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sDEfH31!Z9ZwBV2!7XV~Bf)~k}2y}372pGD#!ns!-2PV!!=9Q;s%XE;jCka_pEF7X_(EC zWh-#~U^@GgtBpdkD=dEgm#oyzzZ|FOrjfcnP^5!z#$L4>B?k`23NC6EyS(1u=iIYp Y_h)&oK39Hx6VM$Dp00i_>zopr04WtxtN;K2 literal 0 HcmV?d00001 diff --git a/Subsurface/Content/Items/Electricity/signalitems.xml b/Subsurface/Content/Items/Electricity/signalitems.xml index 7bcb2e020..c42fd6b19 100644 --- a/Subsurface/Content/Items/Electricity/signalitems.xml +++ b/Subsurface/Content/Items/Electricity/signalitems.xml @@ -185,7 +185,7 @@ linkable="true" price="10"> - + @@ -203,5 +203,30 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Subsurface/Content/Items/Electricity/wifi.png b/Subsurface/Content/Items/Electricity/wifi.png new file mode 100644 index 0000000000000000000000000000000000000000..bb63ff2724eb9b1efc6d3b9c73b271a17c69975e GIT binary patch literal 225 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sDEfH31!Z9ZwBV40_jV~B?y;B*-GhK_-zD~$`2h;$W`f3S~yv4hjoX>_M)9FkIKbvGDNO-UVGKt RW)aW@44$rjF6*2UngD?ePVxW% literal 0 HcmV?d00001 diff --git a/Subsurface/Content/Items/Ladder/item.xml b/Subsurface/Content/Items/Ladder/ladder.xml similarity index 100% rename from Subsurface/Content/Items/Ladder/item.xml rename to Subsurface/Content/Items/Ladder/ladder.xml diff --git a/Subsurface/Content/Items/Reactor/reactor.xml b/Subsurface/Content/Items/Reactor/reactor.xml index 758928870..306b9b1f0 100644 --- a/Subsurface/Content/Items/Reactor/reactor.xml +++ b/Subsurface/Content/Items/Reactor/reactor.xml @@ -34,6 +34,8 @@ + + diff --git a/Subsurface/Content/Items/blank.png b/Subsurface/Content/Items/blank.png new file mode 100644 index 0000000000000000000000000000000000000000..9a1af98011ac848e82df474fb3263f2d88f0bb6e GIT binary patch literal 1631 zcmV-l2B7(gP)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRZ>Mh-(C$dc?N-<{+BZW4D_5qlujGpF&$mWl*H0HweG_qQ{W zvf2C1z1I9(P{nm${cLLvj!TAcUh?9J=v2PEG6 zfD0@z093)Uq3R%vA~_Kp4^5KR#b%+X}kP8z{X2Z3QJXqtAW1#tu;cCU9?R|L`G26W>a;h z2(#9Zrn>rWs9&sV!bu)finBM&|36T>-%%v{_2#|bb5tmfqexnK5S!EvfSVBUN2z9XO%>Y((pwS~j&E}41xQz>%@G|STSd&tZ-K0CC z^A_ifa6Ha7()$R><8rtQ*t?C#kA95#)Ce4PkYVpPrw*aaCt1yEY6d>OKJg6KsNU20 z1O$6{Gxn{X?d$z&UGd?ZH+vu6ub)<370gDhm?1vfD4^5`V11JBWA!l!NPar&8CdP{ zwmFX+xhMzrVZYzh+2nmuT0|^z6{`>FaF&hmx#p#74x&nje2Jep&6Kpne!WM$~Iv!}tk1>V@>&4|2R`y9lW- zBt=oRarNP@-i*i~)D`D^yv}|U|07zae%bFMLej72>f4oF5HoJmQtT(IV;(Z}J&+IF zO!uu5V?y; + + + + + + + + + + diff --git a/Subsurface/Source/Camera.cs b/Subsurface/Source/Camera.cs index 978c2d385..b06f26bdd 100644 --- a/Subsurface/Source/Camera.cs +++ b/Subsurface/Source/Camera.cs @@ -18,12 +18,13 @@ namespace Subsurface private Vector2 position; private float rotation; + private Vector2 prevPosition; + private float prevZoom; + public float Shake; private Vector2 shakePosition; private Vector2 shakeTargetPosition; - - - + //the area of the world inside the camera view private Rectangle worldView; @@ -130,9 +131,9 @@ namespace Subsurface private void UpdateTransform() { - Vector2 interpolatedPosition = position;//Physics.Interpolate(prevPosition,position); + Vector2 interpolatedPosition = Physics.Interpolate(prevPosition, position); - float interpolatedZoom = zoom;// Physics.Interpolate(prevZoom, zoom); + float interpolatedZoom = Physics.Interpolate(prevZoom, zoom); worldView.X = (int)(interpolatedPosition.X - worldView.Width / 2.0); worldView.Y = (int)(interpolatedPosition.Y + worldView.Height / 2.0); @@ -154,13 +155,19 @@ namespace Subsurface { float moveSpeed = 20.0f/zoom; + prevPosition = position; + prevZoom = zoom; + Vector2 moveCam = Vector2.Zero; if (targetPos == Vector2.Zero) { - if (Keyboard.GetState().IsKeyDown(Keys.A)) moveCam.X -= moveSpeed; - if (Keyboard.GetState().IsKeyDown(Keys.D)) moveCam.X += moveSpeed; - if (Keyboard.GetState().IsKeyDown(Keys.S)) moveCam.Y -= moveSpeed; - if (Keyboard.GetState().IsKeyDown(Keys.W)) moveCam.Y += moveSpeed; + + if (PlayerInput.KeyDown(Keys.A)) moveCam.X -= moveSpeed; + if (PlayerInput.KeyDown(Keys.D)) moveCam.X += moveSpeed; + if (PlayerInput.KeyDown(Keys.S)) moveCam.Y -= moveSpeed; + if (PlayerInput.KeyDown(Keys.W)) moveCam.Y += moveSpeed; + + moveCam = moveCam * deltaTime * 60.0f; Zoom = MathHelper.Clamp(Zoom + PlayerInput.ScrollWheelSpeed / 1000.0f, 0.1f, 2.0f); } @@ -179,15 +186,26 @@ namespace Subsurface float newZoom = Math.Min(DefaultZoom - Math.Min(offset.Length() / resolution.Y, 1.0f),1.0f); Zoom += (newZoom - zoom) / ZoomSmoothness; - - moveCam = (targetPos + offset - position) / MoveSmoothness; + + Vector2 diff = (targetPos + offset) - position; + + if (diff == Vector2.Zero) + { + moveCam = Vector2.Zero; + } + else + { + float dist = diff == Vector2.Zero ? 0.0f : diff.Length(); + + moveCam = Vector2.Normalize(diff) * Math.Min(dist, (dist * deltaTime * 60.0f) / MoveSmoothness); + } } shakeTargetPosition = Rand.Vector(Shake); shakePosition = Vector2.Lerp(shakePosition, shakeTargetPosition, 0.5f); Shake = MathHelper.Lerp(Shake, 0.0f, 0.03f); - Translate((moveCam+shakePosition)*deltaTime*60.0f); + Translate(moveCam+shakePosition); } public Vector2 Position diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index 0760b87c1..00093844e 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -36,7 +36,7 @@ namespace Subsurface private CharacterInventory inventory; - public double LastNetworkUpdate; + public float LastNetworkUpdate; public int LargeUpdateTimer; @@ -1037,7 +1037,7 @@ namespace Subsurface message.Write(secondaryKeyDown.Dequeue); //} - message.Write(NetTime.Now); + message.Write((float)NetTime.Now); // Write byte = move direction message.WriteRangedSingle(MathHelper.Clamp(AnimController.TargetMovement.X, -10.0f, 10.0f), -10.0f, 10.0f, 8); @@ -1132,7 +1132,7 @@ namespace Subsurface bool actionKeyState = false; bool secondaryKeyState = false; - double sendingTime = 0.0f; + float sendingTime = 0.0f; Vector2 targetMovement = Vector2.Zero; bool targetDir = false; Vector2 cursorPos = Vector2.Zero; @@ -1142,7 +1142,7 @@ namespace Subsurface actionKeyState = message.ReadBoolean(); secondaryKeyState = message.ReadBoolean(); - sendingTime = message.ReadDouble(); + sendingTime = message.ReadFloat(); targetMovement = new Vector2(message.ReadRangedSingle(-10.0f, 10.0f, 8), message.ReadRangedSingle(-10.0f, 10.0f, 8)); targetMovement.X = MathUtils.Round(targetMovement.X, 0.1f); diff --git a/Subsurface/Source/ContentPackage.cs b/Subsurface/Source/ContentPackage.cs index 16f2dd94b..9a31a1bf3 100644 --- a/Subsurface/Source/ContentPackage.cs +++ b/Subsurface/Source/ContentPackage.cs @@ -15,6 +15,9 @@ namespace Subsurface public class ContentPackage { + + public static string Folder = "Data/ContentPackages/"; + public static List list = new List(); @@ -80,6 +83,7 @@ namespace Subsurface { ContentPackage newPackage = new ContentPackage(); newPackage.name = name; + newPackage.Path = Folder + name; list.Add(newPackage); return newPackage; diff --git a/Subsurface/Source/DebugConsole.cs b/Subsurface/Source/DebugConsole.cs index bab270824..edf99ab91 100644 --- a/Subsurface/Source/DebugConsole.cs +++ b/Subsurface/Source/DebugConsole.cs @@ -136,11 +136,13 @@ namespace Subsurface public static void ExecuteCommand(string command, Game1 game) { +#if !DEBUG if (Game1.Client!=null) { ThrowError("Console commands are disabled in multiplayer mode"); return; } +#endif if (command == "") return; string[] commands = command.Split(' '); diff --git a/Subsurface/Source/GUI/GUI.cs b/Subsurface/Source/GUI/GUI.cs index c0a0bfd7e..70b667c2d 100644 --- a/Subsurface/Source/GUI/GUI.cs +++ b/Subsurface/Source/GUI/GUI.cs @@ -301,8 +301,16 @@ namespace Subsurface spriteBatch.DrawString(Font, "Physics: " + Game1.World.UpdateTime + " - bodies: " + Game1.World.BodyList.Count - + "Camera pos: " + Game1.GameScreen.Cam.Position, + + " Camera pos: " + Game1.GameScreen.Cam.Position, new Vector2(10, 30), Color.White); + + if (Submarine.Loaded!=null) + { + spriteBatch.DrawString(Font, + "Sub pos: " + Submarine.Loaded.Position, + new Vector2(10, 50), Color.White); + } + } diff --git a/Subsurface/Source/GUI/GUIMessageBox.cs b/Subsurface/Source/GUI/GUIMessageBox.cs index f5cfccb00..c56cda83f 100644 --- a/Subsurface/Source/GUI/GUIMessageBox.cs +++ b/Subsurface/Source/GUI/GUIMessageBox.cs @@ -15,6 +15,12 @@ namespace Subsurface //GUIFrame frame; public GUIButton[] Buttons; + public string Text + { + get { return (children[1] as GUITextBlock).Text; } + set { (children[1] as GUITextBlock).Text = value; } + } + public GUIMessageBox(string header, string text) : this(header, text, new string[] {"OK"}) { diff --git a/Subsurface/Source/GUI/GUITextBlock.cs b/Subsurface/Source/GUI/GUITextBlock.cs index 3edce2fd4..8842689c3 100644 --- a/Subsurface/Source/GUI/GUITextBlock.cs +++ b/Subsurface/Source/GUI/GUITextBlock.cs @@ -120,11 +120,7 @@ namespace Subsurface if (parent != null) parent.AddChild(this); - //if (wrap) - //{ - this.Wrap = wrap; - // this.text = ToolBox.WrapText(this.text, rect.Width); - //} + this.Wrap = wrap; SetTextPos(); } @@ -138,7 +134,7 @@ namespace Subsurface if (Wrap && rect.Width>0) { //text = text.Replace("\n"," "); - text = ToolBox.WrapText(text, rect.Width, Font); + text = ToolBox.WrapText(text, rect.Width - padding.X - padding.Z, Font); Vector2 newSize = MeasureText(text); diff --git a/Subsurface/Source/GUI/GUITextBox.cs b/Subsurface/Source/GUI/GUITextBox.cs index 74a4ca8d3..4401d2cd0 100644 --- a/Subsurface/Source/GUI/GUITextBox.cs +++ b/Subsurface/Source/GUI/GUITextBox.cs @@ -146,6 +146,7 @@ namespace Subsurface public void Deselect() { + Selected = false; if (keyboardDispatcher.Subscriber == this) keyboardDispatcher.Subscriber = null; } diff --git a/Subsurface/Source/Game1.cs b/Subsurface/Source/Game1.cs index d4bcb9aff..e6562c43a 100644 --- a/Subsurface/Source/Game1.cs +++ b/Subsurface/Source/Game1.cs @@ -265,7 +265,7 @@ namespace Subsurface DebugConsole.Update(this, (float)deltaTime); - if ((!DebugConsole.IsOpen && !GUI.PauseMenuOpen) || NetworkMember != null) Screen.Selected.Update(deltaTime); + if ((!DebugConsole.IsOpen && !GUI.PauseMenuOpen) || (NetworkMember != null && NetworkMember.GameStarted)) Screen.Selected.Update(deltaTime); GUI.Update((float)deltaTime); diff --git a/Subsurface/Source/GameSession/GameSession.cs b/Subsurface/Source/GameSession/GameSession.cs index 6ea2a2f8d..8ac5a91a9 100644 --- a/Subsurface/Source/GameSession/GameSession.cs +++ b/Subsurface/Source/GameSession/GameSession.cs @@ -132,7 +132,7 @@ namespace Subsurface if (Game1.Server!=null) { - Game1.Server.EndGame(endMessage); + CoroutineManager.StartCoroutine(Game1.Server.EndGame(endMessage)); } else if (Game1.Client==null) diff --git a/Subsurface/Source/Items/Components/Door.cs b/Subsurface/Source/Items/Components/Door.cs index 3558efb76..1a7ee9cd7 100644 --- a/Subsurface/Source/Items/Components/Door.cs +++ b/Subsurface/Source/Items/Components/Door.cs @@ -119,7 +119,6 @@ namespace Subsurface.Items.Components (int)doorSprite.size.X, (int)doorSprite.size.Y); - body = new PhysicsBody(BodyFactory.CreateRectangle(Game1.World, ConvertUnits.ToSimUnits(Math.Max(doorRect.Width, 1)), ConvertUnits.ToSimUnits(Math.Max(doorRect.Height, 1)), diff --git a/Subsurface/Source/Items/Components/Holdable/Holdable.cs b/Subsurface/Source/Items/Components/Holdable/Holdable.cs index fb285428d..33711de9e 100644 --- a/Subsurface/Source/Items/Components/Holdable/Holdable.cs +++ b/Subsurface/Source/Items/Components/Holdable/Holdable.cs @@ -101,7 +101,7 @@ namespace Subsurface.Items.Components Msg = ""; } - if (attachedByDefault) Use(1.0f); + if (attachedByDefault || Screen.Selected == Game1.EditMapScreen) Use(1.0f); //holdAngle = ToolBox.GetAttributeFloat(element, "holdangle", 0.0f); diff --git a/Subsurface/Source/Items/Components/ItemLabel.cs b/Subsurface/Source/Items/Components/ItemLabel.cs new file mode 100644 index 000000000..0b9ff1323 --- /dev/null +++ b/Subsurface/Source/Items/Components/ItemLabel.cs @@ -0,0 +1,66 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System.Xml.Linq; +namespace Subsurface.Items.Components +{ + class ItemLabel : ItemComponent + { + private GUITextBlock textBlock; + + [HasDefaultValue("", true), Editable(100)] + public string Text + { + get { return textBlock.Text; } + set + { + if (value == TextBlock.Text || item.Rect.Width < 5) return; + TextBlock.Text = value; + } + } + + private Color textColor; + [Editable, HasDefaultValue("0.0,0.0,0.0,1.0", true)] + public string TextColor + { + get { return ToolBox.Vector4ToString(textColor.ToVector4()); } + set + { + textColor = new Color(ToolBox.ParseToVector4(value)); + } + } + + private GUITextBlock TextBlock + { + get + { + if (textBlock==null) + { + textBlock = new GUITextBlock(new Rectangle(item.Rect.X,-item.Rect.Y,item.Rect.Width, item.Rect.Height), "", + Color.Transparent, Color.Black, + Alignment.TopLeft, Alignment.Center, + null, null, true); + textBlock.Font = GUI.SmallFont; + textBlock.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); + } + return textBlock; + } + } + + public override void Move(Vector2 amount) + { + textBlock.Rect = new Rectangle(item.Rect.X, -item.Rect.Y, item.Rect.Width, item.Rect.Height); + } + + public ItemLabel(Item item, XElement element) + : base(item, element) + { + } + + public override void Draw(SpriteBatch spriteBatch, bool editing = false) + { + base.Draw(spriteBatch, editing); + + textBlock.Draw(spriteBatch); + } + } +} \ No newline at end of file diff --git a/Subsurface/Source/Items/Components/Machines/Reactor.cs b/Subsurface/Source/Items/Components/Machines/Reactor.cs index b5bc0a300..960667c9c 100644 --- a/Subsurface/Source/Items/Components/Machines/Reactor.cs +++ b/Subsurface/Source/Items/Components/Machines/Reactor.cs @@ -140,7 +140,7 @@ namespace Subsurface.Items.Components float heat = 100 * fissionRate * (AvailableFuel/2000.0f); float heatDissipation = 50 * coolingRate + ExtraCooling; - float deltaTemp = (((heat - heatDissipation) * 5) - temperature) / 1000.0f; + float deltaTemp = (((heat - heatDissipation) * 5) - temperature) / 10000.0f; Temperature = temperature + deltaTemp; if (temperature > meltDownTemp) @@ -155,8 +155,7 @@ namespace Subsurface.Items.Components powerUpTask = new PropertyTask(item, IsRunning, 50.0f, "Power up the reactor"); } } - - + item.Condition -= temperature * deltaTime * 0.00005f; if (temperature > shutDownTemp) @@ -201,8 +200,7 @@ namespace Subsurface.Items.Components //fission rate can't be lowered below a certain amount if the core is too hot FissionRate = Math.Max(fissionRate, heat / 200.0f); - - + //the power generated by the reactor is equal to the temperature currPowerConsumption = -temperature*powerPerTemp; @@ -216,6 +214,8 @@ namespace Subsurface.Items.Components ExtraCooling = 0.0f; AvailableFuel = 0.0f; + + item.SendSignal(((int)temperature).ToString(), "temperature_out"); } public override void UpdateBroken(float deltaTime, Camera cam) @@ -402,6 +402,16 @@ namespace Subsurface.Items.Components GUI.DrawLine(spriteBatch, prevPoint, lastPoint, Color.White); } + public override void ReceiveSignal(string signal, Connection connection, Item sender, float power) + { + switch (connection.Name) + { + case "shutdown": + shutDownTemp = 0.0f; + break; + } + } + public override void FillNetworkData(NetworkEventType type, NetOutgoingMessage message) { message.Write(autoTemp); diff --git a/Subsurface/Source/Items/Components/Signal/Connection.cs b/Subsurface/Source/Items/Components/Signal/Connection.cs index 86ddc2556..258af00b1 100644 --- a/Subsurface/Source/Items/Components/Signal/Connection.cs +++ b/Subsurface/Source/Items/Components/Signal/Connection.cs @@ -319,14 +319,13 @@ namespace Subsurface.Items.Components if (index>-1) { Wires[index].RemoveConnection(this); - Wires[index].Item.SetTransform(item.SimPosition, 0.0f); - Wires[index].Item.Drop(); - Wires[index].Item.body.Enabled = true; + //Wires[index].Item.SetTransform(item.SimPosition, 0.0f); + //Wires[index].Item.Drop(); + //Wires[index].Item.body.Enabled = true; Wires[index] = null; } } - } - + } } diff --git a/Subsurface/Source/Items/Components/Signal/RegExFindComponent.cs b/Subsurface/Source/Items/Components/Signal/RegExFindComponent.cs index 28ea8b161..917c45ac8 100644 --- a/Subsurface/Source/Items/Components/Signal/RegExFindComponent.cs +++ b/Subsurface/Source/Items/Components/Signal/RegExFindComponent.cs @@ -9,6 +9,8 @@ namespace Subsurface.Items.Components private string expression; + private string receivedSignal; + [InGameEditable, HasDefaultValue("1", true)] public string Output { @@ -26,6 +28,27 @@ namespace Subsurface.Items.Components public RegExFindComponent(Item item, XElement element) : base(item, element) { + isActive = true; + } + + public override void Update(float deltaTime, Camera cam) + { + if (string.IsNullOrWhiteSpace(expression)) return; + + bool success = false; + try + { + Regex regex = new Regex(@expression); + Match match = regex.Match(receivedSignal); + success = match.Success; + } + catch + { + item.SendSignal("ERROR", "signal_out"); + return; + } + + item.SendSignal(success ? output : "0", "signal_out"); } public override void ReceiveSignal(string signal, Connection connection, Item sender, float power = 0.0f) @@ -33,22 +56,7 @@ namespace Subsurface.Items.Components switch (connection.Name) { case "signal_in": - if (string.IsNullOrWhiteSpace(expression)) return; - - bool success = false; - try - { - Regex regex = new Regex(@expression); - Match match = regex.Match(signal); - success = match.Success; - } - catch - { - item.SendSignal("ERROR", "signal_out"); - return; - } - - item.SendSignal(success ? output : "0", "signal_out"); + receivedSignal = signal; break; case "set_output": diff --git a/Subsurface/Source/Items/Components/Signal/WifiComponent.cs b/Subsurface/Source/Items/Components/Signal/WifiComponent.cs new file mode 100644 index 000000000..d1486eca7 --- /dev/null +++ b/Subsurface/Source/Items/Components/Signal/WifiComponent.cs @@ -0,0 +1,56 @@ +using Microsoft.Xna.Framework; +using System; +using System.Collections.Generic; +using System.Xml.Linq; + +namespace Subsurface.Items.Components +{ + class WifiComponent : ItemComponent + { + + private static List list = new List(); + + private int channel; + + [InGameEditable, HasDefaultValue(1, true)] + public int Channel + { + get { return channel; } + set + { + channel = MathHelper.Clamp(value, 0, 100); + } + } + + public WifiComponent(Item item, XElement element) + : base (item, element) + { + + list.Add(this); + } + + public override void ReceiveSignal(string signal, Connection connection, Item sender, float power=0.0f) + { + //prevent an ininite loop of wificomponents sending messages between each other + if (sender.GetComponent()!=null) return; + + switch (connection.Name) + { + case "signal_in": + foreach (WifiComponent wifiComp in list) + { + if (wifiComp == this || wifiComp.channel != channel) continue; + wifiComp.item.SendSignal(signal, "signal_out"); + } + break; + } + } + + public override void Remove() + { + base.Remove(); + + list.Remove(this); + } + } +} diff --git a/Subsurface/Source/Items/Item.cs b/Subsurface/Source/Items/Item.cs index cf030ec47..d8cbe19d6 100644 --- a/Subsurface/Source/Items/Item.cs +++ b/Subsurface/Source/Items/Item.cs @@ -551,15 +551,19 @@ namespace Subsurface Color color = (isSelected && editing) ? color = Color.Red : spriteColor; if (isHighlighted) color = Color.Orange; - if (body==null) + if (prefab.sprite!=null) { - prefab.sprite.DrawTiled(spriteBatch, new Vector2(rect.X, -rect.Y), new Vector2(rect.Width, rect.Height), color); - } - else if (body.Enabled) - { - body.Draw(spriteBatch, prefab.sprite, color); + if (body==null) + { + prefab.sprite.DrawTiled(spriteBatch, new Vector2(rect.X, -rect.Y), new Vector2(rect.Width, rect.Height), color); + } + else if (body.Enabled) + { + body.Draw(spriteBatch, prefab.sprite, color); + } } + foreach (ItemComponent component in components) component.Draw(spriteBatch, editing); if (!editing || (body!=null && !body.Enabled)) @@ -670,7 +674,13 @@ namespace Subsurface foreach (var objectProperty in editableProperties) { new GUITextBlock(new Rectangle(0, y, 100, 20), objectProperty.Name, Color.Transparent, Color.White, Alignment.Left, null, editingHUD); - GUITextBox propertyBox = new GUITextBox(new Rectangle(100, y, 200, 20), GUI.style, editingHUD); + + int height = 20; + var editable = objectProperty.Attributes.OfType().FirstOrDefault(); + if (editable != null) height = (int)(Math.Ceiling(editable.MaxLength / 20.0f) * 20.0f); + + GUITextBox propertyBox = new GUITextBox(new Rectangle(100, y, 200, height), GUI.style, editingHUD); + if (height>20) propertyBox.Wrap = true; object value = objectProperty.GetValue(); if (value != null) @@ -681,7 +691,7 @@ namespace Subsurface propertyBox.UserData = objectProperty; propertyBox.OnEnter = EnterProperty; propertyBox.OnTextChanged = PropertyChanged; - y = y + 30; + y = y + height+10; } return editingHUD; } @@ -938,8 +948,8 @@ namespace Subsurface if (objectProperty == null) return false; object prevValue = objectProperty.GetValue(); - - textBox.Selected = false; + + textBox.Deselect(); if (objectProperty.TrySetValue(text)) { diff --git a/Subsurface/Source/Items/ItemPrefab.cs b/Subsurface/Source/Items/ItemPrefab.cs index e13b087be..504bd9016 100644 --- a/Subsurface/Source/Items/ItemPrefab.cs +++ b/Subsurface/Source/Items/ItemPrefab.cs @@ -106,7 +106,7 @@ namespace Subsurface position = placePosition; } - sprite.DrawTiled(spriteBatch, new Vector2(position.X, -position.Y), placeSize, Color.White); + if (sprite != null) sprite.DrawTiled(spriteBatch, new Vector2(position.X, -position.Y), placeSize, Color.White); } if (PlayerInput.GetMouseState.RightButton == ButtonState.Pressed) selected = null; diff --git a/Subsurface/Source/Map/Submarine.cs b/Subsurface/Source/Map/Submarine.cs index e520bc943..3f02177da 100644 --- a/Subsurface/Source/Map/Submarine.cs +++ b/Subsurface/Source/Map/Submarine.cs @@ -50,7 +50,7 @@ namespace Subsurface private string name; - private double lastNetworkUpdate; + private float lastNetworkUpdate; //properties ---------------------------------------------------- @@ -564,7 +564,7 @@ namespace Subsurface public override void FillNetworkData(Networking.NetworkEventType type, NetOutgoingMessage message, object data) { - message.Write(NetTime.Now); + message.Write((float)NetTime.Now); message.Write(Position.X); message.Write(Position.Y); @@ -575,11 +575,11 @@ namespace Subsurface public override void ReadNetworkData(Networking.NetworkEventType type, NetIncomingMessage message) { - double sendingTime; + float sendingTime; Vector2 newTargetPosition, newSpeed; try { - sendingTime = message.ReadDouble(); + sendingTime = message.ReadFloat(); if (sendingTime <= lastNetworkUpdate) return; @@ -595,7 +595,7 @@ namespace Subsurface return; } - if (!speed.IsValid() || targetPosition.IsValid()) return; + if (!newSpeed.IsValid() || !newTargetPosition.IsValid()) return; //newTargetPosition = newTargetPosition + newSpeed * (float)(NetTime.Now - sendingTime); diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index b1f1d0936..0a13ddd5f 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -377,7 +377,7 @@ namespace Subsurface.Networking break; case (byte)PacketTypes.EndGame: string endMessage = inc.ReadString(); - EndGame(endMessage); + CoroutineManager.StartCoroutine(EndGame(endMessage)); break; case (byte)PacketTypes.PlayerJoined: @@ -429,19 +429,48 @@ namespace Subsurface.Networking } } - public void EndGame(string endMessage) + public IEnumerable EndGame(string endMessage) { + gameStarted = false; + + var messageBox = new GUIMessageBox("The round has ended", endMessage); + + Character.Controlled = null; + Game1.LightManager.LosEnabled = false; + + float endPreviewLength = 10.0f; + + DateTime endTime = DateTime.Now + new TimeSpan(0,0,0,0,(int)(1000.0f*endPreviewLength)); + float secondsLeft = endPreviewLength; + + do + { + secondsLeft = (float)(endTime - DateTime.Now).TotalSeconds; + + float camAngle = (float)((DateTime.Now - endTime).TotalSeconds / endPreviewLength) * MathHelper.TwoPi; + Vector2 offset = (new Vector2( + (float)Math.Cos(camAngle) * (Submarine.Borders.Width / 2.0f), + (float)Math.Sin(camAngle) * (Submarine.Borders.Height / 2.0f))); + + Game1.GameScreen.Cam.TargetPos = offset * 0.8f; + //Game1.GameScreen.Cam.MoveCamera((float)deltaTime); + + messageBox.Text = endMessage + "\nReturning to lobby in " + (int)secondsLeft + " s"; + yield return Status.Running; + } while (secondsLeft > 0.0f); + + messageBox.Text = endMessage; + Submarine.Unload(); Game1.NetLobbyScreen.Select(); if (Game1.GameSession!=null) Game1.GameSession.EndShift(""); - new GUIMessageBox("The round has ended", endMessage); - myCharacter = null; - gameStarted = false; + yield return Status.Success; + } public override void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch) diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index 1f4021e8f..6b6d0b572 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -149,13 +149,7 @@ namespace Subsurface.Networking yield return Status.Running; } - - yield return Status.Success; - - - - } private void MasterServerCallBack(IRestResponse response) @@ -617,9 +611,10 @@ namespace Subsurface.Networking return true; } - public void EndGame(string endMessage) + public IEnumerable EndGame(string endMessage) { + gameStarted = false; if (connectedClients.Count > 0) { @@ -639,13 +634,34 @@ namespace Subsurface.Networking } } + float endPreviewLength = 10.0f; + + DateTime endTime = DateTime.Now + new TimeSpan(0, 0, 0, 0, (int)(1000.0f * endPreviewLength)); + float secondsLeft = endPreviewLength; + + do + { + secondsLeft = (float)(endTime - DateTime.Now).TotalSeconds; + + float camAngle = (float)((DateTime.Now - endTime).TotalSeconds / endPreviewLength) * MathHelper.TwoPi; + Vector2 offset = (new Vector2( + (float)Math.Cos(camAngle) * (Submarine.Borders.Width / 2.0f), + (float)Math.Sin(camAngle) * (Submarine.Borders.Height / 2.0f))); + + Game1.GameScreen.Cam.TargetPos = offset * 0.8f; + //Game1.GameScreen.Cam.MoveCamera((float)deltaTime); + + yield return Status.Running; + } while (secondsLeft > 0.0f); + Submarine.Unload(); - - gameStarted = false; Game1.NetLobbyScreen.Select(); DebugConsole.ThrowError(endMessage); + + yield return Status.Success; + } private void DisconnectClient(NetConnection senderConnection) diff --git a/Subsurface/Source/Networking/NetworkMember.cs b/Subsurface/Source/Networking/NetworkMember.cs index e28c54583..7e7f4c7b6 100644 --- a/Subsurface/Source/Networking/NetworkMember.cs +++ b/Subsurface/Source/Networking/NetworkMember.cs @@ -64,6 +64,11 @@ namespace Subsurface.Networking } } + public bool GameStarted + { + get { return gameStarted; } + } + public GUIFrame InGameHUD { get { return inGameHUD; } diff --git a/Subsurface/Source/PlayerInput.cs b/Subsurface/Source/PlayerInput.cs index 75e879775..01a19573b 100644 --- a/Subsurface/Source/PlayerInput.cs +++ b/Subsurface/Source/PlayerInput.cs @@ -3,156 +3,156 @@ using Microsoft.Xna.Framework.Input; namespace Subsurface { - class Key - { - private bool state, stateQueue; - private bool canBeHeld; - - public Key(bool canBeHeld) - { - this.canBeHeld = canBeHeld; - } + class Key + { + private bool state, stateQueue; + private bool canBeHeld; + + public Key(bool canBeHeld) + { + this.canBeHeld = canBeHeld; + } - public bool State - { - get - { - return state; - } - set - { - //if (value == false) return; - state = value; - //if (value) stateQueue = value; - } - } + public bool State + { + get + { + return state; + } + set + { + //if (value == false) return; + state = value; + //if (value) stateQueue = value; + } + } - public void SetState(bool value) - { - state = value; - if (value) stateQueue = value; - } + public void SetState(bool value) + { + state = value; + if (value) stateQueue = value; + } - public bool Dequeue - { - get - { - bool value = stateQueue; - stateQueue = false; - return value; - } - //set - //{ - // stateQueue = value; - //} - } + public bool Dequeue + { + get + { + bool value = stateQueue; + stateQueue = false; + return value; + } + //set + //{ + // stateQueue = value; + //} + } - public void Reset() - { - if (!canBeHeld) state = false; - //stateQueue = false; - } - } + public void Reset() + { + if (!canBeHeld) state = false; + //stateQueue = false; + } + } - static class PlayerInput - { - static MouseState mouseState, oldMouseState; - static KeyboardState keyboardState, oldKeyboardState; + static class PlayerInput + { + static MouseState mouseState, oldMouseState; + static KeyboardState keyboardState, oldKeyboardState; - static double timeSinceClick; + static double timeSinceClick; - const double doubleClickDelay = 0.4; + const double doubleClickDelay = 0.4; - static bool doubleClicked; + static bool doubleClicked; - public static Keys selectKey = Keys.E; + public static Keys selectKey = Keys.E; - public static Vector2 MousePosition - { - get { return new Vector2(mouseState.Y, mouseState.X); } - } + public static Vector2 MousePosition + { + get { return new Vector2(mouseState.X, mouseState.Y); } + } - public static MouseState GetMouseState - { - get { return mouseState; } - } - public static MouseState GetOldMouseState - { - get { return oldMouseState; } - } + public static MouseState GetMouseState + { + get { return mouseState; } + } + public static MouseState GetOldMouseState + { + get { return oldMouseState; } + } - public static Vector2 MouseSpeed - { - get - { + public static Vector2 MouseSpeed + { + get + { return MousePosition - new Vector2(oldMouseState.X, oldMouseState.Y); - } - } + } + } - public static KeyboardState GetKeyboardState - { - get { return keyboardState; } - } + public static KeyboardState GetKeyboardState + { + get { return keyboardState; } + } - public static KeyboardState GetOldKeyboardState - { - get { return oldKeyboardState; } - } + public static KeyboardState GetOldKeyboardState + { + get { return oldKeyboardState; } + } - public static int ScrollWheelSpeed - { - get { return mouseState.ScrollWheelValue - oldMouseState.ScrollWheelValue; } - - } + public static int ScrollWheelSpeed + { + get { return mouseState.ScrollWheelValue - oldMouseState.ScrollWheelValue; } + + } - public static bool LeftButtonDown() - { - return mouseState.LeftButton == ButtonState.Pressed; - } + public static bool LeftButtonDown() + { + return mouseState.LeftButton == ButtonState.Pressed; + } - public static bool LeftButtonClicked() - { - return (oldMouseState.LeftButton == ButtonState.Pressed - && mouseState.LeftButton == ButtonState.Released); - } + public static bool LeftButtonClicked() + { + return (oldMouseState.LeftButton == ButtonState.Pressed + && mouseState.LeftButton == ButtonState.Released); + } - public static bool RightButtonClicked() - { - return (oldMouseState.RightButton == ButtonState.Pressed - && mouseState.RightButton == ButtonState.Released); - } + public static bool RightButtonClicked() + { + return (oldMouseState.RightButton == ButtonState.Pressed + && mouseState.RightButton == ButtonState.Released); + } - public static bool DoubleClicked() - { - return doubleClicked; - } + public static bool DoubleClicked() + { + return doubleClicked; + } - public static bool KeyHit(Keys button) - { - return (oldKeyboardState.IsKeyDown(button) && keyboardState.IsKeyUp(button)); - } + public static bool KeyHit(Keys button) + { + return (oldKeyboardState.IsKeyDown(button) && keyboardState.IsKeyUp(button)); + } - public static bool KeyDown(Keys button) - { - return (keyboardState.IsKeyDown(button)); - } + public static bool KeyDown(Keys button) + { + return (keyboardState.IsKeyDown(button)); + } - public static void Update(double deltaTime) - { - timeSinceClick += deltaTime; + public static void Update(double deltaTime) + { + timeSinceClick += deltaTime; - oldMouseState = mouseState; - mouseState = Mouse.GetState(); + oldMouseState = mouseState; + mouseState = Mouse.GetState(); - oldKeyboardState = keyboardState; - keyboardState = Keyboard.GetState(); + oldKeyboardState = keyboardState; + keyboardState = Keyboard.GetState(); - doubleClicked = false; - if (LeftButtonClicked()) - { - if (timeSinceClick < doubleClickDelay) doubleClicked = true; - timeSinceClick = 0.0; - } - } - } + doubleClicked = false; + if (LeftButtonClicked()) + { + if (timeSinceClick < doubleClickDelay) doubleClicked = true; + timeSinceClick = 0.0; + } + } + } } diff --git a/Subsurface/Source/Properties.cs b/Subsurface/Source/Properties.cs index c985ce848..e27bdf52a 100644 --- a/Subsurface/Source/Properties.cs +++ b/Subsurface/Source/Properties.cs @@ -11,6 +11,12 @@ namespace Subsurface [AttributeUsage(AttributeTargets.Property)] public class Editable : System.Attribute { + public int MaxLength; + + public Editable(int maxLength = 20) + { + MaxLength = maxLength; + } } [AttributeUsage(AttributeTargets.Property)] diff --git a/Subsurface/Source/Screens/EditMapScreen.cs b/Subsurface/Source/Screens/EditMapScreen.cs index 326d199ef..6bfc35afe 100644 --- a/Subsurface/Source/Screens/EditMapScreen.cs +++ b/Subsurface/Source/Screens/EditMapScreen.cs @@ -176,7 +176,7 @@ namespace Subsurface // CreateDummyCharacter(); //} - cam.MoveCamera((float)deltaTime); + if (GUIComponent.MouseOn==null) cam.MoveCamera((float)deltaTime); cam.Zoom = MathHelper.Clamp(cam.Zoom + PlayerInput.ScrollWheelSpeed/1000.0f,0.1f, 2.0f); if (characterMode) diff --git a/Subsurface/Source/Screens/GameScreen.cs b/Subsurface/Source/Screens/GameScreen.cs index 27af439f4..96a4d111a 100644 --- a/Subsurface/Source/Screens/GameScreen.cs +++ b/Subsurface/Source/Screens/GameScreen.cs @@ -75,11 +75,12 @@ namespace Subsurface StatusEffect.UpdateAll((float)deltaTime); - cam.MoveCamera((float)deltaTime); Physics.accumulator = Math.Min(Physics.accumulator, Physics.step * 4); while (Physics.accumulator >= Physics.step) { + cam.MoveCamera((float)Physics.step); + foreach (PhysicsBody pb in PhysicsBody.list) { pb.SetPrevTransform(pb.Position, pb.Rotation); diff --git a/Subsurface/Source/Screens/Screen.cs b/Subsurface/Source/Screens/Screen.cs index 36e95f6d3..e0a8268ab 100644 --- a/Subsurface/Source/Screens/Screen.cs +++ b/Subsurface/Source/Screens/Screen.cs @@ -5,7 +5,7 @@ namespace Subsurface class Screen { private static Screen selected; - + public static Screen Selected { get { return selected; } diff --git a/Subsurface/Source/Utils/MathUtils.cs b/Subsurface/Source/Utils/MathUtils.cs index e16b13542..10b736eee 100644 --- a/Subsurface/Source/Utils/MathUtils.cs +++ b/Subsurface/Source/Utils/MathUtils.cs @@ -29,16 +29,14 @@ namespace Subsurface public static bool IsValid(float value) { - return (!float.IsInfinity(value) && !float.IsInfinity(value)); + return (!float.IsInfinity(value) && !float.IsNaN(value)); } public static bool IsValid(Vector2 vector) { - return (!float.IsInfinity(vector.X) && !float.IsInfinity(vector.Y) && !float.IsNaN(vector.X) && !float.IsNaN(vector.Y)); + return (IsValid(vector.X) && IsValid(vector.Y)); } - - - + public static float CurveAngle(float from, float to, float step) { diff --git a/Subsurface/Source/Utils/ToolBox.cs b/Subsurface/Source/Utils/ToolBox.cs index f64c02bdd..b37a172bc 100644 --- a/Subsurface/Source/Utils/ToolBox.cs +++ b/Subsurface/Source/Utils/ToolBox.cs @@ -36,9 +36,9 @@ namespace Subsurface { font = contentManager.Load(file); } - catch + catch (Exception e) { - DebugConsole.ThrowError("Loading font ''"+file+"'' failed"); + DebugConsole.ThrowError("Loading font ''"+file+"'' failed", e); } return font; diff --git a/Subsurface/StyleCop.Cache b/Subsurface/StyleCop.Cache index c2264d137..456c5e6fd 100644 --- a/Subsurface/StyleCop.Cache +++ b/Subsurface/StyleCop.Cache @@ -6336,9 +6336,6 @@ - - DEBUG;TRACE;WINDOWS - 2014.04.01 10:18:24.000 @@ -6464,4 +6461,30 @@ + + DEBUG;TRACE;WINDOWS + + + + 2014.04.01 10:18:24.000 + 2015.07.02 21:22:42.115 + 2015.08.21 17:49:13.627 + 2014.04.01 10:18:24.000 + 2014.04.01 10:18:24.000 + -1945363787 + 2014.04.01 10:18:24.000 + 0 + 2014.04.01 10:18:24.000 + 0 + 2014.04.01 10:18:24.000 + 0 + 2014.04.01 10:18:24.000 + 0 + 2014.04.01 10:18:24.000 + 0 + 2014.04.01 10:18:24.000 + 0 + + + \ No newline at end of file diff --git a/Subsurface/Subsurface.csproj b/Subsurface/Subsurface.csproj index ff3e2615a..95a6a0383 100644 --- a/Subsurface/Subsurface.csproj +++ b/Subsurface/Subsurface.csproj @@ -76,7 +76,9 @@ + + @@ -301,6 +303,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -310,6 +315,12 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + Designer PreserveNewest @@ -320,6 +331,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest Designer @@ -557,7 +571,7 @@ PreserveNewest - + PreserveNewest diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index 24e07d1335d7d2da193b848b3100e1c7fffdfe57..3a2a2916428771c4ee4051d79f6e6b2f72b89991 100644 GIT binary patch delta 12492 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 I7mbkr2goYZ;{X5v delta 12828 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