diff --git a/Subsurface/Content/Items/Electricity/lamp.png b/Subsurface/Content/Items/Electricity/lamp.png
index 05848b2ae..529fa81a1 100644
Binary files a/Subsurface/Content/Items/Electricity/lamp.png and b/Subsurface/Content/Items/Electricity/lamp.png differ
diff --git a/Subsurface/Content/Items/Electricity/lights.xml b/Subsurface/Content/Items/Electricity/lights.xml
index ecbcfe351..04e0f4f93 100644
--- a/Subsurface/Content/Items/Electricity/lights.xml
+++ b/Subsurface/Content/Items/Electricity/lights.xml
@@ -10,8 +10,8 @@
-
-
+
+
@@ -20,8 +20,25 @@
-
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Subsurface/Source/Items/Components/Door.cs b/Subsurface/Source/Items/Components/Door.cs
index 3ed69e783..a4ce54086 100644
--- a/Subsurface/Source/Items/Components/Door.cs
+++ b/Subsurface/Source/Items/Components/Door.cs
@@ -56,10 +56,15 @@ namespace Barotrauma.Items.Components
get
{
if (linkedGap != null) return linkedGap;
+
foreach (MapEntity e in item.linkedTo)
{
- linkedGap = e as Gap;
- if (linkedGap != null) return linkedGap;
+ linkedGap = e as Gap;
+ if (linkedGap != null)
+ {
+ linkedGap.PassAmbientLight = window != Rectangle.Empty;
+ return linkedGap;
+ }
}
Rectangle rect = item.Rect;
if (isHorizontal)
@@ -75,6 +80,7 @@ namespace Barotrauma.Items.Components
linkedGap = new Gap(rect, Item.Submarine);
linkedGap.Submarine = item.Submarine;
+ linkedGap.PassAmbientLight = window != Rectangle.Empty;
linkedGap.Open = openState;
item.linkedTo.Add(linkedGap);
return linkedGap;
diff --git a/Subsurface/Source/Map/Gap.cs b/Subsurface/Source/Map/Gap.cs
index afc3071f4..5790aec50 100644
--- a/Subsurface/Source/Map/Gap.cs
+++ b/Subsurface/Source/Map/Gap.cs
@@ -30,8 +30,13 @@ namespace Barotrauma
private float higherSurface;
private float lowerSurface;
+ private Vector2 lerpedFlowForce;
+
//if set to true, hull connections of this gap won't be updated when changes are being done to hulls
public bool DisableHullRechecks;
+
+ //can ambient light get through the gap even if it's not open
+ public bool PassAmbientLight;
public float Open
{
@@ -48,8 +53,6 @@ namespace Barotrauma
get { return lerpedFlowForce; }
}
- private Vector2 lerpedFlowForce;
-
public Hull FlowTargetHull
{
get { return flowTargetHull; }
diff --git a/Subsurface/Source/Map/Hull.cs b/Subsurface/Source/Map/Hull.cs
index 83693d7da..9667555b4 100644
--- a/Subsurface/Source/Map/Hull.cs
+++ b/Subsurface/Source/Map/Hull.cs
@@ -723,7 +723,6 @@ namespace Barotrauma
}
var entities = EntityGrid.GetEntities(entityGrids, position, useWorldCoordinates);
-
foreach (Hull hull in entities)
{
if (Submarine.RectContains(useWorldCoordinates ? hull.WorldRect : hull.rect, position)) return hull;
@@ -731,7 +730,7 @@ namespace Barotrauma
return null;
}
-
+
//returns the water block which contains the point (or null if it isn't inside any)
public static Hull FindHullOld(Vector2 position, Hull guess = null, bool useWorldCoordinates = true)
{
diff --git a/Subsurface/Source/Map/Levels/Level.cs b/Subsurface/Source/Map/Levels/Level.cs
index c3adb7194..1dfe397b6 100644
--- a/Subsurface/Source/Map/Levels/Level.cs
+++ b/Subsurface/Source/Map/Levels/Level.cs
@@ -181,7 +181,7 @@ namespace Barotrauma
backgroundColor = generationParams.BackgroundColor;
float avgValue = (backgroundColor.R + backgroundColor.G + backgroundColor.G) / 3;
- GameMain.LightManager.AmbientLight = new Color(backgroundColor * (60.0f / avgValue), 1.0f);
+ GameMain.LightManager.AmbientLight = new Color(backgroundColor * (10.0f / avgValue), 1.0f);
float minWidth = Submarine.MainSub == null ? 0.0f : Math.Max(Submarine.MainSub.Borders.Width, Submarine.MainSub.Borders.Height);
minWidth = Math.Max(minWidth, 6500.0f);
diff --git a/Subsurface/Source/Map/Lights/LightManager.cs b/Subsurface/Source/Map/Lights/LightManager.cs
index 3095465a7..71d658f7b 100644
--- a/Subsurface/Source/Map/Lights/LightManager.cs
+++ b/Subsurface/Source/Map/Lights/LightManager.cs
@@ -8,7 +8,9 @@ namespace Barotrauma.Lights
{
class LightManager
{
- //public static Vector2 ViewPos;
+ private const float AmbientLightUpdateInterval = 0.2f;
+ private const float AmbientLightFalloff = 0.8f;
+
private static Entity viewTarget;
public static Entity ViewTarget
@@ -35,12 +37,17 @@ namespace Barotrauma.Lights
public bool ObstructVision;
private Texture2D visionCircle;
+
+ private Dictionary hullAmbientLights = new Dictionary();
+ private Dictionary smoothedHullAmbientLights = new Dictionary();
+
+ private float ambientLightUpdateTimer;
public LightManager(GraphicsDevice graphics)
{
lights = new List();
- AmbientLight = new Color(60, 60, 60, 255);
+ AmbientLight = new Color(20, 20, 20, 255);
visionCircle = Sprite.LoadTexture("Content/Lights/visioncircle.png");
@@ -53,7 +60,10 @@ namespace Barotrauma.Lights
losTexture = new RenderTarget2D(graphics, GameMain.GraphicsWidth, GameMain.GraphicsHeight);
- if (alphaClearTexture==null)
+ hullAmbientLights = new Dictionary();
+ smoothedHullAmbientLights = new Dictionary();
+
+ if (alphaClearTexture == null)
{
alphaClearTexture = TextureLoader.FromFile("Content/Lights/alphaOne.png");
}
@@ -77,7 +87,38 @@ namespace Barotrauma.Lights
}
}
- public void UpdateLightMap(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam)
+ public void Update(float deltaTime)
+ {
+ if (ambientLightUpdateTimer > 0.0f)
+ {
+ ambientLightUpdateTimer -= deltaTime;
+ }
+ else
+ {
+ CalculateAmbientLights();
+
+ ambientLightUpdateTimer = AmbientLightUpdateInterval;
+ }
+
+ foreach (Hull hull in hullAmbientLights.Keys)
+ {
+ if (!smoothedHullAmbientLights.ContainsKey(hull))
+ {
+ smoothedHullAmbientLights.Add(hull, Color.TransparentBlack);
+ }
+ }
+
+ foreach (Hull hull in smoothedHullAmbientLights.Keys.ToList())
+ {
+ Color targetColor = Color.TransparentBlack;
+
+ hullAmbientLights.TryGetValue(hull, out targetColor);
+
+ smoothedHullAmbientLights[hull] = Color.Lerp(smoothedHullAmbientLights[hull], targetColor, deltaTime);
+ }
+ }
+
+ public void UpdateLightMap(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam, Effect blur)
{
if (!LightingEnabled) return;
@@ -94,7 +135,7 @@ namespace Barotrauma.Lights
foreach (LightSource light in lights)
{
- if (light.Color.A < 0.01f || light.Range < 1.0f || !light.CastShadows) continue;
+ if (light.Color.A < 1 || light.Range < 1.0f || !light.CastShadows) continue;
if (!MathUtils.CircleIntersectsRectangle(light.WorldPosition, light.Range, viewRect)) continue;
//clear alpha to 1
@@ -117,8 +158,7 @@ namespace Barotrauma.Lights
ClearAlphaToOne(graphics, spriteBatch);
-
-
+
spriteBatch.Begin(SpriteSortMode.Deferred, CustomBlendStates.MultiplyWithAlpha, null, null, null, null, cam.Transform);
GameMain.ParticleManager.Draw(spriteBatch, false, Particles.ParticleBlendState.Additive);
@@ -126,7 +166,7 @@ namespace Barotrauma.Lights
foreach (LightSource light in lights)
{
- if (light.Color.A < 0.01f || light.Range < 1.0f || light.CastShadows) continue;
+ if (light.Color.A < 1 || light.Range < 1.0f || light.CastShadows) continue;
//if (!MathUtils.CircleIntersectsRectangle(light.WorldPosition, light.Range, viewRect)) continue;
light.Draw(spriteBatch);
@@ -147,6 +187,27 @@ namespace Barotrauma.Lights
}
spriteBatch.End();
+
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive, null, null, null, null, cam.Transform);
+
+ foreach (Hull hull in smoothedHullAmbientLights.Keys)
+ {
+ if (smoothedHullAmbientLights[hull].A < 0.01f) continue;
+
+ var drawRect =
+ hull.Submarine == null ?
+ hull.Rect :
+ new Rectangle((int)(hull.Submarine.DrawPosition.X + hull.Rect.X), (int)(hull.Submarine.DrawPosition.Y + hull.Rect.Y), hull.Rect.Width, hull.Rect.Height);
+
+ GUI.DrawRectangle(spriteBatch,
+ new Vector2(drawRect.X, -drawRect.Y),
+ new Vector2(hull.Rect.Width, hull.Rect.Height),
+ smoothedHullAmbientLights[hull] * 0.5f, true);
+ }
+
+ spriteBatch.End();
+
+
//clear alpha, to avoid messing stuff up later
ClearAlphaToOne(graphics, spriteBatch);
@@ -173,8 +234,6 @@ namespace Barotrauma.Lights
spriteBatch.Draw(visionCircle, new Vector2(ViewTarget.WorldPosition.X, -ViewTarget.WorldPosition.Y), null, Color.White, rotation,
new Vector2(LightSource.LightTexture.Width*0.2f, LightSource.LightTexture.Height/2), scale, SpriteEffects.None, 0.0f);
-
-
}
else
{
@@ -209,6 +268,86 @@ namespace Barotrauma.Lights
}
graphics.SetRenderTarget(null);
}
+
+
+ private void CalculateAmbientLights()
+ {
+ hullAmbientLights.Clear();
+
+ foreach (LightSource light in lights)
+ {
+ if (light.Color.A < 1f || light.Range < 1.0f) continue;
+
+ var newAmbientLights = AmbientLightHulls(light);
+ foreach (Hull hull in newAmbientLights.Keys)
+ {
+ if (hullAmbientLights.ContainsKey(hull))
+ {
+ //hull already lit by some other light source -> add the ambient lights up
+ hullAmbientLights[hull] = new Color(
+ hullAmbientLights[hull].R + newAmbientLights[hull].R,
+ hullAmbientLights[hull].G + newAmbientLights[hull].G,
+ hullAmbientLights[hull].B + newAmbientLights[hull].B,
+ hullAmbientLights[hull].A + newAmbientLights[hull].A);
+ }
+ else
+ {
+ hullAmbientLights.Add(hull, newAmbientLights[hull]);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Add ambient light to the hull the lightsource is inside + all adjacent hulls connected by a gap
+ ///
+ private Dictionary AmbientLightHulls(LightSource light)
+ {
+ Dictionary hullAmbientLight = new Dictionary();
+
+ var hull = Hull.FindHull(light.WorldPosition);
+ if (hull == null) return hullAmbientLight;
+
+ return AmbientLightHulls(hull, hullAmbientLight, light.Color * (light.Range/2000.0f));
+ }
+
+ ///
+ /// A flood fill algorithm that adds ambient light to all hulls the starting hull is connected to
+ ///
+ private Dictionary AmbientLightHulls(Hull hull, Dictionary hullAmbientLight, Color currColor)
+ {
+ if (hullAmbientLight.ContainsKey(hull))
+ {
+ if (hullAmbientLight[hull].A > currColor.A)
+ return hullAmbientLight;
+ else
+ hullAmbientLight[hull] = currColor;
+ }
+ else
+ {
+ hullAmbientLight.Add(hull, currColor);
+ }
+
+ foreach (Gap g in hull.ConnectedGaps)
+ {
+ for (int i = 0; i < g.linkedTo.Count;i++ )
+ {
+ if (g.linkedTo[i] is Hull)
+ {
+ if (g.linkedTo[i] == hull) continue;
+
+ Color nextHullLight = currColor * AmbientLightFalloff;
+ if (!g.PassAmbientLight) nextHullLight *= g.Open;
+
+ if (nextHullLight.A < 10) continue;
+
+ hullAmbientLight = AmbientLightHulls((Hull)g.linkedTo[i], hullAmbientLight, nextHullLight);
+ }
+ }
+ }
+
+ return hullAmbientLight;
+ }
private void ClearAlphaToOne(GraphicsDevice graphics, SpriteBatch spriteBatch)
{
@@ -217,7 +356,7 @@ namespace Barotrauma.Lights
spriteBatch.End();
}
- public void DrawLightMap(SpriteBatch spriteBatch, Camera cam, Effect effect)
+ public void DrawLightMap(SpriteBatch spriteBatch, Effect effect)
{
if (!LightingEnabled) return;
@@ -227,11 +366,11 @@ namespace Barotrauma.Lights
spriteBatch.End();
}
- public void DrawLOS(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam, Effect effect)
+ public void DrawLOS(SpriteBatch spriteBatch, Effect effect)
{
if (!LosEnabled || ViewTarget == null) return;
- spriteBatch.Begin(SpriteSortMode.Deferred, CustomBlendStates.Multiplicative, null, null, null);
+ spriteBatch.Begin(SpriteSortMode.Deferred, CustomBlendStates.Multiplicative, null, null, null, effect);
spriteBatch.Draw(losTexture, Vector2.Zero, Color.White);
spriteBatch.End();
@@ -264,9 +403,6 @@ namespace Barotrauma.Lights
public static BlendState Multiplicative { get; private set; }
public static BlendState WriteToAlpha { get; private set; }
public static BlendState MultiplyWithAlpha { get; private set; }
-
-
-
}
}
diff --git a/Subsurface/Source/Map/Lights/LightSource.cs b/Subsurface/Source/Map/Lights/LightSource.cs
index 5412b025e..03fff7bfb 100644
--- a/Subsurface/Source/Map/Lights/LightSource.cs
+++ b/Subsurface/Source/Map/Lights/LightSource.cs
@@ -306,20 +306,21 @@ namespace Barotrauma.Lights
Vector2 center = new Vector2(LightTexture.Width / 2, LightTexture.Height / 2);
float scale = range / (lightTexture.Width / 2.0f);
- spriteBatch.Draw(lightTexture, new Vector2(WorldPosition.X, -WorldPosition.Y), null, color, 0, center, scale, SpriteEffects.None, 1);
+ spriteBatch.Draw(lightTexture, new Vector2(WorldPosition.X, -WorldPosition.Y), null, color * (color.A / 255.0f), 0, center, scale, SpriteEffects.None, 1);
}
else
{
- overrideLightTexture.Draw(spriteBatch,
- new Vector2(WorldPosition.X, -WorldPosition.Y), Color,
- overrideLightTexture.Origin, -Rotation,
- new Vector2(overrideLightTexture.size.X/overrideLightTexture.SourceRect.Width, overrideLightTexture.size.Y/overrideLightTexture.SourceRect.Height));
+ overrideLightTexture.Draw(spriteBatch,
+ new Vector2(WorldPosition.X, -WorldPosition.Y), color * (color.A / 255.0f),
+ overrideLightTexture.Origin, -Rotation,
+ new Vector2(overrideLightTexture.size.X / overrideLightTexture.SourceRect.Width, overrideLightTexture.size.Y / overrideLightTexture.SourceRect.Height));
}
}
if (LightSprite != null)
{
LightSprite.Draw(spriteBatch, new Vector2(WorldPosition.X, -WorldPosition.Y), Color, LightSprite.Origin);
+
}
}
diff --git a/Subsurface/Source/Screens/GameScreen.cs b/Subsurface/Source/Screens/GameScreen.cs
index aa1bd038d..55a217098 100644
--- a/Subsurface/Source/Screens/GameScreen.cs
+++ b/Subsurface/Source/Screens/GameScreen.cs
@@ -128,6 +128,8 @@ namespace Barotrauma
{
cam.TargetPos = Lights.LightManager.ViewTarget.WorldPosition;
}
+
+ GameMain.LightManager.Update((float)deltaTime);
cam.MoveCamera((float)deltaTime);
foreach (Submarine sub in Submarine.Loaded)
@@ -205,7 +207,7 @@ namespace Barotrauma
GameMain.LightManager.ObstructVision = Character.Controlled != null && Character.Controlled.ObstructVision;
- GameMain.LightManager.UpdateLightMap(graphics, spriteBatch, cam);
+ GameMain.LightManager.UpdateLightMap(graphics, spriteBatch, cam, lightBlur.Effect);
if (Character.Controlled != null)
{
GameMain.LightManager.UpdateObstructVision(graphics, spriteBatch, cam, Character.Controlled.CursorWorldPosition);
@@ -339,8 +341,7 @@ namespace Barotrauma
spriteBatch.End();
-
- GameMain.LightManager.DrawLightMap(spriteBatch, cam, lightBlur.Effect);
+ GameMain.LightManager.DrawLightMap(spriteBatch, lightBlur.Effect);
spriteBatch.Begin(SpriteSortMode.BackToFront,
BlendState.AlphaBlend, SamplerState.LinearWrap,
@@ -355,7 +356,7 @@ namespace Barotrauma
if (Character.Controlled != null)
{
- GameMain.LightManager.DrawLOS(graphics, spriteBatch, cam, lightBlur.Effect);
+ GameMain.LightManager.DrawLOS(spriteBatch, lightBlur.Effect);
}
}
diff --git a/Subsurface/Submarines/Aegir Mark III.sub b/Subsurface/Submarines/Aegir Mark III.sub
index 2d0af9d3e..79c236a1a 100644
Binary files a/Subsurface/Submarines/Aegir Mark III.sub and b/Subsurface/Submarines/Aegir Mark III.sub differ