diff --git a/.gitignore b/.gitignore
index ee3a6b563..caabdf211 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,7 @@ bld/
[Oo]bj/
*.v12.suo
+*.suo
#performance reports & sessions
*.vsp
diff --git a/.vs/Subsurface_Solution/v14/.suo b/.vs/Subsurface_Solution/v14/.suo
index 195ff13d2..188fc21d5 100644
Binary files a/.vs/Subsurface_Solution/v14/.suo and b/.vs/Subsurface_Solution/v14/.suo differ
diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj
index 68a2ac24e..44af133a5 100644
--- a/Subsurface/Barotrauma.csproj
+++ b/Subsurface/Barotrauma.csproj
@@ -118,6 +118,7 @@
+
@@ -143,6 +144,7 @@
+
@@ -152,6 +154,7 @@
+
@@ -491,6 +494,12 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest
@@ -1086,6 +1095,12 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest
diff --git a/Subsurface/Content/Items/Door/dockingport.png b/Subsurface/Content/Items/Door/dockingport.png
new file mode 100644
index 000000000..6538ddf08
Binary files /dev/null and b/Subsurface/Content/Items/Door/dockingport.png differ
diff --git a/Subsurface/Content/Items/Door/dockingport1.ogg b/Subsurface/Content/Items/Door/dockingport1.ogg
new file mode 100644
index 000000000..3d9aea42e
Binary files /dev/null and b/Subsurface/Content/Items/Door/dockingport1.ogg differ
diff --git a/Subsurface/Content/Items/Door/dockingport2.ogg b/Subsurface/Content/Items/Door/dockingport2.ogg
new file mode 100644
index 000000000..8795bf1fb
Binary files /dev/null and b/Subsurface/Content/Items/Door/dockingport2.ogg differ
diff --git a/Subsurface/Content/Items/Door/dockingport2.png b/Subsurface/Content/Items/Door/dockingport2.png
new file mode 100644
index 000000000..2862aaf62
Binary files /dev/null and b/Subsurface/Content/Items/Door/dockingport2.png differ
diff --git a/Subsurface/Content/Items/Door/doors.xml b/Subsurface/Content/Items/Door/doors.xml
index e628549ff..3b709c5e1 100644
--- a/Subsurface/Content/Items/Door/doors.xml
+++ b/Subsurface/Content/Items/Door/doors.xml
@@ -82,4 +82,58 @@
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Subsurface/Content/Items/Engine/engine.png b/Subsurface/Content/Items/Engine/engine.png
index ff3ed0c09..a99150aa1 100644
Binary files a/Subsurface/Content/Items/Engine/engine.png and b/Subsurface/Content/Items/Engine/engine.png differ
diff --git a/Subsurface/Content/Items/Engine/engine.xml b/Subsurface/Content/Items/Engine/engine.xml
index 51a20b46b..c7739754e 100644
--- a/Subsurface/Content/Items/Engine/engine.xml
+++ b/Subsurface/Content/Items/Engine/engine.xml
@@ -8,7 +8,7 @@
pickthroughwalls="true"
pickdistance="150">
-
+
@@ -29,6 +29,34 @@
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
+
@@ -100,8 +98,7 @@
-
-
+
diff --git a/Subsurface/Source/Camera.cs b/Subsurface/Source/Camera.cs
index 0c48b5ecc..7a3ab5361 100644
--- a/Subsurface/Source/Camera.cs
+++ b/Subsurface/Source/Camera.cs
@@ -1,6 +1,7 @@
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
+using System.Linq;
namespace Barotrauma
{
@@ -124,10 +125,10 @@ namespace Barotrauma
public void Translate(Vector2 amount)
{
position += amount;
- //UpdateTransform();
+
}
- public void UpdateTransform(bool interpolate = true)
+ public void UpdateTransform(bool interpolate = true, bool clampPos = false)
{
Vector2 interpolatedPosition = interpolate ? Physics.Interpolate(prevPosition, position) : position;
@@ -136,6 +137,13 @@ namespace Barotrauma
worldView.X = (int)(interpolatedPosition.X - worldView.Width / 2.0);
worldView.Y = (int)(interpolatedPosition.Y + worldView.Height / 2.0);
+
+ if (Level.Loaded != null && clampPos)
+ {
+ position.Y -= Math.Max(worldView.Y - Level.Loaded.Size.Y, 0.0f);
+ interpolatedPosition.Y -= Math.Max(worldView.Y - Level.Loaded.Size.Y, 0.0f);
+ }
+
transform = Matrix.CreateTranslation(
new Vector3(-interpolatedPosition.X, interpolatedPosition.Y, 0)) *
Matrix.CreateScale(new Vector3(interpolatedZoom, interpolatedZoom, 1)) *
@@ -178,9 +186,13 @@ namespace Barotrauma
if (GameMain.Config.KeyBind(InputType.Up).IsDown()) moveCam.Y += moveSpeed;
}
- if (Submarine.Loaded!=null && Screen.Selected == GameMain.GameScreen)
+ if (Screen.Selected == GameMain.GameScreen)
{
- moveCam += FarseerPhysics.ConvertUnits.ToDisplayUnits(Submarine.Loaded.Velocity*deltaTime);
+ var closestSub = Submarine.GetClosest(WorldViewCenter);
+ if (closestSub != null)
+ {
+ moveCam += FarseerPhysics.ConvertUnits.ToDisplayUnits(closestSub.Velocity * deltaTime);
+ }
}
moveCam = moveCam * deltaTime * 60.0f;
@@ -205,14 +217,14 @@ namespace Barotrauma
Vector2 diff = (targetPos + offset) - position;
- moveCam = diff / MoveSmoothness;
+ moveCam = diff / MoveSmoothness;
}
shakeTargetPosition = Rand.Vector(Shake);
shakePosition = Vector2.Lerp(shakePosition, shakeTargetPosition, 0.5f);
- Shake = MathHelper.Lerp(Shake, 0.0f, deltaTime*2.0f);
+ Shake = MathHelper.Lerp(Shake, 0.0f, deltaTime * 2.0f);
- Translate(moveCam+shakePosition);
+ Translate(moveCam + shakePosition);
}
public Vector2 Position
diff --git a/Subsurface/Source/Characters/AI/HumanAIController.cs b/Subsurface/Source/Characters/AI/HumanAIController.cs
index fe14ee52d..89b4cf85a 100644
--- a/Subsurface/Source/Characters/AI/HumanAIController.cs
+++ b/Subsurface/Source/Characters/AI/HumanAIController.cs
@@ -164,15 +164,15 @@ namespace Barotrauma
GUI.DrawLine(spriteBatch,
new Vector2(Character.WorldPosition.X, -Character.WorldPosition.Y),
- new Vector2(pathSteering.CurrentPath.CurrentNode.Position.X+Submarine.Loaded.Position.X, -(pathSteering.CurrentPath.CurrentNode.Position.Y+Submarine.Loaded.Position.Y)),
+ new Vector2(pathSteering.CurrentPath.CurrentNode.WorldPosition.X, -pathSteering.CurrentPath.CurrentNode.WorldPosition.Y),
Color.LightGreen);
for (int i = 1; i < pathSteering.CurrentPath.Nodes.Count; i++)
{
GUI.DrawLine(spriteBatch,
- new Vector2(pathSteering.CurrentPath.Nodes[i].Position.X + Submarine.Loaded.Position.X, -(pathSteering.CurrentPath.Nodes[i].Position.Y + Submarine.Loaded.Position.Y)),
- new Vector2(pathSteering.CurrentPath.Nodes[i - 1].Position.X + Submarine.Loaded.Position.X, -(pathSteering.CurrentPath.Nodes[i-1].Position.Y + Submarine.Loaded.Position.Y)),
+ new Vector2(pathSteering.CurrentPath.Nodes[i].WorldPosition.X, -pathSteering.CurrentPath.Nodes[i].WorldPosition.Y),
+ new Vector2(pathSteering.CurrentPath.Nodes[i - 1].WorldPosition.Y, -pathSteering.CurrentPath.Nodes[i-1].WorldPosition.Y),
Color.LightGreen);
}
}
diff --git a/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs b/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs
index f84ef8287..872c6b697 100644
--- a/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs
+++ b/Subsurface/Source/Characters/AI/IndoorsSteeringManager.cs
@@ -76,9 +76,13 @@ namespace Barotrauma
currentTarget = target;
Vector2 pos = host.SimPosition;
- if (character!=null && character.Submarine==null)
+ if (character != null && character.Submarine == null)
{
- pos -= Submarine.Loaded.SimPosition;
+ var targetHull = Hull.FindHull(FarseerPhysics.ConvertUnits.ToDisplayUnits(target), null, false);
+ if (targetHull!=null && targetHull.Submarine != null)
+ {
+ pos -= targetHull.SimPosition;
+ }
}
currentPath = pathFinder.FindPath(pos, target);
@@ -99,15 +103,15 @@ namespace Barotrauma
private Vector2 DiffToCurrentNode()
{
- if (currentPath == null) return Vector2.Zero;
+ if (currentPath == null || currentPath.Finished) return Vector2.Zero;
- if (currentPath.CurrentIndex == currentPath.Nodes.Count)
+ if (currentPath.Finished)
{
-
Vector2 pos2 = host.SimPosition;
- if (character != null && character.Submarine == null)
+ if (character != null && character.Submarine == null && CurrentPath.Nodes.Last().Submarine != null)
{
- pos2 -= Submarine.Loaded.SimPosition;
+ //todo: take multiple subs into account
+ pos2 -= CurrentPath.Nodes.Last().Submarine.SimPosition;
}
return currentTarget-pos2;
}
@@ -118,9 +122,11 @@ namespace Barotrauma
if (currentPath.CurrentNode!=null && currentPath.CurrentNode.SimPosition.Y > character.SimPosition.Y+1.0f) allowedDistance*=0.5f;
Vector2 pos = host.SimPosition;
- if (character != null && character.Submarine == null)
+ if (character != null && character.Submarine == null &&
+ CurrentPath.CurrentNode != null && CurrentPath.CurrentNode.Submarine != null)
{
- pos -= Submarine.Loaded.SimPosition;
+ //todo: take multiple subs into account
+ pos -= CurrentPath.CurrentNode.Submarine.SimPosition;
}
if (currentPath.CurrentNode!= null && currentPath.CurrentNode.Ladders!=null)
diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs
index 2c1e84ce5..bdb54cf88 100644
--- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs
+++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveGoTo.cs
@@ -89,7 +89,7 @@ namespace Barotrauma
}
else if (target.Submarine == null)
{
- currTargetPos -= Submarine.Loaded.SimPosition;
+ currTargetPos -= character.Submarine.SimPosition;
}
}
diff --git a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveIdle.cs b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveIdle.cs
index fe7275824..559c70ac9 100644
--- a/Subsurface/Source/Characters/AI/Objectives/AIObjectiveIdle.cs
+++ b/Subsurface/Source/Characters/AI/Objectives/AIObjectiveIdle.cs
@@ -41,7 +41,7 @@ namespace Barotrauma
if (currentTarget != null)
{
Vector2 pos = character.SimPosition;
- if (character != null && character.Submarine == null) pos -= Submarine.Loaded.SimPosition;
+ if (character != null && character.Submarine == null) pos -= Submarine.MainSub.SimPosition;
var path = pathSteering.PathFinder.FindPath(pos, currentTarget.SimPosition);
if (path.Cost > 200.0f && character.AnimController.CurrentHull!=null) return;
diff --git a/Subsurface/Source/Characters/AI/SteeringPath.cs b/Subsurface/Source/Characters/AI/SteeringPath.cs
index 671421195..2a98ac366 100644
--- a/Subsurface/Source/Characters/AI/SteeringPath.cs
+++ b/Subsurface/Source/Characters/AI/SteeringPath.cs
@@ -70,6 +70,11 @@ namespace Barotrauma
}
}
+ public bool Finished
+ {
+ get { return currentIndex >= nodes.Count; }
+ }
+
public void SkipToNextNode()
{
currentIndex++;
diff --git a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs
index f1e758669..af711d721 100644
--- a/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs
+++ b/Subsurface/Source/Characters/Animation/HumanoidAnimController.cs
@@ -734,6 +734,10 @@ namespace Barotrauma
{
ladderSimPos += character.SelectedConstruction.Submarine.SimPosition;
}
+ else if (currentHull.Submarine != null && currentHull.Submarine != character.SelectedConstruction.Submarine)
+ {
+ ladderSimPos += character.SelectedConstruction.Submarine.SimPosition - currentHull.Submarine.SimPosition;
+ }
MoveLimb(head, new Vector2(ladderSimPos.X - 0.27f * Dir, head.SimPosition.Y + 0.05f), 10.5f);
MoveLimb(torso, new Vector2(ladderSimPos.X - 0.27f * Dir, torso.SimPosition.Y), 10.5f);
@@ -742,7 +746,9 @@ namespace Barotrauma
Vector2 handPos = new Vector2(
ladderSimPos.X,
- head.SimPosition.Y + 0.0f + movement.Y * 0.1f - ladderSimPos.Y);
+ head.SimPosition.Y + movement.Y * 0.1f - ladderSimPos.Y);
+
+ handPos.Y = Math.Min(-0.5f, handPos.Y);
MoveLimb(leftHand,
new Vector2(handPos.X,
diff --git a/Subsurface/Source/Characters/Animation/Ragdoll.cs b/Subsurface/Source/Characters/Animation/Ragdoll.cs
index 769d44ca9..25f020050 100644
--- a/Subsurface/Source/Characters/Animation/Ragdoll.cs
+++ b/Subsurface/Source/Characters/Animation/Ragdoll.cs
@@ -572,6 +572,7 @@ namespace Barotrauma
if (setSubmarine)
{
+ //in -> out
if (newHull == null && currentHull.Submarine != null)
{
for (int i = -1; i < 2; i += 2)
@@ -584,17 +585,23 @@ namespace Barotrauma
if (Gap.FindAdjacent(currentHull.ConnectedGaps, findPos, 150.0f) != null) return;
Teleport(ConvertUnits.ToSimUnits(currentHull.Submarine.Position), currentHull.Submarine.Velocity, true);
-
}
+ //out -> in
else if (currentHull == null && newHull.Submarine != null)
{
Teleport(-ConvertUnits.ToSimUnits(newHull.Submarine.Position), -newHull.Submarine.Velocity, false);
}
+ //from one sub to another
+ else if (newHull != null && currentHull != null && newHull.Submarine != currentHull.Submarine)
+ {
+ Teleport(ConvertUnits.ToSimUnits(currentHull.Submarine.Position - newHull.Submarine.Position),
+ Vector2.Zero, false);
+ }
}
CurrentHull = newHull;
- character.Submarine = CurrentHull == null ? null : Submarine.Loaded;
+ character.Submarine = currentHull == null ? null : currentHull.Submarine;
UpdateCollisionCategories();
}
@@ -609,20 +616,7 @@ namespace Barotrauma
while (ce != null && ce.Contact != null)
{
ce.Contact.Enabled = false;
- //if (ce.Contact.IsTouching && ce.Contact.Enabled &&
- // ((inToOut && ce.Contact.FixtureA.Body.UserData is Structure) || (!inToOut && ce.Contact.FixtureA.Body.UserData is Submarine)))
- //{
- // Vector2 normal;
- // FarseerPhysics.Common.FixedArray2 worldPoints;
- // ce.Contact.GetWorldManifold(out normal, out worldPoints);
- // foreach (Limb limb2 in Limbs)
- // {
- // limb2.body.FarseerBody.ApplyLinearImpulse(limb2.Mass * normal);
- // }
-
- // return false;
- //}
ce = ce.Next;
}
}
@@ -632,7 +626,7 @@ namespace Barotrauma
limb.body.LinearVelocity += velocityChange;
}
- character.Stun = 0.1f;
+ //character.Stun = 0.1f;
character.DisableImpactDamageTimer = 0.25f;
SetPosition(refLimb.SimPosition + moveAmount);
diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs
index aa6d60c8f..995f9ecaa 100644
--- a/Subsurface/Source/Characters/Character.cs
+++ b/Subsurface/Source/Characters/Character.cs
@@ -855,7 +855,10 @@ namespace Barotrauma
}
cursorPosition = cam.ScreenToWorld(PlayerInput.MousePosition);
- if (AnimController.CurrentHull != null) cursorPosition -= Submarine.Loaded.Position;
+ if (AnimController.CurrentHull != null && AnimController.CurrentHull.Submarine != null)
+ {
+ cursorPosition -= AnimController.CurrentHull.Submarine.Position;
+ }
Vector2 mouseSimPos = ConvertUnits.ToSimUnits(cursorPosition);
@@ -1006,12 +1009,9 @@ namespace Barotrauma
if (needsAir)
{
bool protectedFromPressure = PressureProtection > 0.0f;
-
- if (Submarine.Loaded != null && Level.Loaded != null)
- {
- protectedFromPressure = protectedFromPressure && WorldPosition.Y > SubmarineBody.DamageDepth;
- }
+ protectedFromPressure = protectedFromPressure && WorldPosition.Y > SubmarineBody.DamageDepth;
+
if (!protectedFromPressure &&
(AnimController.CurrentHull == null || AnimController.CurrentHull.LethalPressure >= 80.0f))
{
diff --git a/Subsurface/Source/Characters/Limb.cs b/Subsurface/Source/Characters/Limb.cs
index 2a77e3192..049c30f8d 100644
--- a/Subsurface/Source/Characters/Limb.cs
+++ b/Subsurface/Source/Characters/Limb.cs
@@ -428,7 +428,7 @@ namespace Barotrauma
{
if (LightSource != null)
{
- LightSource.Submarine = body.Submarine;
+ LightSource.ParentSub = body.Submarine;
LightSource.Position = Position;
}
diff --git a/Subsurface/Source/CoroutineManager.cs b/Subsurface/Source/CoroutineManager.cs
index 7d9187e9c..a6b9929d5 100644
--- a/Subsurface/Source/CoroutineManager.cs
+++ b/Subsurface/Source/CoroutineManager.cs
@@ -86,21 +86,21 @@ namespace Barotrauma
}
}
- try
- {
+ //try
+ //{
Coroutines[i].Coroutine.MoveNext();
- }
+ //}
- catch (Exception e)
- {
- DebugConsole.ThrowError("Coroutine " + Coroutines[i].Name + " threw an exception: " + e.Message);
+ //catch (Exception e)
+ //{
+ // DebugConsole.ThrowError("Coroutine " + Coroutines[i].Name + " threw an exception: " + e.Message);
-#if DEBUG
- throw e;
-#endif
+//#if DEBUG
+// throw e;
+//#endif
- Coroutines.RemoveAt(i);
- }
+// Coroutines.RemoveAt(i);
+// }
}
}
diff --git a/Subsurface/Source/DebugConsole.cs b/Subsurface/Source/DebugConsole.cs
index d6d5ffd54..76ccb4097 100644
--- a/Subsurface/Source/DebugConsole.cs
+++ b/Subsurface/Source/DebugConsole.cs
@@ -213,8 +213,6 @@ namespace Barotrauma
break;
case "near":
case "close":
- if (Submarine.Loaded == null) break;
-
float closestDist = 0.0f;
foreach (WayPoint wp in WayPoint.WayPointList)
{
@@ -223,7 +221,7 @@ namespace Barotrauma
//don't spawn inside hulls
if (Hull.FindHull(wp.WorldPosition, null) != null) continue;
- float dist = Vector2.Distance(wp.WorldPosition, Submarine.Loaded.WorldPosition);
+ float dist = Vector2.Distance(wp.WorldPosition, GameMain.GameScreen.Cam.WorldViewCenter);
if (spawnPoint == null || dist < closestDist)
{
@@ -298,12 +296,12 @@ namespace Barotrauma
case "edit":
if (commands.Length>1)
{
- Submarine.Load(string.Join(" ", commands.Skip(1)));
+ Submarine.Load(string.Join(" ", commands.Skip(1)), true);
}
GameMain.EditMapScreen.Select();
break;
case "test":
- Submarine.Load("aegir mark ii");
+ Submarine.Load("aegir mark ii", true);
GameMain.DebugDraw = true;
GameMain.LightManager.LosEnabled = false;
GameMain.EditMapScreen.Select();
@@ -319,7 +317,9 @@ namespace Barotrauma
Character.Controlled = Character.CharacterList.Find(c => !c.IsNetworkPlayer && c.Name.ToLowerInvariant() == commands[1]);
break;
case "godmode":
- Submarine.Loaded.GodMode = !Submarine.Loaded.GodMode;
+ if (Submarine.MainSub == null) return;
+
+ Submarine.MainSub.GodMode = !Submarine.MainSub.GodMode;
break;
case "dumpids":
int count = commands.Length < 2 ? 10 : int.Parse(commands[1]);
@@ -438,8 +438,11 @@ namespace Barotrauma
return;
}
- if (Submarine.SaveCurrent(System.IO.Path.Combine(Submarine.SavePath, fileName +".sub"))) NewMessage("map saved", Color.Green);
- Submarine.Loaded.CheckForErrors();
+ if (Submarine.SaveCurrent(System.IO.Path.Combine(Submarine.SavePath, fileName + ".sub")))
+ {
+ NewMessage("Sub saved", Color.Green);
+ //Submarine.Loaded.First().CheckForErrors();
+ }
break;
case "loadmap":
@@ -447,10 +450,10 @@ namespace Barotrauma
case "load":
if (commands.Length < 2) break;
- Submarine.Load(string.Join(" ", commands.Skip(1)));
+ Submarine.Load(string.Join(" ", commands.Skip(1)), true);
break;
case "cleansub":
- for (int i = MapEntity.mapEntityList.Count-1; i>=0; i--)
+ for (int i = MapEntity.mapEntityList.Count - 1; i >= 0; i--)
{
MapEntity me = MapEntity.mapEntityList[i];
diff --git a/Subsurface/Source/Events/ArtifactEvent.cs b/Subsurface/Source/Events/ArtifactEvent.cs
index eec8653d0..2ce06c449 100644
--- a/Subsurface/Source/Events/ArtifactEvent.cs
+++ b/Subsurface/Source/Events/ArtifactEvent.cs
@@ -55,7 +55,7 @@ namespace Barotrauma
state = 2;
break;
case 2:
- if (!Submarine.Loaded.AtEndPosition && !Submarine.Loaded.AtStartPosition) return;
+ if (!Submarine.MainSub.AtEndPosition && !Submarine.MainSub.AtStartPosition) return;
Finished();
state = 3;
diff --git a/Subsurface/Source/Events/Missions/CargoMission.cs b/Subsurface/Source/Events/Missions/CargoMission.cs
index 27bb8dbe8..17002449c 100644
--- a/Subsurface/Source/Events/Missions/CargoMission.cs
+++ b/Subsurface/Source/Events/Missions/CargoMission.cs
@@ -96,7 +96,7 @@ namespace Barotrauma
public override void End()
{
- if (Submarine.Loaded != null && Submarine.Loaded.AtEndPosition)
+ if (Submarine.MainSub != null && Submarine.MainSub.AtEndPosition)
{
int deliveredItemCount = items.Count(i => i.CurrentHull != null && i.Condition > 0.0f);
diff --git a/Subsurface/Source/Events/Missions/MonsterMission.cs b/Subsurface/Source/Events/Missions/MonsterMission.cs
index afab51956..503febcaa 100644
--- a/Subsurface/Source/Events/Missions/MonsterMission.cs
+++ b/Subsurface/Source/Events/Missions/MonsterMission.cs
@@ -44,7 +44,7 @@ namespace Barotrauma
radarPosition = monster.Position;
}
else if (GameMain.Client == null)
- { Vector2 diff = monster.WorldPosition-Submarine.Loaded.WorldPosition;
+ { Vector2 diff = monster.WorldPosition - Submarine.MainSub.WorldPosition;
monster.Enabled = FarseerPhysics.ConvertUnits.ToSimUnits(diff.Length()) < NetConfig.CharacterIgnoreDistance;
}
diff --git a/Subsurface/Source/Events/Missions/SalvageMission.cs b/Subsurface/Source/Events/Missions/SalvageMission.cs
index b418cd62e..e0309ea79 100644
--- a/Subsurface/Source/Events/Missions/SalvageMission.cs
+++ b/Subsurface/Source/Events/Missions/SalvageMission.cs
@@ -69,7 +69,7 @@ namespace Barotrauma
state = 1;
break;
case 1:
- if (!Submarine.Loaded.AtEndPosition && !Submarine.Loaded.AtStartPosition) return;
+ if (!Submarine.MainSub.AtEndPosition && !Submarine.MainSub.AtStartPosition) return;
ShowMessage(state);
state = 2;
break;
diff --git a/Subsurface/Source/Events/MonsterEvent.cs b/Subsurface/Source/Events/MonsterEvent.cs
index 1bd0e6eaa..7162c7937 100644
--- a/Subsurface/Source/Events/MonsterEvent.cs
+++ b/Subsurface/Source/Events/MonsterEvent.cs
@@ -83,7 +83,7 @@ namespace Barotrauma
{
if (monster.IsDead) continue;
- if (!isStarted && Vector2.Distance(monster.WorldPosition, Submarine.Loaded.WorldPosition) < 5000.0f) isStarted = true;
+ if (!isStarted && Vector2.Distance(monster.WorldPosition, Submarine.MainSub.WorldPosition) < 5000.0f) isStarted = true;
monstersDead = false;
break;
diff --git a/Subsurface/Source/GUI/GUI.cs b/Subsurface/Source/GUI/GUI.cs
index 64b67e19d..eed1cbe28 100644
--- a/Subsurface/Source/GUI/GUI.cs
+++ b/Subsurface/Source/GUI/GUI.cs
@@ -414,10 +414,10 @@ namespace Barotrauma
"Camera pos: " + GameMain.GameScreen.Cam.Position.ToPoint(),
new Vector2(10, 40), Color.White);
- if (Submarine.Loaded != null)
+ if (Submarine.MainSub != null)
{
spriteBatch.DrawString(SmallFont,
- "Sub pos: " + Submarine.Loaded.Position.ToPoint(),
+ "Sub pos: " + Submarine.MainSub.Position.ToPoint(),
new Vector2(10, 50), Color.White);
}
}
diff --git a/Subsurface/Source/GUI/GUIDropDown.cs b/Subsurface/Source/GUI/GUIDropDown.cs
index 01fd79766..a6bd02787 100644
--- a/Subsurface/Source/GUI/GUIDropDown.cs
+++ b/Subsurface/Source/GUI/GUIDropDown.cs
@@ -34,7 +34,7 @@ namespace Barotrauma
if (parent != null) parent.AddChild(this);
- button = new GUIButton(Rectangle.Empty, "", Color.White, Alignment.TopLeft, Alignment.TopLeft, null, this);
+ button = new GUIButton(Rectangle.Empty, text, Color.White, Alignment.TopLeft, Alignment.TopLeft, null, this);
button.TextColor = Color.White;
button.Color = Color.Black * 0.8f;
diff --git a/Subsurface/Source/GUI/GUIImage.cs b/Subsurface/Source/GUI/GUIImage.cs
index 1fb92135a..16dab4c83 100644
--- a/Subsurface/Source/GUI/GUIImage.cs
+++ b/Subsurface/Source/GUI/GUIImage.cs
@@ -83,12 +83,11 @@ namespace Barotrauma
if (state == ComponentState.Hover) currColor = hoverColor;
if (state == ComponentState.Selected) currColor = selectedColor;
- if (sprite!=null)
+ if (sprite != null && sprite.Texture != null)
{
spriteBatch.Draw(sprite.Texture, new Vector2(rect.X, rect.Y), sourceRect, currColor * (currColor.A / 255.0f), 0.0f, Vector2.Zero,
- Scale, SpriteEffects.None, 0.0f);
- }
-
+ Scale, SpriteEffects.None, 0.0f);
+ }
DrawChildren(spriteBatch);
}
diff --git a/Subsurface/Source/GameSession/CrewManager.cs b/Subsurface/Source/GameSession/CrewManager.cs
index 35261dd84..c9e2e3235 100644
--- a/Subsurface/Source/GameSession/CrewManager.cs
+++ b/Subsurface/Source/GameSession/CrewManager.cs
@@ -277,7 +277,7 @@ namespace Barotrauma
listBox.ClearChildren();
characters.Clear();
- WayPoint[] waypoints = WayPoint.SelectCrewSpawnPoints(characterInfos);
+ WayPoint[] waypoints = WayPoint.SelectCrewSpawnPoints(characterInfos, Submarine.MainSub);
for (int i = 0; i < waypoints.Length; i++)
{
diff --git a/Subsurface/Source/GameSession/GameModes/SinglePlayerMode.cs b/Subsurface/Source/GameSession/GameModes/SinglePlayerMode.cs
index 9e933d519..ce0f38c7f 100644
--- a/Subsurface/Source/GameSession/GameModes/SinglePlayerMode.cs
+++ b/Subsurface/Source/GameSession/GameModes/SinglePlayerMode.cs
@@ -53,7 +53,7 @@ namespace Barotrauma
endShiftButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 220, 20, 200, 25), "End shift", Alignment.TopLeft, GUI.Style);
endShiftButton.Font = GUI.SmallFont;
- endShiftButton.OnClicked = EndShift;
+ endShiftButton.OnClicked = TryEndShift;
for (int i = 0; i < 3; i++)
{
@@ -143,14 +143,14 @@ namespace Barotrauma
CrewManager.Draw(spriteBatch);
- if (Submarine.Loaded == null) return;
+ if (Submarine.MainSub == null) return;
- if (Submarine.Loaded.AtEndPosition)
+ if (Submarine.MainSub.AtEndPosition)
{
endShiftButton.Text = "Enter " + Map.SelectedLocation.Name;
endShiftButton.Draw(spriteBatch);
}
- else if (Submarine.Loaded.AtStartPosition)
+ else if (Submarine.MainSub.AtStartPosition)
{
endShiftButton.Text = "Enter " + Map.CurrentLocation.Name;
endShiftButton.Draw(spriteBatch);
@@ -199,7 +199,7 @@ namespace Barotrauma
if (success)
{
- if (Submarine.Loaded.AtEndPosition)
+ if (Submarine.MainSub.AtEndPosition)
{
Map.MoveToNextLocation();
}
@@ -236,11 +236,44 @@ namespace Barotrauma
Submarine.Unload();
}
+ private bool TryEndShift(GUIButton button, object obj)
+ {
+ int subsNotDocked = Submarine.Loaded.Count(s => s != Submarine.MainSub && !s.DockedTo.Contains(Submarine.MainSub));
+
+ if (subsNotDocked > 0)
+ {
+ string msg = "";
+ if (subsNotDocked == 1)
+ {
+ msg = "One of of your vessels hasn't been docked to " + Submarine.MainSub.Name
+ + ". If you leave now, you will permanently lose it."
+ + " Do you want to leave the vessel behind?";
+ }
+ else
+ {
+ msg = "Some of of your vessels hasn't been docked to " + Submarine.MainSub.Name
+ + ". If you leave now, you will permanently lose them."
+ + " Do you want to leave the vessels behind?";
+ }
+
+ var msgBox = new GUIMessageBox("Warning", msg, new string[] {"Yes", "No"});
+ msgBox.Buttons[0].OnClicked += EndShift;
+ msgBox.Buttons[0].OnClicked += msgBox.Close;
+ msgBox.Buttons[1].OnClicked += msgBox.Close;
+ }
+ else
+ {
+ EndShift(button, obj);
+ }
+
+ return true;
+ }
+
private bool EndShift(GUIButton button, object obj)
{
isRunning = false;
- var cinematic = new TransitionCinematic(Submarine.Loaded, GameMain.GameScreen.Cam, 5.0f);
+ var cinematic = new TransitionCinematic(Submarine.MainSub, GameMain.GameScreen.Cam, 5.0f);
SoundPlayer.OverrideMusicType = CrewManager.characters.Any(c => !c.IsDead) ? "endshift" : "crewdead";
@@ -253,12 +286,12 @@ namespace Barotrauma
{
while (cinematic.Running)
{
- if (Submarine.Loaded == null) yield return CoroutineStatus.Success;
+ if (Submarine.MainSub == null) yield return CoroutineStatus.Success;
yield return CoroutineStatus.Running;
}
- if (Submarine.Loaded == null) yield return CoroutineStatus.Success;
+ if (Submarine.MainSub == null) yield return CoroutineStatus.Success;
End("");
diff --git a/Subsurface/Source/GameSession/GameModes/TraitorMode.cs b/Subsurface/Source/GameSession/GameModes/TraitorMode.cs
index 7051902a5..7c5d99018 100644
--- a/Subsurface/Source/GameSession/GameModes/TraitorMode.cs
+++ b/Subsurface/Source/GameSession/GameModes/TraitorMode.cs
@@ -95,7 +95,7 @@ namespace Barotrauma
endMessage = traitorCharacter.Name + " was a traitor! ";
endMessage += (traitorCharacter.Info.Gender == Gender.Male) ? "His" : "Her";
endMessage += " task was to assassinate " + targetCharacter.Name + ". ";
- endMessage += (Submarine.Loaded.AtEndPosition) ?
+ endMessage += (Submarine.MainSub.AtEndPosition) ?
"The task was unsuccessful - the has submarine reached its destination." :
"The task was unsuccessful.";
}
diff --git a/Subsurface/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs b/Subsurface/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs
index 228b79063..a600e0cfc 100644
--- a/Subsurface/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs
+++ b/Subsurface/Source/GameSession/GameModes/Tutorials/BasicTutorial.cs
@@ -22,7 +22,7 @@ namespace Barotrauma.Tutorials
//spawn some fish next to the player
GameMain.GameScreen.BackgroundCreatureManager.SpawnSprites(2,
- Submarine.Loaded.Position + Character.Controlled.Position);
+ Submarine.MainSub.Position + Character.Controlled.Position);
yield return new WaitForSeconds(4.0f);
@@ -276,7 +276,7 @@ namespace Barotrauma.Tutorials
infoBox = CreateInfoFrame("Steer the submarine downwards, heading further into the cavern.");
- while (Submarine.Loaded.WorldPosition.Y > 24600.0f)
+ while (Submarine.MainSub.WorldPosition.Y > 24600.0f)
{
yield return CoroutineStatus.Running;
}
@@ -300,7 +300,7 @@ namespace Barotrauma.Tutorials
bool broken = false;
do
{
- Submarine.Loaded.Velocity = Vector2.Zero;
+ Submarine.MainSub.Velocity = Vector2.Zero;
moloch.AIController.SelectTarget(steering.Item.CurrentHull.AiTarget);
Vector2 steeringDir = windows[0].WorldPosition - moloch.WorldPosition;
@@ -349,7 +349,7 @@ namespace Barotrauma.Tutorials
}
}
- Submarine.Loaded.GodMode = true;
+ Submarine.MainSub.GodMode = true;
var capacitor1 = Item.ItemList.Find(i => i.HasTag("capacitor1")).GetComponent();
var capacitor2 = Item.ItemList.Find(i => i.HasTag("capacitor1")).GetComponent();
@@ -462,7 +462,7 @@ namespace Barotrauma.Tutorials
yield return CoroutineStatus.Running;
}
- Submarine.Loaded.GodMode = false;
+ Submarine.MainSub.GodMode = false;
infoBox = CreateInfoFrame("The creature has died. Now you should fix the damages in the control room: " +
"Grab a welding tool from the closet in the railgun room.");
@@ -588,7 +588,7 @@ namespace Barotrauma.Tutorials
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
GameMain.LightManager.LosEnabled = false;
- var cinematic = new TransitionCinematic(Submarine.Loaded, GameMain.GameScreen.Cam, 5.0f);
+ var cinematic = new TransitionCinematic(Submarine.MainSub, GameMain.GameScreen.Cam, 5.0f);
while (cinematic.Running)
{
diff --git a/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialMode.cs b/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialMode.cs
index 5a16434a4..d0b80c2ca 100644
--- a/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialMode.cs
+++ b/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialMode.cs
@@ -9,7 +9,7 @@ namespace Barotrauma
public static void StartTutorial(TutorialType tutorialType)
{
- Submarine.Load("Content/Map/TutorialSub.sub", "");
+ Submarine.Load("Content/Map/TutorialSub.sub", "", true);
tutorialType.Initialize();
diff --git a/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialType.cs b/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialType.cs
index 36af62a21..502ec7ec2 100644
--- a/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialType.cs
+++ b/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialType.cs
@@ -36,7 +36,7 @@ namespace Barotrauma.Tutorials
public virtual void Initialize()
{
- GameMain.GameSession = new GameSession(Submarine.Loaded, "", GameModePreset.list.Find(gm => gm.Name.ToLowerInvariant() == "tutorial"));
+ GameMain.GameSession = new GameSession(Submarine.MainSub, "", GameModePreset.list.Find(gm => gm.Name.ToLowerInvariant() == "tutorial"));
(GameMain.GameSession.gameMode as TutorialMode).tutorialType = this;
GameMain.GameSession.StartShift("tuto1");
diff --git a/Subsurface/Source/GameSession/GameSession.cs b/Subsurface/Source/GameSession/GameSession.cs
index b16e0d567..28c67bb6a 100644
--- a/Subsurface/Source/GameSession/GameSession.cs
+++ b/Subsurface/Source/GameSession/GameSession.cs
@@ -68,6 +68,8 @@ namespace Barotrauma
public GameSession(Submarine submarine, string saveFile, GameModePreset gameModePreset = null, string missionType="")
{
+ Submarine.MainSub = submarine;
+
GameMain.GameSession = this;
CrewManager = new CrewManager();
@@ -88,6 +90,8 @@ namespace Barotrauma
public GameSession(Submarine selectedSub, string saveFile, XDocument doc)
: this(selectedSub, saveFile)
{
+ Submarine.MainSub = submarine;
+
GameMain.GameSession = this;
CrewManager = new CrewManager();
@@ -121,7 +125,10 @@ namespace Barotrauma
return;
}
- if (reloadSub || Submarine.Loaded != submarine) submarine.Load();
+ if (reloadSub || Submarine.MainSub != submarine) submarine.Load(true);
+
+ //var secondSub = new Submarine(submarine.FilePath, submarine.MD5Hash.Hash);
+ //secondSub.Load(false);
if (level != null)
{
@@ -129,6 +136,8 @@ namespace Barotrauma
submarine.SetPosition(level.StartPosition - new Vector2(0.0f, 2000.0f));
+ //secondSub.SetPosition(level.EndPosition - new Vector2(0.0f, 2000.0f));
+
GameMain.GameScreen.BackgroundCreatureManager.SpawnSprites(80);
}
diff --git a/Subsurface/Source/GameSession/InfoTextManager.cs b/Subsurface/Source/GameSession/InfoTextManager.cs
index 3e28cfc0a..78bca7b25 100644
--- a/Subsurface/Source/GameSession/InfoTextManager.cs
+++ b/Subsurface/Source/GameSession/InfoTextManager.cs
@@ -51,7 +51,7 @@ namespace Barotrauma
string text = infoList[Rand.Int(infoList.Count)];
- if (Submarine.Loaded!=null) text = text.Replace("[sub]", Submarine.Loaded.Name);
+ if (Submarine.MainSub != null) text = text.Replace("[sub]", Submarine.MainSub.Name);
if (GameMain.GameSession != null && GameMain.GameSession.Map != null)
{
if (GameMain.GameSession.Map.CurrentLocation!=null)
diff --git a/Subsurface/Source/GameSession/ShiftSummary.cs b/Subsurface/Source/GameSession/ShiftSummary.cs
index 45c13bb6a..6c4c03c52 100644
--- a/Subsurface/Source/GameSession/ShiftSummary.cs
+++ b/Subsurface/Source/GameSession/ShiftSummary.cs
@@ -32,7 +32,7 @@ namespace Barotrauma
bool singleplayer = GameMain.NetworkMember == null;
bool gameOver = gameSession.CrewManager.characters.All(c => c.IsDead);
- bool progress = Submarine.Loaded.AtEndPosition;
+ bool progress = Submarine.MainSub.AtEndPosition;
GUIFrame frame = new GUIFrame(new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.Black * 0.8f);
diff --git a/Subsurface/Source/Items/Components/DockingPort.cs b/Subsurface/Source/Items/Components/DockingPort.cs
new file mode 100644
index 000000000..83cd58e32
--- /dev/null
+++ b/Subsurface/Source/Items/Components/DockingPort.cs
@@ -0,0 +1,471 @@
+using FarseerPhysics;
+using FarseerPhysics.Dynamics;
+using FarseerPhysics.Dynamics.Joints;
+using FarseerPhysics.Factories;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml.Linq;
+
+namespace Barotrauma.Items.Components
+{
+
+ class DockingPort : ItemComponent, IDrawableComponent
+ {
+ public static List list = new List();
+
+ private Sprite overlaySprite;
+
+ private Vector2 distanceTolerance;
+
+ private DockingPort dockingTarget;
+
+ private float dockingState;
+ private int dockingDir;
+
+ private Joint joint;
+
+ private Hull[] hulls;
+
+ private Body[] bodies;
+
+ private Gap gap;
+
+ private bool docked;
+
+ [HasDefaultValue("32.0,32.0", false)]
+ public string DistanceTolerance
+ {
+ get { return ToolBox.Vector2ToString(distanceTolerance); }
+ set { distanceTolerance = ToolBox.ParseToVector2(value); }
+ }
+
+ [HasDefaultValue(32.0f, false)]
+ public float DockedDistance
+ {
+ get;
+ set;
+ }
+
+ [HasDefaultValue(true, false)]
+ public bool IsHorizontal
+ {
+ get;
+ set;
+ }
+
+ public bool Docked
+ {
+ get
+ {
+ return docked;
+ }
+ set
+ {
+ if (!docked && value)
+ {
+ if (dockingTarget == null) AttemptDock();
+ if (dockingTarget == null) return;
+
+ docked = true;
+ }
+ else if (docked && !value)
+ {
+ Undock();
+ }
+
+ //base.IsActive = value;
+ }
+ }
+
+ public DockingPort(Item item, XElement element)
+ : base(item, element)
+ {
+ // isOpen = false;
+ foreach (XElement subElement in element.Elements())
+ {
+ string texturePath = ToolBox.GetAttributeString(subElement, "texture", "");
+ switch (subElement.Name.ToString().ToLowerInvariant())
+ {
+ case "sprite":
+ overlaySprite = new Sprite(subElement, texturePath.Contains("/") ? "" : Path.GetDirectoryName(item.Prefab.ConfigFile));
+ break;
+ }
+ }
+
+ IsActive = true;
+
+ list.Add(this);
+ }
+
+ private DockingPort FindAdjacentPort()
+ {
+ foreach (DockingPort port in list)
+ {
+ if (port == this || port.item.Submarine == item.Submarine) continue;
+
+ if (Math.Abs(port.item.WorldPosition.X - item.WorldPosition.X) > distanceTolerance.X) continue;
+ if (Math.Abs(port.item.WorldPosition.Y - item.WorldPosition.Y) > distanceTolerance.Y) continue;
+
+ return port;
+ }
+
+ return null;
+ }
+
+ private void AttemptDock()
+ {
+ var adjacentPort = FindAdjacentPort();
+ if (adjacentPort != null) Dock(adjacentPort);
+ }
+
+ public void Dock(DockingPort target)
+ {
+ if (dockingTarget != null)
+ {
+ Undock();
+ }
+
+ PlaySound(ActionType.OnUse, item.WorldPosition);
+
+ item.linkedTo.Add(target.item);
+
+ if (!target.item.Submarine.DockedTo.Contains(item.Submarine)) target.item.Submarine.DockedTo.Add(item.Submarine);
+ if (!item.Submarine.DockedTo.Contains(target.item.Submarine)) item.Submarine.DockedTo.Add(target.item.Submarine);
+
+ dockingTarget = target;
+ dockingTarget.dockingTarget = this;
+
+ docked = true;
+ dockingTarget.Docked = true;
+
+ if (Character.Controlled != null &&
+ (Character.Controlled.Submarine == dockingTarget.item.Submarine || Character.Controlled.Submarine == item.Submarine))
+ {
+ GameMain.GameScreen.Cam.Shake = Vector2.Distance(dockingTarget.item.Submarine.Velocity, item.Submarine.Velocity);
+ }
+
+ dockingDir = IsHorizontal ?
+ Math.Sign(dockingTarget.item.WorldPosition.X - item.WorldPosition.X) :
+ Math.Sign(item.WorldPosition.Y - dockingTarget.item.WorldPosition.Y);
+ dockingTarget.dockingDir = -dockingDir;
+
+ CreateJoint(false);
+ }
+
+
+ private void CreateJoint(bool useWeldJoint)
+ {
+ Vector2 offset = (IsHorizontal ?
+ Vector2.UnitX * Math.Sign(dockingTarget.item.WorldPosition.X - item.WorldPosition.X) :
+ Vector2.UnitY * Math.Sign(dockingTarget.item.WorldPosition.Y - item.WorldPosition.Y));
+ offset *= DockedDistance * 0.5f;
+
+ Vector2 pos1 = item.WorldPosition + offset;
+
+ Vector2 pos2 = dockingTarget.item.WorldPosition - offset;
+
+ if (useWeldJoint)
+ {
+ joint = JointFactory.CreateWeldJoint(GameMain.World,
+ item.Submarine.SubBody.Body, dockingTarget.item.Submarine.SubBody.Body,
+ ConvertUnits.ToSimUnits(pos1), FarseerPhysics.ConvertUnits.ToSimUnits(pos2), true);
+
+ ((WeldJoint)joint).FrequencyHz = 1.0f;
+ }
+ else
+ {
+ var distanceJoint = JointFactory.CreateDistanceJoint(GameMain.World,
+ item.Submarine.SubBody.Body, dockingTarget.item.Submarine.SubBody.Body,
+ ConvertUnits.ToSimUnits(pos1), FarseerPhysics.ConvertUnits.ToSimUnits(pos2), true);
+
+ distanceJoint.Length = 0.01f;
+ distanceJoint.Frequency = 1.0f;
+ distanceJoint.DampingRatio = 0.8f;
+
+ joint = distanceJoint;
+ }
+
+
+ joint.CollideConnected = true;
+ }
+
+ private void CreateHull()
+ {
+ var hullRects = new Rectangle[] { item.WorldRect, dockingTarget.item.WorldRect };
+ var subs = new Submarine[] { item.Submarine, dockingTarget.item.Submarine };
+
+ hulls = new Hull[2];
+ bodies = new Body[4];
+ if (IsHorizontal)
+ {
+ if (hullRects[0].Center.X > hullRects[1].Center.X)
+ {
+ hullRects = new Rectangle[] { dockingTarget.item.WorldRect, item.WorldRect };
+ subs = new Submarine[] { dockingTarget.item.Submarine,item.Submarine };
+ }
+
+ hullRects[0] = new Rectangle(hullRects[0].Center.X, hullRects[0].Y, ((int)DockedDistance / 2), hullRects[0].Height);
+ hullRects[1] = new Rectangle(hullRects[1].Center.X - ((int)DockedDistance / 2), hullRects[1].Y, ((int)DockedDistance / 2), hullRects[1].Height);
+
+ for (int i = 0; i < 2;i++ )
+ {
+ hullRects[i].Location -= (subs[i].WorldPosition - subs[i].HiddenSubPosition).ToPoint();
+ hulls[i] = new Hull(MapEntityPrefab.list.Find(m => m.Name == "Hull"), hullRects[i], subs[i]);
+ hulls[i].AddToGrid(subs[i]);
+
+ for (int j = 0; j < 2; j++)
+ {
+ bodies[i + j * 2] = BodyFactory.CreateEdge(GameMain.World,
+ ConvertUnits.ToSimUnits(new Vector2(hullRects[i].X, hullRects[i].Y - hullRects[i].Height * j)),
+ ConvertUnits.ToSimUnits(new Vector2(hullRects[i].Right, hullRects[i].Y - hullRects[i].Height * j)));
+ }
+ }
+
+ gap = new Gap(new Rectangle(hullRects[0].Right - 2, hullRects[0].Y, 4, hullRects[0].Height), true, subs[0]);
+
+ gap.linkedTo.Clear();
+ if (hulls[0].WorldRect.X < hulls[1].WorldRect.X)
+ {
+ gap.linkedTo.Add(hulls[0]);
+ gap.linkedTo.Add(hulls[1]);
+ }
+ else
+ {
+ gap.linkedTo.Add(hulls[1]);
+ gap.linkedTo.Add(hulls[0]);
+ }
+
+
+ }
+ else
+ {
+ if (hullRects[0].Center.Y > hullRects[1].Center.Y)
+ {
+ hullRects = new Rectangle[] { dockingTarget.item.WorldRect, item.WorldRect };
+ subs = new Submarine[] { dockingTarget.item.Submarine, item.Submarine };
+ }
+
+ hullRects[0] = new Rectangle(hullRects[0].X, hullRects[0].Y + (int)(-hullRects[0].Height+DockedDistance)/2, hullRects[0].Width, ((int)DockedDistance / 2));
+ hullRects[1] = new Rectangle(hullRects[1].X, hullRects[1].Y - hullRects[1].Height/2, hullRects[1].Width, ((int)DockedDistance / 2));
+
+ for (int i = 0; i < 2; i++)
+ {
+ hullRects[i].Location -= (subs[i].WorldPosition - subs[i].HiddenSubPosition).ToPoint();
+ hulls[i] = new Hull(MapEntityPrefab.list.Find(m => m.Name == "Hull"), hullRects[i], subs[i]);
+ hulls[i].AddToGrid(subs[i]);
+
+ //for (int j = 0; j < 2; j++)
+ //{
+ // bodies[i + j * 2] = BodyFactory.CreateEdge(GameMain.World,
+ // ConvertUnits.ToSimUnits(new Vector2(hullRects[i].X + hullRects[i].Width * j, hullRects[i].Y)),
+ // ConvertUnits.ToSimUnits(new Vector2(hullRects[i].X + hullRects[i].Width * j, hullRects[i].Y-hullRects[i].Height)));
+ //}
+ }
+
+ gap = new Gap(new Rectangle(hullRects[0].X, hullRects[0].Y+2, hullRects[0].Width, 4), false, subs[0]);
+
+ gap.linkedTo.Clear();
+ if (hulls[0].WorldRect.Y > hulls[1].WorldRect.Y)
+ {
+ gap.linkedTo.Add(hulls[0]);
+ gap.linkedTo.Add(hulls[1]);
+ }
+ else
+ {
+ gap.linkedTo.Add(hulls[1]);
+ gap.linkedTo.Add(hulls[0]);
+ }
+ }
+
+
+ foreach (Body body in bodies)
+ {
+ if (body == null) continue;
+ body.BodyType = BodyType.Static;
+ body.Friction = 0.5f;
+
+ body.CollisionCategories = Physics.CollisionWall;
+ }
+
+
+ }
+
+ private void Undock()
+ {
+ if (dockingTarget == null || !docked) return;
+
+ PlaySound(ActionType.OnUse, item.WorldPosition);
+
+ dockingTarget.item.Submarine.DockedTo.Remove(item.Submarine);
+ item.Submarine.DockedTo.Remove(dockingTarget.item.Submarine);
+
+ item.linkedTo.Clear();
+
+ docked = false;
+
+ dockingTarget.Undock();
+ dockingTarget = null;
+
+ if (joint != null)
+ {
+ GameMain.World.RemoveJoint(joint);
+ joint = null;
+ }
+
+ if (hulls != null)
+ {
+ hulls[0].Remove();
+ hulls[1].Remove();
+ hulls = null;
+ }
+
+ if (gap != null)
+ {
+ gap.Remove();
+ gap = null;
+ }
+
+ if (bodies!=null)
+ {
+ foreach (Body body in bodies)
+ {
+ if (body == null) continue;
+ GameMain.World.RemoveBody(body);
+ }
+ bodies = null;
+ }
+
+ }
+
+ public override void Update(float deltaTime, Camera cam)
+ {
+
+
+ if (dockingTarget == null)
+ {
+ dockingState = MathHelper.Lerp(dockingState, 0.0f, deltaTime * 10.0f);
+ if (dockingState < 0.01f) docked = false;
+
+ item.SendSignal(0, "0", "state_out");
+
+ item.SendSignal(0, (FindAdjacentPort() != null) ? "1" : "0", "proximity_sensor");
+
+ }
+ else
+ {
+ if (joint is DistanceJoint)
+ {
+ item.SendSignal(0, "0", "state_out");
+
+ if (Vector2.Distance(joint.WorldAnchorA, joint.WorldAnchorB) < 0.05f)
+ {
+ GameMain.World.RemoveJoint(joint);
+
+ PlaySound(ActionType.OnSecondaryUse, item.WorldPosition);
+
+ CreateJoint(true);
+ CreateHull();
+ }
+ dockingState = MathHelper.Lerp(dockingState, 0.5f, deltaTime * 10.0f);
+ }
+ else
+ {
+ item.SendSignal(0, "1", "state_out");
+
+ dockingState = MathHelper.Lerp(dockingState, 1.0f, deltaTime * 10.0f);
+ }
+ }
+ }
+
+ public void Draw(SpriteBatch spriteBatch, bool editing)
+ {
+ if (dockingState == 0.0f) return;
+
+ Vector2 drawPos = item.DrawPosition;
+ drawPos.Y = -drawPos.Y;
+
+ var rect = overlaySprite.SourceRect;
+
+ if (IsHorizontal)
+ {
+ drawPos.Y -= rect.Height / 2;
+
+ if (dockingDir == 1)
+ {
+ spriteBatch.Draw(overlaySprite.Texture,
+ drawPos,
+ new Rectangle(
+ rect.Center.X + (int)(rect.Width / 2 * (1.0f - dockingState)), rect.Y,
+ (int)(rect.Width / 2 * dockingState), rect.Height), Color.White);
+
+ }
+ else
+ {
+ spriteBatch.Draw(overlaySprite.Texture,
+ drawPos - Vector2.UnitX * (rect.Width / 2 * dockingState),
+ new Rectangle(
+ rect.X, rect.Y,
+ (int)(rect.Width / 2 * dockingState), rect.Height), Color.Red);
+ }
+ }
+ else
+ {
+ drawPos.X -= rect.Width / 2;
+
+ if (dockingDir == 1)
+ {
+ spriteBatch.Draw(overlaySprite.Texture,
+ drawPos,
+ new Rectangle(
+ rect.X, rect.Y + rect.Height/2 + (int)(rect.Height / 2 * (1.0f - dockingState)),
+ rect.Width, (int)(rect.Height / 2 * dockingState)), Color.White);
+
+ }
+ else
+ {
+ spriteBatch.Draw(overlaySprite.Texture,
+ drawPos - Vector2.UnitY * (rect.Height / 2 * dockingState),
+ new Rectangle(
+ rect.X, rect.Y,
+ rect.Width, (int)(rect.Height / 2 * dockingState)), Color.Red);
+ }
+ }
+ }
+
+ protected override void RemoveComponentSpecific()
+ {
+ list.Remove(this);
+ }
+
+ public override void OnMapLoaded()
+ {
+ if (!item.linkedTo.Any()) return;
+
+ Item linkedItem = item.linkedTo.First() as Item;
+ if (linkedItem == null) return;
+
+ DockingPort port = linkedItem.GetComponent();
+ if (port != null) Dock(port);
+ }
+
+ public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power = 0.0f)
+ {
+ switch (connection.Name)
+ {
+ case "toggle":
+ Docked = !docked;
+ break;
+ case "set_active":
+ case "set_state":
+ Docked = signal != "0";
+ break;
+ }
+ }
+ }
+}
diff --git a/Subsurface/Source/Items/Components/Door.cs b/Subsurface/Source/Items/Components/Door.cs
index f9c33c541..ba75e1999 100644
--- a/Subsurface/Source/Items/Components/Door.cs
+++ b/Subsurface/Source/Items/Components/Door.cs
@@ -444,28 +444,31 @@ namespace Barotrauma.Items.Components
if (connection.Name=="toggle")
{
- SetState(!isOpen, false);
+ SetState(!isOpen, false, true);
}
else if (connection.Name == "set_state")
{
- SetState(signal != "0", false);
+ SetState(signal != "0", false, true);
}
-
- item.NewComponentEvent(this, false, true);
}
- private void SetState(bool state, bool isNetWorkMessage)
+ public void SetState(bool open, bool isNetworkMessage, bool sendNetworkMessage = false)
{
- if (GameMain.Client != null && !isNetWorkMessage) return;
+ if (GameMain.Client != null && !isNetworkMessage) return;
- if (isStuck || isOpen == state) return;
+ if (isStuck || isOpen == open) return;
PlaySound(ActionType.OnUse, item.WorldPosition);
- isOpen = state;
+ isOpen = open;
//opening a partially stuck door makes it less stuck
if (isOpen) stuck = MathHelper.Clamp(stuck - 30.0f, 0.0f, 100.0f);
+
+ if (sendNetworkMessage)
+ {
+ item.NewComponentEvent(this, false, true);
+ }
}
public override bool FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetBuffer message)
diff --git a/Subsurface/Source/Items/Components/Holdable/Holdable.cs b/Subsurface/Source/Items/Components/Holdable/Holdable.cs
index fffafd02e..4684d0a9e 100644
--- a/Subsurface/Source/Items/Components/Holdable/Holdable.cs
+++ b/Subsurface/Source/Items/Components/Holdable/Holdable.cs
@@ -101,7 +101,7 @@ namespace Barotrauma.Items.Components
Msg = "";
}
- if (attachedByDefault || (Screen.Selected == GameMain.EditMapScreen && Submarine.Loaded != null)) Use(1.0f);
+ if (attachedByDefault || (Screen.Selected == GameMain.EditMapScreen)) Use(1.0f);
//holdAngle = ToolBox.GetAttributeFloat(element, "holdangle", 0.0f);
diff --git a/Subsurface/Source/Items/Components/Holdable/RepairTool.cs b/Subsurface/Source/Items/Components/Holdable/RepairTool.cs
index 63a4cdd7f..8b288773a 100644
--- a/Subsurface/Source/Items/Components/Holdable/RepairTool.cs
+++ b/Subsurface/Source/Items/Components/Holdable/RepairTool.cs
@@ -132,83 +132,19 @@ namespace Barotrauma.Items.Components
IsActive = true;
activeTimer = 0.1f;
+ Vector2 rayStart = ConvertUnits.ToSimUnits(item.WorldPosition);
+ Vector2 rayEnd = ConvertUnits.ToSimUnits(targetPosition);
- for (int n = 0; n < 2; n++)
+ if (character.Submarine == null)
{
- Vector2 rayStart = ConvertUnits.ToSimUnits(item.WorldPosition);
- Vector2 rayEnd = ConvertUnits.ToSimUnits(targetPosition);
-
- if (n == 0)
+ foreach (Submarine sub in Submarine.Loaded)
{
- //do a raycast in "submarine coordinates"
- rayStart -= Submarine.Loaded.SimPosition;
- rayEnd -= Submarine.Loaded.SimPosition;
+ Repair(rayStart - sub.SimPosition, rayEnd - sub.SimPosition, deltaTime, character, degreeOfSuccess, ignoredBodies);
}
- else
- {
- //do a raycast outside the sub if the character is outside
- if (character.AnimController.CurrentHull != null) continue;
- }
-
- Body targetBody = Submarine.PickBody(rayStart, rayEnd, ignoredBodies);
-
- pickedPosition = Submarine.LastPickedPosition;
-
- if (ExtinquishAmount > 0.0f && item.CurrentHull != null)
- {
- Vector2 displayPos = ConvertUnits.ToDisplayUnits(rayStart + (rayEnd - rayStart) * Submarine.LastPickedFraction * 0.9f);
-
- displayPos += item.CurrentHull.Submarine.Position;
-
- Hull hull = Hull.FindHull(displayPos, item.CurrentHull);
- if (hull != null) hull.Extinquish(deltaTime, ExtinquishAmount, displayPos);
- }
-
- if (targetBody == null || targetBody.UserData == null) continue;
-
- Structure targetStructure;
- Limb targetLimb;
- Item targetItem;
- if ((targetStructure = (targetBody.UserData as Structure)) != null)
- {
- if (!fixableEntities.Contains(targetStructure.Name)) continue;
-
- int sectionIndex = targetStructure.FindSectionIndex(ConvertUnits.ToDisplayUnits(pickedPosition));
- if (sectionIndex < 0) continue;
-
- targetStructure.HighLightSection(sectionIndex);
-
- targetStructure.AddDamage(sectionIndex, -StructureFixAmount * degreeOfSuccess);
-
- //if the next section is small enough, apply the effect to it as well
- //(to make it easier to fix a small "left-over" section)
- for (int i = -1; i < 2; i += 2)
- {
- int nextSectionLength = targetStructure.SectionLength(sectionIndex + i);
- if ((sectionIndex == 1 && i == -1) ||
- (sectionIndex == targetStructure.SectionCount - 2 && i == 1) ||
- (nextSectionLength > 0 && nextSectionLength < Structure.wallSectionSize * 0.3f))
- {
- targetStructure.HighLightSection(sectionIndex + i);
- targetStructure.AddDamage(sectionIndex + i, -StructureFixAmount * degreeOfSuccess);
- }
- }
-
-
- }
- else if ((targetLimb = (targetBody.UserData as Limb)) != null)
- {
- if (character.IsKeyDown(InputType.Aim))
- {
- targetLimb.character.AddDamage(CauseOfDeath.Damage, -LimbFixAmount * degreeOfSuccess, character);
- }
- }
- else if ((targetItem = (targetBody.UserData as Item)) != null)
- {
- targetItem.IsHighlighted = true;
-
- ApplyStatusEffects(ActionType.OnUse, targetItem.AllPropertyObjects, deltaTime);
- }
+ }
+ else
+ {
+ Repair(rayStart - character.Submarine.SimPosition, rayEnd - character.Submarine.SimPosition, deltaTime, character, degreeOfSuccess, ignoredBodies);
}
GameMain.ParticleManager.CreateParticle(particles, item.WorldPosition + TransformedBarrelPos,
@@ -217,6 +153,64 @@ namespace Barotrauma.Items.Components
return true;
}
+ private void Repair(Vector2 rayStart, Vector2 rayEnd, float deltaTime, Character user, float degreeOfSuccess, List ignoredBodies)
+ {
+ if (ExtinquishAmount > 0.0f && item.CurrentHull != null)
+ {
+ Vector2 displayPos = ConvertUnits.ToDisplayUnits(rayStart + (rayEnd - rayStart) * Submarine.LastPickedFraction * 0.9f);
+
+ displayPos += item.CurrentHull.Submarine.Position;
+
+ Hull hull = Hull.FindHull(displayPos, item.CurrentHull);
+ if (hull != null) hull.Extinquish(deltaTime, ExtinquishAmount, displayPos);
+ }
+
+ Body targetBody = Submarine.PickBody(rayStart, rayEnd, ignoredBodies);
+
+ if (targetBody == null || targetBody.UserData == null) return;
+
+ Structure targetStructure;
+ Limb targetLimb;
+ Item targetItem;
+ if ((targetStructure = (targetBody.UserData as Structure)) != null)
+ {
+ if (!fixableEntities.Contains(targetStructure.Name)) return;
+
+ int sectionIndex = targetStructure.FindSectionIndex(ConvertUnits.ToDisplayUnits(pickedPosition));
+ if (sectionIndex < 0) return;
+
+ targetStructure.HighLightSection(sectionIndex);
+
+ targetStructure.AddDamage(sectionIndex, -StructureFixAmount * degreeOfSuccess);
+
+ //if the next section is small enough, apply the effect to it as well
+ //(to make it easier to fix a small "left-over" section)
+ for (int i = -1; i < 2; i += 2)
+ {
+ int nextSectionLength = targetStructure.SectionLength(sectionIndex + i);
+ if ((sectionIndex == 1 && i == -1) ||
+ (sectionIndex == targetStructure.SectionCount - 2 && i == 1) ||
+ (nextSectionLength > 0 && nextSectionLength < Structure.wallSectionSize * 0.3f))
+ {
+ targetStructure.HighLightSection(sectionIndex + i);
+ targetStructure.AddDamage(sectionIndex + i, -StructureFixAmount * degreeOfSuccess);
+ }
+ }
+
+
+ }
+ else if ((targetLimb = (targetBody.UserData as Limb)) != null)
+ {
+ targetLimb.character.AddDamage(CauseOfDeath.Damage, -LimbFixAmount * degreeOfSuccess, user);
+ }
+ else if ((targetItem = (targetBody.UserData as Item)) != null)
+ {
+ targetItem.IsHighlighted = true;
+
+ ApplyStatusEffects(ActionType.OnUse, targetItem.AllPropertyObjects, deltaTime);
+ }
+ }
+
public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
{
Gap leak = objective.OperateTarget as Gap;
diff --git a/Subsurface/Source/Items/Components/Machines/Engine.cs b/Subsurface/Source/Items/Components/Machines/Engine.cs
index a97d3030c..bf3be00fe 100644
--- a/Subsurface/Source/Items/Components/Machines/Engine.cs
+++ b/Subsurface/Source/Items/Components/Machines/Engine.cs
@@ -86,7 +86,7 @@ namespace Barotrauma.Items.Components
{
Vector2 currForce = new Vector2((force / 100.0f) * maxForce * (voltage / minVoltage), 0.0f);
- Submarine.Loaded.ApplyForce(currForce);
+ item.Submarine.ApplyForce(currForce);
if (item.CurrentHull != null)
{
diff --git a/Subsurface/Source/Items/Components/Machines/MiniMap.cs b/Subsurface/Source/Items/Components/Machines/MiniMap.cs
index a03ecc9d2..55cef9917 100644
--- a/Subsurface/Source/Items/Components/Machines/MiniMap.cs
+++ b/Subsurface/Source/Items/Components/Machines/MiniMap.cs
@@ -36,6 +36,8 @@ namespace Barotrauma.Items.Components
public override void DrawHUD(SpriteBatch spriteBatch, Character character)
{
+ if (item.Submarine == null) return;
+
int width = GuiFrame.Rect.Width, height = GuiFrame.Rect.Height;
int x = GuiFrame.Rect.X;
int y = GuiFrame.Rect.Y;
@@ -48,12 +50,12 @@ namespace Barotrauma.Items.Components
Rectangle miniMap = new Rectangle(x + 20, y + 40, width - 40, height - 60);
- float size = Math.Min((float)miniMap.Width / (float)Submarine.Borders.Width, (float)miniMap.Height / (float)Submarine.Borders.Height);
+ float size = Math.Min((float)miniMap.Width / (float)item.Submarine.Borders.Width, (float)miniMap.Height / (float)item.Submarine.Borders.Height);
foreach (Hull hull in Hull.hullList)
{
Rectangle hullRect = new Rectangle(
- miniMap.X + (int)((hull.Rect.X - Submarine.HiddenSubPosition.X - Submarine.Borders.X) * size),
- miniMap.Y - (int)((hull.Rect.Y - Submarine.HiddenSubPosition.Y - Submarine.Borders.Y) * size),
+ miniMap.X + (int)((hull.Rect.X - item.Submarine.HiddenSubPosition.X - item.Submarine.Borders.X) * size),
+ miniMap.Y - (int)((hull.Rect.Y - item.Submarine.HiddenSubPosition.Y - item.Submarine.Borders.Y) * size),
(int)(hull.Rect.Width * size),
(int)(hull.Rect.Height * size));
diff --git a/Subsurface/Source/Items/Components/Machines/Radar.cs b/Subsurface/Source/Items/Components/Machines/Radar.cs
index be281b135..b35a82a98 100644
--- a/Subsurface/Source/Items/Components/Machines/Radar.cs
+++ b/Subsurface/Source/Items/Components/Machines/Radar.cs
@@ -124,38 +124,41 @@ namespace Barotrauma.Items.Components
float radius = rect.Width / 2.0f;
float displayScale = radius / range;
-
- if (DetectSubmarineWalls)
+
+ foreach (Submarine submarine in Submarine.Loaded)
{
- for (int i = 0; i < Submarine.Loaded.HullVertices.Count; i++)
- {
- Vector2 start = ConvertUnits.ToDisplayUnits(Submarine.Loaded.HullVertices[i]);
- Vector2 end = ConvertUnits.ToDisplayUnits(Submarine.Loaded.HullVertices[(i + 1) % Submarine.Loaded.HullVertices.Count]);
+ if (item.Submarine == submarine && !DetectSubmarineWalls) continue;
- if (item.CurrentHull!=null)
+ for (int i = 0; i < submarine.HullVertices.Count; i++)
+ {
+ Vector2 start = ConvertUnits.ToDisplayUnits(submarine.HullVertices[i]);
+ Vector2 end = ConvertUnits.ToDisplayUnits(submarine.HullVertices[(i + 1) % submarine.HullVertices.Count]);
+
+ if (item.Submarine == submarine)
{
start += Rand.Vector(500.0f);
end += Rand.Vector(500.0f);
}
CreateBlipsForLine(
- start + Submarine.Loaded.WorldPosition,
- end + Submarine.Loaded.WorldPosition,
+ start + submarine.WorldPosition,
+ end + submarine.WorldPosition,
radius, displayScale, 200.0f, 2.0f);
}
-
}
- else
+
+
+ if (item.Submarine != null && !DetectSubmarineWalls)
{
float simScale = displayScale * Physics.DisplayToSimRation;
- Vector2 offset = ConvertUnits.ToSimUnits(Submarine.Loaded.WorldPosition - item.WorldPosition);
+ Vector2 offset = ConvertUnits.ToSimUnits(item.Submarine.WorldPosition - item.WorldPosition);
- for (int i = 0; i < Submarine.Loaded.HullVertices.Count; i++)
+ for (int i = 0; i < item.Submarine.HullVertices.Count; i++)
{
- Vector2 start = (Submarine.Loaded.HullVertices[i] + offset) * simScale;
+ Vector2 start = (item.Submarine.HullVertices[i] + offset) * simScale;
start.Y = -start.Y;
- Vector2 end = (Submarine.Loaded.HullVertices[(i + 1) % Submarine.Loaded.HullVertices.Count] + offset) * simScale;
+ Vector2 end = (item.Submarine.HullVertices[(i + 1) % item.Submarine.HullVertices.Count] + offset) * simScale;
end.Y = -end.Y;
GUI.DrawLine(spriteBatch, center + start, center + end, Color.Green);
diff --git a/Subsurface/Source/Items/Components/Machines/Steering.cs b/Subsurface/Source/Items/Components/Machines/Steering.cs
index c625eeb59..b0afc57d6 100644
--- a/Subsurface/Source/Items/Components/Machines/Steering.cs
+++ b/Subsurface/Source/Items/Components/Machines/Steering.cs
@@ -33,8 +33,10 @@ namespace Barotrauma.Items.Components
private float autopilotRayCastTimer;
private float neutralBallastLevel;
+
+ public Vector2? TargetPosition;
- bool AutoPilot
+ public bool AutoPilot
{
get { return autoPilot; }
set
@@ -52,7 +54,7 @@ namespace Barotrauma.Items.Components
if (pathFinder==null) pathFinder = new PathFinder(WayPoint.WayPointList, false);
steeringPath = pathFinder.FindPath(
ConvertUnits.ToSimUnits(item.WorldPosition),
- ConvertUnits.ToSimUnits(Level.Loaded.EndPosition));
+ TargetPosition == null ? ConvertUnits.ToSimUnits(Level.Loaded.EndPosition) : (Vector2)TargetPosition);
}
else
{
@@ -62,6 +64,12 @@ namespace Barotrauma.Items.Components
}
}
+ public bool MaintainPos
+ {
+ get { return maintainPosTickBox.Selected; }
+ set { maintainPosTickBox.Selected = value; }
+ }
+
[Editable, HasDefaultValue(0.5f, true)]
public float NeutralBallastLevel
@@ -128,7 +136,7 @@ namespace Barotrauma.Items.Components
}
}
- if (voltage < minVoltage) return;
+ if (voltage < minVoltage && powerConsumption > 0.0f) return;
if (autoPilot)
{
@@ -158,15 +166,15 @@ namespace Barotrauma.Items.Components
GuiFrame.Update(1.0f / 60.0f);
GuiFrame.Draw(spriteBatch);
- if (voltage < minVoltage) return;
+ if (voltage < minVoltage && powerConsumption > 0.0f) return;
Rectangle velRect = new Rectangle(x + 20, y + 20, width - 40, height - 40);
//GUI.DrawRectangle(spriteBatch, velRect, Color.White, false);
- if (Submarine.Loaded != null && Level.Loaded != null)
+ if (item.Submarine != null && Level.Loaded != null)
{
- Vector2 realWorldVelocity = ConvertUnits.ToDisplayUnits(Submarine.Loaded.Velocity * Physics.DisplayToRealWorldRatio) * 3.6f;
- float realWorldDepth = Math.Abs(Submarine.Loaded.Position.Y - Level.Loaded.Size.Y) * Physics.DisplayToRealWorldRatio;
+ Vector2 realWorldVelocity = ConvertUnits.ToDisplayUnits(item.Submarine.Velocity * Physics.DisplayToRealWorldRatio) * 3.6f;
+ float realWorldDepth = Math.Abs(item.Submarine.Position.Y - Level.Loaded.Size.Y) * Physics.DisplayToRealWorldRatio;
GUI.DrawString(spriteBatch, new Vector2(x + 20, y + height - 65),
"Velocity: " + (int)realWorldVelocity.X + " km/h", Color.LightGreen, null, 0, GUI.SmallFont);
GUI.DrawString(spriteBatch, new Vector2(x + 20, y + height - 50),
@@ -220,7 +228,7 @@ namespace Barotrauma.Items.Components
if (autopilotRayCastTimer <= 0.0f && steeringPath.NextNode != null)
{
- Vector2 diff = Vector2.Normalize(ConvertUnits.ToSimUnits(steeringPath.NextNode.Position - Submarine.Loaded.WorldPosition));
+ Vector2 diff = Vector2.Normalize(ConvertUnits.ToSimUnits(steeringPath.NextNode.Position - item.Submarine.WorldPosition));
bool nextVisible = true;
for (int x = -1; x < 2; x += 2)
@@ -228,9 +236,9 @@ namespace Barotrauma.Items.Components
for (int y = -1; y < 2; y += 2)
{
Vector2 cornerPos =
- new Vector2(Submarine.Borders.Width * x, Submarine.Borders.Height * y) / 2.0f;
+ new Vector2(item.Submarine.Borders.Width * x, item.Submarine.Borders.Height * y) / 2.0f;
- cornerPos = ConvertUnits.ToSimUnits(cornerPos * 1.2f + Submarine.Loaded.WorldPosition);
+ cornerPos = ConvertUnits.ToSimUnits(cornerPos * 1.2f + item.Submarine.WorldPosition);
float dist = Vector2.Distance(cornerPos, steeringPath.NextNode.SimPosition);
diff --git a/Subsurface/Source/Items/Components/Power/PowerContainer.cs b/Subsurface/Source/Items/Components/Power/PowerContainer.cs
index f6400c72e..1fcf4a172 100644
--- a/Subsurface/Source/Items/Components/Power/PowerContainer.cs
+++ b/Subsurface/Source/Items/Components/Power/PowerContainer.cs
@@ -113,7 +113,7 @@ namespace Barotrauma.Items.Components
public override void Update(float deltaTime, Camera cam)
{
float chargeRate = (float)(Math.Sqrt(charge / capacity));
- //float gridPower = 0.0f;
+ float gridPower = 0.0f;
float gridLoad = 0.0f;
//if (item.linkedTo.Count == 0) return;
@@ -126,7 +126,8 @@ namespace Barotrauma.Items.Components
PowerTransfer pt = c2.Item.GetComponent();
if (pt == null || !pt.IsActive) continue;
- gridLoad += pt.PowerLoad;
+ gridLoad += pt.PowerLoad;
+ gridPower -= pt.CurrPowerConsumption;
}
}
@@ -171,27 +172,21 @@ namespace Barotrauma.Items.Components
// -maxOutput * chargeRate,
// 0.1f);
- if (outputVoltage < 1.0f)
+ if (gridPower < gridLoad)
{
+ // CurrPowerOutput = MathHelper.Lerp(
+ //CurrPowerOutput, Math.Min(maxOutput * chargeRate, gridLoad), 0.05f);
+
CurrPowerOutput = MathHelper.Lerp(
- CurrPowerOutput, Math.Min(maxOutput * chargeRate, gridLoad), 0.05f);
+ CurrPowerOutput,
+ Math.Min(maxOutput * chargeRate, gridLoad - (gridLoad * outputVoltage)),
+ 0.05f);
}
else
{
CurrPowerOutput = MathHelper.Lerp(CurrPowerOutput, 0.0f, 0.05f);
}
- CurrPowerOutput = MathHelper.Lerp(
- CurrPowerOutput,
- Math.Min(maxOutput * chargeRate, gridLoad - (gridLoad * outputVoltage)),
- 0.05f);
-
-
-
- //powerConsumption = MathHelper.Lerp(
- // powerConsumption,
- // -Math.Min(maxOutput * chargeRate, gridLoad - (power)),
- // 0.1f);
//powerConsumption = Math.Min(powerConsumption, 0.0f);
Charge -= CurrPowerOutput / 3600.0f;
diff --git a/Subsurface/Source/Items/Components/Power/PowerTransfer.cs b/Subsurface/Source/Items/Components/Power/PowerTransfer.cs
index c443b8e1d..3dbf0d3e4 100644
--- a/Subsurface/Source/Items/Components/Power/PowerTransfer.cs
+++ b/Subsurface/Source/Items/Components/Power/PowerTransfer.cs
@@ -62,6 +62,7 @@ namespace Barotrauma.Items.Components
pt.powerLoad += (fullLoad - pt.powerLoad) / inertia;
pt.currPowerConsumption += (-fullPower - pt.currPowerConsumption) / inertia;
pt.Item.SendSignal(0, "", "power", fullPower / Math.Max(fullLoad, 1.0f));
+ pt.Item.SendSignal(0, "", "power_out", fullPower / Math.Max(fullLoad, 1.0f));
//damage the item if voltage is too high
//(except if running as a client)
@@ -117,7 +118,6 @@ namespace Barotrauma.Items.Components
{
if (!c.IsPower) continue;
-
var recipients = c.Recipients;
foreach (Connection recipient in recipients)
@@ -138,7 +138,7 @@ namespace Barotrauma.Items.Components
PowerContainer powerContainer = powered as PowerContainer;
if (powerTransfer != null)
{
- if (powerTransfer.updateTimer>0) continue;
+ //if (powerTransfer.updateTimer>0) continue;
powerTransfer.CheckJunctions(deltaTime);
}
else if (powerContainer != null)
diff --git a/Subsurface/Source/Items/Components/Signal/LightComponent.cs b/Subsurface/Source/Items/Components/Signal/LightComponent.cs
index 4fa63fdd7..a761383d3 100644
--- a/Subsurface/Source/Items/Components/Signal/LightComponent.cs
+++ b/Subsurface/Source/Items/Components/Signal/LightComponent.cs
@@ -102,7 +102,7 @@ namespace Barotrauma.Items.Components
: base (item, element)
{
light = new LightSource(element);
- light.Submarine = item.CurrentHull == null ? null : item.CurrentHull.Submarine;
+ light.ParentSub = item.CurrentHull == null ? null : item.CurrentHull.Submarine;
light.Position = item.Position;
light.CastShadows = castShadows;
@@ -121,7 +121,7 @@ namespace Barotrauma.Items.Components
{
base.Update(deltaTime, cam);
- light.Submarine = item.Submarine;
+ light.ParentSub = item.Submarine;
ApplyStatusEffects(ActionType.OnActive, deltaTime);
diff --git a/Subsurface/Source/Items/Components/Signal/SignalCheckComponent.cs b/Subsurface/Source/Items/Components/Signal/SignalCheckComponent.cs
index b2e4133d9..82b7fa423 100644
--- a/Subsurface/Source/Items/Components/Signal/SignalCheckComponent.cs
+++ b/Subsurface/Source/Items/Components/Signal/SignalCheckComponent.cs
@@ -4,7 +4,7 @@ namespace Barotrauma.Items.Components
{
class SignalCheckComponent : ItemComponent
{
- private string output;
+ private string output, falseOutput;
private string targetSignal;
@@ -14,6 +14,12 @@ namespace Barotrauma.Items.Components
get { return output; }
set { output = value; }
}
+ [InGameEditable, HasDefaultValue("0", true)]
+ public string FalseOutput
+ {
+ get { return falseOutput; }
+ set { falseOutput = value; }
+ }
[InGameEditable, HasDefaultValue("", true)]
public string TargetSignal
@@ -32,7 +38,10 @@ namespace Barotrauma.Items.Components
switch (connection.Name)
{
case "signal_in":
- item.SendSignal(stepsTaken, (signal == targetSignal) ? output : "0", "signal_out");
+ string signalOut = (signal == targetSignal) ? output : falseOutput;
+
+ if (string.IsNullOrWhiteSpace(signalOut)) return;
+ item.SendSignal(stepsTaken, signalOut, "signal_out");
break;
case "set_output":
diff --git a/Subsurface/Source/Items/Components/Signal/Wire.cs b/Subsurface/Source/Items/Components/Signal/Wire.cs
index 9cb18be5f..a1bbe5540 100644
--- a/Subsurface/Source/Items/Components/Signal/Wire.cs
+++ b/Subsurface/Source/Items/Components/Signal/Wire.cs
@@ -109,6 +109,8 @@ namespace Barotrauma.Items.Components
}
}
+ item.Submarine = newConnection.Item.Submarine;
+
for (int i = 0; i < 2; i++)
{
if (connections[i] != null) continue;
@@ -117,16 +119,18 @@ namespace Barotrauma.Items.Components
if (!addNode) break;
- if (Nodes.Count > 0 && Nodes[0] == newConnection.Item.Position - Submarine.HiddenSubPosition) break;
- if (Nodes.Count > 1 && Nodes[Nodes.Count-1] == newConnection.Item.Position - Submarine.HiddenSubPosition) break;
+ if (Nodes.Count > 0 && Nodes[0] == newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition) break;
+ if (Nodes.Count > 1 && Nodes[Nodes.Count-1] == newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition) break;
+
+
if (i == 0)
{
- Nodes.Insert(0, newConnection.Item.Position - Submarine.HiddenSubPosition);
+ Nodes.Insert(0, newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition);
}
else
{
- Nodes.Add(newConnection.Item.Position - Submarine.HiddenSubPosition);
+ Nodes.Add(newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition);
}
@@ -184,7 +188,7 @@ namespace Barotrauma.Items.Components
{
if (Nodes.Count == 0) return;
- item.FindHull();
+ //item.FindHull();
//Vector2 position = item.Position;
@@ -200,7 +204,11 @@ namespace Barotrauma.Items.Components
// position.Y += item.CurrentHull.Rect.Y - item.CurrentHull.Rect.Height;
//}
- newNodePos = RoundNode(item.Position, item.CurrentHull)-Submarine.HiddenSubPosition;
+ Submarine sub = null;
+ if (connections[0] != null && connections[0].Item.Submarine != null) sub = connections[0].Item.Submarine;
+ if (connections[1] != null && connections[1].Item.Submarine != null) sub = connections[1].Item.Submarine;
+
+ newNodePos = RoundNode(item.Position, item.CurrentHull) - sub.HiddenSubPosition;
//if (Vector2.Distance(position, nodes[nodes.Count - 1]) > nodeDistance*10)
//{
@@ -366,7 +374,7 @@ namespace Barotrauma.Items.Components
for (int i = 0; i < Nodes.Count; i++)
{
Vector2 worldPos = Nodes[i];
- if (Submarine.Loaded != null) worldPos += Submarine.Loaded.Position + Submarine.HiddenSubPosition;
+ if (item.Submarine != null) worldPos += item.Submarine.Position + item.Submarine.HiddenSubPosition;
worldPos.Y = -worldPos.Y;
GUI.DrawRectangle(spriteBatch, worldPos + new Vector2(-3, -3), new Vector2(6, 6), item.Color, true, 0.0f);
@@ -407,7 +415,12 @@ namespace Barotrauma.Items.Components
MapEntity.DisableSelect = true;
//Nodes[(int)selectedNodeIndex] = GameMain.EditMapScreen.Cam.ScreenToWorld(PlayerInput.MousePosition)-Submarine.HiddenSubPosition+Submarine.Loaded.Position;
- Vector2 nodeWorldPos = GameMain.EditMapScreen.Cam.ScreenToWorld(PlayerInput.MousePosition) - Submarine.HiddenSubPosition - Submarine.Loaded.Position;// Nodes[(int)selectedNodeIndex];
+
+ Submarine sub = null;
+ if (connections[0] != null && connections[0].Item.Submarine != null) sub = connections[0].Item.Submarine;
+ if (connections[1] != null && connections[1].Item.Submarine != null) sub = connections[1].Item.Submarine;
+
+ Vector2 nodeWorldPos = GameMain.EditMapScreen.Cam.ScreenToWorld(PlayerInput.MousePosition) - sub.HiddenSubPosition - sub.Position;// Nodes[(int)selectedNodeIndex];
nodeWorldPos.X = MathUtils.Round(nodeWorldPos.X, Submarine.GridSize.X / 2.0f);
nodeWorldPos.Y = MathUtils.Round(nodeWorldPos.Y, Submarine.GridSize.Y / 2.0f);
@@ -428,10 +441,10 @@ namespace Barotrauma.Items.Components
private void DrawSection(SpriteBatch spriteBatch, Vector2 start, Vector2 end, Color color, float width = 0.3f)
{
- if (Submarine.Loaded!=null)
+ if (item.Submarine != null)
{
- start += Submarine.Loaded.DrawPosition + Submarine.HiddenSubPosition;
- end += Submarine.Loaded.DrawPosition + Submarine.HiddenSubPosition;
+ start += item.Submarine.DrawPosition + item.Submarine.HiddenSubPosition;
+ end += item.Submarine.DrawPosition + item.Submarine.HiddenSubPosition;
}
start.Y = -start.Y;
diff --git a/Subsurface/Source/Items/Item.cs b/Subsurface/Source/Items/Item.cs
index 6ba173892..2f79d7a0a 100644
--- a/Subsurface/Source/Items/Item.cs
+++ b/Subsurface/Source/Items/Item.cs
@@ -19,7 +19,7 @@ namespace Barotrauma
public enum ActionType
{
- Always, OnPicked, OnUse,
+ Always, OnPicked, OnUse, OnSecondaryUse,
OnWearing, OnContaining, OnContained,
OnActive, OnFailure, OnBroken,
OnFire, InWater,
@@ -523,9 +523,9 @@ namespace Barotrauma
}
CurrentHull = Hull.FindHull(WorldPosition, CurrentHull);
- if (body != null)
+ if (body != null && body.Enabled)
{
- Submarine = CurrentHull == null ? null : Submarine.Loaded;
+ Submarine = CurrentHull == null ? null : CurrentHull.Submarine;
body.Submarine = Submarine;
}
@@ -1248,6 +1248,7 @@ namespace Barotrauma
{
picked = true;
ic.ApplyStatusEffects(ActionType.OnPicked, 1.0f, picker);
+ ic.PlaySound(ActionType.OnPicked, picker.WorldPosition);
if (picker==Character.Controlled) GUIComponent.MouseOn = null;
@@ -1432,12 +1433,14 @@ namespace Barotrauma
return true;
}
- public override XElement Save(XDocument doc)
+ public override XElement Save(XElement parentElement)
{
XElement element = new XElement("Item");
element.Add(new XAttribute("name", prefab.Name),
new XAttribute("ID", ID));
+
+ System.Diagnostics.Debug.Assert(Submarine != null);
if (ResizeHorizontal || ResizeVertical)
{
@@ -1473,7 +1476,7 @@ namespace Barotrauma
ic.Save(element);
}
- doc.Root.Add(element);
+ parentElement.Add(element);
return element;
}
diff --git a/Subsurface/Source/Items/ItemPrefab.cs b/Subsurface/Source/Items/ItemPrefab.cs
index e75d2e392..e23f345f3 100644
--- a/Subsurface/Source/Items/ItemPrefab.cs
+++ b/Subsurface/Source/Items/ItemPrefab.cs
@@ -109,7 +109,7 @@ namespace Barotrauma
public override void UpdatePlacing(SpriteBatch spriteBatch, Camera cam)
{
- Vector2 position = Submarine.MouseToWorldGrid(cam);
+ Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);
if (PlayerInput.RightButtonClicked())
{
@@ -121,10 +121,10 @@ namespace Barotrauma
{
if (PlayerInput.LeftButtonClicked())
{
- var item = new Item(new Rectangle((int)position.X, (int)position.Y, (int)sprite.size.X, (int)sprite.size.Y), this, Submarine.Loaded);
+ var item = new Item(new Rectangle((int)position.X, (int)position.Y, (int)sprite.size.X, (int)sprite.size.Y), this, Submarine.MainSub);
//constructor.Invoke(lobject);
- item.Submarine = Submarine.Loaded;
- item.SetTransform(ConvertUnits.ToSimUnits(Submarine.Loaded==null ? item.Position : item.Position - Submarine.Loaded.Position), 0.0f);
+ item.Submarine = Submarine.MainSub;
+ item.SetTransform(ConvertUnits.ToSimUnits(Submarine.MainSub==null ? item.Position : item.Position - Submarine.MainSub.Position), 0.0f);
item.FindHull();
placePosition = Vector2.Zero;
@@ -152,11 +152,11 @@ namespace Barotrauma
if (PlayerInput.LeftButtonReleased())
{
- var item = new Item(new Rectangle((int)placePosition.X, (int)placePosition.Y, (int)placeSize.X, (int)placeSize.Y), this, Submarine.Loaded);
+ var item = new Item(new Rectangle((int)placePosition.X, (int)placePosition.Y, (int)placeSize.X, (int)placeSize.Y), this, Submarine.MainSub);
placePosition = Vector2.Zero;
- item.Submarine = Submarine.Loaded;
- item.SetTransform(ConvertUnits.ToSimUnits(Submarine.Loaded == null ? item.Position : item.Position - Submarine.Loaded.Position), 0.0f);
+ item.Submarine = Submarine.MainSub;
+ item.SetTransform(ConvertUnits.ToSimUnits(Submarine.MainSub == null ? item.Position : item.Position - Submarine.MainSub.Position), 0.0f);
item.FindHull();
//selected = null;
diff --git a/Subsurface/Source/Items/ItemSpawner.cs b/Subsurface/Source/Items/ItemSpawner.cs
index 73a53a293..7899ba652 100644
--- a/Subsurface/Source/Items/ItemSpawner.cs
+++ b/Subsurface/Source/Items/ItemSpawner.cs
@@ -13,20 +13,20 @@ namespace Barotrauma
spawnQueue = new Queue>();
}
- public void QueueItem(ItemPrefab itemPrefab, Vector2 position, bool isNetworkMessage = false)
- {
- if (!isNetworkMessage && GameMain.Client!=null)
- {
- //clients aren't allowed to spawn new items unless the server says so
- return;
- }
+ //public void QueueItem(ItemPrefab itemPrefab, Vector2 position, bool isNetworkMessage = false)
+ //{
+ // if (!isNetworkMessage && GameMain.Client!=null)
+ // {
+ // //clients aren't allowed to spawn new items unless the server says so
+ // return;
+ // }
- var itemInfo = new Pair();
- itemInfo.First = itemPrefab;
- itemInfo.Second = position;
+ // var itemInfo = new Pair();
+ // itemInfo.First = itemPrefab;
+ // itemInfo.Second = position;
- spawnQueue.Enqueue(itemInfo);
- }
+ // spawnQueue.Enqueue(itemInfo);
+ //}
public void QueueItem(ItemPrefab itemPrefab, Inventory inventory, bool isNetworkMessage = false)
{
@@ -54,15 +54,17 @@ namespace Barotrauma
{
var itemInfo = spawnQueue.Dequeue();
- if (itemInfo.Second is Vector2)
- {
- Vector2 position = (Vector2)itemInfo.Second - Submarine.HiddenSubPosition;
+ //if (itemInfo.Second is Vector2)
+ //{
+ // //todo: take multiple subs into account
+ // Vector2 position = (Vector2)itemInfo.Second - Submarine.MainSub.HiddenSubPosition;
- items.Add(new Item(itemInfo.First, position, null));
- inventories.Add(null);
+ // items.Add(new Item(itemInfo.First, position, null));
+ // inventories.Add(null);
- }
- else if (itemInfo.Second is Inventory)
+ //}
+ //else
+ if (itemInfo.Second is Inventory)
{
var item = new Item(itemInfo.First, Vector2.Zero, null);
diff --git a/Subsurface/Source/Map/Entity.cs b/Subsurface/Source/Map/Entity.cs
index cad366b60..ccb0f386c 100644
--- a/Subsurface/Source/Map/Entity.cs
+++ b/Subsurface/Source/Map/Entity.cs
@@ -81,7 +81,7 @@ namespace Barotrauma
//give an unique ID
bool IDfound;
- id = 1;//Rand.Int(int.MaxValue);
+ id = submarine == null ? (ushort)1 : submarine.IdOffset;
do
{
id += 1;
diff --git a/Subsurface/Source/Map/EntityGrid.cs b/Subsurface/Source/Map/EntityGrid.cs
index b5b5b9d90..efd1088ef 100644
--- a/Subsurface/Source/Map/EntityGrid.cs
+++ b/Subsurface/Source/Map/EntityGrid.cs
@@ -12,9 +12,12 @@ namespace Barotrauma
private float cellSize;
- public EntityGrid(Rectangle limits, float cellSize)
+ public readonly Submarine Submarine;
+
+ public EntityGrid(Submarine submarine, float cellSize)
{
- this.limits = limits;
+ this.limits = submarine.Borders;
+ this.Submarine = submarine;
this.cellSize = cellSize;
entities = new List[(int)Math.Ceiling(limits.Width / cellSize), (int)Math.Ceiling(limits.Height / cellSize)];
@@ -71,11 +74,28 @@ namespace Barotrauma
}
}
+ public static List GetEntities(List entityGrids, Vector2 position, bool useWorldCoordinates = true)
+ {
+ List entities = new List();
+ foreach (EntityGrid entityGrid in entityGrids)
+ {
+ Vector2 transformedPosition = position;
+ if (useWorldCoordinates)
+ {
+ transformedPosition -= entityGrid.Submarine.Position;
+ }
+
+ entities.AddRange(entityGrid.GetEntities(transformedPosition));
+ }
+
+ return entities;
+ }
+
public List GetEntities(Vector2 position)
{
if (!MathUtils.IsValid(position)) new List();
- if (Submarine.Loaded != null) position -= Submarine.HiddenSubPosition;
+ if (Submarine != null) position -= Submarine.HiddenSubPosition;
Point indices = GetIndices(position);
diff --git a/Subsurface/Source/Map/Gap.cs b/Subsurface/Source/Map/Gap.cs
index 930cb574c..7c266cac7 100644
--- a/Subsurface/Source/Map/Gap.cs
+++ b/Subsurface/Source/Map/Gap.cs
@@ -83,7 +83,7 @@ namespace Barotrauma
}
public Gap(MapEntityPrefab prefab, Rectangle rectangle)
- : this (rectangle, Submarine.Loaded)
+ : this (rectangle, Submarine.MainSub)
{ }
public Gap(Rectangle newRect, Submarine submarine)
@@ -173,8 +173,6 @@ namespace Barotrauma
{
Vector2 center = new Vector2(WorldRect.X + rect.Width / 2.0f, -(WorldRect.Y - rect.Height/ 2.0f));
-
-
GUI.DrawLine(sb, center, center + new Vector2(flowForce.X, -flowForce.Y)/10.0f, Color.Red);
GUI.DrawLine(sb, center + Vector2.One * 5.0f, center + new Vector2(lerpedFlowForce.X, -lerpedFlowForce.Y) / 10.0f + Vector2.One * 5.0f, Color.Orange);
@@ -253,7 +251,7 @@ namespace Barotrauma
var particle = GameMain.ParticleManager.CreateParticle(
"watersplash",
- (Submarine.Loaded == null ? pos : pos + Submarine.Loaded.Position) - Vector2.UnitY * Rand.Range(0.0f, 10.0f),
+ (Submarine == null ? pos : pos + Submarine.Position) - Vector2.UnitY * Rand.Range(0.0f, 10.0f),
velocity);
if (particle != null)
@@ -269,7 +267,7 @@ namespace Barotrauma
GameMain.ParticleManager.CreateParticle(
"bubbles",
- Submarine.Loaded == null ? pos : pos + Submarine.Loaded.Position,
+ Submarine == null ? pos : pos + Submarine.Position,
flowForce / 10.0f);
}
}
@@ -288,14 +286,14 @@ namespace Barotrauma
var splash = GameMain.ParticleManager.CreateParticle(
"watersplash",
- Submarine.Loaded == null ? pos : pos + Submarine.Loaded.Position,
+ Submarine == null ? pos : pos + Submarine.Position,
-velocity, 0, FlowTargetHull);
if (splash != null) splash.Size = splash.Size * MathHelper.Clamp(rect.Width / 50.0f, 0.8f, 4.0f);
GameMain.ParticleManager.CreateParticle(
"bubbles",
- Submarine.Loaded == null ? pos : pos + Submarine.Loaded.Position,
+ Submarine == null ? pos : pos + Submarine.Position,
flowForce / 2.0f, 0, FlowTargetHull);
}
}
@@ -329,6 +327,18 @@ namespace Barotrauma
if (linkedTo.Count < 2) return;
Hull hull1 = (Hull)linkedTo[0];
Hull hull2 = (Hull)linkedTo[1];
+
+ Vector2 subOffset = Vector2.Zero;
+ if (hull1.Submarine != Submarine)
+ {
+ subOffset =Submarine.Position - hull1.Submarine.Position;
+ }
+ else if (hull2.Submarine != Submarine)
+ {
+
+ subOffset = hull2.Submarine.Position - Submarine.Position;
+
+ }
if (hull1.Volume == 0.0 && hull2.Volume == 0.0) return;
@@ -341,13 +351,14 @@ namespace Barotrauma
//horizontal gap (such as a regular door)
if (isHorizontal)
{
- higherSurface = Math.Max(hull1.Surface,hull2.Surface);
- float delta=0.0f;
+ higherSurface = Math.Max(hull1.Surface, hull2.Surface + subOffset.Y);
+ float delta=0.0f;
+
//water level is above the lower boundary of the gap
- if (Math.Max(hull1.Surface+hull1.WaveY[hull1.WaveY.Length - 1], hull2.Surface+hull2.WaveY[0]) > rect.Y - size)
+ if (Math.Max(hull1.Surface+hull1.WaveY[hull1.WaveY.Length - 1], hull2.Surface + subOffset.Y +hull2.WaveY[0]) > rect.Y - size)
{
- int dir = (hull1.Pressure > hull2.Pressure) ? 1 : -1;
+ int dir = (hull1.Pressure > hull2.Pressure+subOffset.Y) ? 1 : -1;
//water flowing from the righthand room to the lefthand room
if (dir == -1)
@@ -360,38 +371,42 @@ namespace Barotrauma
flowTargetHull = hull1;
//make sure not to move more than what the room contains
- delta = Math.Min((hull2.Pressure - hull1.Pressure) * 5.0f * sizeModifier, Math.Min(hull2.Volume, hull2.FullVolume));
+ delta = Math.Min(((hull2.Pressure + subOffset.Y) - hull1.Pressure) * 5.0f * sizeModifier, Math.Min(hull2.Volume, hull2.FullVolume));
//make sure not to place more water to the target room than it can hold
delta = Math.Min(delta, hull1.FullVolume + Hull.MaxCompress - (hull1.Volume));
hull1.Volume += delta;
hull2.Volume -= delta;
if (hull1.Volume > hull1.FullVolume)
- hull1.Pressure = Math.Max(hull1.Pressure, (hull1.Pressure + hull2.Pressure) / 2);
+ {
+ hull1.Pressure = Math.Max(hull1.Pressure, (hull1.Pressure + hull2.Pressure+subOffset.Y) / 2);
+ }
flowForce = new Vector2(-delta, 0.0f);
}
else if (dir == 1)
{
if (!(hull1.Volume > 0.0f)) return;
- lowerSurface = hull2.Surface - hull2.WaveY[1];
+ //lowerSurface = hull2.Surface - hull2.WaveY[1];
flowTargetHull = hull2;
//make sure not to move more than what the room contains
- delta = Math.Min((hull1.Pressure - hull2.Pressure) * 5.0f * sizeModifier, Math.Min(hull1.Volume, hull1.FullVolume));
+ delta = Math.Min((hull1.Pressure - (hull2.Pressure + subOffset.Y)) * 5.0f * sizeModifier, Math.Min(hull1.Volume, hull1.FullVolume));
//make sure not to place more water to the target room than it can hold
delta = Math.Min(delta, hull2.FullVolume + Hull.MaxCompress - (hull2.Volume));
hull1.Volume -= delta;
hull2.Volume += delta;
if (hull2.Volume > hull2.FullVolume)
- hull2.Pressure = Math.Max(hull2.Pressure, (hull1.Pressure + hull2.Pressure) / 2);
+ {
+ hull2.Pressure = Math.Max(hull2.Pressure, ((hull1.Pressure-subOffset.Y) + hull2.Pressure) / 2);
+ }
flowForce = new Vector2(delta, 0.0f);
}
- if (delta>100.0f)
+ if (delta>100.0f && subOffset == Vector2.Zero)
{
float avg = (hull1.Surface + hull2.Surface) / 2.0f;
//float avgVel = (hull2.WaveVel[1] + hull1.WaveVel[hull1.WaveY.Length - 2]) / 2.0f;
@@ -419,11 +434,11 @@ namespace Barotrauma
else
{
//lower room is full of water
- if (hull2.Pressure > hull1.Pressure)
+ if ((hull2.Pressure + subOffset.Y) > hull1.Pressure)
{
float delta = Math.Min(hull2.Volume - hull2.FullVolume + Hull.MaxCompress / 2.0f, deltaTime * 8000.0f * sizeModifier);
- flowForce = new Vector2(0.0f, Math.Min(hull2.Pressure - hull1.Pressure, 500.0f));
+ flowForce = new Vector2(0.0f, Math.Min((hull2.Pressure + subOffset.Y) - hull1.Pressure, 500.0f));
delta = Math.Max(delta, 0.0f);
hull1.Volume += delta;
@@ -433,7 +448,7 @@ namespace Barotrauma
if (hull1.Volume > hull1.FullVolume)
{
- hull1.Pressure = Math.Max(hull1.Pressure, (hull1.Pressure + hull2.Pressure) / 2);
+ hull1.Pressure = Math.Max(hull1.Pressure, (hull1.Pressure + (hull2.Pressure + subOffset.Y)) / 2);
}
}
@@ -446,16 +461,16 @@ namespace Barotrauma
float delta = Math.Min(hull1.Volume, deltaTime * 25000f * sizeModifier);
//make sure not to place more water to the target room than it can hold
delta = Math.Min(delta, (hull2.FullVolume + Math.Max(hull1.Volume - hull1.FullVolume, 0.0f)) - hull2.Volume + Hull.MaxCompress / 4.0f);
-
+
hull1.Volume -= delta;
hull2.Volume += delta;
if (hull2.Volume > hull2.FullVolume)
{
- hull2.Pressure = Math.Max(hull2.Pressure, (hull1.Pressure + hull2.Pressure) / 2);
+ hull2.Pressure = Math.Max(hull2.Pressure, ((hull1.Pressure - subOffset.Y) + hull2.Pressure) / 2);
}
- flowForce = new Vector2(0.0f,-delta);
+ flowForce = new Vector2(0.0f, -delta);
flowForce.X = hull1.WaveY[hull1.GetWaveIndex(rect.X)] - hull1.WaveY[hull1.GetWaveIndex(rect.Right)] * 10.0f;
@@ -552,7 +567,7 @@ namespace Barotrauma
}
else
{
- hull1.LethalPressure += (Submarine.Loaded != null && Submarine.Loaded.AtDamageDepth) ? 100.0f * deltaTime : 10.0f * deltaTime;
+ hull1.LethalPressure += (Submarine != null && Submarine.AtDamageDepth) ? 100.0f * deltaTime : 10.0f * deltaTime;
}
}
else
@@ -567,7 +582,7 @@ namespace Barotrauma
}
if (hull1.Volume >= hull1.FullVolume - Hull.MaxCompress)
{
- hull1.LethalPressure += (Submarine.Loaded != null && Submarine.Loaded.AtDamageDepth) ? 100.0f * deltaTime : 10.0f * deltaTime;
+ hull1.LethalPressure += (Submarine != null && Submarine.AtDamageDepth) ? 100.0f * deltaTime : 10.0f * deltaTime;
}
}
@@ -625,10 +640,9 @@ namespace Barotrauma
GapList.Remove(this);
- foreach (MapEntity entity in linkedTo)
+ foreach (Hull hull in Hull.hullList)
{
- var hull = entity as Hull;
- if (hull.ConnectedGaps.Contains(this)) hull.ConnectedGaps.Remove(this);
+ hull.ConnectedGaps.Remove(this);
}
}
@@ -639,7 +653,7 @@ namespace Barotrauma
FindHulls();
}
- public override XElement Save(XDocument doc)
+ public override XElement Save(XElement parentElement)
{
XElement element = new XElement("Gap");
@@ -663,7 +677,7 @@ namespace Barotrauma
// }
//}
- doc.Root.Add(element);
+ parentElement.Add(element);
return element;
}
diff --git a/Subsurface/Source/Map/Hull.cs b/Subsurface/Source/Map/Hull.cs
index 9b9fb22eb..681b02dd6 100644
--- a/Subsurface/Source/Map/Hull.cs
+++ b/Subsurface/Source/Map/Hull.cs
@@ -15,7 +15,7 @@ namespace Barotrauma
class Hull : MapEntity, IPropertyObject
{
public static List hullList = new List();
- private static EntityGrid entityGrid;
+ private static List entityGrids = new List();
public static bool ShowHulls = true;
@@ -53,6 +53,7 @@ namespace Barotrauma
private bool update;
+ private Sound currentFlowSound;
private int soundIndex;
private float soundVolume;
@@ -178,7 +179,7 @@ namespace Barotrauma
}
public Hull(MapEntityPrefab prefab, Rectangle rectangle)
- : this (prefab, rectangle, Submarine.Loaded)
+ : this (prefab, rectangle, Submarine.MainSub)
{
}
@@ -248,13 +249,30 @@ namespace Barotrauma
return rect;
}
- public static void GenerateEntityGrid()
+ public static void GenerateEntityGrid(Submarine submarine)
{
- entityGrid = new EntityGrid(Submarine.Borders, 200.0f);
+ var newGrid = new EntityGrid(submarine, 200.0f);
+
+ entityGrids.Add(newGrid);
foreach (Hull hull in hullList)
{
- entityGrid.InsertEntity(hull);
+ if (hull.Submarine == submarine) newGrid.InsertEntity(hull);
+ }
+ }
+
+ public void AddToGrid(Submarine submarine)
+ {
+ foreach (EntityGrid grid in entityGrids)
+ {
+ if (grid.Submarine != submarine) continue;
+
+ rect.Location -= submarine.HiddenSubPosition.ToPoint();
+
+ grid.InsertEntity(this);
+
+ rect.Location += submarine.HiddenSubPosition.ToPoint();
+ return;
}
}
@@ -293,6 +311,7 @@ namespace Barotrauma
public override void Remove()
{
base.Remove();
+ hullList.Remove(this);
if (Submarine == null || !Submarine.Loading)
{
@@ -313,10 +332,15 @@ namespace Barotrauma
}
//renderer.Dispose();
+ if (entityGrids != null)
+ {
+ foreach (EntityGrid entityGrid in entityGrids)
+ {
+ entityGrid.RemoveEntity(this);
+ }
+ }
- if (entityGrid != null) entityGrid.RemoveEntity(this);
- hullList.Remove(this);
}
public void AddFireSource(FireSource fireSource, bool createNetworkEvent = true)
@@ -369,12 +393,24 @@ namespace Barotrauma
foreach (Gap gap in ConnectedGaps)
{
float gapFlow = gap.LerpedFlowForce.Length();
+
+#if DEBUG
+ var asd = MapEntity.FindEntityByID(gap.ID);
+
+ if (asd != gap)
+ {
+ int adslkmfdlasfk = 9;
+ }
+#endif
+
+
if (gapFlow > strongestFlow)
{
strongestFlow = gapFlow;
}
}
+
if (strongestFlow>0.1f)
{
soundVolume = soundVolume + ((strongestFlow < 100.0f) ? -deltaTime * 0.5f : deltaTime * 0.5f);
@@ -383,13 +419,24 @@ namespace Barotrauma
int index = (int)Math.Floor(strongestFlow / 100.0f);
index = Math.Min(index, 2);
- soundIndex = SoundPlayer.flowSounds[index].Loop(soundIndex, soundVolume, WorldPosition, 2000.0f);
+ var flowSound = SoundPlayer.flowSounds[index];
+ if (flowSound != currentFlowSound && soundIndex > -1)
+ {
+ Sounds.SoundManager.Stop(soundIndex);
+ currentFlowSound = null;
+ soundIndex = -1;
+ }
+
+ currentFlowSound = flowSound;
+
+ soundIndex = currentFlowSound.Loop(soundIndex, soundVolume, WorldPosition, 2000.0f);
}
else
{
if (soundIndex > -1)
{
Sounds.SoundManager.Stop(soundIndex);
+ currentFlowSound = null;
soundIndex = -1;
}
}
@@ -653,15 +700,14 @@ namespace Barotrauma
//returns the water block which contains the point (or null if it isn't inside any)
public static Hull FindHull(Vector2 position, Hull guess = null, bool useWorldCoordinates = true)
{
- if (entityGrid == null) return null;
+ if (entityGrids == null) return null;
if (guess != null)
{
if (Submarine.RectContains(useWorldCoordinates ? guess.WorldRect : guess.rect, position)) return guess;
}
- var entities = entityGrid.GetEntities(
- useWorldCoordinates && Submarine.Loaded!=null ? position-Submarine.Loaded.Position : position);
+ var entities = EntityGrid.GetEntities(entityGrids, position, useWorldCoordinates);
foreach (Hull hull in entities)
{
@@ -706,7 +752,7 @@ namespace Barotrauma
// return gaps;
//}
- public override XElement Save(XDocument doc)
+ public override XElement Save(XElement parentElement)
{
XElement element = new XElement("Hull");
@@ -719,8 +765,8 @@ namespace Barotrauma
rect.Width + "," + rect.Height),
new XAttribute("water", volume)
);
-
- doc.Root.Add(element);
+
+ parentElement.Add(element);
return element;
}
@@ -836,7 +882,7 @@ namespace Barotrauma
}
else
{
- var newFire = new FireSource(pos + Submarine.Loaded.Position, this, true);
+ var newFire = new FireSource(pos + Submarine.Position, this, true);
newFire.Size = new Vector2(
newFire.Hull == null ? size : size * newFire.Hull.rect.Width,
newFire.Size.Y);
diff --git a/Subsurface/Source/Map/Levels/Level.cs b/Subsurface/Source/Map/Levels/Level.cs
index 338de50a6..5516f9ed2 100644
--- a/Subsurface/Source/Map/Levels/Level.cs
+++ b/Subsurface/Source/Map/Levels/Level.cs
@@ -17,6 +17,8 @@ namespace Barotrauma
class Level
{
+ public const float ShaftHeight = 1000.0f;
+
public static Level Loaded
{
get { return loaded; }
@@ -56,7 +58,7 @@ namespace Barotrauma
private WrappingWall[,] wrappingWalls;
- private float shaftHeight;
+ //private float shaftHeight;
//List bodies;
private List cells;
@@ -121,7 +123,7 @@ namespace Barotrauma
{
get { return backgroundColor; }
}
-
+
public Level(string seed, float difficulty, int width, int height, int siteInterval)
{
this.seed = seed;
@@ -181,7 +183,7 @@ namespace Barotrauma
float avgValue = (backgroundColor.R + backgroundColor.G + backgroundColor.G) / 3;
GameMain.LightManager.AmbientLight = new Color(backgroundColor*(40.0f/avgValue), 1.0f);
- float minWidth = Submarine.Loaded == null ? 0.0f : Math.Max(Submarine.Borders.Width, Submarine.Borders.Height);
+ float minWidth = Submarine.MainSub == null ? 0.0f : Math.Max(Submarine.MainSub.Borders.Width, Submarine.MainSub.Borders.Height);
minWidth = Math.Max(minWidth, 6500.0f);
startPosition = new Vector2(minWidth * 2, Rand.Range(minWidth * 2, borders.Height - minWidth * 2, false));
@@ -513,7 +515,7 @@ namespace Barotrauma
ShaftBodies = new Body[2];
for (int i = 0; i < 2; i++)
{
- ShaftBodies[i] = BodyFactory.CreateRectangle(GameMain.World, 200.0f, 10.0f, 5.0f);
+ ShaftBodies[i] = BodyFactory.CreateRectangle(GameMain.World, 200.0f, ConvertUnits.ToSimUnits(ShaftHeight), 5.0f);
ShaftBodies[i].BodyType = BodyType.Static;
ShaftBodies[i].CollisionCategories = Physics.CollisionLevel;
@@ -585,7 +587,7 @@ namespace Barotrauma
{
List wayPoints = new List();
- var newWaypoint = new WayPoint(new Rectangle((int)pathCells[0].Center.X, (int)(borders.Height + shaftHeight), 10, 10), null);
+ var newWaypoint = new WayPoint(new Rectangle((int)pathCells[0].Center.X, borders.Height, 10, 10), null);
newWaypoint.MoveWithLevel = true;
wayPoints.Add(newWaypoint);
@@ -625,7 +627,7 @@ namespace Barotrauma
//prevWaypoint = newWaypoint;
}
- newWaypoint = new WayPoint(new Rectangle((int)pathCells[pathCells.Count - 1].Center.X, (int)(borders.Height + shaftHeight), 10, 10), null);
+ newWaypoint = new WayPoint(new Rectangle((int)pathCells[pathCells.Count - 1].Center.X, borders.Height, 10, 10), null);
newWaypoint.MoveWithLevel = true;
wayPoints.Add(newWaypoint);
@@ -783,9 +785,9 @@ namespace Barotrauma
public void Update (float deltaTime)
{
- if (Submarine.Loaded != null)
+ if (Submarine.MainSub != null)
{
- WrappingWall.UpdateWallShift(Submarine.Loaded.WorldPosition, wrappingWalls);
+ WrappingWall.UpdateWallShift(Submarine.MainSub.WorldPosition, wrappingWalls);
}
renderer.Update(deltaTime);
diff --git a/Subsurface/Source/Map/Levels/Ruins/RuinGenerator.cs b/Subsurface/Source/Map/Levels/Ruins/RuinGenerator.cs
index cf4c1e67f..832339281 100644
--- a/Subsurface/Source/Map/Levels/Ruins/RuinGenerator.cs
+++ b/Subsurface/Source/Map/Levels/Ruins/RuinGenerator.cs
@@ -319,9 +319,11 @@ namespace Barotrauma.RuinGeneration
(int)((wall.B.X - wall.A.X) + radius*2.0f),
(int)((wall.B.Y - wall.A.Y) + radius*2.0f));
+ //cut a section off from both ends of a horizontal wall to get nicer looking corners
if (wall.A.Y == wall.B.Y)
{
rect.Inflate(-32, 0);
+ if (rect.Width < Submarine.GridSize.X) continue;
}
var structure = new Structure(rect, structurePrefab.Prefab as StructurePrefab, null);
diff --git a/Subsurface/Source/Map/Lights/ConvexHull.cs b/Subsurface/Source/Map/Lights/ConvexHull.cs
index 7453f2246..73e791966 100644
--- a/Subsurface/Source/Map/Lights/ConvexHull.cs
+++ b/Subsurface/Source/Map/Lights/ConvexHull.cs
@@ -42,9 +42,21 @@ namespace Barotrauma.Lights
}
}
+ class ConvexHullList
+ {
+ public readonly Submarine Submarine;
+ public List List;
+
+ public ConvexHullList(Submarine submarine)
+ {
+ Submarine = submarine;
+ List = new List();
+ }
+ }
+
class ConvexHull
{
- public static List list = new List();
+ public static List HullLists = new List();
static BasicEffect shadowEffect;
static BasicEffect penumbraEffect;
@@ -116,15 +128,20 @@ namespace Barotrauma.Lights
Enabled = true;
- foreach (ConvexHull ch in list)
+ var chList = HullLists.Find(x => x.Submarine == parent.Submarine);
+ if (chList == null)
+ {
+ chList = new ConvexHullList(parent.Submarine);
+ HullLists.Add(chList);
+ }
+
+ foreach (ConvexHull ch in chList.List)
{
UpdateIgnoredEdges(ch);
ch.UpdateIgnoredEdges(this);
}
-
- list.Add(this);
-
+ chList.List.Add(this);
}
private void UpdateIgnoredEdges(ConvexHull ch)
@@ -219,7 +236,7 @@ namespace Barotrauma.Lights
{
foreach (KeyValuePair cachedShadow in cachedShadows)
{
- cachedShadow.Key.NeedsHullUpdate();
+ cachedShadow.Key.NeedsHullUpdate = true;
cachedShadow.Value.Dispose();
}
cachedShadows.Clear();
@@ -375,7 +392,18 @@ namespace Barotrauma.Lights
Vector2 lightSourcePos = light.Position;
- if (light.Submarine==null && parentEntity != null && parentEntity.Submarine != null) lightSourcePos -= parentEntity.Submarine.Position;
+ if (parentEntity != null && parentEntity.Submarine != null)
+ {
+ if (light.ParentSub == null)
+ {
+ lightSourcePos -= parentEntity.Submarine.Position;
+ }
+ else if (light.ParentSub != parentEntity.Submarine)
+ {
+ lightSourcePos += (light.ParentSub.Position-parentEntity.Submarine.Position);
+ }
+
+ }
CachedShadow cachedShadow = null;
if (!cachedShadows.TryGetValue(light, out cachedShadow) ||
@@ -456,7 +484,16 @@ namespace Barotrauma.Lights
{
ClearCachedShadows();
- list.Remove(this);
+ var chList = HullLists.Find(x => x.Submarine == parentEntity.Submarine);
+
+ if (chList != null)
+ {
+ chList.List.Remove(this);
+ if (chList.List.Count == 0)
+ {
+ HullLists.Remove(chList);
+ }
+ }
}
diff --git a/Subsurface/Source/Map/Lights/LightManager.cs b/Subsurface/Source/Map/Lights/LightManager.cs
index 21093cc70..7281cf055 100644
--- a/Subsurface/Source/Map/Lights/LightManager.cs
+++ b/Subsurface/Source/Map/Lights/LightManager.cs
@@ -73,7 +73,7 @@ namespace Barotrauma.Lights
{
foreach (LightSource light in lights)
{
- light.UpdateHullsInRange();
+ light.NeedsHullUpdate = true;
}
}
@@ -94,9 +94,8 @@ namespace Barotrauma.Lights
foreach (LightSource light in lights)
{
- if (light.Color.A < 0.01f || light.Range < 1.0f) continue;
- if (light.hullsInRange == null) light.UpdateHullsInRange();
- if (!light.hullsInRange.Any() || !MathUtils.CircleIntersectsRectangle(light.WorldPosition, light.Range, viewRect)) continue;
+ if (light.Color.A < 0.01f || light.Range < 1.0f || !light.CastShadows) continue;
+ if (!MathUtils.CircleIntersectsRectangle(light.WorldPosition, light.Range, viewRect)) continue;
//clear alpha to 1
ClearAlphaToOne(graphics, spriteBatch);
@@ -106,12 +105,7 @@ namespace Barotrauma.Lights
graphics.RasterizerState = RasterizerState.CullNone;
graphics.BlendState = CustomBlendStates.WriteToAlpha;
- foreach (ConvexHull ch in light.hullsInRange)
- {
- //if (!MathUtils.CircleIntersectsRectangle(light.Position, light.Range, ch.BoundingBox)) continue;
- //draw shadow
- ch.DrawShadows(graphics, cam, light, shadowTransform, false);
- }
+ light.DrawShadows(graphics, cam, shadowTransform);
//draw the light shape
//where Alpha is 0, nothing will be written
@@ -130,7 +124,7 @@ namespace Barotrauma.Lights
foreach (LightSource light in lights)
{
- if (light.hullsInRange==null || light.hullsInRange.Any() || light.Color.A < 0.01f) continue;
+ if (light.Color.A < 0.01f || light.Range < 1.0f || light.CastShadows) continue;
//if (!MathUtils.CircleIntersectsRectangle(light.WorldPosition, light.Range, viewRect)) continue;
light.Draw(spriteBatch);
@@ -185,13 +179,18 @@ namespace Barotrauma.Lights
Matrix shadowTransform = cam.ShaderTransform
* Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f;
- foreach (ConvexHull convexHull in ConvexHull.list)
- {
- if (!convexHull.Intersects(camView)) continue;
- //if (!camView.Intersects(convexHull.BoundingBox)) continue;
+ var convexHulls = LightSource.GetHullsInRange(viewTarget.Position, cam.WorldView.Width*0.75f, viewTarget.Submarine);
- convexHull.DrawShadows(graphics, cam, pos, shadowTransform);
- }
+ if (convexHulls != null)
+ {
+ foreach (ConvexHull convexHull in convexHulls)
+ {
+ if (!convexHull.Intersects(camView)) continue;
+ //if (!camView.Intersects(convexHull.BoundingBox)) continue;
+
+ convexHull.DrawShadows(graphics, cam, pos, shadowTransform);
+ }
+ }
}
graphics.SetRenderTarget(null);
}
diff --git a/Subsurface/Source/Map/Lights/LightSource.cs b/Subsurface/Source/Map/Lights/LightSource.cs
index 46e04bf90..0542cd359 100644
--- a/Subsurface/Source/Map/Lights/LightSource.cs
+++ b/Subsurface/Source/Map/Lights/LightSource.cs
@@ -12,7 +12,7 @@ namespace Barotrauma.Lights
{
private static Texture2D lightTexture;
- public List hullsInRange;
+ private List hullsInRange;
private Color color;
@@ -24,7 +24,7 @@ namespace Barotrauma.Lights
private Sprite overrideLightTexture;
- public Entity Submarine;
+ public Entity ParentSub;
public bool CastShadows;
@@ -33,6 +33,8 @@ namespace Barotrauma.Lights
private Vector2 prevHullUpdatePosition;
+ public bool NeedsHullUpdate;
+
private Vector2 position;
public Vector2 Position
{
@@ -43,8 +45,8 @@ namespace Barotrauma.Lights
position = value;
if (Vector2.Distance(prevHullUpdatePosition, position) < 5.0f) return;
-
- UpdateHullsInRange();
+
+ NeedsHullUpdate = true;
prevHullUpdatePosition = position;
}
}
@@ -57,7 +59,7 @@ namespace Barotrauma.Lights
public Vector2 WorldPosition
{
- get { return (Submarine == null) ? position : position + Submarine.Position; }
+ get { return (ParentSub == null) ? position : position + ParentSub.Position; }
}
public static Texture2D LightTexture
@@ -86,9 +88,9 @@ namespace Barotrauma.Lights
{
range = MathHelper.Clamp(value, 0.0f, 2048.0f);
- if (Math.Abs(prevHullUpdateRange - range) < 5.0f) return;
-
- UpdateHullsInRange();
+ if (Math.Abs(prevHullUpdateRange - range) < 10.0f) return;
+
+ NeedsHullUpdate = true;
prevHullUpdateRange = range;
}
}
@@ -117,9 +119,9 @@ namespace Barotrauma.Lights
public LightSource(Vector2 position, float range, Color color, Submarine submarine)
{
- hullsInRange = new List();
+ hullsInRange = new List();
- this.Submarine = submarine;
+ this.ParentSub = submarine;
this.position = position;
this.range = range;
@@ -132,37 +134,166 @@ namespace Barotrauma.Lights
GameMain.LightManager.AddLight(this);
}
- public void UpdateHullsInRange()
+ public void DrawShadows(GraphicsDevice graphics, Camera cam, Matrix shadowTransform)
{
if (!CastShadows) return;
-
- if (hullsInRange == null) hullsInRange = new List();
-
- hullsInRange.Clear();
if (range < 1.0f || color.A < 0.01f) return;
- foreach (ConvexHull ch in ConvexHull.list)
+ foreach (Submarine sub in Submarine.Loaded)
{
- if (Submarine == null && ch.ParentEntity.Submarine != null)
+ var hulls = GetHullsInRange(sub);
+
+ if (hulls == null) continue;
+
+ foreach ( ConvexHull ch in hulls)
{
- if (MathUtils.CircleIntersectsRectangle(position - ch.ParentEntity.Submarine.Position, range, ch.BoundingBox))
+ ch.DrawShadows(graphics, cam, this, shadowTransform, false);
+ }
+ }
+
+ var outsideHulls = GetHullsInRange(null);
+
+ NeedsHullUpdate = false;
+
+ if (outsideHulls == null) return;
+ foreach (ConvexHull ch in outsideHulls)
+ {
+ ch.DrawShadows(graphics, cam, this, shadowTransform, false);
+ }
+ }
+
+ private List GetHullsInRange(Submarine sub)
+ {
+ var chList = hullsInRange.Find(x => x.Submarine == sub);
+
+ if (chList == null)
+ {
+ chList = new ConvexHullList(sub);
+ hullsInRange.Add(chList);
+ }
+ List list = chList.List;
+
+
+ Vector2 lightPos = position;
+ if (ParentSub == null)
+ {
+ //light and the convexhull are both outside
+ if (sub == null)
+ {
+ if (NeedsHullUpdate)
{
- hullsInRange.Add(ch);
+ var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub);
+
+ list = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox));
+ chList.List = list;
}
}
- else if (MathUtils.CircleIntersectsRectangle(position, range, ch.BoundingBox))
+ //light is outside, convexhull inside a sub
+ else
{
- hullsInRange.Add(ch);
+ //todo: check
+ lightPos -= sub.Position;
+
+ Rectangle subBorders = sub.Borders;
+ subBorders.Location += sub.HiddenSubPosition.ToPoint() - new Point(0, sub.Borders.Height);
+
+ //only draw if the light overlaps with the sub
+ if (!MathUtils.CircleIntersectsRectangle(lightPos, range, subBorders)) return null;
+
+ var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub);
+ list = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox));
}
-
}
+ else
+ {
+ //light is inside, convexhull outside
+ if (sub == null) return null;
+
+ //light and convexhull are both inside the same sub
+ if (sub == ParentSub)
+ {
+ if (NeedsHullUpdate)
+ {
+ var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub);
+
+ list = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox));
+ chList.List = list;
+ }
+ }
+ //light and convexhull are inside different subs
+ else
+ {
+ lightPos -= (sub.Position - ParentSub.Position);
+
+ Rectangle subBorders = sub.Borders;
+ subBorders.Location += sub.HiddenSubPosition.ToPoint() - new Point(0, sub.Borders.Height);
+
+ //only draw if the light overlaps with the sub
+ if (!MathUtils.CircleIntersectsRectangle(lightPos, range, subBorders)) return null;
+
+ var fullChList = ConvexHull.HullLists.Find(x => x.Submarine == sub);
+ list = fullChList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox));
+ }
+ }
+
+ return list;
}
- public void NeedsHullUpdate()
+ public static List GetHullsInRange(Vector2 position, float range, Submarine ParentSub)
{
- hullsInRange = null;
+ List list = new List();
+
+ foreach (ConvexHullList chList in ConvexHull.HullLists)
+ {
+ Vector2 lightPos = position;
+ if (ParentSub == null)
+ {
+ //light and the convexhull are both outside
+ if (chList.Submarine == null)
+ {
+ list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
+
+ }
+ //light is outside, convexhull inside a sub
+ else
+ {
+ if (!MathUtils.CircleIntersectsRectangle(lightPos - chList.Submarine.WorldPosition, range, chList.Submarine.Borders)) continue;
+
+ lightPos -= (chList.Submarine.WorldPosition - chList.Submarine.HiddenSubPosition);
+
+ list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
+ }
+ }
+ else
+ {
+ //light is inside, convexhull outside
+ if (chList.Submarine == null) continue;
+
+ //light and convexhull are both inside the same sub
+ if (chList.Submarine == ParentSub)
+ {
+ list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
+ }
+ //light and convexhull are inside different subs
+ else
+ {
+ lightPos -= (chList.Submarine.Position - ParentSub.Position);
+
+ Rectangle subBorders = chList.Submarine.Borders;
+ subBorders.Location += chList.Submarine.HiddenSubPosition.ToPoint() - new Point(0, chList.Submarine.Borders.Height);
+
+ if (!MathUtils.CircleIntersectsRectangle(lightPos, range, subBorders)) continue;
+
+ list.AddRange(chList.List.FindAll(ch => MathUtils.CircleIntersectsRectangle(lightPos, range, ch.BoundingBox)));
+ }
+ }
+ }
+
+
+ return list;
}
+
public void Draw(SpriteBatch spriteBatch)
{
if (range > 1.0f)
diff --git a/Subsurface/Source/Map/LinkedSubmarine.cs b/Subsurface/Source/Map/LinkedSubmarine.cs
new file mode 100644
index 000000000..90286dfb0
--- /dev/null
+++ b/Subsurface/Source/Map/LinkedSubmarine.cs
@@ -0,0 +1,310 @@
+using Barotrauma.Items.Components;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml.Linq;
+
+namespace Barotrauma
+{
+
+ class LinkedSubmarinePrefab : MapEntityPrefab
+ {
+ public readonly Submarine mainSub;
+
+ public LinkedSubmarinePrefab(Submarine submarine)
+ {
+ this.mainSub = submarine;
+ }
+
+ protected override void CreateInstance(Rectangle rect)
+ {
+ System.Diagnostics.Debug.Assert(Submarine.MainSub != null);
+
+ LinkedSubmarine.Create(Submarine.MainSub, mainSub.FilePath, rect.Location.ToVector2());
+ }
+ }
+
+ class LinkedSubmarine : MapEntity
+ {
+ private List wallVertices;
+
+ private string filePath;
+
+ private Submarine sub;
+
+ private XElement saveElement;
+
+ public override bool IsLinkable
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public LinkedSubmarine(Submarine submarine)
+ : base(null, submarine)
+ {
+ linkedTo = new System.Collections.ObjectModel.ObservableCollection();
+ linkedToID = new List();
+
+ InsertToList();
+ }
+
+ public static LinkedSubmarine Create(Submarine mainSub, string filePath, Vector2 position)
+ {
+ LinkedSubmarine sl = new LinkedSubmarine(mainSub);
+ sl.filePath = filePath;
+
+ XDocument doc = Submarine.OpenFile(filePath);
+ if (doc == null || doc.Root == null) return null;
+
+ sl.GenerateWallVertices(doc.Root);
+
+ //for (int i = 0; i < sl.wallVertices.Count; i++)
+ //{
+ // sl.wallVertices[i] = sl.wallVertices[i] += position;
+ //}
+
+ sl.Rect = new Rectangle(
+ (int)sl.wallVertices.Min(v => v.X + position.X),
+ (int)sl.wallVertices.Max(v => v.Y + position.Y),
+ (int)sl.wallVertices.Max(v => v.X + position.X),
+ (int)sl.wallVertices.Min(v => v.Y + position.Y));
+
+ sl.rect = new Rectangle(sl.rect.X, sl.rect.Y, sl.rect.Width - sl.rect.X, sl.rect.Y - sl.rect.Height);
+
+ return sl;
+ }
+
+ public override bool IsMouseOn(Vector2 position)
+ {
+ return Vector2.Distance(position, WorldPosition) < 50.0f;
+ }
+
+ public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true)
+ {
+ if (!editing || wallVertices == null) return;
+
+ Color color = (isHighlighted) ? Color.Orange : Color.Green;
+ if (isSelected) color = Color.Red;
+
+ Vector2 pos = new Vector2(rect.X + rect.Width/2, rect.Y - rect.Height/2);
+
+ for (int i = 0; i < wallVertices.Count; i++)
+ {
+ Vector2 startPos = wallVertices[i] + pos;
+ startPos.Y = -startPos.Y;
+
+ Vector2 endPos = wallVertices[(i + 1) % wallVertices.Count] + pos;
+ endPos.Y = -endPos.Y;
+
+ GUI.DrawLine(spriteBatch,
+ startPos,
+ endPos,
+ color, 0.0f, 5);
+ }
+
+ pos.Y = -pos.Y;
+ GUI.DrawLine(spriteBatch, pos + Vector2.UnitY * 50.0f, pos - Vector2.UnitY * 50.0f, color, 0.0f, 5);
+ GUI.DrawLine(spriteBatch, pos + Vector2.UnitX * 50.0f, pos - Vector2.UnitX * 50.0f, color, 0.0f, 5);
+
+
+ foreach (MapEntity e in linkedTo)
+ {
+ GUI.DrawLine(spriteBatch,
+ new Vector2(WorldPosition.X, -WorldPosition.Y),
+ new Vector2(e.WorldPosition.X, -e.WorldPosition.Y),
+ Color.Red * 0.3f);
+ }
+ }
+
+ public override void DrawEditing(SpriteBatch spriteBatch, Camera cam)
+ {
+ if (editingHUD == null || editingHUD.UserData as LinkedSubmarine != this)
+ {
+ editingHUD = CreateEditingHUD();
+ }
+
+ editingHUD.Draw(spriteBatch);
+ editingHUD.Update((float)Physics.step);
+
+ if (!PlayerInput.LeftButtonClicked() || !PlayerInput.KeyDown(Keys.Space)) return;
+
+ Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
+
+ foreach (MapEntity entity in mapEntityList)
+ {
+ if (entity == this || !entity.IsHighlighted || !(entity is Item) || !entity.IsMouseOn(position)) continue;
+ if (((Item)entity).GetComponent() == null) continue;
+ if (linkedTo.Contains(entity))
+ {
+ linkedTo.Remove(entity);
+ }
+ else
+ {
+ linkedTo.Add(entity);
+ }
+ }
+ }
+
+
+ private GUIComponent CreateEditingHUD(bool inGame = false)
+ {
+ int width = 450;
+ int x = GameMain.GraphicsWidth / 2 - width / 2, y = 10;
+
+ editingHUD = new GUIFrame(new Rectangle(x, y, width, 100), GUI.Style);
+ editingHUD.Padding = new Vector4(10, 10, 0, 0);
+ editingHUD.UserData = this;
+
+ new GUITextBlock(new Rectangle(0, 0, 100, 20), "Linked submarine", GUI.Style,
+ Alignment.TopLeft, Alignment.TopLeft, editingHUD, false, GUI.LargeFont);
+
+ y += 20;
+
+ if (!inGame)
+ {
+ new GUITextBlock(new Rectangle(0, 0, 0, 20), "Hold space to link to a docking port",
+ GUI.Style, Alignment.TopRight, Alignment.TopRight, editingHUD).Font = GUI.SmallFont;
+ y += 25;
+
+ }
+ return editingHUD;
+ }
+
+
+ private void GenerateWallVertices(XElement rootElement)
+ {
+ List points = new List();
+
+ var wallPrefabs =
+ MapEntityPrefab.list.FindAll(mp => (mp is StructurePrefab) && ((StructurePrefab)mp).HasBody);
+
+ foreach (XElement element in rootElement.Elements())
+ {
+ if (element.Name != "Structure") continue;
+
+ string name = ToolBox.GetAttributeString(element, "name", "");
+ if (!wallPrefabs.Any(wp => wp.Name == name)) continue;
+
+ var rect = ToolBox.GetAttributeVector4(element, "rect", Vector4.Zero);
+
+ points.Add(new Vector2(rect.X, rect.Y));
+ points.Add(new Vector2(rect.X + rect.Z, rect.Y));
+ points.Add(new Vector2(rect.X, rect.Y - rect.W));
+ points.Add(new Vector2(rect.X + rect.Z, rect.Y - rect.W));
+ }
+
+ wallVertices = MathUtils.GiftWrap(points);
+ }
+
+ public override XElement Save(XElement parentElement)
+ {
+ XElement saveElement = null;
+
+ if (sub == null)
+ {
+ var doc = Submarine.OpenFile(filePath);
+ saveElement = doc.Root;
+
+ saveElement.Name = "LinkedSubmarine";
+
+ saveElement.Add(new XAttribute("filepath", filePath));
+
+ var linkedPort = linkedTo.FirstOrDefault(lt => (lt is Item) && ((Item)lt).GetComponent() != null);
+ if (linkedPort != null)
+ {
+ saveElement.Add(new XAttribute("linkedto", linkedPort.ID));
+ }
+ }
+ else
+ {
+ if (!sub.DockedTo.Contains(Submarine.MainSub)) return null;
+
+ saveElement = new XElement("LinkedSubmarine");
+
+ sub.SaveToXElement(saveElement);
+ }
+
+ saveElement.Add(new XAttribute("pos", ToolBox.Vector2ToString(Position - Submarine.HiddenSubPosition)));
+
+ parentElement.Add(saveElement);
+
+ return saveElement;
+ }
+
+ public static void Load(XElement element, Submarine submarine)
+ {
+ Vector2 pos = ToolBox.GetAttributeVector2(element, "pos", Vector2.Zero);
+
+ LinkedSubmarine linkedSub = null;
+
+ if (Screen.Selected == GameMain.EditMapScreen)
+ {
+ string filePath = ToolBox.GetAttributeString(element, "filepath", "");
+
+ linkedSub = Create(submarine, filePath, pos);
+ }
+ else
+ {
+ linkedSub = new LinkedSubmarine(submarine);
+ linkedSub.saveElement = element;
+
+ linkedSub.rect.Location = pos.ToPoint();
+ }
+
+ string linkedToString = ToolBox.GetAttributeString(element, "linkedto", "");
+ if (linkedToString != "")
+ {
+ string[] linkedToIds = linkedToString.Split(',');
+ for (int i = 0; i < linkedToIds.Length; i++)
+ {
+ linkedSub.linkedToID.Add((ushort)int.Parse(linkedToIds[i]));
+ }
+ }
+
+ }
+
+ public override void OnMapLoaded()
+ {
+ if (saveElement == null) return;
+
+ sub = Submarine.Load(saveElement, false);
+ sub.SetPosition(WorldPosition - Submarine.WorldPosition);
+ sub.Submarine = Submarine;
+
+ var linkedItem = linkedTo.FirstOrDefault(lt => (lt is Item) && ((Item)lt).GetComponent() != null);
+
+ if (linkedItem != null)
+ {
+ var linkedPort = ((Item)linkedItem).GetComponent();
+
+ DockingPort myPort = null;
+ float closestDistance = 0.0f;
+
+ foreach (DockingPort port in DockingPort.list)
+ {
+ if (port.Item.Submarine != sub || port.IsHorizontal != linkedPort.IsHorizontal) continue;
+
+ float dist = Vector2.Distance(port.Item.WorldPosition, linkedPort.Item.WorldPosition);
+ if (myPort == null || dist < closestDistance)
+ {
+ myPort = port;
+ closestDistance = dist;
+ }
+ }
+
+ if (myPort != null)
+ {
+ myPort.Dock(linkedPort);
+ }
+ }
+ }
+ }
+}
diff --git a/Subsurface/Source/Map/MapEntity.cs b/Subsurface/Source/Map/MapEntity.cs
index 0e9867f99..f079fb7d9 100644
--- a/Subsurface/Source/Map/MapEntity.cs
+++ b/Subsurface/Source/Map/MapEntity.cs
@@ -518,7 +518,7 @@ namespace Barotrauma
Vector2 placePosition = new Vector2(rect.X, rect.Y);
Vector2 placeSize = new Vector2(rect.Width, rect.Height);
- Vector2 mousePos = Submarine.MouseToWorldGrid(cam);
+ Vector2 mousePos = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);
if (resizeDirX >0)
{
@@ -596,7 +596,7 @@ namespace Barotrauma
}
- public virtual XElement Save(XDocument doc)
+ public virtual XElement Save(XElement parentElement)
{
DebugConsole.ThrowError("Saving entity " + GetType() + " failed.");
return null;
@@ -607,10 +607,11 @@ namespace Barotrauma
/// Has to be done after all the entities have been loaded (an entity can't
/// be linked to some other entity that hasn't been loaded yet)
///
- public static void MapLoaded()
+ public static void MapLoaded(Submarine sub)
{
foreach (MapEntity e in mapEntityList)
{
+ if (e.Submarine != sub) continue;
if (e.linkedToID == null) continue;
if (e.linkedToID.Count == 0) continue;
@@ -623,14 +624,29 @@ namespace Barotrauma
if (linked != null) e.linkedTo.Add(linked);
}
}
+
+ List linkedSubs = new List();
for (int i = 0; i x.Remove());
}
@@ -520,7 +528,7 @@ namespace Barotrauma
public AttackResult AddDamage(IDamageable attacker, Vector2 worldPosition, Attack attack, float deltaTime, bool playSound = false)
{
- if (Submarine.Loaded != null && Submarine.Loaded.GodMode && Submarine == Submarine.Loaded) return new AttackResult(0.0f, 0.0f);
+ if (Submarine != null && Submarine.GodMode) return new AttackResult(0.0f, 0.0f);
if (!prefab.HasBody || prefab.IsPlatform) return new AttackResult(0.0f, 0.0f);
Vector2 transformedPos = worldPosition;
@@ -546,7 +554,7 @@ namespace Barotrauma
private void SetDamage(int sectionIndex, float damage)
{
- if (Submarine.Loaded != null && Submarine.Loaded.GodMode) return;
+ if (Submarine != null && Submarine.GodMode) return;
if (!prefab.HasBody) return;
if (!MathUtils.IsValid(damage)) return;
@@ -668,7 +676,7 @@ namespace Barotrauma
}
- public override XElement Save(XDocument doc)
+ public override XElement Save(XElement parentElement)
{
XElement element = new XElement("Structure");
@@ -696,7 +704,7 @@ namespace Barotrauma
element.Add(sectionElement);
}
- doc.Root.Add(element);
+ parentElement.Add(element);
return element;
}
diff --git a/Subsurface/Source/Map/StructurePrefab.cs b/Subsurface/Source/Map/StructurePrefab.cs
index abedc550c..9d9f7f123 100644
--- a/Subsurface/Source/Map/StructurePrefab.cs
+++ b/Subsurface/Source/Map/StructurePrefab.cs
@@ -128,7 +128,7 @@ namespace Barotrauma
public override void UpdatePlacing(SpriteBatch spriteBatch, Camera cam)
{
- Vector2 position = Submarine.MouseToWorldGrid(cam);
+ Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);
//Vector2 placeSize = size;
Rectangle newRect = new Rectangle((int)position.X, (int)position.Y, (int)size.X, (int)size.Y);
@@ -137,7 +137,7 @@ namespace Barotrauma
if (placePosition == Vector2.Zero)
{
if (PlayerInput.LeftButtonHeld())
- placePosition = Submarine.MouseToWorldGrid(cam);
+ placePosition = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);
newRect.X = (int)position.X;
newRect.Y = (int)position.Y;
@@ -154,14 +154,10 @@ namespace Barotrauma
if (PlayerInput.LeftButtonReleased())
{
- if (Submarine.Loaded != null)
- {
- newRect.Location -= Submarine.Loaded.Position.ToPoint();
- }
+ newRect.Location -= Submarine.MainSub.Position.ToPoint();
- var structure = new Structure(newRect, this, Submarine.Loaded);
-
- structure.Submarine = Submarine.Loaded;
+ var structure = new Structure(newRect, this, Submarine.MainSub);
+ structure.Submarine = Submarine.MainSub;
selected = null;
return;
diff --git a/Subsurface/Source/Map/Submarine.cs b/Subsurface/Source/Map/Submarine.cs
index 59446d81d..cc0d87b10 100644
--- a/Subsurface/Source/Map/Submarine.cs
+++ b/Subsurface/Source/Map/Submarine.cs
@@ -22,22 +22,36 @@ namespace Barotrauma
{
public static string SavePath = "Submarines";
+ public static readonly Vector2 HiddenSubStartPosition = new Vector2(-50000.0f, 80000.0f);
//position of the "actual submarine" which is rendered wherever the SubmarineBody is
//should be in an unreachable place
- public static readonly Vector2 HiddenSubPosition = new Vector2(-50000.0f, 80000.0f);
+ public Vector2 HiddenSubPosition
+ {
+ get;
+ private set;
+ }
+
+ public ushort IdOffset
+ {
+ get;
+ private set;
+ }
public static List SavedSubmarines = new List();
public static readonly Vector2 GridSize = new Vector2(16.0f, 16.0f);
- private static Submarine loaded;
+ public static Submarine MainSub;
+ private static List loaded = new List();
private SubmarineBody subBody;
+ public readonly List DockedTo;
+
private static Vector2 lastPickedPosition;
private static float lastPickedFraction;
- Md5Hash hash;
+ private Md5Hash hash;
private string filePath;
private string name;
@@ -45,8 +59,7 @@ namespace Barotrauma
private Vector2 prevPosition;
private float lastNetworkUpdate;
-
-
+
//properties ----------------------------------------------------
public string Name
@@ -89,23 +102,28 @@ namespace Barotrauma
{
if (hash != null) return hash;
- XDocument doc = OpenDoc(filePath);
+ XDocument doc = OpenFile(filePath);
hash = new Md5Hash(doc);
return hash;
}
}
- public static Submarine Loaded
+ public static List Loaded
{
get { return loaded; }
}
- public static Rectangle Borders
+ public SubmarineBody SubBody
+ {
+ get { return subBody; }
+ }
+
+ public Rectangle Borders
{
get
{
- return (loaded==null) ? Rectangle.Empty : Loaded.subBody.Borders;
+ return subBody.Borders;
}
}
@@ -206,7 +224,7 @@ namespace Barotrauma
if (tryLoad)
{
- XDocument doc = OpenDoc(filePath);
+ XDocument doc = OpenFile(filePath);
if (doc != null && doc.Root != null)
{
@@ -214,6 +232,8 @@ namespace Barotrauma
}
}
+ DockedTo = new List();
+
ID = ushort.MaxValue;
base.Remove();
@@ -255,17 +275,17 @@ namespace Barotrauma
//math/physics stuff ----------------------------------------------------
- public static Vector2 MouseToWorldGrid(Camera cam)
+ public static Vector2 MouseToWorldGrid(Camera cam, Submarine sub)
{
Vector2 position = PlayerInput.MousePosition;
position = cam.ScreenToWorld(position);
Vector2 worldGridPos = VectorToWorldGrid(position);
- if (loaded != null)
+ if (sub != null)
{
- worldGridPos.X += loaded.Position.X % GridSize.X;
- worldGridPos.Y += loaded.Position.Y % GridSize.Y;
+ worldGridPos.X += sub.Position.X % GridSize.X;
+ worldGridPos.Y += sub.Position.Y % GridSize.Y;
}
return worldGridPos;
@@ -421,7 +441,19 @@ namespace Barotrauma
{
if (!MathUtils.IsValid(position)) return;
+ Vector2 prevPos = subBody.Position;
+
subBody.SetPosition(position);
+
+ foreach (Submarine sub in loaded)
+ {
+ if (sub != this && sub.Submarine == this)
+ {
+ sub.SetPosition(position + sub.WorldPosition);
+ sub.Submarine = null;
+ }
+
+ }
//Level.Loaded.SetPosition(-position);
//prevPosition = position;
}
@@ -435,6 +467,23 @@ namespace Barotrauma
//Level.Loaded.Move(-amount);
}
+ public static Submarine GetClosest(Vector2 worldPosition)
+ {
+ Submarine closest = null;
+ float closestDist = 0.0f;
+ foreach (Submarine sub in Submarine.loaded)
+ {
+ float dist = Vector2.Distance(worldPosition, sub.WorldPosition);
+ if (closest == null || dist < closestDist)
+ {
+ closest = sub;
+ closestDist = dist;
+ }
+ }
+
+ return closest;
+ }
+
public override bool FillNetworkData(Networking.NetworkEventType type, NetBuffer message, object data)
{
if (subBody == null) return false;
@@ -492,14 +541,7 @@ namespace Barotrauma
name = System.IO.Path.GetFileNameWithoutExtension(filePath);
XDocument doc = new XDocument(new XElement("Submarine"));
- doc.Root.Add(new XAttribute("name", name));
- doc.Root.Add(new XAttribute("description", Description == null ? "" : Description));
-
- foreach (MapEntity e in MapEntity.mapEntityList)
- {
- if (e.MoveWithLevel) continue;
- e.Save(doc);
- }
+ SaveToXElement(doc.Root);
hash = new Md5Hash(doc);
doc.Root.Add(new XAttribute("md5hash", hash.Hash));
@@ -517,17 +559,29 @@ namespace Barotrauma
return true;
}
+ public void SaveToXElement(XElement element)
+ {
+ element.Add(new XAttribute("name", name));
+ element.Add(new XAttribute("description", Description == null ? "" : Description));
+
+ foreach (MapEntity e in MapEntity.mapEntityList)
+ {
+ if (e.MoveWithLevel || e.Submarine != this) continue;
+ e.Save(element);
+ }
+ }
+
public static bool SaveCurrent(string filePath)
{
- if (loaded==null)
+ if (Submarine.MainSub == null)
{
- loaded = new Submarine(filePath);
+ Submarine.MainSub = new Submarine(filePath);
// return;
}
- loaded.filePath = filePath;
+ Submarine.MainSub.filePath = filePath;
- return loaded.SaveAs(filePath);
+ return Submarine.MainSub.SaveAs(filePath);
}
public void CheckForErrors()
@@ -614,7 +668,7 @@ namespace Barotrauma
//if (GameMain.NetLobbyScreen!=null) GameMain.NetLobbyScreen.UpdateSubList(Submarine.SavedSubmarines);
}
- private XDocument OpenDoc(string file)
+ public static XDocument OpenFile(string file)
{
XDocument doc = null;
string extension = "";
@@ -684,18 +738,36 @@ namespace Barotrauma
return doc;
}
- public void Load()
+ public void Load(bool unloadPrevious, XElement submarineElement = null)
{
- Unload();
+ if (unloadPrevious) Unload();
Loading = true;
- XDocument doc = OpenDoc(filePath);
- if (doc == null || doc.Root == null) return;
+ if (submarineElement == null)
+ {
+ XDocument doc = OpenFile(filePath);
+ if (doc == null || doc.Root == null) return;
- Description = ToolBox.GetAttributeString(doc.Root, "description", "");
+ submarineElement = doc.Root;
+ }
- foreach (XElement element in doc.Root.Elements())
+ Description = ToolBox.GetAttributeString(submarineElement, "description", "");
+
+
+ HiddenSubPosition = HiddenSubStartPosition;
+ foreach (Submarine sub in Submarine.loaded)
+ {
+ HiddenSubPosition += Vector2.UnitY * (sub.Borders.Height + 5000.0f);
+ }
+
+ IdOffset = 0;
+ foreach (MapEntity me in MapEntity.mapEntityList)
+ {
+ IdOffset = Math.Max(IdOffset, me.ID);
+ }
+
+ foreach (XElement element in submarineElement.Elements())
{
string typeName = element.Name.ToString();
@@ -728,11 +800,13 @@ namespace Barotrauma
Vector2 center = Vector2.Zero;
- if (Hull.hullList.Any())
+ var matchingHulls = Hull.hullList.FindAll(h => h.Submarine == this);
+
+ if (matchingHulls.Any())
{
- Vector2 topLeft = new Vector2(Hull.hullList[0].Rect.X, Hull.hullList[0].Rect.Y);
- Vector2 bottomRight = new Vector2(Hull.hullList[0].Rect.X, Hull.hullList[0].Rect.Y);
- foreach (Hull hull in Hull.hullList)
+ Vector2 topLeft = new Vector2(matchingHulls[0].Rect.X, matchingHulls[0].Rect.Y);
+ Vector2 bottomRight = new Vector2(matchingHulls[0].Rect.X, matchingHulls[0].Rect.Y);
+ foreach (Hull hull in matchingHulls)
{
if (hull.Rect.X < topLeft.X) topLeft.X = hull.Rect.X;
if (hull.Rect.Y > topLeft.Y) topLeft.Y = hull.Rect.Y;
@@ -747,6 +821,8 @@ namespace Barotrauma
foreach (Item item in Item.ItemList)
{
+ if (item.Submarine != this) continue;
+
var wire = item.GetComponent();
if (wire == null) continue;
@@ -758,7 +834,7 @@ namespace Barotrauma
for (int i = 0; i < MapEntity.mapEntityList.Count; i++)
{
- if (MapEntity.mapEntityList[i].Submarine == null) continue;
+ if (MapEntity.mapEntityList[i].Submarine != this) continue;
MapEntity.mapEntityList[i].Move(-center);
}
@@ -766,10 +842,10 @@ namespace Barotrauma
subBody = new SubmarineBody(this);
subBody.SetPosition(HiddenSubPosition);
-
- loaded = this;
- Hull.GenerateEntityGrid();
+ loaded.Add(this);
+
+ Hull.GenerateEntityGrid(this);
for (int i = 0; i < MapEntity.mapEntityList.Count; i++)
{
@@ -779,28 +855,40 @@ namespace Barotrauma
Loading = false;
- MapEntity.MapLoaded();
+ MapEntity.MapLoaded(this);
//WayPoint.GenerateSubWaypoints();
GameMain.LightManager.OnMapLoaded();
- ID = ushort.MaxValue;
+ ID = (ushort)(ushort.MaxValue - Submarine.loaded.IndexOf(this));
}
- public static Submarine Load(string fileName)
+ public static Submarine Load(XElement element, bool unloadPrevious)
{
- return Load(fileName, SavePath);
+ if (unloadPrevious) Unload();
+
+ //tryload -> false
+
+ Submarine sub = new Submarine(ToolBox.GetAttributeString(element, "name", ""), "", false);
+ sub.Load(unloadPrevious, element);
+
+ return sub;
}
- public static Submarine Load(string fileName, string folder)
+ public static Submarine Load(string fileName, bool unloadPrevious)
{
- Unload();
+ return Load(fileName, SavePath, unloadPrevious);
+ }
+
+ public static Submarine Load(string fileName, string folder, bool unloadPrevious)
+ {
+ if (unloadPrevious) Unload();
string path = string.IsNullOrWhiteSpace(folder) ? fileName : System.IO.Path.Combine(SavePath, fileName);
Submarine sub = new Submarine(path);
- sub.Load();
+ sub.Load(unloadPrevious);
//Entity.dictionary.Add(int.MaxValue, sub);
@@ -809,33 +897,38 @@ namespace Barotrauma
public static void Unload()
{
- if (loaded == null) return;
Sound.OnGameEnd();
if (GameMain.LightManager != null) GameMain.LightManager.ClearLights();
-
- loaded.Remove();
+
+
+ foreach (Submarine sub in loaded)
+ {
+ sub.Remove();
+ }
loaded.Clear();
- loaded = null;
- }
- private void Clear()
- {
if (GameMain.GameScreen.Cam != null) GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
Entity.RemoveAll();
-
- subBody = null;
-
- PhysicsBody.list.Clear();
+ PhysicsBody.list.Clear();
+
Ragdoll.list.Clear();
GameMain.World.Clear();
}
+ public override void Remove()
+ {
+ base.Remove();
+
+ subBody = null;
+
+ DockedTo.Clear();
+ }
}
}
diff --git a/Subsurface/Source/Map/SubmarineBody.cs b/Subsurface/Source/Map/SubmarineBody.cs
index 5341d9f7a..2802e4fd0 100644
--- a/Subsurface/Source/Map/SubmarineBody.cs
+++ b/Subsurface/Source/Map/SubmarineBody.cs
@@ -33,11 +33,11 @@ namespace Barotrauma
private readonly Submarine submarine;
- private readonly Body body;
+ public readonly Body Body;
private Vector2? targetPosition;
- private float mass = 10000.0f;
+ //private float mass = 10000.0f;
public Rectangle Borders
{
@@ -47,11 +47,11 @@ namespace Barotrauma
public Vector2 Velocity
{
- get { return body.LinearVelocity; }
+ get { return Body.LinearVelocity; }
set
{
if (!MathUtils.IsValid(value)) return;
- body.LinearVelocity = value;
+ Body.LinearVelocity = value;
}
}
@@ -67,7 +67,7 @@ namespace Barotrauma
public Vector2 Position
{
- get { return ConvertUnits.ToDisplayUnits(body.Position); }
+ get { return ConvertUnits.ToDisplayUnits(Body.Position); }
}
public bool AtDamageDepth
@@ -82,7 +82,7 @@ namespace Barotrauma
if (!Hull.hullList.Any())
{
- body = BodyFactory.CreateRectangle(GameMain.World, 1.0f, 1.0f, 1.0f);
+ Body = BodyFactory.CreateRectangle(GameMain.World, 1.0f, 1.0f, 1.0f);
DebugConsole.ThrowError("WARNING: no hulls found, generating a physics body for the submarine failed.");
}
else
@@ -110,59 +110,53 @@ namespace Barotrauma
//var triangulatedVertices = Triangulate.ConvexPartition(shapevertices, TriangulationAlgorithm.Bayazit);
- body = BodyFactory.CreateBody(GameMain.World, this);
+ Body = BodyFactory.CreateBody(GameMain.World, this);
foreach (Structure wall in Structure.WallList)
{
+ if (wall.Submarine != submarine) continue;
+
Rectangle rect = wall.Rect;
FixtureFactory.AttachRectangle(
ConvertUnits.ToSimUnits(rect.Width),
ConvertUnits.ToSimUnits(rect.Height),
- 5.0f,
+ 50.0f,
ConvertUnits.ToSimUnits(new Vector2(rect.X + rect.Width / 2, rect.Y - rect.Height / 2)),
- body, this);
+ Body, this);
}
- //foreach (Hull hull in Hull.hullList)
- //{
- // Rectangle rect = hull.Rect;
- // foreach (Structure wall in Structure.WallList)
- // {
- // if (!Submarine.RectsOverlap(wall.Rect, hull.Rect)) continue;
-
- // Rectangle wallRect = wall.IsHorizontal ?
- // new Rectangle(hull.Rect.X, wall.Rect.Y, hull.Rect.Width, wall.Rect.Height) :
- // new Rectangle(wall.Rect.X, hull.Rect.Y, wall.Rect.Width, hull.Rect.Height);
-
- // rect = Rectangle.Union(
- // new Rectangle(wallRect.X, wallRect.Y - wallRect.Height, wallRect.Width, wallRect.Height),
- // new Rectangle(rect.X, rect.Y - rect.Height, rect.Width, rect.Height));
- // rect.Y = rect.Y + rect.Height;
- // }
-
- // FixtureFactory.AttachRectangle(
- // ConvertUnits.ToSimUnits(rect.Width),
- // ConvertUnits.ToSimUnits(rect.Height),
- // 5.0f,
- // ConvertUnits.ToSimUnits(new Vector2(rect.X + rect.Width / 2, rect.Y - rect.Height / 2)),
- // body, this);
- //}
+ foreach (Hull hull in Hull.hullList)
+ {
+ Rectangle rect = hull.Rect;
+ FixtureFactory.AttachRectangle(
+ ConvertUnits.ToSimUnits(rect.Width),
+ ConvertUnits.ToSimUnits(rect.Height),
+ 5.0f,
+ ConvertUnits.ToSimUnits(new Vector2(rect.X + rect.Width / 2, rect.Y - rect.Height / 2)),
+ Body, this);
+ }
}
- body.BodyType = BodyType.Dynamic;
- body.CollisionCategories = Physics.CollisionWall;
- body.CollidesWith = Physics.CollisionItem | Physics.CollisionLevel | Physics.CollisionCharacter | Physics.CollisionProjectile;
- body.Restitution = Restitution;
- body.Friction = Friction;
- body.FixedRotation = true;
- body.Mass = mass;
- body.Awake = true;
- body.SleepingAllowed = false;
- body.IgnoreGravity = true;
- body.OnCollision += OnCollision;
- body.UserData = submarine;
+ Body.BodyType = BodyType.Dynamic;
+ Body.CollisionCategories = Physics.CollisionWall;
+ Body.CollidesWith =
+ Physics.CollisionItem |
+ Physics.CollisionLevel |
+ Physics.CollisionCharacter |
+ Physics.CollisionProjectile |
+ Physics.CollisionWall;
+
+ Body.Restitution = Restitution;
+ Body.Friction = Friction;
+ Body.FixedRotation = true;
+ //mass = Body.Mass;
+ Body.Awake = true;
+ Body.SleepingAllowed = false;
+ Body.IgnoreGravity = true;
+ Body.OnCollision += OnCollision;
+ Body.UserData = submarine;
}
@@ -175,48 +169,17 @@ namespace Barotrauma
List points = new List();
- Vector2 leftMost = Vector2.Zero;
-
foreach (Structure wall in Structure.WallList)
{
- for (int x = -1; x <= 1; x += 2)
- {
- for (int y = -1; y <= 1; y += 2)
- {
- Vector2 corner = new Vector2(wall.Rect.X + wall.Rect.Width / 2.0f, wall.Rect.Y - wall.Rect.Height / 2.0f);
- corner.X += x * wall.Rect.Width / 2.0f;
- corner.Y += y * wall.Rect.Height / 2.0f;
+ if (wall.Submarine != submarine) continue;
- if (points.Contains(corner)) continue;
-
- points.Add(corner);
- if (leftMost == Vector2.Zero || corner.X < leftMost.X) leftMost = corner;
- }
- }
+ points.Add(new Vector2(wall.Rect.X, wall.Rect.Y));
+ points.Add(new Vector2(wall.Rect.X + wall.Rect.Width, wall.Rect.Y));
+ points.Add(new Vector2(wall.Rect.X, wall.Rect.Y - wall.Rect.Height));
+ points.Add(new Vector2(wall.Rect.X + wall.Rect.Width, wall.Rect.Y - wall.Rect.Height));
}
- List hullPoints = new List();
-
- Vector2 currPoint = leftMost;
- Vector2 endPoint;
- do
- {
- hullPoints.Add(currPoint);
- endPoint = points[0];
-
- for (int i = 1; i < points.Count; i++)
- {
- if ((currPoint == endPoint)
- || (MathUtils.VectorOrientation(currPoint, endPoint, points[i]) == -1))
- {
- endPoint = points[i];
- }
- }
-
- currPoint = endPoint;
-
- }
- while (endPoint != hullPoints[0]);
+ List hullPoints = MathUtils.GiftWrap(points);
return hullPoints;
}
@@ -229,11 +192,15 @@ namespace Barotrauma
if (dist > 1000.0f) //immediately snap the sub to the target position if more than 1000.0f units away
{
- Vector2 moveAmount = (Vector2)targetPosition - ConvertUnits.ToDisplayUnits(body.Position);
+ Vector2 moveAmount = (Vector2)targetPosition - ConvertUnits.ToDisplayUnits(Body.Position);
ForceTranslate(moveAmount);
- GameMain.GameScreen.Cam.UpdateTransform(false);
+ if ((Character.Controlled != null && Character.Controlled.Submarine == submarine) ||
+ (Character.Controlled == null && Submarine.GetClosest(GameMain.GameScreen.Cam.WorldViewCenter) == submarine))
+ {
+ GameMain.GameScreen.Cam.UpdateTransform(false);
+ }
submarine.SetPrevTransform(submarine.Position);
submarine.UpdateTransform();
@@ -262,14 +229,14 @@ namespace Barotrauma
Vector2 totalForce = CalculateBuoyancy();
- if (body.LinearVelocity.LengthSquared() > 0.000001f)
+ if (Body.LinearVelocity.LengthSquared() > 0.000001f)
{
float dragCoefficient = 0.01f;
- float speedLength = (body.LinearVelocity == Vector2.Zero) ? 0.0f : body.LinearVelocity.Length();
- float drag = speedLength * speedLength * dragCoefficient * mass;
+ float speedLength = (Body.LinearVelocity == Vector2.Zero) ? 0.0f : Body.LinearVelocity.Length();
+ float drag = speedLength * speedLength * dragCoefficient * Body.Mass;
- totalForce += -Vector2.Normalize(body.LinearVelocity) * drag;
+ totalForce += -Vector2.Normalize(Body.LinearVelocity) * drag;
}
ApplyForce(totalForce);
@@ -284,11 +251,15 @@ namespace Barotrauma
/// Amount to move in display units
private void ForceTranslate(Vector2 amount)
{
- body.SetTransform(body.Position + ConvertUnits.ToSimUnits(amount), 0.0f);
+ Body.SetTransform(Body.Position + ConvertUnits.ToSimUnits(amount), 0.0f);
if (Character.Controlled != null) Character.Controlled.CursorPosition += amount;
- GameMain.GameScreen.Cam.Position += amount;
- if (GameMain.GameScreen.Cam.TargetPos != Vector2.Zero) GameMain.GameScreen.Cam.TargetPos += amount;
+ if ((Character.Controlled != null && Character.Controlled.Submarine == submarine) ||
+ (Character.Controlled == null && Submarine.GetClosest(GameMain.GameScreen.Cam.WorldViewCenter) == submarine))
+ {
+ GameMain.GameScreen.Cam.Position += amount;
+ if (GameMain.GameScreen.Cam.TargetPos != Vector2.Zero) GameMain.GameScreen.Cam.TargetPos += amount;
+ }
}
@@ -300,7 +271,7 @@ namespace Barotrauma
private void DisplaceCharacters(Vector2 subTranslation)
{
Rectangle worldBorders = Borders;
- worldBorders.Location += ConvertUnits.ToDisplayUnits(body.Position).ToPoint();
+ worldBorders.Location += ConvertUnits.ToDisplayUnits(Body.Position).ToPoint();
Vector2 translateDir = Vector2.Normalize(subTranslation);
@@ -336,6 +307,8 @@ namespace Barotrauma
float volume = 0.0f;
foreach (Hull hull in Hull.hullList)
{
+ if (hull.Submarine != submarine) continue;
+
waterVolume += hull.Volume;
volume += hull.FullVolume;
}
@@ -345,19 +318,19 @@ namespace Barotrauma
float neutralPercentage = 0.07f;
float buoyancy = Math.Max(neutralPercentage - waterPercentage, -neutralPercentage*2.0f);
- buoyancy *= mass;
+ buoyancy *= Body.Mass;
return new Vector2(0.0f, buoyancy*10.0f);
}
public void ApplyForce(Vector2 force)
{
- body.ApplyForce(force);
+ Body.ApplyForce(force);
}
public void SetPosition(Vector2 position)
{
- body.SetTransform(ConvertUnits.ToSimUnits(position), 0.0f);
+ Body.SetTransform(ConvertUnits.ToSimUnits(position), 0.0f);
}
private void UpdateDepthDamage(float deltaTime)
@@ -392,7 +365,7 @@ namespace Barotrauma
(Rand.Int(2) == 0) ? Borders.Y : Borders.Y - Borders.Height);
}
- damagePos += submarine.Position + Submarine.HiddenSubPosition;
+ damagePos += submarine.Position + submarine.HiddenSubPosition;
SoundPlayer.PlayDamageSound(DamageSoundType.Pressure, 50.0f, damagePos, 10000.0f);
GameMain.GameScreen.Cam.Shake = depth * PressureDamageMultiplier * 0.1f;
@@ -405,18 +378,15 @@ namespace Barotrauma
public bool OnCollision(Fixture f1, Fixture f2, Contact contact)
{
- VoronoiCell cell = f2.Body.UserData as VoronoiCell;
-
- if (cell == null)
+ Limb limb = f2.Body.UserData as Limb;
+ if (limb!= null)
{
- Limb limb = f2.Body.UserData as Limb;
- if (limb == null) return true;
bool collision = HandleLimbCollision(contact, limb);
if (collision && limb.Mass > 100.0f)
{
- Vector2 normal = Vector2.Normalize(body.Position - limb.SimPosition);
+ Vector2 normal = Vector2.Normalize(Body.Position - limb.SimPosition);
float impact = Math.Min(Vector2.Dot(Velocity - limb.LinearVelocity, -normal), 5.0f);
@@ -426,12 +396,32 @@ namespace Barotrauma
return collision;
}
- var collisionNormal = Vector2.Normalize(ConvertUnits.ToDisplayUnits(body.Position) - cell.Center);
+ VoronoiCell cell = f2.Body.UserData as VoronoiCell;
+ if (cell != null)
+ {
+ var collisionNormal = Vector2.Normalize(ConvertUnits.ToDisplayUnits(Body.Position) - cell.Center);
- float wallImpact = Vector2.Dot(Velocity, -collisionNormal);
+ float wallImpact = Vector2.Dot(Velocity, -collisionNormal);
- ApplyImpact(wallImpact, -collisionNormal, contact);
+ ApplyImpact(wallImpact, -collisionNormal, contact);
+ return true;
+ }
+
+ Submarine sub = f2.Body.UserData as Submarine;
+ if (sub != null)
+ {
+ Debug.Assert(sub != submarine);
+
+ Vector2 normal;
+ FixedArray2 points;
+ contact.GetWorldManifold(out normal, out points);
+
+ ApplyImpact(Vector2.Dot(Velocity - sub.Velocity, normal) / 2.0f, normal, contact);
+
+ return true;
+ }
+
return true;
}
@@ -498,7 +488,7 @@ namespace Barotrauma
foreach (Character c in Character.CharacterList)
{
- if (c.AnimController.CurrentHull == null) continue;
+ if (c.Submarine != submarine) continue;
if (impact > 2.0f) c.StartStun((impact - 2.0f) * 0.1f);
diff --git a/Subsurface/Source/Map/TransitionCinematic.cs b/Subsurface/Source/Map/TransitionCinematic.cs
index ce2fa7f5c..b0e14352b 100644
--- a/Subsurface/Source/Map/TransitionCinematic.cs
+++ b/Subsurface/Source/Map/TransitionCinematic.cs
@@ -66,7 +66,7 @@ namespace Barotrauma
cam.Zoom = Math.Max(0.2f, cam.Zoom - CoroutineManager.UnscaledDeltaTime * 0.1f);
- Vector2 cameraPos = sub.Position + Submarine.HiddenSubPosition;
+ Vector2 cameraPos = sub.Position + Submarine.MainSub.HiddenSubPosition;
cameraPos.Y = Math.Min(cameraPos.Y, ConvertUnits.ToDisplayUnits(Level.Loaded.ShaftBodies[0].Position.Y) - cam.WorldView.Height/2.0f);
GUI.ScreenOverlayColor = Color.Lerp(Color.TransparentBlack, Color.Black, timer/duration);
diff --git a/Subsurface/Source/Map/WayPoint.cs b/Subsurface/Source/Map/WayPoint.cs
index 2197edc70..1a0f77b70 100644
--- a/Subsurface/Source/Map/WayPoint.cs
+++ b/Subsurface/Source/Map/WayPoint.cs
@@ -83,7 +83,7 @@ namespace Barotrauma
}
public WayPoint(MapEntityPrefab prefab, Rectangle rectangle)
- : this (rectangle, Submarine.Loaded)
+ : this (rectangle, Submarine.MainSub)
{
if (prefab.Name.Contains("Spawn"))
{
@@ -306,7 +306,7 @@ namespace Barotrauma
return editingHUD;
}
- public static void GenerateSubWaypoints()
+ public static void GenerateSubWaypoints(Submarine submarine)
{
if (!Hull.hullList.Any())
{
@@ -332,13 +332,13 @@ namespace Barotrauma
if (hull.Rect.Width();
if (door != null)
{
- WayPoint newPoint = new WayPoint(door.Item.Position, SpawnType.Path, Submarine.Loaded);
+ WayPoint newPoint = new WayPoint(door.Item.Position, SpawnType.Path, submarine);
newPoint.Ladders = ladders;
newPoint.ConnectedGap = door.LinkedGap;
@@ -538,7 +539,7 @@ namespace Barotrauma
if (gap.Rect.Height < 150.0f) continue;
var wayPoint = new WayPoint(
- new Vector2(gap.Rect.Center.X, gap.Rect.Y - gap.Rect.Height + heightFromFloor), SpawnType.Path, Submarine.Loaded, gap);
+ new Vector2(gap.Rect.Center.X, gap.Rect.Y - gap.Rect.Height + heightFromFloor), SpawnType.Path, submarine, gap);
for (int dir = -1; dir <= 1; dir += 2)
{
@@ -557,7 +558,7 @@ namespace Barotrauma
if (gap.Rect.Width < 100.0f) continue;
var wayPoint = new WayPoint(
- new Vector2(gap.Rect.Center.X, gap.Rect.Y - gap.Rect.Height/2), SpawnType.Path, Submarine.Loaded, gap);
+ new Vector2(gap.Rect.Center.X, gap.Rect.Y - gap.Rect.Height/2), SpawnType.Path, submarine, gap);
for (int dir = -1; dir <= 1; dir += 2)
{
@@ -583,35 +584,35 @@ namespace Barotrauma
WayPoint closest = null;
- foreach (WayPoint wp in WayPointList)
+ foreach (WayPoint wp in WayPointList)
+ {
+ if (wp.SpawnType != SpawnType.Path || wp == this) continue;
+
+ float diff = 0.0f;
+ if (horizontalSearch)
{
- if (wp.SpawnType != SpawnType.Path || wp == this) continue;
+ if ((wp.Position.Y - Position.Y) < tolerance.X || (wp.Position.Y - Position.Y) > tolerance.Y) continue;
- float diff = 0.0f;
- if (horizontalSearch)
- {
- if ((wp.Position.Y - Position.Y) < tolerance.X || (wp.Position.Y - Position.Y) > tolerance.Y) continue;
-
- diff = wp.Position.X - Position.X;
- }
- else
- {
- if ((wp.Position.X - Position.X) < tolerance.X || (wp.Position.X - Position.X) > tolerance.Y) continue;
-
- diff = wp.Position.Y - Position.Y;
- }
-
- if (Math.Sign(diff) != dir) continue;
-
- float dist = Vector2.Distance(wp.Position, Position);
- if (closest == null || dist < closestDist)
- {
- if (Submarine.CheckVisibility(SimPosition, wp.SimPosition) != null) continue;
-
- closestDist = dist;
- closest = wp;
- }
+ diff = wp.Position.X - Position.X;
}
+ else
+ {
+ if ((wp.Position.X - Position.X) < tolerance.X || (wp.Position.X - Position.X) > tolerance.Y) continue;
+
+ diff = wp.Position.Y - Position.Y;
+ }
+
+ if (Math.Sign(diff) != dir) continue;
+
+ float dist = Vector2.Distance(wp.Position, Position);
+ if (closest == null || dist < closestDist)
+ {
+ if (Submarine.CheckVisibility(SimPosition, wp.SimPosition) != null) continue;
+
+ closestDist = dist;
+ closest = wp;
+ }
+ }
return closest;
@@ -640,13 +641,11 @@ namespace Barotrauma
return wayPoints[Rand.Int(wayPoints.Count(), false)];
}
- public static WayPoint[] SelectCrewSpawnPoints(List crew)
+ public static WayPoint[] SelectCrewSpawnPoints(List crew, Submarine submarine)
{
- List unassignedWayPoints = new List();
- foreach (WayPoint wp in WayPointList)
- {
- if (wp.spawnType == SpawnType.Human) unassignedWayPoints.Add(wp);
- }
+ List subWayPoints = WayPointList.FindAll(wp => wp.Submarine == submarine);
+
+ List unassignedWayPoints = subWayPoints.FindAll(wp => wp.spawnType == SpawnType.Human);
WayPoint[] assignedWayPoints = new WayPoint[crew.Count];
@@ -669,7 +668,7 @@ namespace Barotrauma
if (assignedWayPoints[i] != null) continue;
//try to assign a spawnpoint that matches the job, even if the spawnpoint is already assigned to someone else
- foreach (WayPoint wp in WayPointList)
+ foreach (WayPoint wp in subWayPoints)
{
if (wp.spawnType != SpawnType.Human || wp.assignedJob != crew[i].Job.Prefab) continue;
@@ -680,7 +679,7 @@ namespace Barotrauma
if (assignedWayPoints[i] != null) continue;
//try to assign a spawnpoint that isn't meant for any specific job
- var nonJobSpecificPoints = WayPointList.FindAll(wp => wp.spawnType == SpawnType.Human && wp.assignedJob == null);
+ var nonJobSpecificPoints = subWayPoints.FindAll(wp => wp.spawnType == SpawnType.Human && wp.assignedJob == null);
if (nonJobSpecificPoints.Any())
{
@@ -719,7 +718,7 @@ namespace Barotrauma
}
}
- public override XElement Save(XDocument doc)
+ public override XElement Save(XElement parentElement)
{
if (MoveWithLevel) return null;
XElement element = new XElement("WayPoint");
@@ -740,7 +739,7 @@ namespace Barotrauma
if (ConnectedGap != null) element.Add(new XAttribute("gap", ConnectedGap.ID));
if (Ladders != null) element.Add(new XAttribute("ladders", Ladders.Item.ID));
- doc.Root.Add(element);
+ parentElement.Add(element);
if (linkedTo != null)
{
diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs
index 0cc704603..bfc5100d6 100644
--- a/Subsurface/Source/Networking/GameClient.cs
+++ b/Subsurface/Source/Networking/GameClient.cs
@@ -413,6 +413,11 @@ namespace Barotrauma.Networking
reliableChannel.Update(deltaTime);
+ if (gameStarted && respawnManager != null)
+ {
+ respawnManager.Update(deltaTime);
+ }
+
if (updateTimer > DateTime.Now) return;
if (myCharacter != null)
@@ -518,6 +523,9 @@ namespace Barotrauma.Networking
string endMessage = inc.ReadString();
CoroutineManager.StartCoroutine(EndGame(endMessage));
break;
+ case (byte)PacketTypes.Respawn:
+ if (gameStarted && respawnManager != null) respawnManager.ReadNetworkEvent(inc);
+ break;
case (byte)PacketTypes.PlayerJoined:
Client otherClient = new Client(inc.ReadString(), inc.ReadByte());
@@ -672,7 +680,9 @@ namespace Barotrauma.Networking
GameMain.GameSession = new GameSession(GameMain.NetLobbyScreen.SelectedSub, "", gameMode, Mission.MissionTypes[missionTypeIndex]);
GameMain.GameSession.StartShift(levelSeed);
-
+
+ respawnManager = new RespawnManager(this);
+
yield return CoroutineStatus.Running;
//myCharacter = ReadCharacterData(inc);
@@ -725,11 +735,13 @@ namespace Barotrauma.Networking
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
GameMain.LightManager.LosEnabled = false;
+ respawnManager = null;
+
float endPreviewLength = 10.0f;
if (Screen.Selected == GameMain.GameScreen)
{
- var cinematic = new TransitionCinematic(Submarine.Loaded, GameMain.GameScreen.Cam, endPreviewLength);
+ var cinematic = new TransitionCinematic(Submarine.MainSub, GameMain.GameScreen.Cam, endPreviewLength);
float secondsLeft = endPreviewLength;
@@ -774,11 +786,6 @@ namespace Barotrauma.Networking
if (fileStreamReceiver != null &&
(fileStreamReceiver.Status == FileTransferStatus.Receiving || fileStreamReceiver.Status == FileTransferStatus.NotStarted))
{
- //Vector2 pos = Screen.Selected == GameMain.NetLobbyScreen ?
- // new Vector2(GameMain.NetLobbyScreen.SubList.Rect.X, GameMain.NetLobbyScreen.SubList.Rect.Bottom+5) : new Vector2(GameMain.GraphicsWidth / 2 - 200, 10);
-
-
-
Vector2 pos = new Vector2(GameMain.GraphicsWidth / 2 - 130, GameMain.NetLobbyScreen.InfoFrame.Rect.Y / 2 - 15);
GUI.DrawString(spriteBatch,
@@ -799,6 +806,16 @@ namespace Barotrauma.Networking
}
}
+ if (respawnManager != null && respawnManager.CurrentState == RespawnManager.State.Waiting &&
+ myCharacter != null && myCharacter.IsDead)
+ {
+ GUI.DrawString(spriteBatch,
+ new Vector2(GameMain.GraphicsWidth - 300.0f, 20),
+ "Respawning in " + (int)respawnManager.RespawnTimer + " s",
+ Color.White, null, 0, GUI.SmallFont);
+ }
+
+
if (!GameMain.DebugDraw) return;
int width = 200, height = 300;
@@ -1023,7 +1040,7 @@ namespace Barotrauma.Networking
client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
}
- private Character ReadCharacterData(NetIncomingMessage inc, bool isMyCharacter)
+ public Character ReadCharacterData(NetIncomingMessage inc, bool isMyCharacter)
{
string newName = inc.ReadString();
ushort ID = inc.ReadUInt16();
diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs
index 27a98914e..f29fad662 100644
--- a/Subsurface/Source/Networking/GameServer.cs
+++ b/Subsurface/Source/Networking/GameServer.cs
@@ -282,6 +282,8 @@ namespace Barotrauma.Networking
{
inGameHUD.Update((float)Physics.step);
+ respawnManager.Update(deltaTime);
+
bool isCrewDead =
connectedClients.Find(c => c.Character != null && !c.Character.IsDead)==null &&
(myCharacter == null || myCharacter.IsDead);
@@ -289,7 +291,7 @@ namespace Barotrauma.Networking
//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))
+ (endRoundAtLevelEnd && Submarine.MainSub != null && Submarine.MainSub.AtEndPosition))
{
if (AutoRestart && isCrewDead)
{
@@ -363,9 +365,10 @@ namespace Barotrauma.Networking
{
if (!(c is AICharacter) || c.IsDead) continue;
- Vector2 diff = c.WorldPosition-Submarine.Loaded.WorldPosition;
+ //todo: take multiple subs into account
+ //Vector2 diff = c.WorldPosition - Submarine.MainSub.WorldPosition;
- if (FarseerPhysics.ConvertUnits.ToSimUnits(diff.Length()) > NetConfig.CharacterIgnoreDistance) continue;
+ //if (FarseerPhysics.ConvertUnits.ToSimUnits(diff.Length()) > NetConfig.CharacterIgnoreDistance) continue;
new NetworkEvent(NetworkEventType.EntityUpdate, c.ID, false);
}
@@ -389,7 +392,13 @@ namespace Barotrauma.Networking
private void SparseUpdate()
{
- if (gameStarted) new NetworkEvent(Submarine.Loaded.ID, false);
+ if (gameStarted)
+ {
+ foreach (Submarine sub in Submarine.Loaded)
+ {
+ new NetworkEvent(sub.ID, false);
+ }
+ }
foreach (Character c in Character.CharacterList)
{
@@ -397,9 +406,10 @@ namespace Barotrauma.Networking
if (c is AICharacter)
{
- Vector2 diff = c.WorldPosition - Submarine.Loaded.WorldPosition;
+ //todo: take multiple subs into account
+ //Vector2 diff = c.WorldPosition - Submarine.MainSub.WorldPosition;
- if (FarseerPhysics.ConvertUnits.ToSimUnits(diff.Length()) > NetConfig.CharacterIgnoreDistance) continue;
+ //if (FarseerPhysics.ConvertUnits.ToSimUnits(diff.Length()) > NetConfig.CharacterIgnoreDistance) continue;
}
new NetworkEvent(NetworkEventType.ImportantEntityUpdate, c.ID, false);
@@ -601,7 +611,7 @@ namespace Barotrauma.Networking
case (byte)PacketTypes.SpectateRequest:
if (gameStarted && allowSpectating)
{
- var startMessage = CreateStartMessage(roundStartSeed, Submarine.Loaded, GameMain.GameSession.gameMode.Preset);
+ var startMessage = CreateStartMessage(roundStartSeed, Submarine.MainSub, GameMain.GameSession.gameMode.Preset);
server.SendMessage(startMessage, inc.SenderConnection, NetDeliveryMethod.ReliableUnordered);
dataSender.Spectating = true;
@@ -840,6 +850,10 @@ namespace Barotrauma.Networking
//save "normal" events again
existingEvents = new List(NetworkEvent.Events);
}
+
+ yield return new WaitForSeconds(0.1f);
+
+ sender.inGame = true;
yield return CoroutineStatus.Success;
}
@@ -941,6 +955,8 @@ namespace Barotrauma.Networking
GameServer.Log("Game mode: " + selectedMode.Name, Color.Cyan);
GameServer.Log("Level seed: " + GameMain.NetLobbyScreen.LevelSeed, Color.Cyan);
+ respawnManager = new RespawnManager(this);
+
yield return CoroutineStatus.Running;
List characterInfos = new List();
@@ -964,7 +980,7 @@ namespace Barotrauma.Networking
characterInfos.Add(characterInfo);
}
- WayPoint[] assignedWayPoints = WayPoint.SelectCrewSpawnPoints(characterInfos);
+ WayPoint[] assignedWayPoints = WayPoint.SelectCrewSpawnPoints(characterInfos, Submarine.MainSub);
for (int i = 0; i < connectedClients.Count; i++)
{
@@ -985,7 +1001,7 @@ namespace Barotrauma.Networking
GameMain.GameSession.CrewManager.characters.Add(myCharacter);
}
- var startMessage = CreateStartMessage(roundStartSeed, Submarine.Loaded, GameMain.GameSession.gameMode.Preset);
+ var startMessage = CreateStartMessage(roundStartSeed, Submarine.MainSub, GameMain.GameSession.gameMode.Preset);
SendMessage(startMessage, NetDeliveryMethod.ReliableUnordered);
@@ -1090,6 +1106,8 @@ namespace Barotrauma.Networking
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
GameMain.LightManager.LosEnabled = false;
+ respawnManager = null;
+
gameStarted = false;
if (connectedClients.Count > 0)
@@ -1113,7 +1131,7 @@ namespace Barotrauma.Networking
float endPreviewLength = 10.0f;
- var cinematic = new TransitionCinematic(Submarine.Loaded, GameMain.GameScreen.Cam, endPreviewLength);
+ var cinematic = new TransitionCinematic(Submarine.MainSub, GameMain.GameScreen.Cam, endPreviewLength);
float secondsLeft = endPreviewLength;
@@ -1132,6 +1150,14 @@ namespace Barotrauma.Networking
}
+ public void SendRespawnManagerMsg()
+ {
+ NetOutgoingMessage msg = server.CreateMessage();
+ respawnManager.WriteNetworkEvent(msg);
+
+ SendMessage(msg, NetDeliveryMethod.ReliableUnordered);
+ }
+
private void DisconnectClient(NetConnection senderConnection, string msg = "", string targetmsg = "")
{
Client client = connectedClients.Find(x => x.Connection == senderConnection);
@@ -1322,6 +1348,14 @@ namespace Barotrauma.Networking
log.LogFrame.Draw(spriteBatch);
}
+ if (respawnManager != null && respawnManager.CurrentState == RespawnManager.State.Waiting && respawnManager.CountdownStarted)
+ {
+ GUI.DrawString(spriteBatch,
+ new Vector2(GameMain.GraphicsWidth - 500.0f, 20),
+ "Respawning in " + (int)respawnManager.RespawnTimer + " s",
+ Color.White, null, 0, GUI.SmallFont);
+ }
+
if (!ShowNetStats) return;
int width = 200, height = 300;
@@ -1603,7 +1637,7 @@ namespace Barotrauma.Networking
}
}
- private void WriteCharacterData(NetOutgoingMessage message, string name, Character character)
+ public void WriteCharacterData(NetOutgoingMessage message, string name, Character character)
{
message.Write(name);
message.Write(character.ID);
diff --git a/Subsurface/Source/Networking/NetworkMember.cs b/Subsurface/Source/Networking/NetworkMember.cs
index 7a167d71f..6b7edd427 100644
--- a/Subsurface/Source/Networking/NetworkMember.cs
+++ b/Subsurface/Source/Networking/NetworkMember.cs
@@ -39,7 +39,9 @@ namespace Barotrauma.Networking
RequestFile, FileStream,
- SpectateRequest
+ SpectateRequest,
+
+ Respawn
}
enum VoteType
@@ -74,6 +76,9 @@ namespace Barotrauma.Networking
protected Character myCharacter;
protected CharacterInfo characterInfo;
+
+ protected RespawnManager respawnManager;
+
public Voting Voting;
public Character Character
diff --git a/Subsurface/Source/Networking/RespawnManager.cs b/Subsurface/Source/Networking/RespawnManager.cs
new file mode 100644
index 000000000..1b5a4d2f5
--- /dev/null
+++ b/Subsurface/Source/Networking/RespawnManager.cs
@@ -0,0 +1,312 @@
+using Barotrauma.Items.Components;
+using FarseerPhysics;
+using Lidgren.Network;
+using Microsoft.Xna.Framework;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Barotrauma.Networking
+{
+ class RespawnManager
+ {
+ const int MinCharactersToRespawn = 1;
+
+ const float RespawnInterval = 20.0f;
+
+ public enum State
+ {
+ Waiting,
+ Transporting,
+ Returning
+ }
+
+ private NetworkMember networkMember;
+
+ private State state;
+
+ private Submarine respawnShuttle;
+ private Steering shuttleSteering;
+ private List shuttleDoors;
+
+ public float RespawnTimer
+ {
+ get { return respawnTimer; }
+ }
+
+ public bool CountdownStarted
+ {
+ get;
+ private set;
+ }
+
+ public State CurrentState
+ {
+ get { return state; }
+ }
+
+ private float respawnTimer, shuttleReturnTimer;
+
+ public RespawnManager(NetworkMember server)
+ {
+ this.networkMember = server;
+
+ respawnShuttle = new Submarine("Submarines/Shuttle Mark I.sub");
+ respawnShuttle.Load(false);
+
+ ResetShuttlePos();
+
+ respawnShuttle.GodMode = true;
+
+ shuttleDoors = new List();
+ foreach (Item item in Item.ItemList)
+ {
+ if (item.Submarine != respawnShuttle) continue;
+
+ var steering = item.GetComponent();
+ if (steering != null) shuttleSteering = steering;
+
+ var door = item.GetComponent();
+ if (door != null) shuttleDoors.Add(door);
+ }
+
+ shuttleSteering.TargetPosition = ConvertUnits.ToSimUnits(Level.Loaded.StartPosition);
+
+ respawnTimer = RespawnInterval;
+ }
+
+ private List GetClientsToRespawn()
+ {
+ return networkMember.ConnectedClients.FindAll(c => c.inGame && (c.Character == null || c.Character.IsDead));
+ }
+
+ public void Update(float deltaTime)
+ {
+ switch (state)
+ {
+ case State.Waiting:
+ UpdateWaiting(deltaTime);
+ break;
+ case State.Transporting:
+ UpdateTransporting(deltaTime);
+ break;
+ case State.Returning:
+ UpdateReturning(deltaTime);
+ break;
+ }
+ }
+
+ private void UpdateWaiting(float deltaTime)
+ {
+ var server = networkMember as GameServer;
+ if (server == null)
+ {
+ if (CountdownStarted)
+ {
+ respawnTimer = Math.Max(0.0f, respawnTimer - deltaTime);
+ }
+ return;
+ }
+
+ respawnShuttle.Velocity = Vector2.Zero;
+
+ shuttleSteering.AutoPilot = false;
+ shuttleSteering.MaintainPos = false;
+
+ int characterToRespawnCount = GetClientsToRespawn().Count;
+ if (server.Character != null && server.Character.IsDead) characterToRespawnCount++;
+
+ CountdownStarted = characterToRespawnCount >= MinCharactersToRespawn;
+
+ if (!CountdownStarted) return;
+
+ respawnTimer -= deltaTime;
+ if (respawnTimer <= 0.0f)
+ {
+ respawnTimer = RespawnInterval;
+
+ Respawn();
+ }
+ }
+
+ private void UpdateTransporting(float deltaTime)
+ {
+ var server = networkMember as GameServer;
+ if (server == null) return;
+
+ if (Character.CharacterList.Any(c => c.Submarine == respawnShuttle && !c.IsDead)) return;
+
+ shuttleReturnTimer += deltaTime;
+ if (shuttleReturnTimer > 10.0f)
+ {
+ state = State.Returning;
+
+ server.SendRespawnManagerMsg();
+ shuttleReturnTimer = 0.0f;
+ }
+ }
+
+ private void UpdateReturning(float deltaTime)
+ {
+ shuttleReturnTimer += deltaTime;
+
+ if (shuttleReturnTimer > 1.0f)
+ {
+ shuttleSteering.AutoPilot = true;
+ shuttleSteering.MaintainPos = false;
+
+ foreach (Door door in shuttleDoors)
+ {
+ if (door.IsOpen) door.SetState(false, false, true);
+ }
+
+ var server = networkMember as GameServer;
+ if (server == null) return;
+
+ //shuttle has returned if the path has been traversed or the shuttle is close enough to the exit
+ if (shuttleSteering.SteeringPath != null && shuttleSteering.SteeringPath.Finished
+ || (respawnShuttle.WorldPosition.Y + respawnShuttle.Borders.Y > Level.Loaded.StartPosition.Y - Level.ShaftHeight &&
+ Math.Abs(Level.Loaded.StartPosition.X - respawnShuttle.WorldPosition.X) < 1000.0f))
+ {
+ CoroutineManager.StartCoroutine(
+ ForceShuttleToPos(new Vector2(Level.Loaded.StartPosition.X, Level.Loaded.Size.Y + 1000.0f), 100.0f));
+
+ if (GameMain.GameSession != null && GameMain.GameSession.Map != null)
+ {
+ string msg = "The transportation shuttle has returned to " + GameMain.GameSession.Map.SelectedLocation;
+
+ server.SendChatMessage(ChatMessage.Create("", msg, ChatMessageType.Server, null), server.ConnectedClients);
+ }
+
+ state = State.Waiting;
+ server.SendRespawnManagerMsg();
+ }
+
+ shuttleReturnTimer = 0.0f;
+ }
+ }
+
+ private void Respawn()
+ {
+ var server = networkMember as GameServer;
+ if (server == null) return;
+
+ state = State.Transporting;
+
+ ResetShuttlePos();
+
+ server.SendChatMessage(ChatMessage.Create("", "Transportation shuttle dispatched", ChatMessageType.Server, null), server.ConnectedClients);
+
+ server.SendRespawnManagerMsg();
+
+ CoroutineManager.StartCoroutine(ForceShuttleToPos(Level.Loaded.StartPosition - Vector2.UnitY * Level.ShaftHeight, 100.0f));
+ }
+
+ private IEnumerable