- multiple submarines can be "merged" into one file (to be used as escape vessels etc)
- WIP docking ports
This commit is contained in:
@@ -639,7 +639,7 @@ namespace Barotrauma
|
||||
FindHulls();
|
||||
}
|
||||
|
||||
public override XElement Save(XDocument doc)
|
||||
public override XElement Save(XElement parentElement)
|
||||
{
|
||||
XElement element = new XElement("Gap");
|
||||
|
||||
@@ -663,7 +663,7 @@ namespace Barotrauma
|
||||
// }
|
||||
//}
|
||||
|
||||
doc.Root.Add(element);
|
||||
parentElement.Add(element);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
@@ -260,6 +260,21 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsMouseOn(Vector2 position)
|
||||
{
|
||||
if (!GameMain.DebugDraw && !ShowHulls) return false;
|
||||
@@ -295,6 +310,7 @@ namespace Barotrauma
|
||||
public override void Remove()
|
||||
{
|
||||
base.Remove();
|
||||
hullList.Remove(this);
|
||||
|
||||
if (Submarine == null || !Submarine.Loading)
|
||||
{
|
||||
@@ -324,7 +340,6 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
|
||||
hullList.Remove(this);
|
||||
}
|
||||
|
||||
public void AddFireSource(FireSource fireSource, bool createNetworkEvent = true)
|
||||
@@ -712,7 +727,7 @@ namespace Barotrauma
|
||||
// return gaps;
|
||||
//}
|
||||
|
||||
public override XElement Save(XDocument doc)
|
||||
public override XElement Save(XElement parentElement)
|
||||
{
|
||||
XElement element = new XElement("Hull");
|
||||
|
||||
@@ -725,8 +740,8 @@ namespace Barotrauma
|
||||
rect.Width + "," + rect.Height),
|
||||
new XAttribute("water", volume)
|
||||
);
|
||||
|
||||
doc.Root.Add(element);
|
||||
|
||||
parentElement.Add(element);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -625,15 +625,29 @@ namespace Barotrauma
|
||||
if (linked != null) e.linkedTo.Add(linked);
|
||||
}
|
||||
}
|
||||
|
||||
List<LinkedSubmarine> linkedSubs = new List<LinkedSubmarine>();
|
||||
|
||||
for (int i = 0; i<mapEntityList.Count; i++)
|
||||
{
|
||||
if (mapEntityList[i].Submarine != sub) continue;
|
||||
|
||||
if (mapEntityList[i] is LinkedSubmarine)
|
||||
{
|
||||
linkedSubs.Add((LinkedSubmarine)mapEntityList[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
mapEntityList[i].OnMapLoaded();
|
||||
}
|
||||
|
||||
Item.UpdateHulls();
|
||||
Gap.UpdateHulls();
|
||||
Gap.UpdateHulls();
|
||||
|
||||
foreach (LinkedSubmarine linkedSub in linkedSubs)
|
||||
{
|
||||
linkedSub.OnMapLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -114,6 +114,11 @@ namespace Barotrauma
|
||||
ep.name = "Spawnpoint";
|
||||
ep.constructor = typeof(WayPoint).GetConstructor(new Type[] { typeof(MapEntityPrefab), typeof(Rectangle) });
|
||||
list.Add(ep);
|
||||
|
||||
//ep = new MapEntityPrefab();
|
||||
//ep.name = "Linked Submarine";
|
||||
//ep.Category = 0;
|
||||
//list.Add(ep);
|
||||
|
||||
}
|
||||
|
||||
@@ -154,8 +159,7 @@ namespace Barotrauma
|
||||
|
||||
if (PlayerInput.LeftButtonReleased())
|
||||
{
|
||||
object[] lobject = new object[] { this, newRect };
|
||||
constructor.Invoke(lobject);
|
||||
CreateInstance(newRect);
|
||||
placePosition = Vector2.Zero;
|
||||
selected = null;
|
||||
}
|
||||
@@ -170,7 +174,12 @@ namespace Barotrauma
|
||||
selected = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected virtual void CreateInstance(Rectangle rect)
|
||||
{
|
||||
object[] lobject = new object[] { this, rect };
|
||||
constructor.Invoke(lobject);
|
||||
}
|
||||
|
||||
public static bool SelectPrefab(object selection)
|
||||
{
|
||||
|
||||
@@ -668,7 +668,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
|
||||
public override XElement Save(XDocument doc)
|
||||
public override XElement Save(XElement parentElement)
|
||||
{
|
||||
XElement element = new XElement("Structure");
|
||||
|
||||
@@ -696,7 +696,7 @@ namespace Barotrauma
|
||||
element.Add(sectionElement);
|
||||
}
|
||||
|
||||
doc.Root.Add(element);
|
||||
parentElement.Add(element);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (hash != null) return hash;
|
||||
|
||||
XDocument doc = OpenDoc(filePath);
|
||||
XDocument doc = OpenFile(filePath);
|
||||
hash = new Md5Hash(doc);
|
||||
|
||||
return hash;
|
||||
@@ -223,7 +223,7 @@ namespace Barotrauma
|
||||
|
||||
if (tryLoad)
|
||||
{
|
||||
XDocument doc = OpenDoc(filePath);
|
||||
XDocument doc = OpenFile(filePath);
|
||||
|
||||
if (doc != null && doc.Root != null)
|
||||
{
|
||||
@@ -438,7 +438,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;
|
||||
}
|
||||
@@ -532,7 +544,7 @@ namespace Barotrauma
|
||||
foreach (MapEntity e in MapEntity.mapEntityList)
|
||||
{
|
||||
if (e.MoveWithLevel ||e.Submarine != this) continue;
|
||||
e.Save(doc);
|
||||
e.Save(doc.Root);
|
||||
}
|
||||
|
||||
hash = new Md5Hash(doc);
|
||||
@@ -648,7 +660,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 = "";
|
||||
@@ -718,16 +730,21 @@ namespace Barotrauma
|
||||
return doc;
|
||||
}
|
||||
|
||||
public void Load(bool unloadPrevious)
|
||||
public void Load(bool unloadPrevious, XElement submarineElement = null)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
Description = ToolBox.GetAttributeString(submarineElement, "description", "");
|
||||
|
||||
|
||||
HiddenSubPosition = HiddenSubStartPosition;
|
||||
@@ -742,7 +759,7 @@ namespace Barotrauma
|
||||
IdOffset = Math.Max(IdOffset, me.ID);
|
||||
}
|
||||
|
||||
foreach (XElement element in doc.Root.Elements())
|
||||
foreach (XElement element in submarineElement.Elements())
|
||||
{
|
||||
string typeName = element.Name.ToString();
|
||||
|
||||
@@ -836,7 +853,19 @@ namespace Barotrauma
|
||||
|
||||
GameMain.LightManager.OnMapLoaded();
|
||||
|
||||
ID = ushort.MaxValue;
|
||||
ID = (ushort)(ushort.MaxValue - Submarine.loaded.Count);
|
||||
}
|
||||
|
||||
public static Submarine Load(XElement element, bool unloadPrevious)
|
||||
{
|
||||
if (unloadPrevious) Unload();
|
||||
|
||||
//tryload -> false
|
||||
|
||||
Submarine sub = new Submarine(ToolBox.GetAttributeString(element, "name", ""));
|
||||
sub.Load(unloadPrevious, element);
|
||||
|
||||
return sub;
|
||||
}
|
||||
|
||||
public static Submarine Load(string fileName, bool unloadPrevious)
|
||||
@@ -851,7 +880,7 @@ namespace Barotrauma
|
||||
string path = string.IsNullOrWhiteSpace(folder) ? fileName : System.IO.Path.Combine(SavePath, fileName);
|
||||
|
||||
Submarine sub = new Submarine(path);
|
||||
sub.Load(false);
|
||||
sub.Load(unloadPrevious);
|
||||
|
||||
//Entity.dictionary.Add(int.MaxValue, sub);
|
||||
|
||||
|
||||
@@ -125,30 +125,16 @@ namespace Barotrauma
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -183,50 +169,17 @@ namespace Barotrauma
|
||||
|
||||
List<Vector2> points = new List<Vector2>();
|
||||
|
||||
Vector2 leftMost = Vector2.Zero;
|
||||
|
||||
foreach (Structure wall in Structure.WallList)
|
||||
{
|
||||
if (wall.Submarine != submarine) continue;
|
||||
|
||||
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 (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<Vector2> hullPoints = new List<Vector2>();
|
||||
|
||||
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<Vector2> hullPoints = MathUtils.GiftWrap(points);
|
||||
|
||||
return hullPoints;
|
||||
}
|
||||
|
||||
171
Subsurface/Source/Map/SubmarineLink.cs
Normal file
171
Subsurface/Source/Map/SubmarineLink.cs
Normal file
@@ -0,0 +1,171 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
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<Vector2> wallVertices;
|
||||
|
||||
private string filePath;
|
||||
|
||||
private XElement saveElement;
|
||||
|
||||
public LinkedSubmarine(Submarine submarine)
|
||||
: base(null, submarine)
|
||||
{
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
private void GenerateWallVertices(XElement rootElement)
|
||||
{
|
||||
List<Vector2> points = new List<Vector2>();
|
||||
|
||||
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)
|
||||
{
|
||||
var doc = Submarine.OpenFile(filePath);
|
||||
|
||||
doc.Root.Name = "LinkedSubmarine";
|
||||
|
||||
doc.Root.Add(
|
||||
new XAttribute("filepath", filePath),
|
||||
new XAttribute("pos", ToolBox.Vector2ToString(Position - Submarine.HiddenSubPosition)));
|
||||
|
||||
parentElement.Add(doc.Root);
|
||||
|
||||
return doc.Root;
|
||||
}
|
||||
|
||||
public static void Load(XElement element, Submarine submarine)
|
||||
{
|
||||
Vector2 pos = ToolBox.GetAttributeVector2(element, "pos", Vector2.Zero);
|
||||
|
||||
if (Screen.Selected == GameMain.EditMapScreen)
|
||||
{
|
||||
string filePath = ToolBox.GetAttributeString(element, "filepath", "");
|
||||
|
||||
Create(submarine, filePath, pos);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var ls = new LinkedSubmarine(submarine);
|
||||
ls.saveElement = element;
|
||||
|
||||
ls.rect.Location = pos.ToPoint();
|
||||
}
|
||||
|
||||
public override void OnMapLoaded()
|
||||
{
|
||||
if (saveElement == null) return;
|
||||
var sub = Submarine.Load(saveElement, false);
|
||||
sub.SetPosition(WorldPosition - Submarine.WorldPosition);
|
||||
sub.Submarine = Submarine;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -718,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");
|
||||
@@ -739,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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user