From 14ee39e59a4bb2cf15249595452135510245635b Mon Sep 17 00:00:00 2001 From: Regalis Date: Mon, 1 Feb 2016 22:21:26 +0200 Subject: [PATCH] Endworm & moloch immune to bleeding, showing right sub name in save file info, disable charactermode before saving, option to end round when the end of the level is reached, maintain position option in steering --- .../Content/Characters/Endworm/endworm.xml | 2 +- .../Content/Characters/Moloch/moloch.xml | 2 +- Subsurface/Content/Items/Button/button.xml | 5 + .../Content/Items/Diving/divinggear.xml | 14 ++ Subsurface/Content/Items/Tools/tools.xml | 21 ++- .../Source/Characters/Animation/Ragdoll.cs | 2 +- Subsurface/Source/Characters/Character.cs | 18 ++- Subsurface/Source/DebugConsole.cs | 7 +- Subsurface/Source/Events/ScriptedEvent.cs | 24 +-- Subsurface/Source/GameSession/GameSession.cs | 5 +- .../Items/Components/Machines/Steering.cs | 139 ++++++++++++++---- Subsurface/Source/Map/Submarine.cs | 2 +- Subsurface/Source/Map/SubmarineBody.cs | 2 +- Subsurface/Source/Networking/GameServer.cs | 24 +-- .../Source/Networking/GameServerSettings.cs | 26 ++-- Subsurface/Source/Screens/EditMapScreen.cs | 40 +++-- Subsurface/Source/Screens/MainMenuScreen.cs | 6 +- Subsurface/Source/Utils/SaveUtil.cs | 25 +--- Subsurface/Source/Utils/UpdaterUtil.cs | 2 +- Subsurface_Solution.v12.suo | Bin 914432 -> 922112 bytes 20 files changed, 257 insertions(+), 109 deletions(-) diff --git a/Subsurface/Content/Characters/Endworm/endworm.xml b/Subsurface/Content/Characters/Endworm/endworm.xml index a63bc2a19..eb183714c 100644 --- a/Subsurface/Content/Characters/Endworm/endworm.xml +++ b/Subsurface/Content/Characters/Endworm/endworm.xml @@ -1,5 +1,5 @@  - + diff --git a/Subsurface/Content/Characters/Moloch/moloch.xml b/Subsurface/Content/Characters/Moloch/moloch.xml index 2b5ebfe84..a1bcb33b2 100644 --- a/Subsurface/Content/Characters/Moloch/moloch.xml +++ b/Subsurface/Content/Characters/Moloch/moloch.xml @@ -1,5 +1,5 @@  - + diff --git a/Subsurface/Content/Items/Button/button.xml b/Subsurface/Content/Items/Button/button.xml index 6bf1cf042..3971265a6 100644 --- a/Subsurface/Content/Items/Button/button.xml +++ b/Subsurface/Content/Items/Button/button.xml @@ -8,6 +8,11 @@ + + + + + diff --git a/Subsurface/Content/Items/Diving/divinggear.xml b/Subsurface/Content/Items/Diving/divinggear.xml index aaea39e6c..67dc8e0ec 100644 --- a/Subsurface/Content/Items/Diving/divinggear.xml +++ b/Subsurface/Content/Items/Diving/divinggear.xml @@ -7,6 +7,10 @@ pickdistance="150" price="50"> + + + + @@ -26,6 +30,10 @@ price="50" description="Small enough to carry around in case of need, but won't protect you from the water pressure in the event of a full-blown hull breach."> + + + + @@ -101,6 +109,12 @@ price="50" description="A battery-powered underwater propulsion device."> + + + + + + diff --git a/Subsurface/Content/Items/Tools/tools.xml b/Subsurface/Content/Items/Tools/tools.xml index a9b318614..4df507e77 100644 --- a/Subsurface/Content/Items/Tools/tools.xml +++ b/Subsurface/Content/Items/Tools/tools.xml @@ -10,6 +10,11 @@ + + + + + @@ -56,6 +61,11 @@ price="100" description="Cuts through various materials using a jet of ionized oxygen."> + + + + + @@ -94,6 +104,10 @@ pickdistance="150" price="50"> + + + + @@ -113,6 +127,11 @@ price="100" description="A handheld carbon dioxide extinguisher."> + + + + + @@ -135,7 +154,7 @@ Tags="smallitem" pickdistance="200" price="10"> - + diff --git a/Subsurface/Source/Characters/Animation/Ragdoll.cs b/Subsurface/Source/Characters/Animation/Ragdoll.cs index e5ca45086..4bf6c609e 100644 --- a/Subsurface/Source/Characters/Animation/Ragdoll.cs +++ b/Subsurface/Source/Characters/Animation/Ragdoll.cs @@ -315,7 +315,7 @@ namespace Barotrauma //the collision is ignored if the lowest limb is under the platform if (lowestLimb==null || lowestLimb.Position.Y < structure.Rect.Y) return false; } - else if (structure.StairDirection!=Direction.None && lowestLimb != null) + else if (structure.StairDirection != Direction.None && lowestLimb != null) { float stairPosY = structure.StairDirection == Direction.Right ? lowestLimb.Position.X - structure.Rect.X : structure.Rect.Width - (lowestLimb.Position.X - structure.Rect.X); diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index 0ab519ce5..417abdda3 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -253,6 +253,12 @@ namespace Barotrauma } } + public bool DoesBleed + { + get; + private set; + } + public float PressureTimer { @@ -402,6 +408,8 @@ namespace Barotrauma maxHealth = ToolBox.GetAttributeFloat(doc.Root, "health", 100.0f); health = maxHealth; + DoesBleed = ToolBox.GetAttributeBool(doc.Root, "doesbleed", true); + needsAir = ToolBox.GetAttributeBool(doc.Root, "needsair", false); drowningTime = ToolBox.GetAttributeFloat(doc.Root, "drowningtime", 10.0f); @@ -958,7 +966,7 @@ namespace Barotrauma PressureProtection -= deltaTime*100.0f; } - Health -= bleeding; + Health -= bleeding*deltaTime; if (health <= 0.0f) Kill(CauseOfDeath.Bloodloss, false); } @@ -1093,9 +1101,11 @@ namespace Barotrauma //health -= attackResult.Damage; //if (health <= 0.0f && damageType == DamageType.Burn) Kill(CauseOfDeath.Burn); - - Bleeding += attackResult.Bleeding; - + if (DoesBleed) + { + Bleeding += attackResult.Bleeding; + } + return attackResult; } diff --git a/Subsurface/Source/DebugConsole.cs b/Subsurface/Source/DebugConsole.cs index 0f305bae9..985985281 100644 --- a/Subsurface/Source/DebugConsole.cs +++ b/Subsurface/Source/DebugConsole.cs @@ -359,6 +359,11 @@ namespace Barotrauma case "save": if (commands.Length < 2) break; + if (GameMain.EditMapScreen.CharacterMode) + { + GameMain.EditMapScreen.ToggleCharacterMode(); + } + string fileName = string.Join(" ", commands.Skip(1)); if (fileName.Contains("../")) { @@ -369,7 +374,7 @@ namespace Barotrauma if (WayPoint.WayPointList.Find(wp => !wp.MoveWithLevel && wp.SpawnType == SpawnType.Path)==null) { - DebugConsole.ThrowError("No waypoints found in the submarine. Did you forget to generate the waypoints?"); + DebugConsole.ThrowError("No waypoints found in the submarine. AI controlled crew members won't be able to navigate without waypoints."); } if (WayPoint.WayPointList.Find(wp => wp.SpawnType == SpawnType.Cargo) == null) diff --git a/Subsurface/Source/Events/ScriptedEvent.cs b/Subsurface/Source/Events/ScriptedEvent.cs index 73a6e75d5..6528cf79c 100644 --- a/Subsurface/Source/Events/ScriptedEvent.cs +++ b/Subsurface/Source/Events/ScriptedEvent.cs @@ -10,10 +10,10 @@ namespace Barotrauma { private static string configFile = "Content/randomevents.xml"; - const int MaxPreviousEvents = 6; - const float PreviouslyUsedWeight = 10.0f; + //const int MaxPreviousEvents = 6; + //const float PreviouslyUsedWeight = 10.0f; - static List previousEvents = new List(); + //static List previousEvents = new List(); protected string name; protected string description; @@ -109,16 +109,16 @@ namespace Barotrauma eventProbability[i] = ToolBox.GetAttributeInt(element, "commonness", 1); //if the event has been previously selected, it's less likely to be selected now - int previousEventIndex = previousEvents.FindIndex(x => x == i); - if (previousEventIndex >= 0) - { - //how many shifts ago was the event last selected - int eventDist = eventCount - previousEventIndex; + //int previousEventIndex = previousEvents.FindIndex(x => x == i); + //if (previousEventIndex >= 0) + //{ + // //how many shifts ago was the event last selected + // int eventDist = eventCount - previousEventIndex; - float weighting = (1.0f / eventDist) * PreviouslyUsedWeight; + // float weighting = (1.0f / eventDist) * PreviouslyUsedWeight; - eventProbability[i] *= weighting; - } + // eventProbability[i] *= weighting; + //} probabilitySum += eventProbability[i]; @@ -153,7 +153,7 @@ namespace Barotrauma ConstructorInfo constructor = t.GetConstructor(new[] { typeof(XElement) }); object instance = constructor.Invoke(new object[] { element }); - previousEvents.Add(i); + //previousEvents.Add(i); return (ScriptedEvent)instance; } diff --git a/Subsurface/Source/GameSession/GameSession.cs b/Subsurface/Source/GameSession/GameSession.cs index 5a515a208..d16c47c3e 100644 --- a/Subsurface/Source/GameSession/GameSession.cs +++ b/Subsurface/Source/GameSession/GameSession.cs @@ -78,15 +78,14 @@ namespace Barotrauma this.submarine = submarine; } - public GameSession(Submarine selectedSub, string saveFile, string filePath) + public GameSession(Submarine selectedSub, string saveFile, XDocument doc) : this(selectedSub, saveFile) { GameMain.GameSession = this; CrewManager = new CrewManager(); - XDocument doc = ToolBox.TryLoadXml(filePath); - if (doc == null) return; + selectedSub.Name = ToolBox.GetAttributeString(doc.Root, "submarine", selectedSub.Name); foreach (XElement subElement in doc.Root.Elements()) { diff --git a/Subsurface/Source/Items/Components/Machines/Steering.cs b/Subsurface/Source/Items/Components/Machines/Steering.cs index 2ae6cf44b..c9e4353e6 100644 --- a/Subsurface/Source/Items/Components/Machines/Steering.cs +++ b/Subsurface/Source/Items/Components/Machines/Steering.cs @@ -17,8 +17,12 @@ namespace Barotrauma.Items.Components private Vector2 currVelocity; private Vector2 targetVelocity; + private GUITickBox maintainPosTickBox; + private bool autoPilot; + private Vector2? posToMaintain; + private SteeringPath steeringPath; private PathFinder pathFinder; @@ -39,6 +43,9 @@ namespace Barotrauma.Items.Components autoPilot = value; + maintainPosTickBox.Enabled = autoPilot; + + if (autoPilot) { if (pathFinder==null) pathFinder = new PathFinder(WayPoint.WayPointList, false); @@ -46,6 +53,11 @@ namespace Barotrauma.Items.Components ConvertUnits.ToSimUnits(item.WorldPosition), ConvertUnits.ToSimUnits(Level.Loaded.EndPosition)); } + else + { + maintainPosTickBox.Selected = false; + posToMaintain = null; + } } } @@ -87,7 +99,6 @@ namespace Barotrauma.Items.Components IsActive = true; var tickBox = new GUITickBox(new Rectangle(0,25,20,20), "Autopilot", Alignment.TopLeft, GuiFrame); - tickBox.OnSelected = (GUITickBox box) => { AutoPilot = box.Selected; @@ -95,6 +106,10 @@ namespace Barotrauma.Items.Components return true; }; + + maintainPosTickBox = new GUITickBox(new Rectangle(0, 50, 20, 20), "Maintain position", Alignment.TopLeft, GuiFrame); + maintainPosTickBox.Enabled = false; + maintainPosTickBox.OnSelected = ToggleMaintainPosition; } public override void Update(float deltaTime, Camera cam) @@ -179,47 +194,95 @@ namespace Barotrauma.Items.Components private void UpdateAutoPilot(float deltaTime) { - autopilotRayCastTimer -= deltaTime; - - steeringPath.CheckProgress(ConvertUnits.ToSimUnits(item.WorldPosition), 10.0f); - - if (autopilotRayCastTimer<=0.0f && steeringPath.NextNode != null) + if (posToMaintain==null) { - Vector2 diff = ConvertUnits.ToSimUnits(steeringPath.NextNode.Position - item.WorldPosition); - bool nextVisible = true; - for (int x = -1; x < 2; x += 2) + autopilotRayCastTimer -= deltaTime; + + steeringPath.CheckProgress(ConvertUnits.ToSimUnits(item.WorldPosition), 10.0f); + + if (autopilotRayCastTimer<=0.0f && steeringPath.NextNode != null) { - for (int y = -1; y < 2; y += 2) + Vector2 diff = Vector2.Normalize(ConvertUnits.ToSimUnits(steeringPath.NextNode.Position - Submarine.Loaded.WorldPosition)); + + bool nextVisible = true; + for (int x = -1; x < 2; x += 2) { - Vector2 cornerPos = - new Vector2(Submarine.Borders.Width * x, Submarine.Borders.Height * y) / 2.0f; + for (int y = -1; y < 2; y += 2) + { + Vector2 cornerPos = + new Vector2(Submarine.Borders.Width * x, Submarine.Borders.Height * y) / 2.0f; - cornerPos = ConvertUnits.ToSimUnits(cornerPos * 1.2f + Submarine.Loaded.Position); + cornerPos = ConvertUnits.ToSimUnits(cornerPos * 1.2f + Submarine.Loaded.WorldPosition); - if (Submarine.PickBody(cornerPos, cornerPos + diff, null, Physics.CollisionLevel) == null) continue; + float dist = Vector2.Distance(cornerPos, steeringPath.NextNode.SimPosition); - nextVisible = false; - x = 2; - y = 2; + if (Submarine.PickBody(cornerPos, cornerPos + diff*dist, null, Physics.CollisionLevel) == null) continue; + + nextVisible = false; + x = 2; + y = 2; + } } + + if (nextVisible) steeringPath.SkipToNextNode(); + + autopilotRayCastTimer = AutopilotRayCastInterval; } - if (nextVisible) steeringPath.SkipToNextNode(); - - autopilotRayCastTimer = AutopilotRayCastInterval; + if (steeringPath.CurrentNode != null) + { + SteerTowardsPosition(steeringPath.CurrentNode.WorldPosition); + } + } + else + { + SteerTowardsPosition((Vector2)posToMaintain); } - if (steeringPath.CurrentNode != null) + } + + private void SteerTowardsPosition(Vector2 worldPosition) + { + float prediction = 10.0f; + + Vector2 futurePosition = ConvertUnits.ToDisplayUnits(item.Submarine.Velocity) * prediction; + Vector2 targetSpeed = ((worldPosition - item.WorldPosition) - futurePosition); + + if (targetSpeed.Length()>500.0f) { - float prediction = 5.0f; - - Vector2 futurePosition = ConvertUnits.ToDisplayUnits(item.Submarine.Velocity) * prediction; - Vector2 targetSpeed = ((steeringPath.CurrentNode.WorldPosition - item.WorldPosition) - futurePosition); - targetSpeed = Vector2.Normalize(targetSpeed); TargetVelocity = targetSpeed * 100.0f; } + else + { + targetVelocity = targetSpeed/5.0f; + } + + + } + + private bool ToggleMaintainPosition(GUITickBox tickBox) + { + item.NewComponentEvent(this, true, true); + + if (tickBox.Selected) + { + if (Submarine.Loaded == null) + { + posToMaintain = null; + } + else + { + posToMaintain = item.WorldPosition; + } + } + else + { + posToMaintain = null; + } + + return true; } public override void ReceiveSignal(string signal, Connection connection, Item sender, float power=0.0f) @@ -236,6 +299,15 @@ namespace Barotrauma.Items.Components message.Write(targetVelocity.Y); message.Write(autoPilot); + if (autoPilot) + { + message.Write(posToMaintain != null); + if (posToMaintain != null) + { + message.Write(((Vector2)posToMaintain).X); + message.Write(((Vector2)posToMaintain).Y); + } + } return true; } @@ -245,10 +317,22 @@ namespace Barotrauma.Items.Components Vector2 newTargetVelocity = Vector2.Zero; bool newAutoPilot = false; + Vector2? newPosToMaintain = null; + try { newTargetVelocity = new Vector2(message.ReadFloat(), message.ReadFloat()); newAutoPilot = message.ReadBoolean(); + if (newAutoPilot) + { + bool maintainPos = message.ReadBoolean(); + if (maintainPos) + { + newPosToMaintain = new Vector2( + message.ReadFloat(), + message.ReadFloat()); + } + } } catch @@ -258,6 +342,9 @@ namespace Barotrauma.Items.Components TargetVelocity = newTargetVelocity; AutoPilot = newAutoPilot; + + maintainPosTickBox.Selected = newPosToMaintain != null; + posToMaintain = newPosToMaintain; } } } diff --git a/Subsurface/Source/Map/Submarine.cs b/Subsurface/Source/Map/Submarine.cs index f2d4859a1..6ef3443e1 100644 --- a/Subsurface/Source/Map/Submarine.cs +++ b/Subsurface/Source/Map/Submarine.cs @@ -55,7 +55,7 @@ namespace Barotrauma public string Name { get { return name; } - //set { name = value; } + set { name = value; } } public static Vector2 LastPickedPosition diff --git a/Subsurface/Source/Map/SubmarineBody.cs b/Subsurface/Source/Map/SubmarineBody.cs index 335fb4265..6e1094c55 100644 --- a/Subsurface/Source/Map/SubmarineBody.cs +++ b/Subsurface/Source/Map/SubmarineBody.cs @@ -468,7 +468,7 @@ namespace Barotrauma Vector2 limbForce = direction * impact * 0.5f; float length = limbForce.Length(); - if (length > 10.0f) limbForce = (limbForce / length) * 10.0f; + if (length > 5.0f) limbForce = (limbForce / length) * 5.0f; foreach (Character c in Character.CharacterList) { diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index f6fdbd56c..143c2e9c8 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -181,14 +181,16 @@ namespace Barotrauma.Networking if (DateTime.Now > timeOut) { restRequestHandle.Abort(); - DebugConsole.ThrowError("Couldn't connect to master server (request timed out)"); - registeredToMaster = false; + DebugConsole.NewMessage("Couldn't connect to master server (request timed out)", Color.Red); + break; + //registeredToMaster = false; } - System.Diagnostics.Debug.WriteLine("took "+sw.ElapsedMilliseconds+" ms"); yield return CoroutineStatus.Running; } + System.Diagnostics.Debug.WriteLine("took "+sw.ElapsedMilliseconds+" ms"); + yield return CoroutineStatus.Success; } @@ -198,15 +200,13 @@ namespace Barotrauma.Networking if (response.ErrorException != null) { - DebugConsole.ThrowError("Error while registering to master server", response.ErrorException); - registeredToMaster = false; + DebugConsole.NewMessage("Error while registering to master server (" + response.ErrorException + ")", Color.Red); return; } if (response.StatusCode != System.Net.HttpStatusCode.OK) { DebugConsole.NewMessage("Error while reporting to master server (" + response.StatusCode + ": " + response.StatusDescription + ")", Color.Red); - //registeredToMaster = false; return; } } @@ -224,10 +224,14 @@ namespace Barotrauma.Networking { inGameHUD.Update((float)Physics.step); - //if all characters dead - if (AutoRestart && + bool isCrewDead = ConnectedClients.Find(c => c.Character != null && !c.Character.IsDead)==null && - (myCharacter == null || myCharacter.IsDead)) + (myCharacter == null || myCharacter.IsDead); + + //restart if all characters are dead or submarine is at the end of the level + if ((AutoRestart && isCrewDead) + || + (endRoundAtLevelEnd && Submarine.Loaded!=null && Submarine.Loaded.AtEndPosition)) { EndButtonHit(null, null); UpdateNetLobby(null,null); @@ -284,7 +288,7 @@ namespace Barotrauma.Networking { if (gameStarted) { - if (myCharacter != null) new NetworkEvent(NetworkEventType.EntityUpdate, myCharacter.ID, false); + if (myCharacter != null && !myCharacter.IsDead) new NetworkEvent(NetworkEventType.EntityUpdate, myCharacter.ID, false); foreach (Character c in Character.CharacterList) { diff --git a/Subsurface/Source/Networking/GameServerSettings.cs b/Subsurface/Source/Networking/GameServerSettings.cs index 5c5d76964..3daeadaa9 100644 --- a/Subsurface/Source/Networking/GameServerSettings.cs +++ b/Subsurface/Source/Networking/GameServerSettings.cs @@ -20,7 +20,7 @@ namespace Barotrauma.Networking { public bool ShowNetStats; - private TimeSpan refreshMasterInterval = new TimeSpan(0, 0, 40); + private TimeSpan refreshMasterInterval = new TimeSpan(0, 0, 30); private TimeSpan sparseUpdateInterval = new TimeSpan(0, 0, 0, 3); private SelectionMode subSelectionMode, modeSelectionMode; @@ -41,6 +41,8 @@ namespace Barotrauma.Networking private bool allowSpectating = true; + private bool endRoundAtLevelEnd = true; + public bool AutoRestart { get { return (ConnectedClients.Count == 0) ? false : autoRestart; } @@ -85,16 +87,22 @@ namespace Barotrauma.Networking private void CreateSettingsFrame() { - settingsFrame = new GUIFrame(new Rectangle(0,0,GameMain.GraphicsWidth,GameMain.GraphicsHeight), Color.Black*0.5f); + settingsFrame = new GUIFrame(new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.Black * 0.5f); - GUIFrame innerFrame = new GUIFrame(new Rectangle(0,0,400,400), null, Alignment.Center, GUI.Style, settingsFrame); + GUIFrame innerFrame = new GUIFrame(new Rectangle(0, 0, 400, 400), null, Alignment.Center, GUI.Style, settingsFrame); - var randomizeLevelBox = new GUITickBox(new Rectangle(0, 0, 20, 20), "Randomize level seed", Alignment.Left, innerFrame); + new GUITextBlock(new Rectangle(0, -15, 0, 20), "Server settings", GUI.Style, innerFrame, GUI.LargeFont); + + var randomizeLevelBox = new GUITickBox(new Rectangle(0, 30, 20, 20), "Randomize level seed", Alignment.Left, innerFrame); randomizeLevelBox.Selected = randomizeSeed; randomizeLevelBox.OnSelected = ToggleRandomizeSeed; + + var endBox = new GUITickBox(new Rectangle(0, 60, 20, 20), "End round when destination reached", Alignment.Left, innerFrame); + endBox.Selected = endRoundAtLevelEnd; + endBox.OnSelected = (GUITickBox) => { endRoundAtLevelEnd = GUITickBox.Selected; return true; }; - new GUITextBlock(new Rectangle(0, 35, 100, 20), "Submarine selection:", GUI.Style, innerFrame); - var selectionFrame = new GUIFrame(new Rectangle(0, 60, 300, 20), null, innerFrame); + new GUITextBlock(new Rectangle(0, 95, 100, 20), "Submarine selection:", GUI.Style, innerFrame); + var selectionFrame = new GUIFrame(new Rectangle(0, 120, 300, 20), null, innerFrame); for (int i = 0; i<3; i++) { var selectionTick = new GUITickBox(new Rectangle(i * 100, 0, 20, 20), ((SelectionMode)i).ToString(), Alignment.Left, selectionFrame); @@ -103,8 +111,8 @@ namespace Barotrauma.Networking selectionTick.UserData = (SelectionMode)i; } - new GUITextBlock(new Rectangle(0, 85, 100, 20), "Mode selection:", GUI.Style, innerFrame); - selectionFrame = new GUIFrame(new Rectangle(0, 110, 300, 20), null, innerFrame); + new GUITextBlock(new Rectangle(0, 145, 100, 20), "Mode selection:", GUI.Style, innerFrame); + selectionFrame = new GUIFrame(new Rectangle(0, 170, 300, 20), null, innerFrame); for (int i = 0; i<3; i++) { var selectionTick = new GUITickBox(new Rectangle(i*100, 0, 20, 20), ((SelectionMode)i).ToString(), Alignment.Left, selectionFrame); @@ -113,7 +121,7 @@ namespace Barotrauma.Networking selectionTick.UserData = (SelectionMode)i; } - var allowSpecBox = new GUITickBox(new Rectangle(0, 150, 20, 20), "Allow spectating", Alignment.Left, innerFrame); + var allowSpecBox = new GUITickBox(new Rectangle(0, 210, 20, 20), "Allow spectating", Alignment.Left, innerFrame); allowSpecBox.Selected = true; allowSpecBox.OnSelected = ToggleAllowSpectating; diff --git a/Subsurface/Source/Screens/EditMapScreen.cs b/Subsurface/Source/Screens/EditMapScreen.cs index b34b2255a..b0b02e5a1 100644 --- a/Subsurface/Source/Screens/EditMapScreen.cs +++ b/Subsurface/Source/Screens/EditMapScreen.cs @@ -292,7 +292,13 @@ namespace Barotrauma selectedTab = (int)obj; return true; } - + + + public void ToggleCharacterMode() + { + ToggleCharacterMode(null,null); + } + private bool ToggleCharacterMode(GUIButton button, object obj) { selectedTab = -1; @@ -397,28 +403,30 @@ namespace Barotrauma if (characterMode) { - if (Entity.FindEntityByID(dummyCharacter.ID)!=dummyCharacter) + if (dummyCharacter == null || Entity.FindEntityByID(dummyCharacter.ID)!=dummyCharacter) { ToggleCharacterMode(null, null); } - - foreach (MapEntity me in MapEntity.mapEntityList) + else { - me.IsHighlighted = false; - } - - if (dummyCharacter.SelectedConstruction==null) - { - Vector2 mouseSimPos = FarseerPhysics.ConvertUnits.ToSimUnits(dummyCharacter.CursorPosition); - foreach (Limb limb in dummyCharacter.AnimController.Limbs) + foreach (MapEntity me in MapEntity.mapEntityList) { - limb.body.SetTransform(mouseSimPos, 0.0f); + me.IsHighlighted = false; } - } - dummyCharacter.ControlLocalPlayer((float)deltaTime, cam, false); - dummyCharacter.Control((float)deltaTime, cam); - cam.TargetPos = Vector2.Zero; + if (dummyCharacter.SelectedConstruction==null) + { + Vector2 mouseSimPos = FarseerPhysics.ConvertUnits.ToSimUnits(dummyCharacter.CursorPosition); + foreach (Limb limb in dummyCharacter.AnimController.Limbs) + { + limb.body.SetTransform(mouseSimPos, 0.0f); + } + } + + dummyCharacter.ControlLocalPlayer((float)deltaTime, cam, false); + dummyCharacter.Control((float)deltaTime, cam); + cam.TargetPos = Vector2.Zero; + } } else { diff --git a/Subsurface/Source/Screens/MainMenuScreen.cs b/Subsurface/Source/Screens/MainMenuScreen.cs index 547c6382a..49e649c3f 100644 --- a/Subsurface/Source/Screens/MainMenuScreen.cs +++ b/Subsurface/Source/Screens/MainMenuScreen.cs @@ -480,9 +480,9 @@ namespace Barotrauma Directory.CreateDirectory(SaveUtil.TempPath); } - File.Copy(selectedSub.FilePath, Path.Combine(SaveUtil.TempPath, "map.sub"), true); + File.Copy(selectedSub.FilePath, Path.Combine(SaveUtil.TempPath, selectedSub.Name+".sub"), true); - selectedSub = new Submarine(Path.Combine(SaveUtil.TempPath, "map.sub"), ""); + selectedSub = new Submarine(Path.Combine(SaveUtil.TempPath, selectedSub.Name + ".sub"), ""); GameMain.GameSession = new GameSession(selectedSub, saveNameBox.Text, GameModePreset.list.Find(gm => gm.Name == "Single Player")); (GameMain.GameSession.gameMode as SinglePlayerMode).GenerateMap(seedBox.Text); @@ -515,7 +515,7 @@ namespace Barotrauma } catch (Exception e) { - DebugConsole.ThrowError("Loading map ''"+saveFile+"'' failed", e); + DebugConsole.ThrowError("Loading save ''"+saveFile+"'' failed", e); return false; } diff --git a/Subsurface/Source/Utils/SaveUtil.cs b/Subsurface/Source/Utils/SaveUtil.cs index dda2aa11a..7f4990037 100644 --- a/Subsurface/Source/Utils/SaveUtil.cs +++ b/Subsurface/Source/Utils/SaveUtil.cs @@ -25,30 +25,16 @@ namespace Barotrauma string tempPath = Path.Combine(SaveFolder, "temp"); - //if (Directory.Exists(tempPath)) - //{ - // Directory.Delete(tempPath, true); - //} - if (!Directory.Exists(tempPath)) { - // DecompressToDirectory(fileName, tempPath, null); - //} - //else - //{ Directory.CreateDirectory(tempPath); } - - - // - //Directory.CreateDirectory(Path.GetDirectoryName(filePath) + "\\temp"); - try { - if (Submarine.Loaded!=null) + if (Submarine.Loaded != null) { - Submarine.Loaded.SaveAs(Path.Combine(tempPath, "map.sub")); + Submarine.Loaded.SaveAs(Path.Combine(tempPath, Submarine.Loaded.Name+".sub")); } } catch (Exception e) @@ -83,8 +69,11 @@ namespace Barotrauma DecompressToDirectory(filePath, TempPath, null); - Submarine selectedMap = new Submarine(Path.Combine(TempPath, "map.sub"), "");// Submarine.Load(); - GameMain.GameSession = new GameSession(selectedMap, fileName, Path.Combine(TempPath, "gamesession.xml")); + XDocument doc = ToolBox.TryLoadXml(Path.Combine(TempPath, "gamesession.xml")); + + string subPath = Path.Combine(TempPath, ToolBox.GetAttributeString(doc.Root, "submarine", "")); + Submarine selectedMap = new Submarine(subPath, "");// Submarine.Load(); + GameMain.GameSession = new GameSession(selectedMap, fileName, doc); //Directory.Delete(tempPath, true); } diff --git a/Subsurface/Source/Utils/UpdaterUtil.cs b/Subsurface/Source/Utils/UpdaterUtil.cs index 97f11f4e0..41eb8c3a0 100644 --- a/Subsurface/Source/Utils/UpdaterUtil.cs +++ b/Subsurface/Source/Utils/UpdaterUtil.cs @@ -174,7 +174,7 @@ namespace Barotrauma string relativePath = GetRelativePath(file, currentDir); string dirRoot = relativePath.Split(Path.DirectorySeparatorChar).First(); - if (dirRoot == "Data") continue; + if (dirRoot != "Content" && dirRoot != "") continue; if (filesToKeep.Contains(relativePath)) continue; diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index 522cba9625d66f762ebebf79dccc069fe5eac0ae..75965e6de37897662f7c5f52493015c609ae3ab0 100644 GIT binary patch delta 17472 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