(6eeea9b7c) v0.9.10.0.0
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Barotrauma.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace Barotrauma
|
||||
{
|
||||
id += 1;
|
||||
IDfound = dictionary.ContainsKey(id);
|
||||
} while (IDfound);
|
||||
} while (IDfound || id == NullEntityID || id == EntitySpawnerID);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ namespace Barotrauma
|
||||
if (powered == null || !powered.VulnerableToEMP) continue;
|
||||
if (item.Repairables.Any())
|
||||
{
|
||||
item.Condition -= 100 * EmpStrength * distFactor;
|
||||
item.Condition -= item.MaxCondition * EmpStrength * distFactor;
|
||||
}
|
||||
|
||||
//discharge batteries
|
||||
@@ -157,42 +157,47 @@ namespace Barotrauma
|
||||
|
||||
if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient)
|
||||
{
|
||||
if (flames)
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
foreach (Item item in Item.ItemList)
|
||||
if (item.Condition <= 0.0f) { continue; }
|
||||
if (Vector2.Distance(item.WorldPosition, worldPosition) > attack.Range * 0.5f) { continue; }
|
||||
if (flames && !item.FireProof)
|
||||
{
|
||||
if (item.CurrentHull != hull || item.FireProof || item.Condition <= 0.0f) { continue; }
|
||||
|
||||
//don't apply OnFire effects if the item is inside a fireproof container
|
||||
//(or if it's inside a container that's inside a fireproof container, etc)
|
||||
Item container = item.Container;
|
||||
bool fireProof = false;
|
||||
while (container != null)
|
||||
{
|
||||
if (container.FireProof) { fireProof = true; break; }
|
||||
if (container.FireProof)
|
||||
{
|
||||
fireProof = true;
|
||||
break;
|
||||
}
|
||||
container = container.Container;
|
||||
}
|
||||
|
||||
if (fireProof || Vector2.Distance(item.WorldPosition, worldPosition) > attack.Range * 0.5f) { continue; }
|
||||
|
||||
item.ApplyStatusEffects(ActionType.OnFire, 1.0f);
|
||||
if (item.Condition <= 0.0f && GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
|
||||
if (!fireProof)
|
||||
{
|
||||
GameMain.NetworkMember.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnFire });
|
||||
item.ApplyStatusEffects(ActionType.OnFire, 1.0f);
|
||||
if (item.Condition <= 0.0f && GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
GameMain.NetworkMember.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnFire });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (item.Prefab.DamagedByExplosions && !item.Indestructible)
|
||||
if (item.Prefab.DamagedByExplosions && !item.Indestructible)
|
||||
{
|
||||
float limbRadius = item.body == null ? 0.0f : item.body.GetMaxExtent();
|
||||
float dist = Vector2.Distance(item.WorldPosition, worldPosition);
|
||||
dist = Math.Max(0.0f, dist - ConvertUnits.ToDisplayUnits(limbRadius));
|
||||
if (dist > attack.Range)
|
||||
{
|
||||
float limbRadius = item.body == null ? 0.0f : item.body.GetMaxExtent();
|
||||
float dist = Vector2.Distance(item.WorldPosition, worldPosition);
|
||||
dist = Math.Max(0.0f, dist - ConvertUnits.ToDisplayUnits(limbRadius));
|
||||
|
||||
if (dist > attack.Range) { continue; }
|
||||
|
||||
float distFactor = 1.0f - dist / attack.Range;
|
||||
float damageAmount = attack.GetItemDamage(1.0f);
|
||||
item.Condition -= damageAmount * distFactor;
|
||||
continue;
|
||||
}
|
||||
float distFactor = 1.0f - dist / attack.Range;
|
||||
float damageAmount = attack.GetItemDamage(1.0f) * item.Prefab.ExplosionDamageMultiplier;
|
||||
item.Condition -= damageAmount * distFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -200,10 +205,9 @@ namespace Barotrauma
|
||||
|
||||
partial void ExplodeProjSpecific(Vector2 worldPosition, Hull hull);
|
||||
|
||||
|
||||
public static void DamageCharacters(Vector2 worldPosition, Attack attack, float force, Entity damageSource, Character attacker)
|
||||
{
|
||||
if (attack.Range <= 0.0f) return;
|
||||
if (attack.Range <= 0.0f) { return; }
|
||||
|
||||
//long range for the broad distance check, because large characters may still be in range even if their collider isn't
|
||||
float broadRange = Math.Max(attack.Range * 10.0f, 10000.0f);
|
||||
@@ -226,13 +230,14 @@ namespace Barotrauma
|
||||
explosionPos = ConvertUnits.ToSimUnits(explosionPos);
|
||||
|
||||
Dictionary<Limb, float> distFactors = new Dictionary<Limb, float>();
|
||||
Dictionary<Limb, float> damages = new Dictionary<Limb, float>();
|
||||
foreach (Limb limb in c.AnimController.Limbs)
|
||||
{
|
||||
float dist = Vector2.Distance(limb.WorldPosition, worldPosition);
|
||||
|
||||
//calculate distance from the "outer surface" of the physics body
|
||||
//doesn't take the rotation of the limb into account, but should be accurate enough for this purpose
|
||||
float limbRadius = Math.Max(Math.Max(limb.body.width * 0.5f, limb.body.height * 0.5f), limb.body.radius);
|
||||
float limbRadius = limb.body.GetMaxExtent();
|
||||
dist = Math.Max(0.0f, dist - ConvertUnits.ToDisplayUnits(limbRadius));
|
||||
|
||||
if (dist > attack.Range) { continue; }
|
||||
@@ -240,14 +245,18 @@ namespace Barotrauma
|
||||
float distFactor = 1.0f - dist / attack.Range;
|
||||
|
||||
//solid obstacles between the explosion and the limb reduce the effect of the explosion by 90%
|
||||
if (Submarine.CheckVisibility(limb.SimPosition, explosionPos) != null) distFactor *= 0.1f;
|
||||
if (Submarine.CheckVisibility(limb.SimPosition, explosionPos) != null)
|
||||
{
|
||||
distFactor *= 0.1f;
|
||||
}
|
||||
|
||||
distFactors.Add(limb, distFactor);
|
||||
|
||||
List<Affliction> modifiedAfflictions = new List<Affliction>();
|
||||
int limbCount = c.AnimController.Limbs.Count(l => !l.IsSevered && !l.ignoreCollisions);
|
||||
foreach (Affliction affliction in attack.Afflictions.Keys)
|
||||
{
|
||||
modifiedAfflictions.Add(affliction.CreateMultiplied(distFactor / c.AnimController.Limbs.Length));
|
||||
modifiedAfflictions.Add(affliction.CreateMultiplied(distFactor / limbCount));
|
||||
}
|
||||
c.LastDamageSource = damageSource;
|
||||
if (attacker == null)
|
||||
@@ -255,14 +264,18 @@ namespace Barotrauma
|
||||
if (damageSource is Item item)
|
||||
{
|
||||
attacker = item.GetComponent<Projectile>()?.User;
|
||||
if (attacker == null) attacker = item.GetComponent<MeleeWeapon>()?.User;
|
||||
if (attacker == null)
|
||||
{
|
||||
attacker = item.GetComponent<MeleeWeapon>()?.User;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//use a position slightly from the limb's position towards the explosion
|
||||
//ensures that the attack hits the correct limb and that the direction of the hit can be determined correctly in the AddDamage methods
|
||||
Vector2 hitPos = limb.WorldPosition + (worldPosition - limb.WorldPosition) / dist * 0.01f;
|
||||
c.AddDamage(hitPos, modifiedAfflictions, attack.Stun * distFactor, false, attacker: attacker);
|
||||
AttackResult attackResult = c.AddDamage(hitPos, modifiedAfflictions, attack.Stun * distFactor, false, attacker: attacker);
|
||||
damages.Add(limb, attackResult.Damage);
|
||||
|
||||
if (attack.StatusEffects != null && attack.StatusEffects.Any())
|
||||
{
|
||||
@@ -279,22 +292,27 @@ namespace Barotrauma
|
||||
if (limb.WorldPosition != worldPosition && !MathUtils.NearlyEqual(force, 0.0f))
|
||||
{
|
||||
Vector2 limbDiff = Vector2.Normalize(limb.WorldPosition - worldPosition);
|
||||
if (!MathUtils.IsValid(limbDiff)) limbDiff = Rand.Vector(1.0f);
|
||||
if (!MathUtils.IsValid(limbDiff)) { limbDiff = Rand.Vector(1.0f); }
|
||||
Vector2 impulse = limbDiff * distFactor * force;
|
||||
Vector2 impulsePoint = limb.SimPosition - limbDiff * limbRadius;
|
||||
limb.body.ApplyLinearImpulse(impulse, impulsePoint, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
limb.body.ApplyLinearImpulse(impulse, impulsePoint, maxVelocity: NetConfig.MaxPhysicsBodyVelocity * 0.2f);
|
||||
}
|
||||
}
|
||||
|
||||
//sever joints
|
||||
if (c.IsDead && attack.SeverLimbsProbability > 0.0f)
|
||||
if (attack.SeverLimbsProbability > 0.0f)
|
||||
{
|
||||
foreach (Limb limb in c.AnimController.Limbs)
|
||||
{
|
||||
if (!distFactors.ContainsKey(limb)) { continue; }
|
||||
if (Rand.Range(0.0f, 1.0f) < attack.SeverLimbsProbability * distFactors[limb])
|
||||
if (limb.character.Removed || limb.Removed) { continue; }
|
||||
if (limb.IsSevered) { continue; }
|
||||
if (!c.IsDead && !limb.CanBeSeveredAlive) { continue; }
|
||||
if (distFactors.TryGetValue(limb, out float distFactor))
|
||||
{
|
||||
c.TrySeverLimbJoints(limb, 1.0f);
|
||||
if (damages.TryGetValue(limb, out float damage))
|
||||
{
|
||||
c.TrySeverLimbJoints(limb, attack.SeverLimbsProbability * distFactor, damage, allowBeheading: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Barotrauma.Extensions;
|
||||
#if CLIENT
|
||||
using Barotrauma.Sounds;
|
||||
using Barotrauma.Lights;
|
||||
using Barotrauma.Particles;
|
||||
#endif
|
||||
using FarseerPhysics;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -15,6 +17,7 @@ namespace Barotrauma
|
||||
{
|
||||
const float OxygenConsumption = 50.0f;
|
||||
const float GrowSpeed = 20.0f;
|
||||
const float MaxDamageRange = 250.0f;
|
||||
|
||||
protected Hull hull;
|
||||
|
||||
@@ -65,7 +68,7 @@ namespace Barotrauma
|
||||
|
||||
public virtual float DamageRange
|
||||
{
|
||||
get { return (float)Math.Sqrt(size.X) * 20.0f; }
|
||||
get { return Math.Min((float)Math.Sqrt(size.X) * 10.0f, MaxDamageRange); }
|
||||
}
|
||||
|
||||
public Hull Hull
|
||||
@@ -123,8 +126,8 @@ namespace Barotrauma
|
||||
{
|
||||
i = Math.Min(i, fireSources.Count - 1);
|
||||
j = Math.Min(j, i - 1);
|
||||
|
||||
if (!fireSources[i].CheckOverLap(fireSources[j])) continue;
|
||||
|
||||
if (!fireSources[i].CheckOverLap(fireSources[j])) { continue; }
|
||||
|
||||
float leftEdge = Math.Min(fireSources[i].position.X, fireSources[j].position.X);
|
||||
|
||||
@@ -133,12 +136,10 @@ namespace Barotrauma
|
||||
- leftEdge;
|
||||
|
||||
fireSources[j].position.X = leftEdge;
|
||||
|
||||
#if CLIENT
|
||||
fireSources[j].burnDecals.AddRange(fireSources[i].burnDecals);
|
||||
fireSources[j].burnDecals.Sort((d1, d2) => { return Math.Sign(d1.WorldPosition.X - d2.WorldPosition.X); });
|
||||
#endif
|
||||
|
||||
fireSources[i].Remove();
|
||||
}
|
||||
}
|
||||
@@ -210,21 +211,32 @@ namespace Barotrauma
|
||||
|
||||
private void DamageCharacters(float deltaTime)
|
||||
{
|
||||
if (size.X <= 0.0f) return;
|
||||
if (size.X <= 0.0f) { return; }
|
||||
|
||||
for (int i = 0; i < Character.CharacterList.Count; i++)
|
||||
{
|
||||
Character c = Character.CharacterList[i];
|
||||
if (c.AnimController.CurrentHull == null || c.IsDead) continue;
|
||||
if (c.CurrentHull == null || c.IsDead) { continue; }
|
||||
|
||||
if (!IsInDamageRange(c, DamageRange)) continue;
|
||||
if (!IsInDamageRange(c, DamageRange)) { continue; }
|
||||
|
||||
float dmg = (float)Math.Sqrt(size.X) * deltaTime / c.AnimController.Limbs.Length;
|
||||
//GetApproximateDistance returns float.MaxValue if there's no path through open gaps between the hulls (e.g. if there's a door/wall in between)
|
||||
if (hull.GetApproximateDistance(Position, c.Position, c.CurrentHull, 10000.0f) > size.X + DamageRange)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float dmg = (float)Math.Sqrt(Math.Min(500, size.X)) * deltaTime / c.AnimController.Limbs.Count(l => !l.IsSevered);
|
||||
foreach (Limb limb in c.AnimController.Limbs)
|
||||
{
|
||||
if (limb.IsSevered) { continue; }
|
||||
c.LastDamageSource = null;
|
||||
c.DamageLimb(WorldPosition, limb, new List<Affliction>() { AfflictionPrefab.Burn.Instantiate(dmg) }, 0.0f, false, 0.0f);
|
||||
c.DamageLimb(WorldPosition, limb, AfflictionPrefab.Burn.Instantiate(dmg).ToEnumerable(), 0.0f, false, 0.0f);
|
||||
}
|
||||
#if CLIENT
|
||||
//let clients display the client-side damage immediately, otherwise they may not be able to react to the damage fast enough
|
||||
c.CharacterHealth.DisplayedVitality = c.Vitality;
|
||||
#endif
|
||||
c.ApplyStatusEffects(ActionType.OnFire, deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ namespace Barotrauma
|
||||
//the force of the water flow which is exerted on physics bodies
|
||||
private Vector2 flowForce;
|
||||
private Hull flowTargetHull;
|
||||
|
||||
private float openedTimer = 1.0f;
|
||||
|
||||
private float higherSurface;
|
||||
private float lowerSurface;
|
||||
@@ -54,7 +56,11 @@ namespace Barotrauma
|
||||
public float Open
|
||||
{
|
||||
get { return open; }
|
||||
set { open = MathHelper.Clamp(value, 0.0f, 1.0f); }
|
||||
set
|
||||
{
|
||||
if (value > open) { openedTimer = 1.0f; }
|
||||
open = MathHelper.Clamp(value, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
public float Size => IsHorizontal ? Rect.Height : Rect.Width;
|
||||
@@ -124,6 +130,7 @@ namespace Barotrauma
|
||||
InsertToList();
|
||||
|
||||
outsideCollisionBlocker = GameMain.World.CreateEdge(-Vector2.UnitX * 2.0f, Vector2.UnitX * 2.0f);
|
||||
outsideCollisionBlocker.UserData = $"CollisionBlocker (Gap {ID})";
|
||||
outsideCollisionBlocker.BodyType = BodyType.Static;
|
||||
outsideCollisionBlocker.CollisionCategories = Physics.CollisionWall;
|
||||
outsideCollisionBlocker.CollidesWith = Physics.CollisionCharacter;
|
||||
@@ -277,57 +284,18 @@ namespace Barotrauma
|
||||
|
||||
flowForce.X = MathHelper.Clamp(flowForce.X, -MaxFlowForce, MaxFlowForce);
|
||||
flowForce.Y = MathHelper.Clamp(flowForce.Y, -MaxFlowForce, MaxFlowForce);
|
||||
lerpedFlowForce = Vector2.Lerp(lerpedFlowForce, flowForce, deltaTime * 5.0f);
|
||||
if (openedTimer > 0.0f && flowForce.Length() > lerpedFlowForce.Length())
|
||||
{
|
||||
//if the gap has just been opened/created, allow it to exert a large force instantly without any smoothing
|
||||
lerpedFlowForce = flowForce;
|
||||
}
|
||||
else
|
||||
{
|
||||
lerpedFlowForce = Vector2.Lerp(lerpedFlowForce, flowForce, deltaTime * 5.0f);
|
||||
}
|
||||
openedTimer -= deltaTime;
|
||||
|
||||
EmitParticles(deltaTime);
|
||||
|
||||
if (flowTargetHull != null && lerpedFlowForce.LengthSquared() > 0.0001f)
|
||||
{
|
||||
foreach (Character character in Character.CharacterList)
|
||||
{
|
||||
if (character.CurrentHull == null) continue;
|
||||
if (character.CurrentHull != linkedTo[0] as Hull &&
|
||||
(linkedTo.Count < 2 || character.CurrentHull != linkedTo[1] as Hull))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (Limb limb in character.AnimController.Limbs)
|
||||
{
|
||||
if (!limb.inWater) continue;
|
||||
|
||||
float dist = Vector2.Distance(limb.WorldPosition, WorldPosition);
|
||||
if (dist > lerpedFlowForce.Length()) continue;
|
||||
|
||||
Vector2 force = lerpedFlowForce / (float)Math.Max(Math.Sqrt(dist), 20.0f) * 0.025f;
|
||||
|
||||
//vertical gaps only apply forces if the character is roughly above/below the gap
|
||||
if (!IsHorizontal)
|
||||
{
|
||||
float xDist = Math.Abs(limb.WorldPosition.X - WorldPosition.X);
|
||||
if (xDist > rect.Width || rect.Width == 0) break;
|
||||
|
||||
force *= 1.0f - xDist / rect.Width;
|
||||
}
|
||||
|
||||
if (!MathUtils.IsValid(force))
|
||||
{
|
||||
string errorMsg = "Attempted to apply invalid flow force to the character \"" + character.Name +
|
||||
"\", gap pos: " + WorldPosition +
|
||||
", limb pos: " + limb.WorldPosition +
|
||||
", flowforce: " + flowForce + ", lerpedFlowForce:" + lerpedFlowForce +
|
||||
", dist: " + dist;
|
||||
|
||||
DebugConsole.Log(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Gap.Update:InvalidFlowForce:" + character.Name,
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
errorMsg);
|
||||
continue;
|
||||
}
|
||||
character.AnimController.Collider.ApplyForce(force * limb.body.Mass, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial void EmitParticles(float deltaTime);
|
||||
|
||||
@@ -22,9 +22,9 @@ namespace Barotrauma
|
||||
public const float OxygenConsumptionSpeed = 700.0f;
|
||||
|
||||
public const int WaveWidth = 32;
|
||||
public static float WaveStiffness = 0.02f;
|
||||
public static float WaveSpread = 0.05f;
|
||||
public static float WaveDampening = 0.05f;
|
||||
public static float WaveStiffness = 0.01f;
|
||||
public static float WaveSpread = 0.02f;
|
||||
public static float WaveDampening = 0.02f;
|
||||
|
||||
//how much excess water the room can contain, relative to the volume of the room.
|
||||
//needed to make it possible for pressure to "push" water up through U-shaped hull configurations
|
||||
@@ -83,6 +83,21 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
private Color ambientLight;
|
||||
|
||||
[Editable, Serialize("0,0,0,0", true)]
|
||||
public Color AmbientLight
|
||||
{
|
||||
get { return ambientLight; }
|
||||
set
|
||||
{
|
||||
ambientLight = value;
|
||||
#if CLIENT
|
||||
lastAmbientLightEditTime = Timing.TotalTime;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public override Rectangle Rect
|
||||
{
|
||||
get
|
||||
@@ -501,54 +516,34 @@ namespace Barotrauma
|
||||
rightDelta[i] = WaveSpread * (waveY[i] - waveY[i + 1]);
|
||||
waveVel[i + 1] += rightDelta[i];
|
||||
}
|
||||
|
||||
for (int i = 1; i < waveY.Length - 1; i++)
|
||||
{
|
||||
waveY[i - 1] += leftDelta[i];
|
||||
waveY[i + 1] += rightDelta[i];
|
||||
}
|
||||
}
|
||||
|
||||
//make waves propagate through horizontal gaps
|
||||
foreach (Gap gap in ConnectedGaps)
|
||||
{
|
||||
if (!gap.IsRoomToRoom || !gap.IsHorizontal || gap.Open <= 0.0f) continue;
|
||||
if (surface > gap.Rect.Y || surface < gap.Rect.Y - gap.Rect.Height) continue;
|
||||
|
||||
Hull hull2 = this == gap.linkedTo[0] as Hull ? (Hull)gap.linkedTo[1] : (Hull)gap.linkedTo[0];
|
||||
float otherSurfaceY = hull2.surface;
|
||||
if (otherSurfaceY > gap.Rect.Y || otherSurfaceY < gap.Rect.Y - gap.Rect.Height) continue;
|
||||
|
||||
float surfaceDiff = (surface - otherSurfaceY) * gap.Open;
|
||||
if (this != gap.linkedTo[0] as Hull)
|
||||
{
|
||||
//the first hull linked to the gap handles the wave propagation,
|
||||
//the second just updates the surfaces to the same level
|
||||
if (surfaceDiff < 32.0f)
|
||||
{
|
||||
hull2.waveY[hull2.waveY.Length - 1] = surfaceDiff * 0.5f;
|
||||
waveY[0] = -surfaceDiff * 0.5f;
|
||||
}
|
||||
//let the first linked hull handle the water propagation
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!gap.IsRoomToRoom || !gap.IsHorizontal || gap.Open <= 0.0f) { continue; }
|
||||
if (surface > gap.Rect.Y || surface < gap.Rect.Y - gap.Rect.Height) { continue; }
|
||||
|
||||
Hull hull2 = this == gap.linkedTo[0] as Hull ? (Hull)gap.linkedTo[1] : (Hull)gap.linkedTo[0];
|
||||
float otherSurfaceY = hull2.surface;
|
||||
if (otherSurfaceY > gap.Rect.Y || otherSurfaceY < gap.Rect.Y - gap.Rect.Height) { continue; }
|
||||
|
||||
float surfaceDiff = (surface - otherSurfaceY) * gap.Open;
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
int i = waveY.Length - 1;
|
||||
rightDelta[waveY.Length - 1] = WaveSpread * (hull2.waveY[0] - waveY[waveY.Length - 1] - surfaceDiff) * 0.5f;
|
||||
waveVel[waveY.Length - 1] += rightDelta[waveY.Length - 1];
|
||||
waveY[waveY.Length - 1] += rightDelta[waveY.Length - 1];
|
||||
|
||||
leftDelta[i] = WaveSpread * (waveY[i] - waveY[i - 1]);
|
||||
waveVel[i - 1] += leftDelta[i];
|
||||
|
||||
rightDelta[i] = WaveSpread * (waveY[i] - hull2.waveY[0] + surfaceDiff);
|
||||
hull2.waveVel[0] += rightDelta[i];
|
||||
|
||||
i = 0;
|
||||
|
||||
hull2.leftDelta[i] = WaveSpread * (hull2.waveY[i] - waveY[waveY.Length - 1] - surfaceDiff);
|
||||
waveVel[waveVel.Length - 1] += hull2.leftDelta[i];
|
||||
|
||||
hull2.rightDelta[i] = WaveSpread * (hull2.waveY[i] - hull2.waveY[i + 1]);
|
||||
hull2.waveVel[i + 1] += hull2.rightDelta[i];
|
||||
hull2.leftDelta[0] = WaveSpread * (waveY[waveY.Length - 1] - hull2.waveY[0] + surfaceDiff) * 0.5f;
|
||||
hull2.waveVel[0] += hull2.leftDelta[0];
|
||||
hull2.waveY[0] += hull2.leftDelta[0];
|
||||
}
|
||||
|
||||
if (surfaceDiff < 32.0f)
|
||||
@@ -557,13 +552,19 @@ namespace Barotrauma
|
||||
hull2.waveY[0] = surfaceDiff * 0.5f;
|
||||
waveY[waveY.Length - 1] = -surfaceDiff * 0.5f;
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
|
||||
//apply spread (two iterations)
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
for (int i = 1; i < waveY.Length - 1; i++)
|
||||
{
|
||||
hull2.waveY[0] += rightDelta[waveY.Length - 1];
|
||||
waveY[waveY.Length - 1] += hull2.leftDelta[0];
|
||||
waveY[i - 1] += leftDelta[i];
|
||||
waveY[i + 1] += rightDelta[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (waterVolume < Volume)
|
||||
{
|
||||
LethalPressure -= 10.0f * deltaTime;
|
||||
@@ -609,37 +610,33 @@ namespace Barotrauma
|
||||
FireSources.Remove(fire);
|
||||
}
|
||||
|
||||
private HashSet<Hull> adjacentHulls = new HashSet<Hull>();
|
||||
public IEnumerable<Hull> GetConnectedHulls(bool includingThis, int? searchDepth = null)
|
||||
private readonly HashSet<Hull> adjacentHulls = new HashSet<Hull>();
|
||||
public IEnumerable<Hull> GetConnectedHulls(bool includingThis, int? searchDepth = null, bool ignoreClosedGaps = false)
|
||||
{
|
||||
adjacentHulls.Clear();
|
||||
int startStep = 0;
|
||||
searchDepth = searchDepth ?? 100;
|
||||
return GetAdjacentHulls(includingThis, adjacentHulls, ref startStep, searchDepth.Value);
|
||||
searchDepth ??= 100;
|
||||
GetAdjacentHulls(adjacentHulls, ref startStep, searchDepth.Value, ignoreClosedGaps);
|
||||
if (!includingThis) { adjacentHulls.Remove(this); }
|
||||
return adjacentHulls;
|
||||
}
|
||||
|
||||
private HashSet<Hull> GetAdjacentHulls(bool includingThis, HashSet<Hull> connectedHulls, ref int step, int searchDepth)
|
||||
private void GetAdjacentHulls(HashSet<Hull> connectedHulls, ref int step, int searchDepth, bool ignoreClosedGaps = false)
|
||||
{
|
||||
if (includingThis)
|
||||
{
|
||||
connectedHulls.Add(this);
|
||||
}
|
||||
if (step > searchDepth)
|
||||
{
|
||||
return connectedHulls;
|
||||
}
|
||||
connectedHulls.Add(this);
|
||||
if (step > searchDepth) { return; }
|
||||
foreach (Gap g in ConnectedGaps)
|
||||
{
|
||||
if (ignoreClosedGaps && g.Open <= 0.0f) { continue; }
|
||||
for (int i = 0; i < 2 && i < g.linkedTo.Count; i++)
|
||||
{
|
||||
if (g.linkedTo[i] is Hull hull && !connectedHulls.Contains(hull))
|
||||
{
|
||||
step++;
|
||||
hull.GetAdjacentHulls(true, connectedHulls, ref step, searchDepth);
|
||||
hull.GetAdjacentHulls(connectedHulls, ref step, searchDepth, ignoreClosedGaps);
|
||||
}
|
||||
}
|
||||
}
|
||||
return connectedHulls;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -666,7 +663,7 @@ namespace Barotrauma
|
||||
if (g.ConnectedDoor != null && !g.ConnectedDoor.IsBroken)
|
||||
{
|
||||
//gap blocked if the door is not open or the predicted state is not open
|
||||
if (!g.ConnectedDoor.IsOpen || (g.ConnectedDoor.PredictedState.HasValue && !g.ConnectedDoor.PredictedState.Value))
|
||||
if ((!g.ConnectedDoor.IsOpen && !g.ConnectedDoor.IsBroken) || (g.ConnectedDoor.PredictedState.HasValue && !g.ConnectedDoor.PredictedState.Value))
|
||||
{
|
||||
if (g.ConnectedDoor.OpenState < 0.1f) continue;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Barotrauma.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
@@ -10,11 +10,14 @@ namespace Barotrauma
|
||||
{
|
||||
partial class ItemAssemblyPrefab : MapEntityPrefab
|
||||
{
|
||||
private string name;
|
||||
private readonly string name;
|
||||
public override string Name { get { return name; } }
|
||||
|
||||
public static readonly PrefabCollection<ItemAssemblyPrefab> Prefabs = new PrefabCollection<ItemAssemblyPrefab>();
|
||||
|
||||
public static readonly string VanillaSaveFolder = Path.Combine("Content", "Items", "Assemblies");
|
||||
public static readonly string SaveFolder = "ItemAssemblies";
|
||||
|
||||
private bool disposed = false;
|
||||
public override void Dispose()
|
||||
{
|
||||
@@ -50,12 +53,25 @@ namespace Barotrauma
|
||||
name = TextManager.Get("EntityName." + identifier, returnNull: true) ?? originalName;
|
||||
Description = TextManager.Get("EntityDescription." + identifier, returnNull: true) ?? Description;
|
||||
|
||||
List<ushort> containedItemIDs = new List<ushort>();
|
||||
foreach (XElement entityElement in doc.Root.Elements())
|
||||
{
|
||||
var containerElement = entityElement.Elements().FirstOrDefault(e => e.Name.LocalName.Equals("itemcontainer", StringComparison.OrdinalIgnoreCase));
|
||||
if (containerElement == null) { continue; }
|
||||
|
||||
var itemIds = containerElement.GetAttributeIntArray("contained", new int[0]);
|
||||
containedItemIDs.AddRange(itemIds.Select(id => (ushort)id));
|
||||
}
|
||||
|
||||
int minX = int.MaxValue, minY = int.MaxValue;
|
||||
int maxX = int.MinValue, maxY = int.MinValue;
|
||||
DisplayEntities = new List<Pair<MapEntityPrefab, Rectangle>>();
|
||||
foreach (XElement entityElement in doc.Root.Elements())
|
||||
{
|
||||
string identifier = entityElement.GetAttributeString("identifier", "");
|
||||
ushort id = (ushort)entityElement.GetAttributeInt("ID", 0);
|
||||
if (id > 0 && containedItemIDs.Contains(id)) { continue; }
|
||||
|
||||
string identifier = entityElement.GetAttributeString("identifier", entityElement.Name.ToString().ToLowerInvariant());
|
||||
MapEntityPrefab mapEntity = List.FirstOrDefault(p => p.Identifier == identifier);
|
||||
if (mapEntity == null)
|
||||
{
|
||||
@@ -64,9 +80,9 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
Rectangle rect = entityElement.GetAttributeRect("rect", Rectangle.Empty);
|
||||
if (mapEntity != null && !entityElement.GetAttributeBool("hideinassemblypreview", false))
|
||||
if (mapEntity != null && !entityElement.Elements().Any(e => e.Name.LocalName.Equals("wire", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
DisplayEntities.Add(new Pair<MapEntityPrefab, Rectangle>(mapEntity, rect));
|
||||
if (!entityElement.GetAttributeBool("hideinassemblypreview", false)) { DisplayEntities.Add(new Pair<MapEntityPrefab, Rectangle>(mapEntity, rect)); }
|
||||
minX = Math.Min(minX, rect.X);
|
||||
minY = Math.Min(minY, rect.Y - rect.Height);
|
||||
maxX = Math.Max(maxX, rect.Right);
|
||||
@@ -74,7 +90,9 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
Bounds = new Rectangle(minX, minY, maxX - minX, maxY - minY);
|
||||
Bounds = minX == int.MaxValue ?
|
||||
new Rectangle(0, 0, 1, 1) :
|
||||
new Rectangle(minX, minY, maxX - minX, maxY - minY);
|
||||
|
||||
Prefabs.Add(this, false);
|
||||
}
|
||||
@@ -142,11 +160,14 @@ namespace Barotrauma
|
||||
|
||||
List<string> itemAssemblyFiles = new List<string>();
|
||||
|
||||
//find assembly files in the item assembly folder
|
||||
string directoryPath = Path.Combine("Content", "Items", "Assemblies");
|
||||
if (Directory.Exists(directoryPath))
|
||||
//find assembly files in the item assembly folders
|
||||
if (Directory.Exists(VanillaSaveFolder))
|
||||
{
|
||||
itemAssemblyFiles.AddRange(Directory.GetFiles(directoryPath));
|
||||
itemAssemblyFiles.AddRange(Directory.GetFiles(VanillaSaveFolder));
|
||||
}
|
||||
if (Directory.Exists(SaveFolder))
|
||||
{
|
||||
itemAssemblyFiles.AddRange(Directory.GetFiles(SaveFolder));
|
||||
}
|
||||
|
||||
//find assembly files in selected content packages
|
||||
|
||||
@@ -27,19 +27,19 @@ namespace Barotrauma
|
||||
|
||||
foreach (GraphEdge ge in graphEdges)
|
||||
{
|
||||
if (Vector2.DistanceSquared(ge.Point1, ge.Point2) < 0.001f) continue;
|
||||
if (Vector2.DistanceSquared(ge.Point1, ge.Point2) < 0.001f) { continue; }
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Site site = (i == 0) ? ge.Site1 : ge.Site2;
|
||||
|
||||
int x = (int)(Math.Floor((site.Coord.X-borders.X) / gridCellSize));
|
||||
int y = (int)(Math.Floor((site.Coord.Y-borders.Y) / gridCellSize));
|
||||
int x = (int)(Math.Floor((site.Coord.X - borders.X) / gridCellSize));
|
||||
int y = (int)(Math.Floor((site.Coord.Y - borders.Y) / gridCellSize));
|
||||
|
||||
x = MathHelper.Clamp(x, 0, cellGrid.GetLength(0)-1);
|
||||
y = MathHelper.Clamp(y, 0, cellGrid.GetLength(1)-1);
|
||||
|
||||
VoronoiCell cell = cellGrid[x,y].Find(c => c.Site == site);
|
||||
x = MathHelper.Clamp(x, 0, cellGrid.GetLength(0) - 1);
|
||||
y = MathHelper.Clamp(y, 0, cellGrid.GetLength(1) - 1);
|
||||
|
||||
VoronoiCell cell = cellGrid[x, y].Find(c => c.Site == site);
|
||||
|
||||
if (cell == null)
|
||||
{
|
||||
@@ -60,14 +60,62 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
//add edges to the borders of the graph
|
||||
foreach (var cell in cells)
|
||||
{
|
||||
Vector2? point1 = null, point2 = null;
|
||||
foreach (GraphEdge ge in cell.Edges)
|
||||
{
|
||||
if (MathUtils.NearlyEqual(ge.Point1.X, borders.X) || MathUtils.NearlyEqual(ge.Point1.X, borders.Right) ||
|
||||
MathUtils.NearlyEqual(ge.Point1.Y, borders.Y) || MathUtils.NearlyEqual(ge.Point1.Y, borders.Bottom))
|
||||
{
|
||||
if (point1 == null)
|
||||
{
|
||||
point1 = ge.Point1;
|
||||
}
|
||||
else if (point2 == null)
|
||||
{
|
||||
if (MathUtils.NearlyEqual(point1.Value, ge.Point1)) { continue; }
|
||||
point2 = ge.Point1;
|
||||
}
|
||||
}
|
||||
if (MathUtils.NearlyEqual(ge.Point2.X, borders.X) || MathUtils.NearlyEqual(ge.Point2.X, borders.Right) ||
|
||||
MathUtils.NearlyEqual(ge.Point2.Y, borders.Y) || MathUtils.NearlyEqual(ge.Point2.Y, borders.Bottom))
|
||||
{
|
||||
if (point1 == null)
|
||||
{
|
||||
point1 = ge.Point2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MathUtils.NearlyEqual(point1.Value, ge.Point2)) { continue; }
|
||||
point2 = ge.Point2;
|
||||
}
|
||||
}
|
||||
if (point1.HasValue && point2.HasValue)
|
||||
{
|
||||
Debug.Assert(point1 != point2);
|
||||
var newEdge = new GraphEdge(point1.Value, point2.Value)
|
||||
{
|
||||
Cell1 = cell,
|
||||
IsSolid = true,
|
||||
Site1 = cell.Site,
|
||||
OutsideLevel = true
|
||||
};
|
||||
cell.Edges.Add(newEdge);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cells;
|
||||
}
|
||||
|
||||
|
||||
private static Vector2 GetEdgeNormal(GraphEdge edge, VoronoiCell cell = null)
|
||||
{
|
||||
if (cell == null) cell = edge.AdjacentCell(null);
|
||||
if (cell == null) return Vector2.UnitX;
|
||||
if (cell == null) { cell = edge.AdjacentCell(null); }
|
||||
if (cell == null) { return Vector2.UnitX; }
|
||||
|
||||
CompareCCW compare = new CompareCCW(cell.Center);
|
||||
if (compare.Compare(edge.Point1, edge.Point2) == -1)
|
||||
@@ -77,9 +125,7 @@ namespace Barotrauma
|
||||
edge.Point2 = temp;
|
||||
}
|
||||
|
||||
Vector2 normal = Vector2.Zero;
|
||||
|
||||
normal = Vector2.Normalize(edge.Point2 - edge.Point1);
|
||||
Vector2 normal = Vector2.Normalize(edge.Point2 - edge.Point1);
|
||||
Vector2 diffToCell = Vector2.Normalize(cell.Center - edge.Point2);
|
||||
|
||||
normal = new Vector2(-normal.Y, normal.X);
|
||||
@@ -136,7 +182,7 @@ namespace Barotrauma
|
||||
currentCell.CellType = CellType.Path;
|
||||
pathCells.Add(currentCell);
|
||||
|
||||
int currentTargetIndex = 1;
|
||||
int currentTargetIndex = 0;
|
||||
|
||||
int iterationsLeft = cells.Count;
|
||||
|
||||
@@ -148,7 +194,7 @@ namespace Barotrauma
|
||||
foreach (GraphEdge edge in currentCell.Edges)
|
||||
{
|
||||
var adjacentCell = edge.AdjacentCell(currentCell);
|
||||
if (limits.Contains(adjacentCell.Site.Coord.X, adjacentCell.Site.Coord.Y))
|
||||
if (adjacentCell != null && limits.Contains(adjacentCell.Site.Coord.X, adjacentCell.Site.Coord.Y))
|
||||
{
|
||||
allowedEdges.Add(edge);
|
||||
}
|
||||
@@ -161,6 +207,7 @@ namespace Barotrauma
|
||||
for (int i = 0; i < currentCell.Edges.Count; i++)
|
||||
{
|
||||
var adjacentCell = currentCell.Edges[i].AdjacentCell(currentCell);
|
||||
if (adjacentCell == null) { continue; }
|
||||
double dist = MathUtils.Distance(
|
||||
adjacentCell.Site.Coord.X, adjacentCell.Site.Coord.Y,
|
||||
targetCells[currentTargetIndex].Site.Coord.X, targetCells[currentTargetIndex].Site.Coord.Y);
|
||||
|
||||
@@ -18,6 +18,10 @@ namespace Barotrauma
|
||||
//all entities are disabled after they reach this depth
|
||||
public const int MaxEntityDepth = -300000;
|
||||
public const float ShaftHeight = 1000.0f;
|
||||
/// <summary>
|
||||
/// The level generator won't try to adjust the width of the main path above this limit.
|
||||
/// </summary>
|
||||
public const int MaxSubmarineWidth = 16000;
|
||||
|
||||
public static Level Loaded
|
||||
{
|
||||
@@ -141,8 +145,6 @@ namespace Barotrauma
|
||||
get { return positionsOfInterest; }
|
||||
}
|
||||
|
||||
public readonly List<InterestingPosition> UsedPositions = new List<InterestingPosition>();
|
||||
|
||||
public Submarine StartOutpost { get; private set; }
|
||||
public Submarine EndOutpost { get; private set; }
|
||||
|
||||
@@ -324,26 +326,25 @@ namespace Barotrauma
|
||||
SeaFloorTopPos = generationParams.SeaFloorDepth + generationParams.MountainHeightMax + generationParams.SeaFloorVariance;
|
||||
|
||||
int minWidth = 6500;
|
||||
int maxWidth = 50000;
|
||||
if (Submarine.MainSub != null)
|
||||
{
|
||||
Rectangle dockedSubBorders = Submarine.MainSub.GetDockedBorders();
|
||||
dockedSubBorders.Inflate(dockedSubBorders.Size.ToVector2() * 0.15f);
|
||||
minWidth = Math.Max(minWidth, Math.Max(dockedSubBorders.Width, dockedSubBorders.Height));
|
||||
minWidth = Math.Min(minWidth, maxWidth);
|
||||
minWidth = Math.Min(minWidth, MaxSubmarineWidth);
|
||||
}
|
||||
|
||||
Rectangle pathBorders = borders;
|
||||
pathBorders.Inflate(-minWidth * 2, -minWidth);
|
||||
pathBorders.Inflate(-Math.Min(minWidth * 2, MaxSubmarineWidth), -minWidth);
|
||||
|
||||
Debug.Assert(pathBorders.Width > 0 && pathBorders.Height > 0, "The size of the level's path area was negative.");
|
||||
|
||||
startPosition = new Point(
|
||||
Rand.Range(minWidth, minWidth * 2, Rand.RandSync.Server),
|
||||
minWidth,
|
||||
Rand.Range(borders.Height / 2, borders.Height - minWidth * 2, Rand.RandSync.Server));
|
||||
|
||||
endPosition = new Point(
|
||||
borders.Width - Rand.Range(minWidth, minWidth * 2, Rand.RandSync.Server),
|
||||
borders.Width - minWidth,
|
||||
Rand.Range(borders.Height / 2, borders.Height - minWidth * 2, Rand.RandSync.Server));
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
@@ -356,19 +357,25 @@ namespace Barotrauma
|
||||
Point nodeInterval = generationParams.MainPathNodeIntervalRange;
|
||||
|
||||
for (int x = startPosition.X + nodeInterval.X;
|
||||
x < endPosition.X - nodeInterval.X;
|
||||
x < endPosition.X - nodeInterval.X;
|
||||
x += Rand.Range(nodeInterval.X, nodeInterval.Y, Rand.RandSync.Server))
|
||||
{
|
||||
pathNodes.Add(new Point(x, Rand.Range(pathBorders.Y, pathBorders.Bottom, Rand.RandSync.Server)));
|
||||
}
|
||||
|
||||
pathNodes.Add(new Point(endPosition.X, borders.Height));
|
||||
|
||||
if (pathNodes.Count <= 2)
|
||||
if (pathNodes.Count == 1)
|
||||
{
|
||||
pathNodes.Insert(1, borders.Center);
|
||||
pathNodes.Add(new Point(pathBorders.Center.X, pathBorders.Y));
|
||||
}
|
||||
//if all nodes ended up high up in the level, move one down to make sure we utilize the full height of the level
|
||||
else if (pathNodes.GetRange(1, pathNodes.Count - 1).All(p => p.Y > pathBorders.Y + pathBorders.Height * 0.25f))
|
||||
{
|
||||
int nodeIndex = Rand.Range(1, pathNodes.Count, Rand.RandSync.Server);
|
||||
pathNodes[nodeIndex] = new Point(pathNodes[nodeIndex].X, pathBorders.Y);
|
||||
}
|
||||
|
||||
pathNodes.Add(new Point(endPosition.X, borders.Height));
|
||||
|
||||
GenerateTunnels(pathNodes, minWidth);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
@@ -547,21 +554,21 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (GraphEdge edge in cell.Edges)
|
||||
{
|
||||
if (mirroredEdges.Contains(edge)) continue;
|
||||
if (mirroredEdges.Contains(edge)) { continue; }
|
||||
edge.Point1.X = borders.Width - edge.Point1.X;
|
||||
edge.Point2.X = borders.Width - edge.Point2.X;
|
||||
if (!mirroredSites.Contains(edge.Site1))
|
||||
if (edge.Site1 != null && !mirroredSites.Contains(edge.Site1))
|
||||
{
|
||||
//make sure that sites right at the edge of a grid cell end up in the same cell as in the non-mirrored level
|
||||
if (edge.Site1.Coord.X % GridCellSize < 1.0f &&
|
||||
edge.Site1.Coord.X % GridCellSize >= 0.0f) edge.Site1.Coord.X += 1.0f;
|
||||
edge.Site1.Coord.X % GridCellSize >= 0.0f) { edge.Site1.Coord.X += 1.0f; }
|
||||
edge.Site1.Coord.X = borders.Width - edge.Site1.Coord.X;
|
||||
mirroredSites.Add(edge.Site1);
|
||||
}
|
||||
if (!mirroredSites.Contains(edge.Site2))
|
||||
if (edge.Site2 != null && !mirroredSites.Contains(edge.Site2))
|
||||
{
|
||||
if (edge.Site2.Coord.X % GridCellSize < 1.0f &&
|
||||
edge.Site2.Coord.X % GridCellSize >= 0.0f) edge.Site2.Coord.X += 1.0f;
|
||||
edge.Site2.Coord.X % GridCellSize >= 0.0f) { edge.Site2.Coord.X += 1.0f; }
|
||||
edge.Site2.Coord.X = borders.Width - edge.Site2.Coord.X;
|
||||
mirroredSites.Add(edge.Site2);
|
||||
}
|
||||
@@ -1583,8 +1590,8 @@ namespace Barotrauma
|
||||
var subDoc = SubmarineInfo.OpenFile(contentFile.Path);
|
||||
Rectangle borders = Submarine.GetBorders(subDoc.Root);
|
||||
string wreckName = System.IO.Path.GetFileNameWithoutExtension(contentFile.Path);
|
||||
// Add some vertical margin so that the wreck doesn't block the path entirely. It's still possible that some larger subs can't pass by.
|
||||
Point paddedDimensions = new Point(borders.Width, borders.Height + 3000);
|
||||
// Add some margin so that the wreck doesn't block the path entirely. It's still possible that some larger subs can't pass by.
|
||||
Point paddedDimensions = new Point(borders.Width + 3000, borders.Height + 3000);
|
||||
tempSW.Restart();
|
||||
// For storing the translations. Used only for debugging.
|
||||
var positions = new List<Vector2>();
|
||||
@@ -1593,6 +1600,7 @@ namespace Barotrauma
|
||||
int attemptsLeft = maxAttempts;
|
||||
bool success = false;
|
||||
Vector2 spawnPoint = Vector2.Zero;
|
||||
var allCells = Loaded.GetAllCells();
|
||||
while (attemptsLeft > 0)
|
||||
{
|
||||
if (attemptsLeft < maxAttempts)
|
||||
@@ -1621,7 +1629,7 @@ namespace Barotrauma
|
||||
tempSW.Stop();
|
||||
if (success)
|
||||
{
|
||||
Debug.WriteLine($"Wreck {wreckName} successfully positioned to {spawnPoint} in {tempSW.ElapsedMilliseconds.ToString()} (ms)");
|
||||
Debug.WriteLine($"Wreck {wreckName} successfully positioned to {spawnPoint} in {tempSW.ElapsedMilliseconds} (ms)");
|
||||
tempSW.Restart();
|
||||
SubmarineInfo info = new SubmarineInfo(contentFile.Path)
|
||||
{
|
||||
@@ -1630,7 +1638,7 @@ namespace Barotrauma
|
||||
Submarine wreck = new Submarine(info);
|
||||
wreck.MakeWreck();
|
||||
tempSW.Stop();
|
||||
Debug.WriteLine($"Wreck {wreck.Info.Name} loaded in { tempSW.ElapsedMilliseconds.ToString()} (ms)");
|
||||
Debug.WriteLine($"Wreck {wreck.Info.Name} loaded in { tempSW.ElapsedMilliseconds} (ms)");
|
||||
wrecks.Add(wreck);
|
||||
wreck.SetPosition(spawnPoint);
|
||||
wreckPositions.Add(wreck, positions);
|
||||
@@ -1643,7 +1651,8 @@ namespace Barotrauma
|
||||
hull.WaterVolume = hull.Volume * Rand.Range(Loaded.GenerationParams.WreckFloodingHullMinWaterPercentage, Loaded.GenerationParams.WreckFloodingHullMaxWaterPercentage, Rand.RandSync.Server);
|
||||
}
|
||||
}
|
||||
if (Rand.Value(Rand.RandSync.Server) <= Loaded.GenerationParams.ThalamusProbability)
|
||||
// Only spawn thalamus when the wreck has some thalamus items defined.
|
||||
if (Rand.Value(Rand.RandSync.Server) <= Loaded.GenerationParams.ThalamusProbability && wreck.GetItems(false).Any(i => i.Prefab.Category == MapEntityCategory.Thalamus))
|
||||
{
|
||||
if (!wreck.CreateWreckAI())
|
||||
{
|
||||
@@ -1839,8 +1848,7 @@ namespace Barotrauma
|
||||
{
|
||||
return true;
|
||||
}
|
||||
var cells = Loaded.GetAllCells().Where(c => c.Body != null && Vector2.DistanceSquared(pos, c.Center) <= maxDistance);
|
||||
return cells.Any(c => c.BodyVertices.Any(v => bounds.ContainsWorld(v)));
|
||||
return cells.Any(c => c.Body != null && Vector2.DistanceSquared(pos, c.Center) <= maxDistance && c.BodyVertices.Any(v => bounds.ContainsWorld(v)));
|
||||
}
|
||||
}
|
||||
totalSW.Stop();
|
||||
|
||||
@@ -238,7 +238,8 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
|
||||
[Editable, Serialize("5000, 10000", true, description: "The distance between the nodes that are used to generate the main path through the level (min, max). Larger values produce a straighter path.")]
|
||||
[Editable(VectorComponentLabels = new string[] { "editable.minvalue", "editable.maxvalue" }),
|
||||
Serialize("5000, 10000", true, description: "The distance between the nodes that are used to generate the main path through the level (min, max). Larger values produce a straighter path.")]
|
||||
public Point MainPathNodeIntervalRange
|
||||
{
|
||||
get { return mainPathNodeIntervalRange; }
|
||||
@@ -256,7 +257,8 @@ namespace Barotrauma
|
||||
set { smallTunnelCount = MathHelper.Clamp(value, 0, 100); }
|
||||
}
|
||||
|
||||
[Editable, Serialize("5000, 10000", true, description: "The minimum and maximum length of small tunnels placed along the main path.")]
|
||||
[Editable(VectorComponentLabels = new string[] { "editable.minvalue", "editable.maxvalue" }),
|
||||
Serialize("5000, 10000", true, description: "The minimum and maximum length of small tunnels placed along the main path.")]
|
||||
public Point SmallTunnelLengthRange
|
||||
{
|
||||
get { return smallTunnelLengthRange; }
|
||||
|
||||
@@ -358,19 +358,23 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
//check if there are any other contacts with the entity
|
||||
//check if there are contacts with any other fixture of the trigger
|
||||
//(the OnSeparation callback happens when two fixtures separate,
|
||||
//e.g. if a body stops touching the circular fixture at the end of a capsule-shaped body)
|
||||
ContactEdge contactEdge = fixtureA.Body.ContactList;
|
||||
while (contactEdge != null)
|
||||
{
|
||||
if (contactEdge.Contact != null &&
|
||||
contactEdge.Contact.Enabled &&
|
||||
contactEdge.Contact.IsTouching)
|
||||
{
|
||||
var otherEntity = GetEntity(contactEdge.Contact.FixtureB == fixtureB ?
|
||||
contactEdge.Contact.FixtureB :
|
||||
contactEdge.Contact.FixtureA);
|
||||
if (otherEntity == entity) return;
|
||||
if (contactEdge.Contact.FixtureA != fixtureA && contactEdge.Contact.FixtureB != fixtureA)
|
||||
{
|
||||
var otherEntity = GetEntity(contactEdge.Contact.FixtureB == fixtureB ?
|
||||
contactEdge.Contact.FixtureB :
|
||||
contactEdge.Contact.FixtureA);
|
||||
if (otherEntity == entity) { return; }
|
||||
}
|
||||
}
|
||||
contactEdge = contactEdge.Next;
|
||||
}
|
||||
@@ -418,10 +422,20 @@ namespace Barotrauma
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
if (ParentTrigger != null && !ParentTrigger.IsTriggered) return;
|
||||
if (ParentTrigger != null && !ParentTrigger.IsTriggered) { return; }
|
||||
|
||||
triggerers.RemoveWhere(t => t.Removed);
|
||||
|
||||
if (physicsBody != null)
|
||||
{
|
||||
//failsafe to ensure triggerers get removed when they're far from the trigger
|
||||
float maxExtent = Math.Max(ConvertUnits.ToDisplayUnits(physicsBody.GetMaxExtent() * 5), 5000.0f);
|
||||
triggerers.RemoveWhere(t =>
|
||||
{
|
||||
return Vector2.Distance(t.WorldPosition, WorldPosition) > maxExtent;
|
||||
});
|
||||
}
|
||||
|
||||
bool isNotClient = true;
|
||||
#if CLIENT
|
||||
isNotClient = GameMain.Client == null;
|
||||
@@ -511,6 +525,7 @@ namespace Barotrauma
|
||||
ApplyForce(character.AnimController.Collider, deltaTime);
|
||||
foreach (Limb limb in character.AnimController.Limbs)
|
||||
{
|
||||
if (limb.IsSevered) { continue; }
|
||||
ApplyForce(limb.body, deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.IO;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.RuinGeneration
|
||||
@@ -174,7 +174,7 @@ namespace Barotrauma.RuinGeneration
|
||||
|
||||
public static void SaveAll()
|
||||
{
|
||||
XmlWriterSettings settings = new XmlWriterSettings
|
||||
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings
|
||||
{
|
||||
Indent = true,
|
||||
NewLineOnAttributes = true
|
||||
|
||||
@@ -654,13 +654,14 @@ namespace Barotrauma.RuinGeneration
|
||||
{
|
||||
connectionPanel.Locked = true;
|
||||
connectionPanel.CanBeSelected = false;
|
||||
connectionPanel.Item.ShouldBeSaved = false;
|
||||
}
|
||||
|
||||
// Hide wires for now
|
||||
// Hide wires
|
||||
if (ic is Wire wire)
|
||||
{
|
||||
wire.Hidden = true;
|
||||
wire.CanBeSelected = false;
|
||||
wire.Item.ShouldBeSaved = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using Barotrauma.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Barotrauma.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
@@ -174,7 +174,11 @@ namespace Barotrauma
|
||||
int newWidth = ResizeHorizontal ? rect.Width : (int)(defaultRect.Width * relativeScale);
|
||||
int newHeight = ResizeVertical ? rect.Height : (int)(defaultRect.Height * relativeScale);
|
||||
Rect = new Rectangle(rect.X, rect.Y, newWidth, newHeight);
|
||||
if (Sections != null)
|
||||
if (StairDirection != Direction.None)
|
||||
{
|
||||
CreateStairBodies();
|
||||
}
|
||||
else if (Sections != null)
|
||||
{
|
||||
UpdateSections();
|
||||
}
|
||||
@@ -283,6 +287,13 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize(false, true), Editable]
|
||||
public bool NoAITarget
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public Dictionary<string, SerializableProperty> SerializableProperties
|
||||
{
|
||||
get;
|
||||
@@ -354,6 +365,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
StairDirection = Prefab.StairDirection;
|
||||
NoAITarget = Prefab.NoAITarget;
|
||||
SerializableProperties = SerializableProperty.GetProperties(this);
|
||||
|
||||
InitProjSpecific();
|
||||
@@ -381,7 +393,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
// Only add ai targets automatically to submarine/outpost walls
|
||||
if (aiTarget == null && HasBody && Tags.Contains("wall") && submarine != null && !submarine.Info.IsWreck && !Prefab.NoAITarget)
|
||||
if (aiTarget == null && HasBody && Tags.Contains("wall") && submarine != null && !submarine.Info.IsWreck && !NoAITarget)
|
||||
{
|
||||
aiTarget = new AITarget(this)
|
||||
{
|
||||
@@ -423,6 +435,7 @@ namespace Barotrauma
|
||||
private void CreateStairBodies()
|
||||
{
|
||||
Bodies = new List<Body>();
|
||||
bodyDebugDimensions.Clear();
|
||||
|
||||
float stairAngle = MathHelper.ToRadians(Math.Min(Prefab.StairAngle, 75.0f));
|
||||
|
||||
@@ -440,7 +453,7 @@ namespace Barotrauma
|
||||
newBody.Friction = 0.8f;
|
||||
newBody.UserData = this;
|
||||
|
||||
newBody.Position = ConvertUnits.ToSimUnits(stairPos) + BodyOffset;
|
||||
newBody.Position = ConvertUnits.ToSimUnits(stairPos) + BodyOffset * Scale;
|
||||
|
||||
bodyDebugDimensions.Add(new Vector2(bodyWidth, bodyHeight));
|
||||
|
||||
@@ -567,12 +580,12 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (MapEntity mapEntity in mapEntityList)
|
||||
{
|
||||
if (!(mapEntity is Structure structure)) continue;
|
||||
if (!structure.Prefab.AllowAttachItems) continue;
|
||||
if (structure.Bodies != null && structure.Bodies.Count > 0) continue;
|
||||
if (!(mapEntity is Structure structure)) { continue; }
|
||||
if (!structure.Prefab.AllowAttachItems) { continue; }
|
||||
if (structure.Bodies != null && structure.Bodies.Count > 0) { continue; }
|
||||
Rectangle worldRect = mapEntity.WorldRect;
|
||||
if (worldPosition.X < worldRect.X || worldPosition.X > worldRect.Right) continue;
|
||||
if (worldPosition.Y > worldRect.Y || worldPosition.Y < worldRect.Y - worldRect.Height) continue;
|
||||
if (worldPosition.X < worldRect.X || worldPosition.X > worldRect.Right) { continue; }
|
||||
if (worldPosition.Y > worldRect.Y || worldPosition.Y < worldRect.Y - worldRect.Height) { continue; }
|
||||
return structure;
|
||||
}
|
||||
return null;
|
||||
@@ -818,7 +831,10 @@ namespace Barotrauma
|
||||
Vector2 sectionPos = new Vector2(
|
||||
Sections[sectionIndex].rect.X + Sections[sectionIndex].rect.Width / 2.0f,
|
||||
Sections[sectionIndex].rect.Y - Sections[sectionIndex].rect.Height / 2.0f);
|
||||
if (world && Submarine != null) sectionPos += Submarine.Position;
|
||||
if (world && Submarine != null)
|
||||
{
|
||||
sectionPos += Submarine.Position;
|
||||
}
|
||||
return sectionPos;
|
||||
}
|
||||
else
|
||||
@@ -839,7 +855,10 @@ namespace Barotrauma
|
||||
(float)Math.Cos(IsHorizontal ? -BodyRotation : MathHelper.PiOver2 - BodyRotation),
|
||||
(float)Math.Sin(IsHorizontal ? -BodyRotation : MathHelper.PiOver2 - BodyRotation)) * diffFromCenter;
|
||||
|
||||
if (world && Submarine != null) sectionPos += Submarine.Position;
|
||||
if (world && Submarine != null)
|
||||
{
|
||||
sectionPos += Submarine.Position;
|
||||
}
|
||||
return sectionPos;
|
||||
}
|
||||
|
||||
@@ -1255,6 +1274,11 @@ namespace Barotrauma
|
||||
s.UseDropShadow = prefab.Body;
|
||||
}
|
||||
|
||||
if (element.Attribute("noaitarget") == null)
|
||||
{
|
||||
s.NoAITarget = prefab.NoAITarget;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -1327,6 +1351,7 @@ namespace Barotrauma
|
||||
SerializableProperties = SerializableProperty.DeserializeProperties(this, Prefab.ConfigElement);
|
||||
Sprite.ReloadXML();
|
||||
SpriteDepth = Sprite.Depth;
|
||||
NoAITarget = Prefab.NoAITarget;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
|
||||
@@ -4,7 +4,7 @@ using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using System.IO;
|
||||
using Barotrauma.IO;
|
||||
#if CLIENT
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
#endif
|
||||
|
||||
@@ -7,7 +7,7 @@ using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using Barotrauma.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -740,7 +740,7 @@ namespace Barotrauma
|
||||
|
||||
public void FlipX(List<Submarine> parents = null)
|
||||
{
|
||||
if (parents == null) parents = new List<Submarine>();
|
||||
if (parents == null) { parents = new List<Submarine>(); }
|
||||
parents.Add(this);
|
||||
|
||||
flippedX = !flippedX;
|
||||
@@ -748,20 +748,25 @@ namespace Barotrauma
|
||||
Item.UpdateHulls();
|
||||
|
||||
List<Item> bodyItems = Item.ItemList.FindAll(it => it.Submarine == this && it.body != null);
|
||||
|
||||
List<MapEntity> subEntities = MapEntity.mapEntityList.FindAll(me => me.Submarine == this);
|
||||
|
||||
foreach (MapEntity e in subEntities)
|
||||
{
|
||||
if (e is Item) continue;
|
||||
if (e is LinkedSubmarine)
|
||||
if (e is LinkedSubmarine linkedSub)
|
||||
{
|
||||
Submarine sub = ((LinkedSubmarine)e).Sub;
|
||||
if (!parents.Contains(sub))
|
||||
Submarine sub = linkedSub.Sub;
|
||||
if (sub == null)
|
||||
{
|
||||
Vector2 relative1 = linkedSub.Position - SubBody.Position;
|
||||
relative1.X = -relative1.X;
|
||||
linkedSub.Rect = new Rectangle((relative1 + SubBody.Position).ToPoint(), linkedSub.Rect.Size);
|
||||
}
|
||||
else if (!parents.Contains(sub))
|
||||
{
|
||||
Vector2 relative1 = sub.SubBody.Position - SubBody.Position;
|
||||
relative1.X = -relative1.X;
|
||||
sub.SetPosition(relative1 + SubBody.Position);
|
||||
sub.SetPosition(relative1 + SubBody.Position, new List<Submarine>(parents));
|
||||
sub.FlipX(parents);
|
||||
}
|
||||
}
|
||||
@@ -779,7 +784,7 @@ namespace Barotrauma
|
||||
Vector2 pos = new Vector2(subBody.Position.X, subBody.Position.Y);
|
||||
subBody.Body.Remove();
|
||||
subBody = new SubmarineBody(this);
|
||||
SetPosition(pos);
|
||||
SetPosition(pos, new List<Submarine>(parents.Where(p => p != this)));
|
||||
|
||||
if (entityGrid != null)
|
||||
{
|
||||
@@ -812,20 +817,24 @@ namespace Barotrauma
|
||||
|
||||
Item.UpdateHulls();
|
||||
Gap.UpdateHulls();
|
||||
#if CLIENT
|
||||
Lights.ConvexHull.RecalculateAll(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
//if (PlayerInput.KeyHit(InputType.Crouch) && (this == MainSub)) FlipX();
|
||||
|
||||
if (Level.Loaded == null || subBody == null) { return; }
|
||||
|
||||
if (Info.IsWreck)
|
||||
{
|
||||
WreckAI?.Update(deltaTime);
|
||||
}
|
||||
|
||||
if (WorldPosition.Y < Level.MaxEntityDepth &&
|
||||
if (subBody?.Body == null) { return; }
|
||||
|
||||
if (Level.Loaded != null &&
|
||||
WorldPosition.Y < Level.MaxEntityDepth &&
|
||||
subBody.Body.Enabled &&
|
||||
(GameMain.NetworkMember?.RespawnManager == null || this != GameMain.NetworkMember.RespawnManager.RespawnShuttle))
|
||||
{
|
||||
@@ -852,17 +861,17 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
subBody.Body.LinearVelocity = new Vector2(
|
||||
LockX ? 0.0f : subBody.Body.LinearVelocity.X,
|
||||
LockY ? 0.0f : subBody.Body.LinearVelocity.Y);
|
||||
|
||||
|
||||
subBody.Update(deltaTime);
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (MainSubs[i] == null) continue;
|
||||
if (this != MainSubs[i] && MainSubs[i].DockedTo.Contains(this)) return;
|
||||
if (MainSubs[i] == null) { continue; }
|
||||
if (this != MainSubs[i] && MainSubs[i].DockedTo.Contains(this)) { return; }
|
||||
}
|
||||
|
||||
//send updates more frequently if moving fast
|
||||
@@ -884,9 +893,9 @@ namespace Barotrauma
|
||||
prevPosition = position;
|
||||
}
|
||||
|
||||
public void SetPosition(Vector2 position, List<Submarine> checkd=null)
|
||||
public void SetPosition(Vector2 position, List<Submarine> checkd = null)
|
||||
{
|
||||
if (!MathUtils.IsValid(position)) return;
|
||||
if (!MathUtils.IsValid(position)) { return; }
|
||||
|
||||
if (checkd == null) { checkd = new List<Submarine>(); }
|
||||
if (checkd.Contains(this)) { return; }
|
||||
@@ -898,7 +907,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (Submarine dockedSub in DockedTo)
|
||||
{
|
||||
if (dockedSub.Info.IsOutpost)
|
||||
if (dockedSub.PhysicsBody.BodyType == BodyType.Static)
|
||||
{
|
||||
if (ConnectedDockingPorts.TryGetValue(dockedSub, out DockingPort port))
|
||||
{
|
||||
@@ -1169,7 +1178,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (Hull hull in matchingHulls)
|
||||
{
|
||||
if (string.IsNullOrEmpty(hull.RoomName) || !hull.RoomName.Contains("roomname.", StringComparison.OrdinalIgnoreCase))
|
||||
if (string.IsNullOrEmpty(hull.RoomName))// || !hull.RoomName.Contains("roomname.", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
hull.RoomName = hull.CreateRoomName();
|
||||
}
|
||||
@@ -1229,7 +1238,7 @@ namespace Barotrauma
|
||||
Info.CheckSubsLeftBehind(element);
|
||||
}
|
||||
|
||||
public bool SaveAs(string filePath, MemoryStream previewImage = null)
|
||||
public bool SaveAs(string filePath, System.IO.MemoryStream previewImage = null)
|
||||
{
|
||||
var newInfo = new SubmarineInfo(this)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Networking;
|
||||
using FarseerPhysics;
|
||||
using FarseerPhysics.Collision;
|
||||
using FarseerPhysics.Common;
|
||||
@@ -302,7 +303,7 @@ namespace Barotrauma
|
||||
//-------------------------
|
||||
|
||||
//if outside left or right edge of the level
|
||||
if (Position.X < 0 || Position.X > Level.Loaded.Size.X)
|
||||
if (Level.Loaded != null && (Position.X < 0 || Position.X > Level.Loaded.Size.X))
|
||||
{
|
||||
Rectangle worldBorders = Borders;
|
||||
worldBorders.Location += MathUtils.ToPoint(Position);
|
||||
@@ -386,12 +387,13 @@ namespace Barotrauma
|
||||
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (c.AnimController.CurrentHull != null && c.AnimController.CanEnterSubmarine) continue;
|
||||
if (c.AnimController.CurrentHull != null && c.AnimController.CanEnterSubmarine) { continue; }
|
||||
|
||||
foreach (Limb limb in c.AnimController.Limbs)
|
||||
{
|
||||
if (limb.IsSevered) { continue; }
|
||||
//if the character isn't inside the bounding box, continue
|
||||
if (!Submarine.RectContains(worldBorders, limb.WorldPosition)) continue;
|
||||
if (!Submarine.RectContains(worldBorders, limb.WorldPosition)) { continue; }
|
||||
|
||||
//cast a line from the position of the character to the same direction as the translation of the sub
|
||||
//and see where it intersects with the bounding box
|
||||
@@ -450,16 +452,18 @@ namespace Barotrauma
|
||||
private void UpdateDepthDamage(float deltaTime)
|
||||
{
|
||||
if (Position.Y > DamageDepth) { return; }
|
||||
|
||||
#if CLIENT
|
||||
if (GameMain.GameSession.GameMode is SubTestMode) { return; }
|
||||
#endif
|
||||
float depth = DamageDepth - Position.Y;
|
||||
|
||||
depthDamageTimer -= deltaTime;
|
||||
|
||||
if (depthDamageTimer > 0.0f) return;
|
||||
if (depthDamageTimer > 0.0f) { return; }
|
||||
|
||||
foreach (Structure wall in Structure.WallList)
|
||||
{
|
||||
if (wall.Submarine != submarine) continue;
|
||||
if (wall.Submarine != submarine) { continue; }
|
||||
|
||||
if (wall.Health < depth * 0.01f)
|
||||
{
|
||||
@@ -499,10 +503,14 @@ namespace Barotrauma
|
||||
}
|
||||
return collision;
|
||||
}
|
||||
if (f2.Body.UserData is Character character)
|
||||
else if (f2.Body.UserData is Character character)
|
||||
{
|
||||
return CheckCharacterCollision(contact, character);
|
||||
}
|
||||
else if (f2.UserData is Items.Components.DockingPort)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
lock (impactQueue)
|
||||
{
|
||||
@@ -634,7 +642,7 @@ namespace Barotrauma
|
||||
float damageAmount = contactDot * Body.Mass / limb.character.Mass;
|
||||
limb.character.LastDamageSource = submarine;
|
||||
limb.character.DamageLimb(ConvertUnits.ToDisplayUnits(collision.ImpactPos), limb,
|
||||
new List<Affliction>() { AfflictionPrefab.InternalDamage.Instantiate(damageAmount) }, 0.0f, true, 0.0f);
|
||||
AfflictionPrefab.ImpactDamage.Instantiate(damageAmount).ToEnumerable(), 0.0f, true, 0.0f);
|
||||
|
||||
if (limb.character.IsDead)
|
||||
{
|
||||
@@ -693,8 +701,8 @@ namespace Barotrauma
|
||||
|
||||
//find all contacts between this sub and level walls
|
||||
List<Contact> levelContacts = new List<Contact>();
|
||||
ContactEdge contactEdge = Body.FarseerBody.ContactList;
|
||||
while (contactEdge.Next != null)
|
||||
ContactEdge contactEdge = Body?.FarseerBody?.ContactList;
|
||||
while (contactEdge?.Next != null)
|
||||
{
|
||||
if (contactEdge.Contact.Enabled &&
|
||||
contactEdge.Other.UserData is VoronoiCell &&
|
||||
@@ -706,7 +714,7 @@ namespace Barotrauma
|
||||
contactEdge = contactEdge.Next;
|
||||
}
|
||||
|
||||
if (levelContacts.Count == 0) return;
|
||||
if (levelContacts.Count == 0) { return; }
|
||||
|
||||
//if this sub is in contact with the level, apply artifical impacts
|
||||
//to both subs to prevent the other sub from bouncing on top of this one
|
||||
@@ -795,6 +803,7 @@ namespace Barotrauma
|
||||
|
||||
foreach (Limb limb in c.AnimController.Limbs)
|
||||
{
|
||||
if (limb.IsSevered) { continue; }
|
||||
limb.body.ApplyLinearImpulse(limb.Mass * impulse, 10.0f);
|
||||
}
|
||||
c.AnimController.Collider.ApplyLinearImpulse(c.AnimController.Collider.Mass * impulse, 10.0f);
|
||||
|
||||
@@ -2,7 +2,7 @@ using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using Barotrauma.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -233,7 +233,7 @@ namespace Barotrauma
|
||||
for (int i = 0; i <= maxLoadRetries; i++)
|
||||
{
|
||||
doc = OpenFile(FilePath, out Exception e);
|
||||
if (e != null && !(e is IOException)) { break; }
|
||||
if (e != null && !(e is System.IO.IOException)) { break; }
|
||||
if (doc != null || i == maxLoadRetries || !File.Exists(FilePath)) { break; }
|
||||
DebugConsole.NewMessage("Opening submarine file \"" + FilePath + "\" failed, retrying in 250 ms...");
|
||||
Thread.Sleep(250);
|
||||
@@ -369,13 +369,16 @@ namespace Barotrauma
|
||||
|
||||
|
||||
//saving/loading ----------------------------------------------------
|
||||
public bool SaveAs(string filePath, MemoryStream previewImage=null)
|
||||
public bool SaveAs(string filePath, System.IO.MemoryStream previewImage=null)
|
||||
{
|
||||
var newElement = new XElement(SubmarineElement.Name,
|
||||
SubmarineElement.Attributes().Where(a => !string.Equals(a.Name.LocalName, "previewimage", StringComparison.InvariantCultureIgnoreCase)),
|
||||
SubmarineElement.Attributes().Where(a => !string.Equals(a.Name.LocalName, "previewimage", StringComparison.InvariantCultureIgnoreCase) &&
|
||||
!string.Equals(a.Name.LocalName, "name", StringComparison.InvariantCultureIgnoreCase)),
|
||||
SubmarineElement.Elements());
|
||||
XDocument doc = new XDocument(newElement);
|
||||
|
||||
doc.Root.Add(new XAttribute("name", Name));
|
||||
|
||||
if (previewImage != null)
|
||||
{
|
||||
doc.Root.Add(new XAttribute("previewimage", Convert.ToBase64String(previewImage.ToArray())));
|
||||
@@ -459,7 +462,7 @@ namespace Barotrauma
|
||||
subDirectories = Directory.GetDirectories(SavePath).Where(s =>
|
||||
{
|
||||
DirectoryInfo dir = new DirectoryInfo(s);
|
||||
return (dir.Attributes & FileAttributes.Hidden) == 0;
|
||||
return (dir.Attributes & System.IO.FileAttributes.Hidden) == 0;
|
||||
}).ToArray();
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -559,12 +562,12 @@ namespace Barotrauma
|
||||
|
||||
if (extension == ".sub")
|
||||
{
|
||||
Stream stream = null;
|
||||
System.IO.Stream stream = null;
|
||||
try
|
||||
{
|
||||
stream = SaveUtil.DecompressFiletoStream(file);
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
catch (System.IO.FileNotFoundException e)
|
||||
{
|
||||
exception = e;
|
||||
DebugConsole.ThrowError("Loading submarine \"" + file + "\" failed! (File not found) " + Environment.StackTrace, e);
|
||||
|
||||
@@ -124,13 +124,15 @@ namespace Barotrauma
|
||||
#if CLIENT
|
||||
if (iconSprites == null)
|
||||
{
|
||||
iconSprites = new Dictionary<SpawnType, Sprite>()
|
||||
iconSprites = new Dictionary<string, Sprite>()
|
||||
{
|
||||
{ SpawnType.Path, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(0,0,128,128)) },
|
||||
{ SpawnType.Human, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(128,0,128,128)) },
|
||||
{ SpawnType.Enemy, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(256,0,128,128)) },
|
||||
{ SpawnType.Cargo, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(384,0,128,128)) },
|
||||
{ SpawnType.Corpse, new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(512,0,128,128)) }
|
||||
{ "Path", new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(0,0,128,128)) },
|
||||
{ "Human", new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(128,0,128,128)) },
|
||||
{ "Enemy", new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(256,0,128,128)) },
|
||||
{ "Cargo", new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(384,0,128,128)) },
|
||||
{ "Corpse", new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(512,0,128,128)) },
|
||||
{ "Ladder", new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(0,128,128,128)) },
|
||||
{ "Door", new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(128,128,128,128)) }
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -592,6 +594,11 @@ namespace Barotrauma
|
||||
return assignedWayPoints;
|
||||
}
|
||||
|
||||
public void FindHull()
|
||||
{
|
||||
currentHull = Hull.FindHull(WorldPosition, CurrentHull);
|
||||
}
|
||||
|
||||
public override void OnMapLoaded()
|
||||
{
|
||||
currentHull = Hull.FindHull(WorldPosition, currentHull);
|
||||
|
||||
Reference in New Issue
Block a user