diff --git a/TSOClient/tso.client/Rendering/City/Terrain.cs b/TSOClient/tso.client/Rendering/City/Terrain.cs index 19d127b1..51265042 100644 --- a/TSOClient/tso.client/Rendering/City/Terrain.cs +++ b/TSOClient/tso.client/Rendering/City/Terrain.cs @@ -1212,9 +1212,11 @@ namespace FSO.Client.Rendering.City public void SetTimeOfDay(double time) { time = Math.Min(0.999999999, time); - Time = (float)time; m_TintColor = TimeOfDayConfig.ColorFromTime(time); + Time = (float)time; + time = FinaleUtils.BiasSunTime(time); + if (Weather.Darken > 0) { //tint the outside colour, usually with some darkening effect. @@ -1240,6 +1242,8 @@ namespace FSO.Client.Rendering.City modTime = (time - DayOffset) * 0.5 / DayDuration; } + modTime = FinaleUtils.BiasSunTime(modTime); + Transform *= Matrix.CreateRotationY((float)((modTime+0.5) * Math.PI * 2.0)); //Controls the rotation of the sun/moon around the city. Transform *= Matrix.CreateRotationZ((float)(Math.PI*(45.0/180.0))); //Sun is at an angle of 45 degrees to horizon at it's peak. idk why, it's winter maybe? looks nice either way Transform *= Matrix.CreateRotationY((float)(Math.PI * 0.3)); //Offset from front-back a little. This might need some adjusting for the nicest sunset/sunrise locations. @@ -1820,7 +1824,9 @@ namespace FSO.Client.Rendering.City VertexShader.CurrentTechnique = VertexShader.Techniques[1]; VertexShader.CurrentTechnique.Passes[passIndex].Apply(); - var night = Time < 0.25f || Time > 0.75f; + + double biasTime = FinaleUtils.BiasSunTime(Time); + var night = biasTime < 0.25f || biasTime > 0.75f; if (!useLocked || NearFacades == null) { diff --git a/TSOClient/tso.common/FSO.Common.csproj b/TSOClient/tso.common/FSO.Common.csproj index 1d4973e3..02883c0c 100644 --- a/TSOClient/tso.common/FSO.Common.csproj +++ b/TSOClient/tso.common/FSO.Common.csproj @@ -162,6 +162,7 @@ + diff --git a/TSOClient/tso.common/Rendering/FinaleUtils.cs b/TSOClient/tso.common/Rendering/FinaleUtils.cs new file mode 100644 index 00000000..37ce3c67 --- /dev/null +++ b/TSOClient/tso.common/Rendering/FinaleUtils.cs @@ -0,0 +1,88 @@ +using Microsoft.Xna.Framework; +using System; + +namespace FSO.Common.Rendering +{ + public static class FinaleUtils + { + private static Color[] FinaleColors = new Color[] + { + new Color(2, 2, 2), + new Color(2, 2, 2), + Color.Lerp(new Color(0, 0, 0), new Color(50, 70, 122)*1.25f, 0.5f), + new Color(70, 70, 70)*1.25f, + new Color(217, 109, 50), //sunrise + new Color(255, 255, 255), + new Color(255, 255, 255), //peak + new Color(255, 255, 255), //peak + new Color(255, 255, 255), + new Color(255, 255, 255), + Color.Lerp(new Color(255, 255, 255), new Color(217, 109, 50), 0.33f), + Color.Lerp(new Color(255, 255, 255), new Color(217, 109, 25), 0.66f), + new Color(225, 64, 0), //sunset + new Color(0, 0, 0) + }; + + private static double DayOffset = 0.25; + private static double DayDuration = 0.60; + + private static double TargetEnd = 1.04; + + public static double BiasSunTime(double modTime) + { + if (IsFinale()) + { + double dayMid = DayOffset + DayDuration / 2; + double mainEnd = DayOffset + DayDuration; + + double rescaleDay = (TargetEnd - dayMid) / (mainEnd - dayMid); + + if (modTime > dayMid) + { + modTime = dayMid + (modTime - dayMid) / rescaleDay; + } + } + + return modTime; + } + + public static Vector3 BiasSunIntensity(Vector3 intensity, float time) + { + if (IsFinale()) + { + if (time > 0.70) + { + intensity = Vector3.Lerp(new Vector3(0.6f), new Vector3(1, 0.2f, 0.1f), (time - 0.70f) / 0.25f); + } + else if (time > 0.5) + { + intensity = Vector3.Lerp(intensity, new Vector3(0.6f), (time - 0.5f) / 0.2f); + } + + if (time > 0.995) + { + intensity *= (1f - time) * 200f; + } + } + + return intensity; + } + + public static bool IsFinale() + { + var time = DateTime.UtcNow; + + return time.Year == 2024 && time.Month == 12 && ((time.Day == 8 && time.Hour == 23) || (time.Day == 9 && time.Hour == 0)); + } + + public static float GetDarkness() + { + return IsFinale() ? 1.0f : 0.8f; + } + + public static Color[] SwapFinaleColors(Color[] colors) + { + return IsFinale() ? FinaleColors : colors; + } + } +} diff --git a/TSOClient/tso.common/Rendering/TimeOfDayConfig.cs b/TSOClient/tso.common/Rendering/TimeOfDayConfig.cs index df317743..7c9a4ffb 100644 --- a/TSOClient/tso.common/Rendering/TimeOfDayConfig.cs +++ b/TSOClient/tso.common/Rendering/TimeOfDayConfig.cs @@ -54,14 +54,19 @@ namespace FSO.Common.Rendering public static Color ColorFromTime(double time) { - Color col1 = m_TimeColors[(int)Math.Floor(time * (m_TimeColors.Length - 1))]; //first colour - Color col2 = m_TimeColors[(int)Math.Floor(time * (m_TimeColors.Length - 1)) + 1]; //second colour - if (DarknessMultiplier != 1.0) + Color[] colors = FinaleUtils.SwapFinaleColors(m_TimeColors); + + Color col1 = colors[(int)Math.Floor(time * (colors.Length - 1))]; //first colour + Color col2 = colors[(int)Math.Floor(time * (colors.Length - 1)) + 1]; //second colour + + float darkness = FinaleUtils.GetDarkness(); + + if (darkness != 1.0) { - col1 = Color.Lerp(Color.White, col1, DarknessMultiplier); - col2 = Color.Lerp(Color.White, col2, DarknessMultiplier); + col1 = Color.Lerp(Color.White, col1, darkness); + col2 = Color.Lerp(Color.White, col2, darkness); } - double Progress = (time * (m_TimeColors.Length - 1)) % 1; //interpolation progress (mod 1) + double Progress = (time * (colors.Length - 1)) % 1; //interpolation progress (mod 1) return PowColor(Color.Lerp(col1, col2, (float)Progress), 2.2f); //linearly interpolate between the two colours for this specific time. } diff --git a/TSOClient/tso.content/Content/DX/Effects/2DWorldBatch.xnb b/TSOClient/tso.content/Content/DX/Effects/2DWorldBatch.xnb index 5ac15276..90102d54 100644 Binary files a/TSOClient/tso.content/Content/DX/Effects/2DWorldBatch.xnb and b/TSOClient/tso.content/Content/DX/Effects/2DWorldBatch.xnb differ diff --git a/TSOClient/tso.content/Content/DX/Effects/GrassShader.xnb b/TSOClient/tso.content/Content/DX/Effects/GrassShader.xnb index cec98caa..910a8910 100644 Binary files a/TSOClient/tso.content/Content/DX/Effects/GrassShader.xnb and b/TSOClient/tso.content/Content/DX/Effects/GrassShader.xnb differ diff --git a/TSOClient/tso.content/Content/DX/Effects/GrassShaderiOS.xnb b/TSOClient/tso.content/Content/DX/Effects/GrassShaderiOS.xnb index 5721e3c3..ab705baf 100644 Binary files a/TSOClient/tso.content/Content/DX/Effects/GrassShaderiOS.xnb and b/TSOClient/tso.content/Content/DX/Effects/GrassShaderiOS.xnb differ diff --git a/TSOClient/tso.content/Content/DX/Effects/ParticleShader.xnb b/TSOClient/tso.content/Content/DX/Effects/ParticleShader.xnb index 2d30a6f3..24347009 100644 Binary files a/TSOClient/tso.content/Content/DX/Effects/ParticleShader.xnb and b/TSOClient/tso.content/Content/DX/Effects/ParticleShader.xnb differ diff --git a/TSOClient/tso.content/Content/DX/Effects/RCObject.xnb b/TSOClient/tso.content/Content/DX/Effects/RCObject.xnb index dd79a8af..2e35d95d 100644 Binary files a/TSOClient/tso.content/Content/DX/Effects/RCObject.xnb and b/TSOClient/tso.content/Content/DX/Effects/RCObject.xnb differ diff --git a/TSOClient/tso.content/Content/DX/Fonts/mobile.xnb b/TSOClient/tso.content/Content/DX/Fonts/mobile.xnb index 17396d5a..ae59aefb 100644 Binary files a/TSOClient/tso.content/Content/DX/Fonts/mobile.xnb and b/TSOClient/tso.content/Content/DX/Fonts/mobile.xnb differ diff --git a/TSOClient/tso.content/Content/DX/Fonts/simdialogue.xnb b/TSOClient/tso.content/Content/DX/Fonts/simdialogue.xnb index 59f5fea0..43bd31df 100644 Binary files a/TSOClient/tso.content/Content/DX/Fonts/simdialogue.xnb and b/TSOClient/tso.content/Content/DX/Fonts/simdialogue.xnb differ diff --git a/TSOClient/tso.content/Content/DX/Fonts/trebuchet.xnb b/TSOClient/tso.content/Content/DX/Fonts/trebuchet.xnb index d57c32e5..a3b6a423 100644 Binary files a/TSOClient/tso.content/Content/DX/Fonts/trebuchet.xnb and b/TSOClient/tso.content/Content/DX/Fonts/trebuchet.xnb differ diff --git a/TSOClient/tso.content/Content/OGL/Effects/2DWorldBatch.xnb b/TSOClient/tso.content/Content/OGL/Effects/2DWorldBatch.xnb index 49a8fa46..ace9246b 100644 Binary files a/TSOClient/tso.content/Content/OGL/Effects/2DWorldBatch.xnb and b/TSOClient/tso.content/Content/OGL/Effects/2DWorldBatch.xnb differ diff --git a/TSOClient/tso.content/Content/OGL/Effects/GrassShader.xnb b/TSOClient/tso.content/Content/OGL/Effects/GrassShader.xnb index ac1668cd..0d90a4bd 100644 Binary files a/TSOClient/tso.content/Content/OGL/Effects/GrassShader.xnb and b/TSOClient/tso.content/Content/OGL/Effects/GrassShader.xnb differ diff --git a/TSOClient/tso.content/Content/OGL/Effects/GrassShaderiOS.xnb b/TSOClient/tso.content/Content/OGL/Effects/GrassShaderiOS.xnb index 2eb10796..3bc96be6 100644 Binary files a/TSOClient/tso.content/Content/OGL/Effects/GrassShaderiOS.xnb and b/TSOClient/tso.content/Content/OGL/Effects/GrassShaderiOS.xnb differ diff --git a/TSOClient/tso.content/Content/OGL/Effects/ParticleShader.xnb b/TSOClient/tso.content/Content/OGL/Effects/ParticleShader.xnb index 82931a85..97954255 100644 Binary files a/TSOClient/tso.content/Content/OGL/Effects/ParticleShader.xnb and b/TSOClient/tso.content/Content/OGL/Effects/ParticleShader.xnb differ diff --git a/TSOClient/tso.content/Content/OGL/Effects/RCObject.xnb b/TSOClient/tso.content/Content/OGL/Effects/RCObject.xnb index a25902ed..2fb294a0 100644 Binary files a/TSOClient/tso.content/Content/OGL/Effects/RCObject.xnb and b/TSOClient/tso.content/Content/OGL/Effects/RCObject.xnb differ diff --git a/TSOClient/tso.content/Content/OGL/Effects/RCObjectiOS.xnb b/TSOClient/tso.content/Content/OGL/Effects/RCObjectiOS.xnb index f95fea9c..a0b91a3d 100644 Binary files a/TSOClient/tso.content/Content/OGL/Effects/RCObjectiOS.xnb and b/TSOClient/tso.content/Content/OGL/Effects/RCObjectiOS.xnb differ diff --git a/TSOClient/tso.content/Content/OGL/Fonts/mobile.xnb b/TSOClient/tso.content/Content/OGL/Fonts/mobile.xnb index 01aa0dc3..62e5e2b3 100644 Binary files a/TSOClient/tso.content/Content/OGL/Fonts/mobile.xnb and b/TSOClient/tso.content/Content/OGL/Fonts/mobile.xnb differ diff --git a/TSOClient/tso.content/Content/OGL/Fonts/simdialogue.xnb b/TSOClient/tso.content/Content/OGL/Fonts/simdialogue.xnb index 7f84f704..8f890b24 100644 Binary files a/TSOClient/tso.content/Content/OGL/Fonts/simdialogue.xnb and b/TSOClient/tso.content/Content/OGL/Fonts/simdialogue.xnb differ diff --git a/TSOClient/tso.content/Content/OGL/Fonts/trebuchet.xnb b/TSOClient/tso.content/Content/OGL/Fonts/trebuchet.xnb index 502e5352..83a8e9a4 100644 Binary files a/TSOClient/tso.content/Content/OGL/Fonts/trebuchet.xnb and b/TSOClient/tso.content/Content/OGL/Fonts/trebuchet.xnb differ diff --git a/TSOClient/tso.content/Content/Textures/skycolfinal.png b/TSOClient/tso.content/Content/Textures/skycolfinal.png new file mode 100644 index 00000000..119f6aa1 Binary files /dev/null and b/TSOClient/tso.content/Content/Textures/skycolfinal.png differ diff --git a/TSOClient/tso.content/ContentSrc/Effects/LightingCommon.fx b/TSOClient/tso.content/ContentSrc/Effects/LightingCommon.fx index 96f0d259..25798772 100644 --- a/TSOClient/tso.content/ContentSrc/Effects/LightingCommon.fx +++ b/TSOClient/tso.content/ContentSrc/Effects/LightingCommon.fx @@ -35,14 +35,14 @@ float4 lightColorFloor(float4 intensities) { float avg = (intensities.r + intensities.g + intensities.b) / 3; //floor shadow is how much less than average the alpha component is - float fshad = intensities.a / avg; + float fshad = intensities.a / max(0.0001, avg); return lerp(OutsideDark, float4(intensities.rgb * LightingAdjust, 1), (fshad - MinAvg.x) * MinAvg.y); } float4 lightColorIAvg(float4 intensities, float i, float avg) { - float fshad = intensities.a / avg; + float fshad = intensities.a / max(0.0001, avg); fshad = lerp(fshad, 1, i); return lerp(OutsideDark, float4(intensities.rgb * LightingAdjust, 1), (fshad - MinAvg.x) * MinAvg.y); @@ -53,7 +53,7 @@ float4 lightColorI(float4 intensities, float i) { float avg = (intensities.r + intensities.g + intensities.b) / 3; //floor shadow is how much less than average the alpha component is - float fshad = intensities.a / avg; + float fshad = intensities.a / max(0.0001, avg); fshad = lerp(fshad, 1, i); return lerp(OutsideDark, float4(intensities.rgb * LightingAdjust, 1), (fshad - MinAvg.x) * MinAvg.y); diff --git a/TSOClient/tso.content/ContentSrc/test.png b/TSOClient/tso.content/ContentSrc/test.png index b8e94727..398fdd1d 100644 Binary files a/TSOClient/tso.content/ContentSrc/test.png and b/TSOClient/tso.content/ContentSrc/test.png differ diff --git a/TSOClient/tso.simantics/Primitives/VMBurn.cs b/TSOClient/tso.simantics/Primitives/VMBurn.cs index cd0157e4..d1eba2ef 100644 --- a/TSOClient/tso.simantics/Primitives/VMBurn.cs +++ b/TSOClient/tso.simantics/Primitives/VMBurn.cs @@ -14,10 +14,12 @@ namespace FSO.SimAntics.Primitives public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMBurnOperand)args; - if (!context.VM.TS1 && (context.VM.Tuning.GetTuning("special", 0, 0) != 1f || context.VM.TSOState.CommunityLot)) + if (!context.VM.TS1 && (context.VM.Tuning.GetTuning("special", 0, 0) != 1f)) return VMPrimitiveExitCode.GOTO_FALSE; //fire disabled for now - if ((int)context.VM.Context.NextRandom(10000) >= context.VM.Context.Clock.FirePercent) + bool isSpread = operand.Type != VMBurnType.StackObject; + + if (isSpread && (int)context.VM.Context.NextRandom(10000) >= context.VM.Context.Clock.FirePercent) { return VMPrimitiveExitCode.GOTO_FALSE; } @@ -26,7 +28,7 @@ namespace FSO.SimAntics.Primitives if (context.VM.Context.RoomInfo[myRoom].Room.IsPool) return VMPrimitiveExitCode.GOTO_FALSE; //as fires burn, the chance they can spread lowers dramatically. - context.VM.Context.Clock.FirePercent -= 500; // lower by 5% every spread. 40 spreads reaches 0. + if (isSpread) context.VM.Context.Clock.FirePercent -= 500; // lower by 5% every spread. 40 spreads reaches 0. if (context.VM.Context.Clock.FirePercent < 0) context.VM.Context.Clock.FirePercent = 0; //begin the burn setup. diff --git a/TSOClient/tso.simantics/VMClock.cs b/TSOClient/tso.simantics/VMClock.cs index 190d1de9..c8b5d974 100644 --- a/TSOClient/tso.simantics/VMClock.cs +++ b/TSOClient/tso.simantics/VMClock.cs @@ -15,7 +15,7 @@ namespace FSO.SimAntics public int Month = 6; public int Year = 1997; - public int FirePercent; + public int FirePercent = 20000; public long UTCStart = DateTime.UtcNow.Ticks; public int TimeOfDay diff --git a/TSOClient/tso.world/Components/AbstractSkyDome.cs b/TSOClient/tso.world/Components/AbstractSkyDome.cs index 0f07ac7b..7d86a4d1 100644 --- a/TSOClient/tso.world/Components/AbstractSkyDome.cs +++ b/TSOClient/tso.world/Components/AbstractSkyDome.cs @@ -1,5 +1,6 @@ using FSO.Common; using FSO.Common.Model; +using FSO.Common.Rendering; using FSO.Common.Utils; using FSO.Files; using FSO.LotView.Model; @@ -14,6 +15,7 @@ namespace FSO.LotView.Components public class AbstractSkyDome : IDisposable { private static string DefaultSkyCol = "Textures/skycol.png"; + private static string FinalSkyCol = "Textures/skycolfinal.png"; private VertexBuffer Verts; private IndexBuffer Indices; @@ -24,6 +26,8 @@ namespace FSO.LotView.Components private VertexPositionTexture[] VertexData; private int[] IndexData; + private bool IsFinal; + public AbstractSkyDome(GraphicsDevice GD, float time) { float? customSky = DynamicTuning.Global?.GetTuning("city", 0, 2); @@ -33,10 +37,27 @@ namespace FSO.LotView.Components TryLoadSkyColor(GD, DefaultSkyCol); } + LoadFinalIfNeeded(GD); + InitArrays(); BuildSkyDome(GD, time); } + public void LoadFinalIfNeeded(GraphicsDevice GD) + { + bool needsFinal = FinaleUtils.IsFinale(); + + if (!IsFinal && needsFinal) + { + using (var file = File.OpenRead(Path.Combine(FSOEnvironment.ContentDir, FinalSkyCol))) + { + GradTex = ImageLoader.FromStream(GD, file); + }; + + IsFinal = true; + } + } + private bool TryLoadSkyColor(GraphicsDevice GD, string path) { try @@ -111,6 +132,8 @@ namespace FSO.LotView.Components public void BuildSkyDome(GraphicsDevice GD, float time) { + LoadFinalIfNeeded(GD); + //generate sky dome geometry var subdivs = 65; VertexPositionTexture[] verts = VertexData; @@ -224,7 +247,7 @@ namespace FSO.LotView.Components } gd.BlendState = BlendState.NonPremultiplied; - var night = Night(time); + var night = Night((float)FinaleUtils.BiasSunTime(time)); //draw the sun or moon var pos = sunVector; var z = -pos.X; @@ -241,7 +264,7 @@ namespace FSO.LotView.Components effect.VertexColorEnabled = false; effect.TextureEnabled = true; effect.Texture = (night) ? TextureGenerator.GetMoon(gd) : TextureGenerator.GetSun(gd); - effect.DiffuseColor = new Vector3(color.X, color.Y, color.Z) * ((night) ? 2f : 0.6f); + effect.DiffuseColor = FinaleUtils.BiasSunIntensity(new Vector3(color.X, color.Y, color.Z) * ((night) ? 2f : 0.6f), time); gd.BlendState = (night) ? BlendState.NonPremultiplied : BlendState.Additive; foreach (var pass in effect.CurrentTechnique.Passes) diff --git a/TSOClient/tso.world/LMap/LMapBatch.cs b/TSOClient/tso.world/LMap/LMapBatch.cs index 4b6fbae1..08881a93 100644 --- a/TSOClient/tso.world/LMap/LMapBatch.cs +++ b/TSOClient/tso.world/LMap/LMapBatch.cs @@ -1,4 +1,5 @@ using FSO.Common; +using FSO.Common.Rendering; using FSO.Common.Utils; using FSO.LotView.Components; using FSO.LotView.Effects; @@ -375,6 +376,8 @@ namespace FSO.LotView.LMap DayOffset = 0.25f; DayDuration = 0.60f; + tod = FinaleUtils.BiasSunTime(tod); + bool night = false; double modTime; var offStart = 1 - (DayOffset + DayDuration); diff --git a/TSOClient/tso.world/Model/WeatherController.cs b/TSOClient/tso.world/Model/WeatherController.cs index 9aca056f..bfb2e77d 100644 --- a/TSOClient/tso.world/Model/WeatherController.cs +++ b/TSOClient/tso.world/Model/WeatherController.cs @@ -1,4 +1,5 @@ -using FSO.LotView.Components; +using FSO.Common.Rendering; +using FSO.LotView.Components; using Microsoft.Xna.Framework; using System; using System.Collections.Generic; @@ -88,7 +89,7 @@ namespace FSO.LotView.Model ParticleType ptype; - if (IsManual) + if (IsManual && !FinaleUtils.IsFinale()) { if (WeatherData == LastWeatherData && enabled == LastEnabled) return; LastWeatherData = WeatherData; @@ -167,6 +168,11 @@ namespace FSO.LotView.Model private int GetAutoWeatherIntensity(DateTime time) { + if (FinaleUtils.IsFinale()) + { + return 0; + } + var distance = time - new DateTime(2019, 1, 26); var halfDay = (int)distance.TotalHours; diff --git a/TSOClient/tso.world/Platform/WorldPlatform3D.cs b/TSOClient/tso.world/Platform/WorldPlatform3D.cs index c7a8036e..7eea1b3a 100644 --- a/TSOClient/tso.world/Platform/WorldPlatform3D.cs +++ b/TSOClient/tso.world/Platform/WorldPlatform3D.cs @@ -275,7 +275,7 @@ namespace FSO.LotView.Platform obj.OnRotationChanged(state); obj.OnZoomChanged(state); obj.Container = null; - obj.Position = tilePosition; + obj.UnmoddedPosition = tilePosition; obj.Draw(gd, state); var mat = obj.World * vp;