Merge remote-tracking branch 'origin/master' into dev
# Conflicts: # Barotrauma/BarotraumaClient/ClientSource/DebugConsole.cs # Barotrauma/BarotraumaClient/ClientSource/Events/EventManager.cs # Barotrauma/BarotraumaClient/ClientSource/GUI/CrewManagement.cs # Barotrauma/BarotraumaClient/ClientSource/GUI/MedicalClinicUI.cs # Barotrauma/BarotraumaClient/ClientSource/GUI/Store.cs # Barotrauma/BarotraumaClient/ClientSource/GUI/SubmarineSelection.cs # Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/CampaignMode.cs # Barotrauma/BarotraumaClient/ClientSource/GameSession/GameModes/MultiPlayerCampaign.cs # Barotrauma/BarotraumaClient/ClientSource/GameSession/RoundSummary.cs # Barotrauma/BarotraumaClient/ClientSource/Items/Components/Door.cs # Barotrauma/BarotraumaClient/ClientSource/Items/Components/Machines/Fabricator.cs # Barotrauma/BarotraumaClient/ClientSource/Items/Components/Projectile.cs # Barotrauma/BarotraumaClient/ClientSource/Map/Lights/ConvexHull.cs # Barotrauma/BarotraumaClient/ClientSource/Map/Lights/LightManager.cs # Barotrauma/BarotraumaClient/ClientSource/Map/Lights/LightSource.cs # Barotrauma/BarotraumaClient/ClientSource/Map/Structure.cs # Barotrauma/BarotraumaClient/ClientSource/Networking/GameClient.cs # Barotrauma/BarotraumaClient/ClientSource/Networking/Voip/VoipClient.cs # Barotrauma/BarotraumaClient/ClientSource/Networking/Voting.cs # Barotrauma/BarotraumaClient/ClientSource/Screens/ServerListScreen/ServerListScreen.cs # Barotrauma/BarotraumaClient/LinuxClient.csproj # Barotrauma/BarotraumaClient/MacClient.csproj # Barotrauma/BarotraumaClient/WindowsClient.csproj # Barotrauma/BarotraumaServer/LinuxServer.csproj # Barotrauma/BarotraumaServer/MacServer.csproj # Barotrauma/BarotraumaServer/ServerSource/DebugConsole.cs # Barotrauma/BarotraumaServer/ServerSource/GameSession/MedicalClinic.cs # Barotrauma/BarotraumaServer/ServerSource/Items/Inventory.cs # Barotrauma/BarotraumaServer/ServerSource/Networking/GameServer.cs # Barotrauma/BarotraumaServer/ServerSource/Utils/DoSProtection.cs # Barotrauma/BarotraumaServer/WindowsServer.csproj # Barotrauma/BarotraumaShared/SharedSource/Characters/AI/HumanAIController.cs # Barotrauma/BarotraumaShared/SharedSource/Characters/AI/IndoorsSteeringManager.cs # Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveContainItem.cs # Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveFindSafety.cs # Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGetItem.cs # Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveGoTo.cs # Barotrauma/BarotraumaShared/SharedSource/Characters/AI/Objectives/AIObjectiveIdle.cs # Barotrauma/BarotraumaShared/SharedSource/Characters/AI/ShipCommand/ShipIssueWorkerOperateWeapons.cs # Barotrauma/BarotraumaShared/SharedSource/Characters/Attack.cs # Barotrauma/BarotraumaShared/SharedSource/Characters/Character.cs # Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/Affliction.cs # Barotrauma/BarotraumaShared/SharedSource/Characters/Health/Afflictions/AfflictionPrefab.cs # Barotrauma/BarotraumaShared/SharedSource/Characters/Health/CharacterHealth.cs # Barotrauma/BarotraumaShared/SharedSource/Characters/Params/CharacterParams.cs # Barotrauma/BarotraumaShared/SharedSource/ContentManagement/ContentPackageManager.cs # Barotrauma/BarotraumaShared/SharedSource/Enums.cs # Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/MissionAction.cs # Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCChangeTeamAction.cs # Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCFollowAction.cs # Barotrauma/BarotraumaShared/SharedSource/Events/EventActions/NPCWaitAction.cs # Barotrauma/BarotraumaShared/SharedSource/Events/EventManager.cs # Barotrauma/BarotraumaShared/SharedSource/Events/Missions/Mission.cs # Barotrauma/BarotraumaShared/SharedSource/Events/Missions/PirateMission.cs # Barotrauma/BarotraumaShared/SharedSource/Events/Missions/SalvageMission.cs # Barotrauma/BarotraumaShared/SharedSource/GameSession/CargoManager.cs # Barotrauma/BarotraumaShared/SharedSource/GameSession/Data/Reputation.cs # Barotrauma/BarotraumaShared/SharedSource/GameSession/GameModes/CampaignMode.cs # Barotrauma/BarotraumaShared/SharedSource/GameSession/GameSession.cs # Barotrauma/BarotraumaShared/SharedSource/Items/Components/Door.cs # Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/LevelResource.cs # Barotrauma/BarotraumaShared/SharedSource/Items/Components/Holdable/RangedWeapon.cs # Barotrauma/BarotraumaShared/SharedSource/Items/Components/ItemContainer.cs # Barotrauma/BarotraumaShared/SharedSource/Items/Components/Projectile.cs # Barotrauma/BarotraumaShared/SharedSource/Items/Components/Signal/LightComponent.cs # Barotrauma/BarotraumaShared/SharedSource/Items/Components/Turret.cs # Barotrauma/BarotraumaShared/SharedSource/Items/Item.cs # Barotrauma/BarotraumaShared/SharedSource/Items/ItemPrefab.cs # Barotrauma/BarotraumaShared/SharedSource/Map/Gap.cs # Barotrauma/BarotraumaShared/SharedSource/Map/Levels/Level.cs # Barotrauma/BarotraumaShared/SharedSource/Map/Map/Location.cs # Barotrauma/BarotraumaShared/SharedSource/Map/Map/Map.cs # Barotrauma/BarotraumaShared/SharedSource/Map/Outposts/OutpostGenerator.cs # Barotrauma/BarotraumaShared/SharedSource/Map/Submarine.cs # Barotrauma/BarotraumaShared/SharedSource/Map/SubmarineBody.cs # Barotrauma/BarotraumaShared/SharedSource/Networking/ServerSettings.cs # Barotrauma/BarotraumaShared/SharedSource/Settings/GameSettings.cs # Barotrauma/BarotraumaShared/SharedSource/StatusEffects/PropertyConditional.cs # Barotrauma/BarotraumaShared/SharedSource/StatusEffects/StatusEffect.cs # Barotrauma/BarotraumaShared/changelog.txt
This commit is contained in:
@@ -9,15 +9,17 @@ namespace Barotrauma
|
||||
{
|
||||
private LightSource lightSource;
|
||||
|
||||
partial void UpdateProjSpecific(float growModifier)
|
||||
private float particleTimer;
|
||||
|
||||
partial void UpdateProjSpecific(float growModifier, float deltaTime)
|
||||
{
|
||||
if (this is DummyFireSource)
|
||||
{
|
||||
EmitParticles(size, WorldPosition, hull, growModifier, null);
|
||||
EmitParticles(size, WorldPosition, deltaTime, hull, growModifier, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitParticles(size, WorldPosition, hull, growModifier, OnChangeHull);
|
||||
EmitParticles(size, WorldPosition, deltaTime, hull, growModifier, OnChangeHull);
|
||||
}
|
||||
|
||||
lightSource.Color = new Color(1.0f, 0.45f, 0.3f) * Rand.Range(0.8f, 1.0f);
|
||||
@@ -25,23 +27,29 @@ namespace Barotrauma
|
||||
if (Vector2.DistanceSquared(lightSource.Position, position) > 5.0f) { lightSource.Position = position + Vector2.UnitY * 30.0f; }
|
||||
}
|
||||
|
||||
public static void EmitParticles(Vector2 size, Vector2 worldPosition, Hull hull, float growModifier, Particle.OnChangeHullHandler onChangeHull = null)
|
||||
public void EmitParticles(Vector2 size, Vector2 worldPosition, float deltaTime, Hull hull, float growModifier, Particle.OnChangeHullHandler onChangeHull = null)
|
||||
{
|
||||
float particleCount = Rand.Range(0.0f, size.X / 50.0f);
|
||||
var particlePrefab = ParticleManager.FindPrefab("flame");
|
||||
if (particlePrefab == null) { return; }
|
||||
|
||||
for (int i = 0; i < particleCount; i++)
|
||||
float particlesPerSecond = MathHelper.Clamp(size.X / 2.0f, 10.0f, 200.0f);
|
||||
|
||||
float particleInterval = 1.0f / particlesPerSecond;
|
||||
particleTimer += deltaTime;
|
||||
while (particleTimer > particleInterval)
|
||||
{
|
||||
particleTimer -= particleInterval;
|
||||
Vector2 particlePos = new Vector2(
|
||||
worldPosition.X + Rand.Range(0.0f, size.X),
|
||||
Rand.Range(worldPosition.Y - size.Y, worldPosition.Y + 20.0f));
|
||||
worldPosition.Y - size.Y + particlePrefab.CollisionRadius);
|
||||
|
||||
Vector2 particleVel = new Vector2(
|
||||
particlePos.X - (worldPosition.X + size.X / 2.0f),
|
||||
Math.Max((float)Math.Sqrt(size.X) * Rand.Range(0.0f, 15.0f) * growModifier, 0.0f));
|
||||
|
||||
particleVel.X = MathHelper.Clamp(particleVel.X, -200.0f, 200.0f);
|
||||
|
||||
var particle = GameMain.ParticleManager.CreateParticle("flame",
|
||||
|
||||
var particle = GameMain.ParticleManager.CreateParticle(particlePrefab,
|
||||
particlePos, particleVel, 0.0f, hull);
|
||||
|
||||
if (particle == null) { continue; }
|
||||
@@ -54,7 +62,7 @@ namespace Barotrauma
|
||||
if (Rand.Int(5) == 1)
|
||||
{
|
||||
var smokeParticle = GameMain.ParticleManager.CreateParticle("smoke",
|
||||
particlePos, new Vector2(particleVel.X, particleVel.Y * 0.1f), 0.0f, hull);
|
||||
particlePos, new Vector2(particleVel.X, particleVel.Y * 0.1f), 0.0f, hull);
|
||||
|
||||
if (smokeParticle != null)
|
||||
{
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (var edge in cell.Edges)
|
||||
{
|
||||
if (MathUtils.GetLineIntersection(worldPosition, cell.Center, edge.Point1 + cell.Translation, edge.Point2 + cell.Translation, out Vector2 intersection))
|
||||
if (MathUtils.GetLineSegmentIntersection(worldPosition, cell.Center, edge.Point1 + cell.Translation, edge.Point2 + cell.Translation, out Vector2 intersection))
|
||||
{
|
||||
intersectionFound = true;
|
||||
particlePos = intersection;
|
||||
|
||||
@@ -93,13 +93,16 @@ namespace Barotrauma.Lights
|
||||
|
||||
private readonly int thickness;
|
||||
|
||||
public bool IsExteriorWall;
|
||||
|
||||
public VertexPositionColor[] ShadowVertices { get; private set; }
|
||||
public VertexPositionTexture[] PenumbraVertices { get; private set; }
|
||||
public int ShadowVertexCount { get; private set; }
|
||||
public int PenumbraVertexCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the maximum distance a LOS vertex can be moved to make it align with a nearby LOS segment
|
||||
/// </summary>
|
||||
public float? MaxMergeLosVerticesDist;
|
||||
|
||||
private readonly HashSet<ConvexHull> overlappingHulls = new HashSet<ConvexHull>();
|
||||
|
||||
public MapEntity ParentEntity { get; private set; }
|
||||
@@ -130,7 +133,7 @@ namespace Barotrauma.Lights
|
||||
|
||||
public Rectangle BoundingBox { get; private set; }
|
||||
|
||||
public ConvexHull(Rectangle rect, bool? isHorizontal, MapEntity parent)
|
||||
public ConvexHull(Rectangle rect, bool isHorizontal, MapEntity parent)
|
||||
{
|
||||
shadowEffect ??= new BasicEffect(GameMain.Instance.GraphicsDevice)
|
||||
{
|
||||
@@ -150,15 +153,15 @@ namespace Barotrauma.Lights
|
||||
|
||||
BoundingBox = rect;
|
||||
|
||||
this.isHorizontal = isHorizontal ?? BoundingBox.Width > BoundingBox.Height;
|
||||
this.isHorizontal = isHorizontal;
|
||||
if (ParentEntity is Structure structure)
|
||||
{
|
||||
System.Diagnostics.Debug.Assert(!structure.Removed);
|
||||
Debug.Assert(!structure.Removed);
|
||||
isHorizontal = structure.IsHorizontal;
|
||||
}
|
||||
else if (ParentEntity is Item item)
|
||||
{
|
||||
System.Diagnostics.Debug.Assert(!item.Removed);
|
||||
Debug.Assert(!item.Removed);
|
||||
var door = item.GetComponent<Door>();
|
||||
if (door != null) { isHorizontal = door.IsHorizontal; }
|
||||
}
|
||||
@@ -205,44 +208,97 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
if (ch == this) { return; }
|
||||
|
||||
//hide segments that are roughly at the some position as some other segment (e.g. the ends of two adjacent wall pieces)
|
||||
float mergeDist = MathHelper.Clamp(ch.thickness * 0.55f, 16, 512);
|
||||
mergeDist = Math.Min(mergeDist, Vector2.Distance(losVertices[0].Pos, losVertices[1].Pos) / 2);
|
||||
//merge dist in the direction parallel to the segment
|
||||
//(e.g. how far up/down we can stretch a vertical segment)
|
||||
float mergeDistParallel = MathHelper.Clamp(ch.thickness * 0.65f, 16, 512);
|
||||
if (MaxMergeLosVerticesDist.HasValue)
|
||||
{
|
||||
mergeDistParallel = Math.Max(mergeDistParallel, MaxMergeLosVerticesDist.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Rectangle inflatedAABB = ch.BoundingBox;
|
||||
inflatedAABB.Inflate(2, 2);
|
||||
//if this los segment isn't touching the other's bounding box,
|
||||
//don't extend the segment by more than 50% of it's length
|
||||
if (!inflatedAABB.Contains(losVertices[0].Pos) &&
|
||||
!inflatedAABB.Contains(losVertices[1].Pos))
|
||||
{
|
||||
mergeDistParallel = Math.Min(mergeDistParallel, Vector2.Distance(losVertices[0].Pos, losVertices[1].Pos) * 0.5f);
|
||||
}
|
||||
}
|
||||
//merge dist in the direction perpendicular to the segment
|
||||
//(e.g. how far right/left we can stretch a vertical segment)
|
||||
//do not allow more than ~half of the thickness, because that'd make the segment go outside the convex hull
|
||||
float mergeDistPerpendicular = Math.Min(mergeDistParallel, thickness * 0.35f);
|
||||
|
||||
float mergeDistSqr = mergeDist * mergeDist;
|
||||
Vector2 center = (losVertices[0].Pos + losVertices[1].Pos) / 2;
|
||||
|
||||
bool changed = false;
|
||||
for (int i = 0; i < losVertices.Length; i++)
|
||||
{
|
||||
//find the closest point on the other convex hull segment
|
||||
Vector2 segmentDir = Vector2.Normalize(losVertices[i].Pos - center);
|
||||
//check if the closest point on the other convex hull segment is close enough, disregarding any offsets
|
||||
//otherwise we might end up moving the vertex too much if we stretch it to an already-offset segment
|
||||
if (!isCloseEnough(
|
||||
MathUtils.GetClosestPointOnLineSegment(ch.losVertices[0].Pos, ch.losVertices[1].Pos, losVertices[i].Pos),
|
||||
losVertices[i].Pos))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//check the offset position of the segment next
|
||||
Vector2 closest = MathUtils.GetClosestPointOnLineSegment(
|
||||
ch.losVertices[0].Pos + ch.losOffsets[0],
|
||||
ch.losVertices[1].Pos + ch.losOffsets[1],
|
||||
losVertices[i].Pos);
|
||||
if (Vector2.DistanceSquared(closest, losVertices[i].Pos) > mergeDistSqr) { continue; }
|
||||
if (!isCloseEnough(closest, losVertices[i].Pos)) { continue; }
|
||||
|
||||
//find where the segments would intersect if they had infinite length
|
||||
// if it's close to the closest point, let's use that instead to keep
|
||||
// the direction of the segment unchanged (i.e. vertical segment stays vertical)
|
||||
if (MathUtils.GetLineIntersection(
|
||||
ch.losVertices[0].Pos + ch.losOffsets[0],
|
||||
ch.losVertices[1].Pos + ch.losOffsets[1],
|
||||
losVertices[0].Pos,
|
||||
losVertices[1].Pos,
|
||||
out Vector2 intersection))
|
||||
ch.losVertices[0].Pos + ch.losOffsets[0], ch.losVertices[1].Pos + ch.losOffsets[1],
|
||||
losVertices[0].Pos, losVertices[1].Pos,
|
||||
areLinesInfinite: true, out Vector2 intersection) &&
|
||||
//the intersection needs to be outwards from the vertex we're checking
|
||||
Vector2.Dot(segmentDir, intersection - losVertices[i].Pos) > 0 &&
|
||||
//the intersection needs to be close enough to the default position of the vertex and the closest point
|
||||
//(we don't want to merge the segments somewhere close to infinity!)
|
||||
(Vector2.DistanceSquared(intersection, losVertices[i].Pos) < mergeDistParallel * mergeDistParallel ||
|
||||
Vector2.DistanceSquared(intersection, closest) < 16.0f * 16.0f))
|
||||
{
|
||||
if (Vector2.DistanceSquared(intersection, losVertices[i].Pos) < mergeDistSqr ||
|
||||
Vector2.DistanceSquared(intersection, closest) < 16.0f * 16.0f)
|
||||
{
|
||||
closest = intersection;
|
||||
}
|
||||
closest = intersection;
|
||||
}
|
||||
|
||||
//don't move the vertices of the segment too close to each other
|
||||
if (Vector2.DistanceSquared(losVertices[1 - i].Pos + losOffsets[1 - i], closest) < mergeDistPerpendicular * mergeDistPerpendicular)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
losOffsets[i] = closest - losVertices[i].Pos;
|
||||
overlappingHulls.Add(ch);
|
||||
ch.overlappingHulls.Add(this);
|
||||
changed = true;
|
||||
|
||||
|
||||
bool isCloseEnough(Vector2 closest, Vector2 vertex)
|
||||
{
|
||||
float dist = Vector2.Distance(closest, vertex);
|
||||
if (dist < 0.001f) { return true; }
|
||||
if (dist > mergeDistParallel) { return false; }
|
||||
|
||||
Vector2 closestDir = (closest - vertex) / dist;
|
||||
|
||||
float dot = Math.Abs(Vector2.Dot(segmentDir, closestDir));
|
||||
float distAlongAxis = dist * dot;
|
||||
if (distAlongAxis > mergeDistParallel) { return false; }
|
||||
|
||||
float distPerpendicular = dist * (1.0f - dot);
|
||||
if (distPerpendicular > mergeDistPerpendicular) { return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (changed && refreshOtherOverlappingHulls)
|
||||
{
|
||||
@@ -253,6 +309,13 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
}
|
||||
|
||||
public bool LosIntersects(Vector2 pos1, Vector2 pos2)
|
||||
{
|
||||
return MathUtils.LineSegmentsIntersect(
|
||||
losVertices[0].Pos + losOffsets[0], losVertices[1].Pos + losOffsets[1],
|
||||
pos1, pos2);
|
||||
}
|
||||
|
||||
public void Rotate(Vector2 origin, float amount)
|
||||
{
|
||||
Matrix rotationMatrix =
|
||||
@@ -347,6 +410,7 @@ namespace Barotrauma.Lights
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
losVertices[i] = new SegmentPoint(losPoints[i], this);
|
||||
losOffsets[i] = Vector2.Zero;
|
||||
}
|
||||
|
||||
overlappingHulls.Clear();
|
||||
@@ -612,8 +676,11 @@ namespace Barotrauma.Lights
|
||||
vertexPos0 += ParentEntity.Submarine.DrawPosition;
|
||||
vertexPos1 += ParentEntity.Submarine.DrawPosition;
|
||||
}
|
||||
Vector2 viewTargetPos = LightManager.ViewTarget.WorldPosition;
|
||||
float alpha = IsSegmentFacing(vertexPos0, vertexPos1, viewTargetPos) ? 1.0f : 0.5f;
|
||||
float alpha = 1.0f;
|
||||
if (LightManager.ViewTarget != null)
|
||||
{
|
||||
alpha = IsSegmentFacing(vertexPos0, vertexPos1, LightManager.ViewTarget.WorldPosition) ? 1.0f : 0.5f;
|
||||
}
|
||||
vertexPos0.Y = -vertexPos0.Y;
|
||||
vertexPos1.Y = -vertexPos1.Y;
|
||||
GUI.DrawLine(spriteBatch, vertexPos0, vertexPos1, color * alpha, width: width);
|
||||
|
||||
@@ -189,7 +189,7 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
}
|
||||
|
||||
private class RayCastTask
|
||||
private sealed class RayCastTask
|
||||
{
|
||||
public LightSource LightSource;
|
||||
public Vector2 DrawPos;
|
||||
@@ -298,7 +298,8 @@ namespace Barotrauma.Lights
|
||||
range *
|
||||
((Character.Controlled?.Submarine != null && light.ParentSub == Character.Controlled?.Submarine) ? 2.0f : 1.0f) *
|
||||
(light.CastShadows ? 10.0f : 1.0f) *
|
||||
(light.LightSourceParams.OverrideLightSpriteAlpha ?? (light.Color.A / 255.0f));
|
||||
(light.LightSourceParams.OverrideLightSpriteAlpha ?? (light.Color.A / 255.0f)) *
|
||||
light.PriorityMultiplier;
|
||||
}
|
||||
|
||||
//find the lights with an active light volume
|
||||
@@ -477,6 +478,17 @@ namespace Barotrauma.Lights
|
||||
light.DrawLightVolume(spriteBatch, lightEffect, transform, recalculationCount < MaxLightVolumeRecalculationsPerFrame, ref recalculationCount);
|
||||
}
|
||||
|
||||
if (ConnectionPanel.ShouldDebugDrawWiring)
|
||||
{
|
||||
foreach (MapEntity e in (Submarine.VisibleEntities ?? MapEntity.mapEntityList))
|
||||
{
|
||||
if (e is Item item && item.GetComponent<Wire>() is Wire wire)
|
||||
{
|
||||
wire.DebugDraw(spriteBatch, alpha: 0.4f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lightEffect.World = transform;
|
||||
|
||||
GameMain.ParticleManager.Draw(spriteBatch, false, null, Particles.ParticleBlendState.Additive);
|
||||
@@ -686,19 +698,42 @@ namespace Barotrauma.Lights
|
||||
if (LosEnabled && LosMode != LosMode.None && ViewTarget != null)
|
||||
{
|
||||
Vector2 pos = ViewTarget.DrawPosition;
|
||||
if (ViewTarget is Character character &&
|
||||
bool centeredOnHead = false;
|
||||
if (ViewTarget is Character character &&
|
||||
character.AnimController?.GetLimb(LimbType.Head) is Limb head &&
|
||||
!head.IsSevered && !head.Removed)
|
||||
{
|
||||
pos = head.body.DrawPosition;
|
||||
centeredOnHead = true;
|
||||
}
|
||||
|
||||
Rectangle camView = new Rectangle(cam.WorldView.X, cam.WorldView.Y - cam.WorldView.Height, cam.WorldView.Width, cam.WorldView.Height);
|
||||
|
||||
Matrix shadowTransform = cam.ShaderTransform
|
||||
* Matrix.CreateOrthographic(GameMain.GraphicsWidth, GameMain.GraphicsHeight, -1, 1) * 0.5f;
|
||||
|
||||
var convexHulls = ConvexHull.GetHullsInRange(ViewTarget.Position, cam.WorldView.Width * 0.75f, ViewTarget.Submarine);
|
||||
|
||||
//make sure the head isn't peeking through any LOS segments, and if it is,
|
||||
//center the LOS on the character's collider instead
|
||||
if (centeredOnHead)
|
||||
{
|
||||
foreach (var ch in convexHulls)
|
||||
{
|
||||
Vector2 currentViewPos = pos;
|
||||
Vector2 defaultViewPos = ViewTarget.DrawPosition;
|
||||
if (ch.ParentEntity?.Submarine != null)
|
||||
{
|
||||
defaultViewPos -= ch.ParentEntity.Submarine.DrawPosition;
|
||||
currentViewPos -= ch.ParentEntity.Submarine.DrawPosition;
|
||||
}
|
||||
//check if a line from the character's collider to the head intersects with the los segment (= head poking through it)
|
||||
if (ch.LosIntersects(defaultViewPos, currentViewPos))
|
||||
{
|
||||
pos = ViewTarget.DrawPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (convexHulls != null)
|
||||
{
|
||||
List<VertexPositionColor> shadowVerts = new List<VertexPositionColor>();
|
||||
@@ -706,7 +741,6 @@ namespace Barotrauma.Lights
|
||||
foreach (ConvexHull convexHull in convexHulls)
|
||||
{
|
||||
if (!convexHull.Enabled || !convexHull.Intersects(camView)) { continue; }
|
||||
if (LosMode == LosMode.BlockOutsideView && !convexHull.IsExteriorWall) { continue; };
|
||||
|
||||
Vector2 relativeLightPos = pos;
|
||||
if (convexHull.ParentEntity?.Submarine != null) { relativeLightPos -= convexHull.ParentEntity.Submarine.Position; }
|
||||
@@ -744,13 +778,14 @@ namespace Barotrauma.Lights
|
||||
|
||||
public void DebugDrawLos(SpriteBatch spriteBatch, Camera cam)
|
||||
{
|
||||
if (ViewTarget == null) { return; }
|
||||
Vector2 pos = ViewTarget?.Position ?? cam.Position;
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, transformMatrix: cam.Transform);
|
||||
var convexHulls = ConvexHull.GetHullsInRange(ViewTarget.Position, cam.WorldView.Width * 0.75f, ViewTarget?.Submarine);
|
||||
var convexHulls = ConvexHull.GetHullsInRange(pos, cam.WorldView.Width * 0.75f, ViewTarget?.Submarine);
|
||||
Rectangle camView = new Rectangle(cam.WorldView.X, cam.WorldView.Y - cam.WorldView.Height, cam.WorldView.Width, cam.WorldView.Height);
|
||||
foreach (ConvexHull convexHull in convexHulls)
|
||||
{
|
||||
if (!convexHull.Enabled || !convexHull.Intersects(camView)) { continue; }
|
||||
if (convexHull.ParentEntity is Structure { CastShadow: false }) { continue; }
|
||||
convexHull.DebugDraw(spriteBatch);
|
||||
}
|
||||
spriteBatch.End();
|
||||
|
||||
@@ -53,10 +53,6 @@ namespace Barotrauma.Lights
|
||||
[Serialize(0f, IsPropertySaveable.Yes), Editable(MinValueFloat = -360, MaxValueFloat = 360, ValueStep = 1, DecimalCount = 0)]
|
||||
public float Rotation { get; set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.Yes, "Directional lights only shine in \"one direction\", meaning no shadows are cast behind them."+
|
||||
" Note that this does not affect how the light texture is drawn: if you want something like a conical spotlight, you should use an appropriate texture for that.")]
|
||||
public bool Directional { get; set; }
|
||||
|
||||
public Vector2 GetOffset() => Vector2.Transform(Offset, Matrix.CreateRotationZ(MathHelper.ToRadians(Rotation)));
|
||||
|
||||
private float flicker;
|
||||
@@ -233,6 +229,7 @@ namespace Barotrauma.Lights
|
||||
|
||||
//do we need to recalculate the vertices of the light volume
|
||||
private bool needsRecalculation;
|
||||
private bool needsRecalculationWhenUpToDate;
|
||||
public bool NeedsRecalculation
|
||||
{
|
||||
get { return needsRecalculation; }
|
||||
@@ -246,9 +243,15 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
}
|
||||
needsRecalculation = value;
|
||||
if (needsRecalculation && state != LightVertexState.UpToDate)
|
||||
{
|
||||
//if we're currently recalculating light vertices, mark that we need to recalculate them again after it's done
|
||||
needsRecalculationWhenUpToDate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//when were the vertices of the light volume last calculated
|
||||
public float LastRecalculationTime { get; private set; }
|
||||
|
||||
@@ -309,8 +312,6 @@ namespace Barotrauma.Lights
|
||||
if (Math.Abs(value - rotation) < 0.001f) { return; }
|
||||
rotation = value;
|
||||
|
||||
dir = new Vector2(MathF.Cos(rotation), -MathF.Sin(rotation));
|
||||
|
||||
if (Math.Abs(rotation - prevCalculatedRotation) < RotationRecalculationThreshold && vertices != null)
|
||||
{
|
||||
return;
|
||||
@@ -321,8 +322,6 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
}
|
||||
|
||||
private Vector2 dir = Vector2.UnitX;
|
||||
|
||||
private Vector2 _spriteScale = Vector2.One;
|
||||
|
||||
public Vector2 SpriteScale
|
||||
@@ -396,6 +395,8 @@ namespace Barotrauma.Lights
|
||||
|
||||
public float Priority;
|
||||
|
||||
public float PriorityMultiplier = 1.0f;
|
||||
|
||||
private Vector2 lightTextureTargetSize;
|
||||
|
||||
public Vector2 LightTextureTargetSize
|
||||
@@ -444,7 +445,7 @@ namespace Barotrauma.Lights
|
||||
public bool Enabled = true;
|
||||
|
||||
private readonly ISerializableEntity conditionalTarget;
|
||||
private readonly PropertyConditional.LogicalOperatorType logicalOperator;
|
||||
private readonly PropertyConditional.Comparison comparison;
|
||||
private readonly List<PropertyConditional> conditionals = new List<PropertyConditional>();
|
||||
|
||||
public LightSource(ContentXElement element, ISerializableEntity conditionalTarget = null)
|
||||
@@ -452,8 +453,11 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
lightSourceParams = new LightSourceParams(element);
|
||||
CastShadows = element.GetAttributeBool("castshadows", true);
|
||||
logicalOperator = element.GetAttributeEnum(nameof(logicalOperator),
|
||||
element.GetAttributeEnum("comparison", logicalOperator));
|
||||
string comparison = element.GetAttributeString("comparison", null);
|
||||
if (comparison != null)
|
||||
{
|
||||
Enum.TryParse(comparison, ignoreCase: true, out this.comparison);
|
||||
}
|
||||
|
||||
if (lightSourceParams.DeformableLightSpriteElement != null)
|
||||
{
|
||||
@@ -466,7 +470,13 @@ namespace Barotrauma.Lights
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "conditional":
|
||||
conditionals.AddRange(PropertyConditional.FromXElement(subElement));
|
||||
foreach (XAttribute attribute in subElement.Attributes())
|
||||
{
|
||||
if (PropertyConditional.IsValid(attribute))
|
||||
{
|
||||
conditionals.Add(new PropertyConditional(attribute));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -529,32 +539,11 @@ namespace Barotrauma.Lights
|
||||
var fullChList = ConvexHull.HullLists.FirstOrDefault(chList => chList.Submarine == sub);
|
||||
if (fullChList == null) { return; }
|
||||
|
||||
//used to check whether the lightsource hits the target hull if the light is directional
|
||||
Vector2 ray = new Vector2(dir.X, -dir.Y) * TextureRange;
|
||||
Vector2 normal = new Vector2(-ray.Y, ray.X);
|
||||
|
||||
chList.List.Clear();
|
||||
foreach (var convexHull in fullChList.List)
|
||||
{
|
||||
if (!convexHull.Enabled) { continue; }
|
||||
if (!MathUtils.CircleIntersectsRectangle(lightPos, TextureRange, convexHull.BoundingBox)) { continue; }
|
||||
if (lightSourceParams.Directional && false)
|
||||
{
|
||||
Rectangle bounds = convexHull.BoundingBox;
|
||||
//invert because GetLineRectangleIntersection uses the messed up rects that start from top-left
|
||||
bounds.Y -= bounds.Height;
|
||||
|
||||
//the ray can't hit if
|
||||
// center is in the opposite direction from the ray (cheapest check first)
|
||||
if (Vector2.Dot(ray, convexHull.BoundingBox.Center.ToVector2() - lightPos) <= 0 &&
|
||||
/*ray doesn't hit the convex hull*/
|
||||
!MathUtils.GetLineRectangleIntersection(lightPos, lightPos + ray, bounds, out _) &&
|
||||
/*normal vectors of the ray don't hit the convex hull */
|
||||
!MathUtils.GetLineRectangleIntersection(lightPos + normal, lightPos - normal, bounds, out _))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
chList.List.Add(convexHull);
|
||||
}
|
||||
chList.IsHidden.RemoveWhere(ch => !chList.List.Contains(ch));
|
||||
@@ -704,7 +693,7 @@ namespace Barotrauma.Lights
|
||||
lock (mutex)
|
||||
{
|
||||
hull.RefreshWorldPositions();
|
||||
hull.GetVisibleSegments(drawPos, visibleSegments);
|
||||
hull.GetVisibleSegments(drawPos, visibleSegments);
|
||||
foreach (var visibleSegment in visibleSegments)
|
||||
{
|
||||
if (visibleSegment.ConvexHull?.ParentEntity?.Submarine != null)
|
||||
@@ -713,7 +702,6 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
foreach (ConvexHull hull in chList.List)
|
||||
@@ -812,7 +800,7 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
else
|
||||
{
|
||||
intersects = MathUtils.GetLineIntersection(p1a, p1b, p2a, p2b, out intersection);
|
||||
intersects = MathUtils.GetLineSegmentIntersection(p1a, p1b, p2a, p2b, out intersection);
|
||||
}
|
||||
|
||||
if (intersects)
|
||||
@@ -1006,7 +994,7 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
else
|
||||
{
|
||||
intersects = MathUtils.GetLineIntersection(rayStart, rayEnd, s.Start.WorldPos, s.End.WorldPos, out intersection);
|
||||
intersects = MathUtils.GetLineSegmentIntersection(rayStart, rayEnd, s.Start.WorldPos, s.End.WorldPos, out intersection);
|
||||
}
|
||||
|
||||
if (intersects)
|
||||
@@ -1041,9 +1029,11 @@ namespace Barotrauma.Lights
|
||||
|
||||
Vector2 drawPos = calculatedDrawPos;
|
||||
|
||||
float cosAngle = (float)Math.Cos(Rotation);
|
||||
float sinAngle = -(float)Math.Sin(Rotation);
|
||||
|
||||
Vector2 uvOffset = Vector2.Zero;
|
||||
Vector2 overrideTextureDims = Vector2.One;
|
||||
Vector2 dir = this.dir;
|
||||
if (OverrideLightTexture != null)
|
||||
{
|
||||
overrideTextureDims = new Vector2(OverrideLightTexture.SourceRect.Width, OverrideLightTexture.SourceRect.Height);
|
||||
@@ -1052,7 +1042,8 @@ namespace Barotrauma.Lights
|
||||
if (LightSpriteEffect == SpriteEffects.FlipHorizontally)
|
||||
{
|
||||
origin.X = OverrideLightTexture.SourceRect.Width - origin.X;
|
||||
dir = -dir;
|
||||
cosAngle = -cosAngle;
|
||||
sinAngle = -sinAngle;
|
||||
}
|
||||
if (LightSpriteEffect == SpriteEffects.FlipVertically) { origin.Y = OverrideLightTexture.SourceRect.Height - origin.Y; }
|
||||
uvOffset = (origin / overrideTextureDims) - new Vector2(0.5f, 0.5f);
|
||||
@@ -1125,8 +1116,8 @@ namespace Barotrauma.Lights
|
||||
//calculate texture coordinates based on the light's rotation
|
||||
Vector2 originDiff = diff;
|
||||
|
||||
diff.X = originDiff.X * dir.X - originDiff.Y * dir.Y;
|
||||
diff.Y = originDiff.X * dir.Y + originDiff.Y * dir.X;
|
||||
diff.X = originDiff.X * cosAngle - originDiff.Y * sinAngle;
|
||||
diff.Y = originDiff.X * sinAngle + originDiff.Y * cosAngle;
|
||||
diff *= (overrideTextureDims / OverrideLightTexture.size);// / (1.0f - Math.Max(Math.Abs(uvOffset.X), Math.Abs(uvOffset.Y)));
|
||||
diff += uvOffset;
|
||||
}
|
||||
@@ -1231,6 +1222,9 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
drawPos.Y = -drawPos.Y;
|
||||
|
||||
float cosAngle = (float)Math.Cos(Rotation);
|
||||
float sinAngle = -(float)Math.Sin(Rotation);
|
||||
|
||||
float bounds = TextureRange;
|
||||
|
||||
if (OverrideLightTexture != null)
|
||||
@@ -1242,8 +1236,8 @@ namespace Barotrauma.Lights
|
||||
origin /= Math.Max(overrideTextureDims.X, overrideTextureDims.Y);
|
||||
origin *= TextureRange;
|
||||
|
||||
drawPos.X += origin.X * dir.Y + origin.Y * dir.X;
|
||||
drawPos.Y += origin.X * dir.X + origin.Y * dir.Y;
|
||||
drawPos.X += origin.X * sinAngle + origin.Y * cosAngle;
|
||||
drawPos.Y += origin.X * cosAngle + origin.Y * sinAngle;
|
||||
}
|
||||
|
||||
//add a square-shaped boundary to make sure we've got something to construct the triangles from
|
||||
@@ -1349,7 +1343,7 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
if (conditionals.None()) { return; }
|
||||
if (conditionalTarget == null) { return; }
|
||||
if (logicalOperator == PropertyConditional.LogicalOperatorType.And)
|
||||
if (comparison == PropertyConditional.Comparison.And)
|
||||
{
|
||||
Enabled = conditionals.All(c => c.Matches(conditionalTarget));
|
||||
}
|
||||
@@ -1405,7 +1399,9 @@ namespace Barotrauma.Lights
|
||||
CalculateLightVertices(verts);
|
||||
|
||||
LastRecalculationTime = (float)Timing.TotalTime;
|
||||
NeedsRecalculation = false;
|
||||
NeedsRecalculation = needsRecalculationWhenUpToDate;
|
||||
needsRecalculationWhenUpToDate = false;
|
||||
|
||||
state = LightVertexState.UpToDate;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,12 +56,12 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
private static readonly List<RoundSound> roundSounds = new List<RoundSound>();
|
||||
private static readonly Dictionary<string, RoundSound> roundSoundByPath = new Dictionary<string, RoundSound>();
|
||||
public static RoundSound? Load(ContentXElement element, bool stream = false)
|
||||
{
|
||||
if (GameMain.SoundManager?.Disabled ?? true) { return null; }
|
||||
|
||||
var filename = element.GetAttributeContentPath("file") ?? element.GetAttributeContentPath("sound");
|
||||
|
||||
if (filename is null)
|
||||
{
|
||||
string errorMsg = "Error when loading round sound (" + element + ") - file path not set";
|
||||
@@ -70,7 +70,11 @@ namespace Barotrauma
|
||||
return null;
|
||||
}
|
||||
|
||||
Sound? existingSound = roundSounds.Find(s => s.Filename == filename?.FullPath && s.Stream == stream && s.Sound is { Disposed: false })?.Sound;
|
||||
Sound? existingSound = null;
|
||||
if (roundSoundByPath.TryGetValue(filename.FullPath, out RoundSound? rs) && rs.Sound is { Disposed: false })
|
||||
{
|
||||
existingSound = rs.Sound;
|
||||
}
|
||||
|
||||
if (existingSound is null)
|
||||
{
|
||||
@@ -99,7 +103,10 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
RoundSound newSound = new RoundSound(element, existingSound);
|
||||
|
||||
if (filename is not null && !newSound.Stream)
|
||||
{
|
||||
roundSoundByPath.TryAdd(filename.FullPath, newSound);
|
||||
}
|
||||
roundSounds.Add(newSound);
|
||||
return newSound;
|
||||
}
|
||||
@@ -124,24 +131,14 @@ namespace Barotrauma
|
||||
roundSound.Sound = existingSound;
|
||||
}
|
||||
|
||||
private static void Remove(RoundSound roundSound)
|
||||
{
|
||||
#warning TODO: what is going on here????
|
||||
roundSound.Sound?.Dispose();
|
||||
|
||||
if (roundSounds.Contains(roundSound)) { roundSounds.Remove(roundSound); }
|
||||
foreach (RoundSound otherSound in roundSounds)
|
||||
{
|
||||
if (otherSound.Sound == roundSound.Sound) { otherSound.Sound = null; }
|
||||
}
|
||||
}
|
||||
|
||||
public static void RemoveAllRoundSounds()
|
||||
{
|
||||
for (int i = roundSounds.Count - 1; i >= 0; i--)
|
||||
foreach (var roundSound in roundSounds)
|
||||
{
|
||||
Remove(roundSounds[i]);
|
||||
roundSound.Sound?.Dispose();
|
||||
}
|
||||
roundSounds.Clear();
|
||||
roundSoundByPath.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,11 +58,8 @@ namespace Barotrauma
|
||||
convexHulls ??= new List<ConvexHull>();
|
||||
var h = new ConvexHull(
|
||||
new Rectangle((position - size / 2).ToPoint(), size.ToPoint()),
|
||||
IsHorizontal,
|
||||
this)
|
||||
{
|
||||
IsExteriorWall = IsExteriorWall
|
||||
};
|
||||
IsHorizontal,
|
||||
this);
|
||||
if (Math.Abs(rotation) > 0.001f)
|
||||
{
|
||||
h.Rotate(position, rotation);
|
||||
@@ -501,7 +498,7 @@ namespace Barotrauma
|
||||
|
||||
private bool ConditionalMatches(PropertyConditional conditional)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(conditional.TargetItemComponent))
|
||||
if (!string.IsNullOrEmpty(conditional.TargetItemComponentName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -116,11 +116,11 @@ namespace Barotrauma
|
||||
|
||||
foreach (MapEntity e in entitiesToRender)
|
||||
{
|
||||
if (!e.DrawOverWater) continue;
|
||||
if (!e.DrawOverWater) { continue; }
|
||||
|
||||
if (predicate != null)
|
||||
{
|
||||
if (!predicate(e)) continue;
|
||||
if (!predicate(e)) { continue; }
|
||||
}
|
||||
|
||||
e.Draw(spriteBatch, editing, false);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -18,7 +19,7 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
List<Submarine> subsToMove = submarine.GetConnectedSubs();
|
||||
var subsToMove = submarine.GetConnectedSubs();
|
||||
foreach (Submarine dockedSub in subsToMove)
|
||||
{
|
||||
if (dockedSub == submarine) { continue; }
|
||||
@@ -51,7 +52,6 @@ namespace Barotrauma
|
||||
sub.PhysicsBody.SetTransformIgnoreContacts(sub.PhysicsBody.SimPosition + ConvertUnits.ToSimUnits(moveAmount), 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (closestSub != null && subsToMove.Contains(closestSub))
|
||||
{
|
||||
GameMain.GameScreen.Cam.Position += moveAmount;
|
||||
|
||||
@@ -67,6 +67,10 @@ namespace Barotrauma
|
||||
else if (ConnectedDoor != null)
|
||||
{
|
||||
sprite = iconSprites["Door"];
|
||||
if (ConnectedDoor.IsHorizontal && Ladders == null)
|
||||
{
|
||||
clr = Color.Yellow;
|
||||
}
|
||||
}
|
||||
else if (Ladders != null)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user