Merge branch 'multisub'
Conflicts: .gitignore Subsurface/Source/Characters/Animation/HumanoidAnimController.cs Subsurface/Source/Items/Components/Holdable/RepairTool.cs Subsurface_Solution.v12.suo
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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<MapEntity>[(int)Math.Ceiling(limits.Width / cellSize), (int)Math.Ceiling(limits.Height / cellSize)];
|
||||
@@ -71,11 +74,28 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public static List<MapEntity> GetEntities(List<EntityGrid> entityGrids, Vector2 position, bool useWorldCoordinates = true)
|
||||
{
|
||||
List<MapEntity> entities = new List<MapEntity>();
|
||||
foreach (EntityGrid entityGrid in entityGrids)
|
||||
{
|
||||
Vector2 transformedPosition = position;
|
||||
if (useWorldCoordinates)
|
||||
{
|
||||
transformedPosition -= entityGrid.Submarine.Position;
|
||||
}
|
||||
|
||||
entities.AddRange(entityGrid.GetEntities(transformedPosition));
|
||||
}
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
public List<MapEntity> GetEntities(Vector2 position)
|
||||
{
|
||||
if (!MathUtils.IsValid(position)) new List<MapEntity>();
|
||||
|
||||
if (Submarine.Loaded != null) position -= Submarine.HiddenSubPosition;
|
||||
if (Submarine != null) position -= Submarine.HiddenSubPosition;
|
||||
|
||||
Point indices = GetIndices(position);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Barotrauma
|
||||
class Hull : MapEntity, IPropertyObject
|
||||
{
|
||||
public static List<Hull> hullList = new List<Hull>();
|
||||
private static EntityGrid entityGrid;
|
||||
private static List<EntityGrid> entityGrids = new List<EntityGrid>();
|
||||
|
||||
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);
|
||||
|
||||
@@ -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<Body> bodies;
|
||||
private List<VoronoiCell> 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<WayPoint> wayPoints = new List<WayPoint>();
|
||||
|
||||
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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -42,9 +42,21 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
}
|
||||
|
||||
class ConvexHullList
|
||||
{
|
||||
public readonly Submarine Submarine;
|
||||
public List<ConvexHull> List;
|
||||
|
||||
public ConvexHullList(Submarine submarine)
|
||||
{
|
||||
Submarine = submarine;
|
||||
List = new List<ConvexHull>();
|
||||
}
|
||||
}
|
||||
|
||||
class ConvexHull
|
||||
{
|
||||
public static List<ConvexHull> list = new List<ConvexHull>();
|
||||
public static List<ConvexHullList> HullLists = new List<ConvexHullList>();
|
||||
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<LightSource, CachedShadow> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
private static Texture2D lightTexture;
|
||||
|
||||
public List<ConvexHull> hullsInRange;
|
||||
private List<ConvexHullList> 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<ConvexHull>();
|
||||
hullsInRange = new List<ConvexHullList>();
|
||||
|
||||
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<ConvexHull>();
|
||||
|
||||
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<ConvexHull> GetHullsInRange(Submarine sub)
|
||||
{
|
||||
var chList = hullsInRange.Find(x => x.Submarine == sub);
|
||||
|
||||
if (chList == null)
|
||||
{
|
||||
chList = new ConvexHullList(sub);
|
||||
hullsInRange.Add(chList);
|
||||
}
|
||||
List<ConvexHull> 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<ConvexHull> GetHullsInRange(Vector2 position, float range, Submarine ParentSub)
|
||||
{
|
||||
hullsInRange = null;
|
||||
List<ConvexHull> list = new List<ConvexHull>();
|
||||
|
||||
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)
|
||||
|
||||
310
Subsurface/Source/Map/LinkedSubmarine.cs
Normal file
310
Subsurface/Source/Map/LinkedSubmarine.cs
Normal file
@@ -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<Vector2> 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<MapEntity>();
|
||||
linkedToID = new List<ushort>();
|
||||
|
||||
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<DockingPort>() == 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<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)
|
||||
{
|
||||
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<DockingPort>() != 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<DockingPort>() != null);
|
||||
|
||||
if (linkedItem != null)
|
||||
{
|
||||
var linkedPort = ((Item)linkedItem).GetComponent<DockingPort>();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
/// </summary>
|
||||
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<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);
|
||||
|
||||
}
|
||||
|
||||
@@ -128,7 +133,7 @@ namespace Barotrauma
|
||||
|
||||
if (placePosition == Vector2.Zero)
|
||||
{
|
||||
Vector2 position = Submarine.MouseToWorldGrid(cam);
|
||||
Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);
|
||||
|
||||
GUI.DrawLine(spriteBatch, new Vector2(position.X-GameMain.GraphicsWidth, -position.Y), new Vector2(position.X+GameMain.GraphicsWidth, -position.Y), Color.White);
|
||||
|
||||
@@ -138,7 +143,7 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector2 position = Submarine.MouseToWorldGrid(cam);
|
||||
Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);
|
||||
|
||||
if (resizeHorizontal) placeSize.X = position.X - placePosition.X;
|
||||
if (resizeVertical) placeSize.Y = placePosition.Y - position.Y;
|
||||
@@ -147,15 +152,14 @@ namespace Barotrauma
|
||||
newRect.Width = (int)Math.Max(newRect.Width, Submarine.GridSize.X);
|
||||
newRect.Height = (int)Math.Max(newRect.Height, Submarine.GridSize.Y);
|
||||
|
||||
if (Submarine.Loaded != null)
|
||||
if (Submarine.MainSub != null)
|
||||
{
|
||||
newRect.Location -= Submarine.Loaded.Position.ToPoint();
|
||||
newRect.Location -= Submarine.MainSub.Position.ToPoint();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -349,6 +349,14 @@ namespace Barotrauma
|
||||
GameMain.World.RemoveBody(b);
|
||||
}
|
||||
|
||||
foreach (WallSection s in sections)
|
||||
{
|
||||
if (s.gap != null)
|
||||
{
|
||||
s.gap.Remove();
|
||||
s.gap = null;
|
||||
}
|
||||
}
|
||||
if (convexHulls != null) convexHulls.ForEach(x => 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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<Submarine> SavedSubmarines = new List<Submarine>();
|
||||
|
||||
public static readonly Vector2 GridSize = new Vector2(16.0f, 16.0f);
|
||||
|
||||
private static Submarine loaded;
|
||||
public static Submarine MainSub;
|
||||
private static List<Submarine> loaded = new List<Submarine>();
|
||||
|
||||
private SubmarineBody subBody;
|
||||
|
||||
public readonly List<Submarine> 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<Submarine> 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<Submarine>();
|
||||
|
||||
|
||||
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<Items.Components.Wire>();
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<Vector2> points = new List<Vector2>();
|
||||
|
||||
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<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;
|
||||
}
|
||||
@@ -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
|
||||
/// <param name="amount">Amount to move in display units</param>
|
||||
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<Vector2> 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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<minDist*3.0f)
|
||||
{
|
||||
new WayPoint(
|
||||
new Vector2(hull.Rect.X + hull.Rect.Width / 2.0f, hull.Rect.Y - hull.Rect.Height + heightFromFloor), SpawnType.Path, Submarine.Loaded);
|
||||
new Vector2(hull.Rect.X + hull.Rect.Width / 2.0f, hull.Rect.Y - hull.Rect.Height + heightFromFloor), SpawnType.Path, submarine);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (float x = hull.Rect.X + minDist; x <= hull.Rect.Right - minDist; x += minDist)
|
||||
{
|
||||
var wayPoint = new WayPoint(new Vector2(x, hull.Rect.Y - hull.Rect.Height + heightFromFloor), SpawnType.Path, Submarine.Loaded);
|
||||
var wayPoint = new WayPoint(new Vector2(x, hull.Rect.Y - hull.Rect.Height + heightFromFloor), SpawnType.Path, submarine);
|
||||
|
||||
if (prevWaypoint != null) wayPoint.ConnectTo(prevWaypoint);
|
||||
|
||||
@@ -357,7 +357,7 @@ namespace Barotrauma
|
||||
borders.Width += outsideWaypointDist * 2;
|
||||
borders.Height += outsideWaypointDist * 2;
|
||||
|
||||
borders.Location -= Submarine.HiddenSubPosition.ToPoint();
|
||||
borders.Location -= submarine.HiddenSubPosition.ToPoint();
|
||||
|
||||
if (borders.Width <= outSideWaypointInterval*2)
|
||||
{
|
||||
@@ -379,8 +379,9 @@ namespace Barotrauma
|
||||
for (float x = borders.X + outSideWaypointInterval; x < borders.Right - outSideWaypointInterval; x += outSideWaypointInterval)
|
||||
{
|
||||
var wayPoint = new WayPoint(
|
||||
new Vector2(x, borders.Y - borders.Height * i) + Submarine.HiddenSubPosition,
|
||||
SpawnType.Path, Submarine.Loaded);
|
||||
new Vector2(x, borders.Y - borders.Height * i) + submarine.HiddenSubPosition,
|
||||
SpawnType.Path, submarine);
|
||||
|
||||
if (x == borders.X + outSideWaypointInterval)
|
||||
{
|
||||
cornerWaypoint[i, 0] = wayPoint;
|
||||
@@ -400,8 +401,8 @@ namespace Barotrauma
|
||||
for (float y = borders.Y - borders.Height; y < borders.Y; y += outSideWaypointInterval)
|
||||
{
|
||||
wayPoint = new WayPoint(
|
||||
new Vector2(borders.X + borders.Width * i, y) + Submarine.HiddenSubPosition,
|
||||
SpawnType.Path, Submarine.Loaded);
|
||||
new Vector2(borders.X + borders.Width * i, y) + submarine.HiddenSubPosition,
|
||||
SpawnType.Path, submarine);
|
||||
|
||||
if (y == borders.Y - borders.Height)
|
||||
{
|
||||
@@ -431,11 +432,11 @@ namespace Barotrauma
|
||||
|
||||
stairPoints[0] = new WayPoint(
|
||||
new Vector2(stairs.Rect.X - 75.0f,
|
||||
stairs.Rect.Y - (stairs.StairDirection == Direction.Left ? 80 : stairs.Rect.Height) + heightFromFloor), SpawnType.Path, Submarine.Loaded);
|
||||
stairs.Rect.Y - (stairs.StairDirection == Direction.Left ? 80 : stairs.Rect.Height) + heightFromFloor), SpawnType.Path, submarine);
|
||||
|
||||
stairPoints[1] = new WayPoint(
|
||||
new Vector2(stairs.Rect.Right + 75.0f,
|
||||
stairs.Rect.Y - (stairs.StairDirection == Direction.Left ? stairs.Rect.Height : 80) + heightFromFloor), SpawnType.Path, Submarine.Loaded);
|
||||
stairs.Rect.Y - (stairs.StairDirection == Direction.Left ? stairs.Rect.Height : 80) + heightFromFloor), SpawnType.Path, submarine);
|
||||
|
||||
for (int i = 0; i < 2; i++ )
|
||||
{
|
||||
@@ -457,9 +458,9 @@ namespace Barotrauma
|
||||
|
||||
WayPoint[] ladderPoints = new WayPoint[2];
|
||||
|
||||
ladderPoints[0] = new WayPoint(new Vector2(item.Rect.Center.X, item.Rect.Y - item.Rect.Height + heightFromFloor), SpawnType.Path, Submarine.Loaded);
|
||||
ladderPoints[0] = new WayPoint(new Vector2(item.Rect.Center.X, item.Rect.Y - item.Rect.Height + heightFromFloor), SpawnType.Path, submarine);
|
||||
|
||||
ladderPoints[1] = new WayPoint(new Vector2(item.Rect.Center.X, item.Rect.Y-1.0f), SpawnType.Path, Submarine.Loaded);
|
||||
ladderPoints[1] = new WayPoint(new Vector2(item.Rect.Center.X, item.Rect.Y-1.0f), SpawnType.Path, submarine);
|
||||
|
||||
|
||||
WayPoint prevPoint = ladderPoints[0];
|
||||
@@ -480,7 +481,7 @@ namespace Barotrauma
|
||||
var door = ((Item)pickedBody.UserData).GetComponent<Door>();
|
||||
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<CharacterInfo> crew)
|
||||
public static WayPoint[] SelectCrewSpawnPoints(List<CharacterInfo> crew, Submarine submarine)
|
||||
{
|
||||
List<WayPoint> unassignedWayPoints = new List<WayPoint>();
|
||||
foreach (WayPoint wp in WayPointList)
|
||||
{
|
||||
if (wp.spawnType == SpawnType.Human) unassignedWayPoints.Add(wp);
|
||||
}
|
||||
List<WayPoint> subWayPoints = WayPointList.FindAll(wp => wp.Submarine == submarine);
|
||||
|
||||
List<WayPoint> 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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user