Added a command for automatic hull generation
It's not perfect by any means, but it should be usable enough as a baseline for most subs.
This commit is contained in:
@@ -28,7 +28,7 @@ namespace Barotrauma
|
|||||||
static GUIFrame frame;
|
static GUIFrame frame;
|
||||||
static GUIListBox listBox;
|
static GUIListBox listBox;
|
||||||
static GUITextBox textBox;
|
static GUITextBox textBox;
|
||||||
|
|
||||||
public static void Init(GameWindow window)
|
public static void Init(GameWindow window)
|
||||||
{
|
{
|
||||||
int x = 20, y = 20;
|
int x = 20, y = 20;
|
||||||
@@ -47,7 +47,7 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
NewMessage("Press F3 to open/close the debug console", Color.Cyan);
|
NewMessage("Press F3 to open/close the debug console", Color.Cyan);
|
||||||
NewMessage("Enter \"help\" for a list of available console commands", Color.Cyan);
|
NewMessage("Enter \"help\" for a list of available console commands", Color.Cyan);
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
textBox.Text = AutoComplete(textBox.Text);
|
textBox.Text = AutoComplete(textBox.Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PlayerInput.KeyHit(Keys.Enter))
|
if (PlayerInput.KeyHit(Keys.Enter))
|
||||||
{
|
{
|
||||||
ExecuteCommand(textBox.Text);
|
ExecuteCommand(textBox.Text);
|
||||||
@@ -164,7 +164,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
listBox.children.RemoveRange(0, listBox.children.Count - MaxMessages);
|
listBox.children.RemoveRange(0, listBox.children.Count - MaxMessages);
|
||||||
}
|
}
|
||||||
|
|
||||||
Messages.Add(msg);
|
Messages.Add(msg);
|
||||||
if (Messages.Count > MaxMessages)
|
if (Messages.Count > MaxMessages)
|
||||||
{
|
{
|
||||||
@@ -190,10 +190,27 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private static void InitProjectSpecific()
|
private static void InitProjectSpecific()
|
||||||
{
|
{
|
||||||
|
commands.Add(new Command("autohull", "", (string[] args) =>
|
||||||
|
{
|
||||||
|
if (Screen.Selected != GameMain.SubEditorScreen) return;
|
||||||
|
|
||||||
|
if (MapEntity.mapEntityList.Any(e => e is Hull || e is Gap))
|
||||||
|
{
|
||||||
|
ShowQuestionPrompt("This submarine already has hulls and/or gaps. This command will delete them. Do you want to continue? Y/N",
|
||||||
|
(option) => {
|
||||||
|
if (option.ToLower() == "y") GameMain.SubEditorScreen.AutoHull();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GameMain.SubEditorScreen.AutoHull();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("startclient", "", (string[] args) =>
|
commands.Add(new Command("startclient", "", (string[] args) =>
|
||||||
{
|
{
|
||||||
if (args.Length == 0) return;
|
if (args.Length == 0) return;
|
||||||
|
|
||||||
if (GameMain.Client == null)
|
if (GameMain.Client == null)
|
||||||
{
|
{
|
||||||
GameMain.NetworkMember = new GameClient("Name");
|
GameMain.NetworkMember = new GameClient("Name");
|
||||||
@@ -227,7 +244,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
GameMain.SubEditorScreen.Select();
|
GameMain.SubEditorScreen.Select();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("editcharacter", "", (string[] args) =>
|
commands.Add(new Command("editcharacter", "", (string[] args) =>
|
||||||
{
|
{
|
||||||
GameMain.CharacterEditorScreen.Select();
|
GameMain.CharacterEditorScreen.Select();
|
||||||
|
|||||||
@@ -901,7 +901,305 @@ namespace Barotrauma
|
|||||||
previouslyUsedList.RemoveChild(textBlock);
|
previouslyUsedList.RemoveChild(textBlock);
|
||||||
previouslyUsedList.children.Insert(0, textBlock);
|
previouslyUsedList.children.Insert(0, textBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AutoHull()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MapEntity.mapEntityList.Count; i++)
|
||||||
|
{
|
||||||
|
MapEntity h = MapEntity.mapEntityList[i];
|
||||||
|
if (h is Hull || h is Gap)
|
||||||
|
{
|
||||||
|
h.Remove();
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Vector2> wallPoints = new List<Vector2>();
|
||||||
|
Vector2 min = Vector2.Zero;
|
||||||
|
Vector2 max = Vector2.Zero;
|
||||||
|
|
||||||
|
List<MapEntity> mapEntityList = new List<MapEntity>();
|
||||||
|
|
||||||
|
foreach (MapEntity e in MapEntity.mapEntityList)
|
||||||
|
{
|
||||||
|
if (e is Item)
|
||||||
|
{
|
||||||
|
Item it = e as Item;
|
||||||
|
Door door = it.GetComponent<Door>();
|
||||||
|
if (door != null)
|
||||||
|
{
|
||||||
|
int halfW = e.WorldRect.Width / 2;
|
||||||
|
wallPoints.Add(new Vector2(e.WorldRect.X + halfW, -e.WorldRect.Y + e.WorldRect.Height));
|
||||||
|
mapEntityList.Add(it);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(e is Structure)) continue;
|
||||||
|
Structure s = e as Structure;
|
||||||
|
if (!s.HasBody) continue;
|
||||||
|
mapEntityList.Add(e);
|
||||||
|
|
||||||
|
if (e.Rect.Width > e.Rect.Height)
|
||||||
|
{
|
||||||
|
int halfH = e.WorldRect.Height / 2;
|
||||||
|
wallPoints.Add(new Vector2(e.WorldRect.X, -e.WorldRect.Y + halfH));
|
||||||
|
wallPoints.Add(new Vector2(e.WorldRect.X + e.WorldRect.Width, -e.WorldRect.Y + halfH));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int halfW = e.WorldRect.Width / 2;
|
||||||
|
wallPoints.Add(new Vector2(e.WorldRect.X + halfW, -e.WorldRect.Y));
|
||||||
|
wallPoints.Add(new Vector2(e.WorldRect.X + halfW, -e.WorldRect.Y + e.WorldRect.Height));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
min = wallPoints[0];
|
||||||
|
max = wallPoints[0];
|
||||||
|
for (int i = 0; i < wallPoints.Count; i++)
|
||||||
|
{
|
||||||
|
min.X = Math.Min(min.X, wallPoints[i].X);
|
||||||
|
min.Y = Math.Min(min.Y, wallPoints[i].Y);
|
||||||
|
max.X = Math.Max(max.X, wallPoints[i].X);
|
||||||
|
max.Y = Math.Max(max.Y, wallPoints[i].Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Rectangle> hullRects = new List<Rectangle>();
|
||||||
|
hullRects.Add(new Rectangle((int)min.X, (int)min.Y, (int)(max.X - min.X), (int)(max.Y - min.Y)));
|
||||||
|
foreach (Vector2 point in wallPoints)
|
||||||
|
{
|
||||||
|
MathUtils.SplitRectanglesHorizontal(hullRects, point);
|
||||||
|
MathUtils.SplitRectanglesVertical(hullRects, point);
|
||||||
|
}
|
||||||
|
|
||||||
|
hullRects.Sort((a, b) =>
|
||||||
|
{
|
||||||
|
if (a.Y < b.Y) return -1;
|
||||||
|
if (a.Y > b.Y) return 1;
|
||||||
|
if (a.X < b.X) return -1;
|
||||||
|
if (a.X > b.X) return 1;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (int i = 0; i < hullRects.Count - 1; i++)
|
||||||
|
{
|
||||||
|
Rectangle rect = hullRects[i];
|
||||||
|
if (hullRects[i + 1].Y > rect.Y) continue;
|
||||||
|
|
||||||
|
Vector2 hullRPoint = new Vector2(rect.X + rect.Width - 8, rect.Y + rect.Height / 2);
|
||||||
|
Vector2 hullLPoint = new Vector2(rect.X, rect.Y + rect.Height / 2);
|
||||||
|
|
||||||
|
MapEntity container = null;
|
||||||
|
foreach (MapEntity e in mapEntityList)
|
||||||
|
{
|
||||||
|
Rectangle entRect = e.WorldRect;
|
||||||
|
entRect.Y = -entRect.Y;
|
||||||
|
if (entRect.Contains(hullRPoint))
|
||||||
|
{
|
||||||
|
if (!entRect.Contains(hullLPoint)) container = e;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (container == null)
|
||||||
|
{
|
||||||
|
rect.Width += hullRects[i + 1].Width;
|
||||||
|
hullRects[i] = rect;
|
||||||
|
hullRects.RemoveAt(i + 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (MapEntity e in mapEntityList)
|
||||||
|
{
|
||||||
|
Rectangle entRect = e.WorldRect;
|
||||||
|
if (entRect.Width < entRect.Height) continue;
|
||||||
|
entRect.Y = -entRect.Y - 16;
|
||||||
|
for (int i = 0; i < hullRects.Count; i++)
|
||||||
|
{
|
||||||
|
Rectangle hullRect = hullRects[i];
|
||||||
|
if (entRect.Intersects(hullRect))
|
||||||
|
{
|
||||||
|
if (hullRect.Y < entRect.Y)
|
||||||
|
{
|
||||||
|
hullRect.Height = Math.Max((entRect.Y + 16 + entRect.Height / 2) - hullRect.Y, hullRect.Height);
|
||||||
|
hullRects[i] = hullRect;
|
||||||
|
}
|
||||||
|
else if (hullRect.Y + hullRect.Height <= entRect.Y + 16 + entRect.Height)
|
||||||
|
{
|
||||||
|
hullRects.RemoveAt(i);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (MapEntity e in mapEntityList)
|
||||||
|
{
|
||||||
|
Rectangle entRect = e.WorldRect;
|
||||||
|
if (entRect.Width < entRect.Height) continue;
|
||||||
|
entRect.Y = -entRect.Y;
|
||||||
|
for (int i = 0; i < hullRects.Count; i++)
|
||||||
|
{
|
||||||
|
Rectangle hullRect = hullRects[i];
|
||||||
|
if (entRect.Intersects(hullRect))
|
||||||
|
{
|
||||||
|
if (hullRect.Y >= entRect.Y - 8 && hullRect.Y + hullRect.Height <= entRect.Y + entRect.Height + 8)
|
||||||
|
{
|
||||||
|
hullRects.RemoveAt(i);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < hullRects.Count;)
|
||||||
|
{
|
||||||
|
Rectangle hullRect = hullRects[i];
|
||||||
|
Vector2 point = new Vector2(hullRect.X+2, hullRect.Y+hullRect.Height/2);
|
||||||
|
MapEntity container = null;
|
||||||
|
foreach (MapEntity e in mapEntityList)
|
||||||
|
{
|
||||||
|
Rectangle entRect = e.WorldRect;
|
||||||
|
entRect.Y = -entRect.Y;
|
||||||
|
if (entRect.Contains(point))
|
||||||
|
{
|
||||||
|
container = e;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (container == null)
|
||||||
|
{
|
||||||
|
hullRects.RemoveAt(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (hullRects[i].Y <= hullRect.Y)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
if (i >= hullRects.Count) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = hullRects.Count-1; i >= 0;)
|
||||||
|
{
|
||||||
|
Rectangle hullRect = hullRects[i];
|
||||||
|
Vector2 point = new Vector2(hullRect.X+hullRect.Width-2, hullRect.Y+hullRect.Height/2);
|
||||||
|
MapEntity container = null;
|
||||||
|
foreach (MapEntity e in mapEntityList)
|
||||||
|
{
|
||||||
|
Rectangle entRect = e.WorldRect;
|
||||||
|
entRect.Y = -entRect.Y;
|
||||||
|
if (entRect.Contains(point))
|
||||||
|
{
|
||||||
|
container = e;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (container == null)
|
||||||
|
{
|
||||||
|
hullRects.RemoveAt(i); i--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (hullRects[i].Y >= hullRect.Y)
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
if (i < 0) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hullRects.Sort((a, b) =>
|
||||||
|
{
|
||||||
|
if (a.X < b.X) return -1;
|
||||||
|
if (a.X > b.X) return 1;
|
||||||
|
if (a.Y < b.Y) return -1;
|
||||||
|
if (a.Y > b.Y) return 1;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (int i = 0; i < hullRects.Count - 1; i++)
|
||||||
|
{
|
||||||
|
Rectangle rect = hullRects[i];
|
||||||
|
if (hullRects[i + 1].Width != rect.Width) continue;
|
||||||
|
if (hullRects[i + 1].X > rect.X) continue;
|
||||||
|
|
||||||
|
Vector2 hullBPoint = new Vector2(rect.X + rect.Width / 2, rect.Y + rect.Height - 8);
|
||||||
|
Vector2 hullUPoint = new Vector2(rect.X + rect.Width / 2, rect.Y);
|
||||||
|
|
||||||
|
MapEntity container = null;
|
||||||
|
foreach (MapEntity e in mapEntityList)
|
||||||
|
{
|
||||||
|
Rectangle entRect = e.WorldRect;
|
||||||
|
entRect.Y = -entRect.Y;
|
||||||
|
if (entRect.Contains(hullBPoint))
|
||||||
|
{
|
||||||
|
if (!entRect.Contains(hullUPoint)) container = e;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (container == null)
|
||||||
|
{
|
||||||
|
rect.Height += hullRects[i + 1].Height;
|
||||||
|
hullRects[i] = rect;
|
||||||
|
hullRects.RemoveAt(i + 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < hullRects.Count;i++)
|
||||||
|
{
|
||||||
|
Rectangle rect = hullRects[i];
|
||||||
|
rect.Y -= 16;
|
||||||
|
rect.Height += 32;
|
||||||
|
hullRects[i] = rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
hullRects.Sort((a, b) =>
|
||||||
|
{
|
||||||
|
if (a.Y < b.Y) return -1;
|
||||||
|
if (a.Y > b.Y) return 1;
|
||||||
|
if (a.X < b.X) return -1;
|
||||||
|
if (a.X > b.X) return 1;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (int i = 0; i < hullRects.Count; i++)
|
||||||
|
{
|
||||||
|
for (int j = i+1; j < hullRects.Count; j++)
|
||||||
|
{
|
||||||
|
if (hullRects[j].Y <= hullRects[i].Y) continue;
|
||||||
|
if (hullRects[j].Intersects(hullRects[i]))
|
||||||
|
{
|
||||||
|
Rectangle rect = hullRects[i];
|
||||||
|
rect.Height = hullRects[j].Y - rect.Y;
|
||||||
|
hullRects[i] = rect;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Rectangle rect in hullRects)
|
||||||
|
{
|
||||||
|
Rectangle hullRect = rect;
|
||||||
|
hullRect.Y = -hullRect.Y;
|
||||||
|
Hull newHull = new Hull(MapEntityPrefab.Find("Hull"),
|
||||||
|
hullRect,
|
||||||
|
Submarine.MainSub);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (MapEntity e in mapEntityList)
|
||||||
|
{
|
||||||
|
if (!(e is Structure)) continue;
|
||||||
|
if (!(e as Structure).IsPlatform) continue;
|
||||||
|
|
||||||
|
Rectangle gapRect = e.WorldRect;
|
||||||
|
gapRect.Y -= 8;
|
||||||
|
gapRect.Height = 16;
|
||||||
|
Gap newGap = new Gap(MapEntityPrefab.Find("Gap"),
|
||||||
|
gapRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void AddToGUIUpdateList()
|
public override void AddToGUIUpdateList()
|
||||||
{
|
{
|
||||||
if (tutorial != null) tutorial.AddToGUIUpdateList();
|
if (tutorial != null) tutorial.AddToGUIUpdateList();
|
||||||
|
|||||||
@@ -349,9 +349,12 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
clientPermissions.Clear();
|
clientPermissions.Clear();
|
||||||
|
|
||||||
if (File.Exists("Data/clientpermissions.txt") && !File.Exists(ClientPermissionsFile))
|
if (!File.Exists(ClientPermissionsFile))
|
||||||
{
|
{
|
||||||
LoadClientPermissionsOld("Data/clientpermissions.txt");
|
if (File.Exists("Data/clientpermissions.txt"))
|
||||||
|
{
|
||||||
|
LoadClientPermissionsOld("Data/clientpermissions.txt");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -508,6 +508,52 @@ namespace Barotrauma
|
|||||||
// Return formatted number with suffix
|
// Return formatted number with suffix
|
||||||
return readable.ToString("0.# ") + suffix;
|
return readable.ToString("0.# ") + suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void SplitRectanglesHorizontal(List<Rectangle> rects, Vector2 point)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < rects.Count; i++)
|
||||||
|
{
|
||||||
|
if (point.Y > rects[i].Y && point.Y < rects[i].Y + rects[i].Height)
|
||||||
|
{
|
||||||
|
Rectangle rect1 = rects[i];
|
||||||
|
Rectangle rect2 = rects[i];
|
||||||
|
|
||||||
|
rect1.Height = (int)(point.Y - rects[i].Y);
|
||||||
|
|
||||||
|
rect2.Height = rects[i].Height - rect1.Height;
|
||||||
|
rect2.Y = rect1.Y + rect1.Height;
|
||||||
|
rects[i] = rect1;
|
||||||
|
rects.Insert(i + 1, rect2); i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SplitRectanglesVertical(List<Rectangle> rects, Vector2 point)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < rects.Count; i++)
|
||||||
|
{
|
||||||
|
if (point.X>rects[i].X && point.X<rects[i].X+rects[i].Width)
|
||||||
|
{
|
||||||
|
Rectangle rect1 = rects[i];
|
||||||
|
Rectangle rect2 = rects[i];
|
||||||
|
|
||||||
|
rect1.Width = (int)(point.X-rects[i].X);
|
||||||
|
|
||||||
|
rect2.Width = rects[i].Width - rect1.Width;
|
||||||
|
rect2.X = rect1.X + rect1.Width;
|
||||||
|
rects[i] = rect1;
|
||||||
|
rects.Insert(i + 1, rect2); i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*for (int i = 0; i < rects.Count; i++)
|
||||||
|
{
|
||||||
|
if (rects[i].Width <= 0 || rects[i].Height <= 0)
|
||||||
|
{
|
||||||
|
rects.RemoveAt(i); i--;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CompareCCW : IComparer<Vector2>
|
class CompareCCW : IComparer<Vector2>
|
||||||
|
|||||||
Reference in New Issue
Block a user