From f6d21c5e081819885ac85d01e889b8f2150dd61b Mon Sep 17 00:00:00 2001 From: bobfishkins23 Date: Fri, 19 Dec 2025 20:41:02 -0500 Subject: [PATCH 01/13] Water shader rework start --- .../SquidBoss/Misc.AuroraWaterMetaballs.cs | 30 +++++---- Content/Bosses/SquidBoss/NPCs.ArenaActor.cs | 6 +- Content/Bosses/SquidBoss/NPCs.IcePlatform.cs | 2 +- .../SquidBoss/NPCs.SquidBoss.Attacks.cs | 2 +- Content/Bosses/SquidBoss/NPCs.SquidBoss.cs | 4 +- Content/CustomHooks/Mechanics.PassiveLight.cs | 10 +++ .../Visuals.DrawUnderCathedralWater.cs | 6 +- .../AuroraWaterSystem/AuroraWaterSystem.cs | 33 ++++++++- Effects/Source/Waves.fx | 67 +++++++++++++++++-- 9 files changed, 129 insertions(+), 31 deletions(-) diff --git a/Content/Bosses/SquidBoss/Misc.AuroraWaterMetaballs.cs b/Content/Bosses/SquidBoss/Misc.AuroraWaterMetaballs.cs index 438e6cbdb..23287c9d1 100644 --- a/Content/Bosses/SquidBoss/Misc.AuroraWaterMetaballs.cs +++ b/Content/Bosses/SquidBoss/Misc.AuroraWaterMetaballs.cs @@ -12,19 +12,13 @@ internal class AuroraWaterMetaballs : MetaballActor { public override bool Active => Main.LocalPlayer.InModBiome(ModContent.GetInstance()); - public override Color OutlineColor => new(255, 254, 255); + public override Color OutlineColor => new(255, 0, 0); public override void DrawShapes(SpriteBatch spriteBatch) { Texture2D tex = Assets.Items.Misc.MagmaGunProj.Value; - for (int k = 0; k < Main.maxNPCs; k++) - { - NPC NPC = Main.npc[k]; - - if (NPC.active && NPC.ModNPC is ArenaActor) - (NPC.ModNPC as ArenaActor).DrawWater(Main.spriteBatch); - } + ArenaActor.latestActor?.DrawWater(Main.spriteBatch); Effect borderNoise = ShaderLoader.GetShader("BorderNoise").Value; @@ -41,7 +35,7 @@ public override void DrawShapes(SpriteBatch spriteBatch) if (dust.active && (dust.type == ModContent.DustType() || dust.type == ModContent.DustType())) { borderNoise.Parameters["offset"].SetValue((float)Main.time / 1000f + dust.rotation); - spriteBatch.Draw(tex, (dust.position - Main.screenPosition) / 2, null, new Color(0.4f, 1, 1), 0f, Vector2.One * 256f, dust.scale * 0.05f, SpriteEffects.None, 0); + spriteBatch.Draw(tex, (dust.position - Main.screenPosition) / 2, null, new Color(0, 255, 0), 0f, Vector2.One * 256f, dust.scale * 0.05f, SpriteEffects.None, 0); } } @@ -50,7 +44,7 @@ public override void DrawShapes(SpriteBatch spriteBatch) Texture2D tex2 = Assets.Bosses.SquidBoss.AuroraWaterSplash.Value; var frame = new Rectangle(0, (int)(6 - proj.timeLeft / 40f * 6) * 106, 72, 106); - spriteBatch.Draw(tex2, (proj.Center - Main.screenPosition) / 2f, frame, new Color(0.4f, 1, 1), 0, new Vector2(36, 53), 0.5f, 0, 0); + spriteBatch.Draw(tex2, (proj.Center - Main.screenPosition) / 2f, frame, new Color(0, 255, 0), 0, new Vector2(36, 53), 0.5f, 0, 0); } spriteBatch.End(); @@ -87,6 +81,9 @@ public override bool PostDraw(SpriteBatch spriteBatch, Texture2D target) if (effect != null) { + Main.spriteBatch.End(); + Main.graphics.GraphicsDevice.SetRenderTarget(Main.screenTargetSwap); + effect.Parameters["uTime"].SetValue((float)Main.timeForVisualEffects * 0.02f); effect.Parameters["power"].SetValue(0.01f); effect.Parameters["offset"].SetValue(new Vector2(Main.screenPosition.X / Main.screenWidth * -0.5f, Main.screenPosition.Y / Main.screenHeight * -0.5f)); @@ -94,14 +91,19 @@ public override bool PostDraw(SpriteBatch spriteBatch, Texture2D target) effect.Parameters["uImageSize1"].SetValue(new Vector2(Main.screenWidth, Main.screenHeight)); effect.Parameters["speed"].SetValue(50f); effect.Parameters["lightTexture"].SetValue(LightingBuffer.screenLightingTarget.RenderTarget); + effect.Parameters["gameTexture"].SetValue(Main.screenTarget); + effect.Parameters["transform"].SetValue(Main.GameViewMatrix.TransformationMatrix); - Main.spriteBatch.End(); - Main.spriteBatch.Begin(default, default, SamplerState.PointClamp, default, Main.Rasterizer, effect, Main.GameViewMatrix.TransformationMatrix); + Main.spriteBatch.Begin(default, default, SamplerState.PointClamp, default, Main.Rasterizer, effect, Matrix.Identity); - Main.spriteBatch.Draw(target, Vector2.Zero, null, Color.Red * 0.4f, 0, Vector2.Zero, 2, 0, 0); + Main.spriteBatch.Draw(target, Vector2.Zero, null, Color.White, 0, Vector2.Zero, 2, 0, 0); Main.spriteBatch.End(); - Main.spriteBatch.Begin(default, default, SamplerState.PointClamp, default, Main.Rasterizer, default, Main.GameViewMatrix.TransformationMatrix); + + Main.graphics.GraphicsDevice.SetRenderTarget(Main.screenTarget); + + Main.spriteBatch.Begin(default, default, SamplerState.PointClamp, default, Main.Rasterizer, default, Matrix.Identity); + Main.spriteBatch.Draw(Main.screenTargetSwap, Vector2.Zero, null, Color.White, 0, Vector2.Zero, 1, 0, 0); } return false; diff --git a/Content/Bosses/SquidBoss/NPCs.ArenaActor.cs b/Content/Bosses/SquidBoss/NPCs.ArenaActor.cs index 17e427350..306a69317 100644 --- a/Content/Bosses/SquidBoss/NPCs.ArenaActor.cs +++ b/Content/Bosses/SquidBoss/NPCs.ArenaActor.cs @@ -27,6 +27,8 @@ class ArenaActor : ModNPC private static VertexPositionColorTexture[] verticies; private static VertexBuffer buffer; + public static ArenaActor latestActor; + public ref float WaterLevel => ref NPC.ai[0]; public ref float VisualTimerA => ref NPC.ai[1]; public ref float VisualTimerB => ref NPC.ai[2]; @@ -106,6 +108,8 @@ private void DoParticleUpdates() public override void AI() { + latestActor = this; + VisualTimerA += 0.04f; //used as timers for visuals VisualTimerB += 0.01f; @@ -316,7 +320,7 @@ public void DrawWater(SpriteBatch spriteBatch) Vector2 pos = NPC.Center + new Vector2(-840, 30 * 16) + new Vector2(0, -tex.Height) - Main.screenPosition; var source = new Rectangle(0, tex.Height - (int)WaterLevel + 5 * 16, tex.Width, (int)WaterLevel - 5 * 16); - spriteBatch.Draw(tex, (pos + source.TopLeft()) * 0.5f, source, new Color(0.4f, 1, 1), 0, default, 0.5f, 0, 0); + spriteBatch.Draw(tex, (pos + source.TopLeft()) * 0.5f, source, new Color(0, 255, 0), 0, default, 0.5f, 0, 0); DrawWaterfalls(spriteBatch); } diff --git a/Content/Bosses/SquidBoss/NPCs.IcePlatform.cs b/Content/Bosses/SquidBoss/NPCs.IcePlatform.cs index 60ef2c05e..9beacb0f8 100644 --- a/Content/Bosses/SquidBoss/NPCs.IcePlatform.cs +++ b/Content/Bosses/SquidBoss/NPCs.IcePlatform.cs @@ -47,7 +47,7 @@ public override void SafeAI() if (Main.npc.Any(n => n.active && n.type == ModContent.NPCType())) { - var actor = Main.npc.FirstOrDefault(n => n.active && n.type == ModContent.NPCType()).ModNPC as ArenaActor; + var actor = ArenaActor.latestActor; if (NPC.position.Y >= HomeYPosition) { diff --git a/Content/Bosses/SquidBoss/NPCs.SquidBoss.Attacks.cs b/Content/Bosses/SquidBoss/NPCs.SquidBoss.Attacks.cs index 1d6700030..9e9317e63 100644 --- a/Content/Bosses/SquidBoss/NPCs.SquidBoss.Attacks.cs +++ b/Content/Bosses/SquidBoss/NPCs.SquidBoss.Attacks.cs @@ -1052,7 +1052,7 @@ private void TentacleSpike2() { RandomizeTarget(); - tentacles[k].Center = new Vector2(Main.npc.FirstOrDefault(n => n.active && n.ModNPC is ArenaActor).Center.X + (k % 2 == 0 ? -500 : 500), NPC.Center.Y + Main.rand.Next(-200, 200)); + tentacles[k].Center = new Vector2(ArenaActor.latestActor.NPC.Center.X + (k % 2 == 0 ? -500 : 500), NPC.Center.Y + Main.rand.Next(-200, 200)); tentacle.basePoint = tentacles[k].Center; tentacle.movementTarget = Main.player[NPC.target].Center; diff --git a/Content/Bosses/SquidBoss/NPCs.SquidBoss.cs b/Content/Bosses/SquidBoss/NPCs.SquidBoss.cs index 972c28c5a..cc9da770c 100644 --- a/Content/Bosses/SquidBoss/NPCs.SquidBoss.cs +++ b/Content/Bosses/SquidBoss/NPCs.SquidBoss.cs @@ -483,7 +483,7 @@ public override void AI() Animate(12, 0, 8); if (arenaActor is null || !arenaActor.active) - arenaActor = Main.npc.FirstOrDefault(n => n.active && n.ModNPC is ArenaActor); + arenaActor = ArenaActor.latestActor.NPC; if (Phase > (int)AIStates.SpawnAnimation) FindEssentialNPCs(); @@ -840,7 +840,7 @@ public override void AI() GlobalTimer++; if (GlobalTimer % 6 == 0) - Main.npc.FirstOrDefault(n => n.active && n.ModNPC is ArenaActor).ai[0]++; //rising water + ArenaActor.latestActor.WaterLevel++; //rising water AttackTimer++; diff --git a/Content/CustomHooks/Mechanics.PassiveLight.cs b/Content/CustomHooks/Mechanics.PassiveLight.cs index 06546fe3e..3fc1955aa 100644 --- a/Content/CustomHooks/Mechanics.PassiveLight.cs +++ b/Content/CustomHooks/Mechanics.PassiveLight.cs @@ -1,4 +1,5 @@ using StarlightRiver.Content.Biomes; +using StarlightRiver.Content.Bosses.SquidBoss; using StarlightRiver.Content.Events; using System.Collections.Generic; using Terraria.ID; @@ -93,6 +94,15 @@ public override void PostUpdateEverything() squidDomeRect.Y += 35; squidDomeRect.Height = 76; } + + if (ArenaActor.latestActor?.WaterLevel > 1100) + { + squidDomeRect.Height = (int)(76 - (ArenaActor.latestActor.WaterLevel - 1100) / 16); + } + else + { + squidDomeRect.Height = 76; + } } } } \ No newline at end of file diff --git a/Content/CustomHooks/Visuals.DrawUnderCathedralWater.cs b/Content/CustomHooks/Visuals.DrawUnderCathedralWater.cs index 88618e862..df34649ad 100644 --- a/Content/CustomHooks/Visuals.DrawUnderCathedralWater.cs +++ b/Content/CustomHooks/Visuals.DrawUnderCathedralWater.cs @@ -43,12 +43,12 @@ public static void DrawWater() Main.spriteBatch.End(); Main.spriteBatch.Begin(default, default, SamplerState.PointClamp, default, Main.Rasterizer, default, Main.GameViewMatrix.TransformationMatrix); - NPC NPC = Main.npc.FirstOrDefault(n => n.active && n.ModNPC is ArenaActor); + NPC npc = ArenaActor.latestActor?.NPC; - if (NPC != null && NPC.active) + if (npc != null && npc.active) { if (ReflectionTarget.canUseTarget || !ModContent.GetInstance().ReflectionConfig.ReflectionsOn) - (NPC.ModNPC as ArenaActor).DrawBigWindow(Main.spriteBatch); + (npc.ModNPC as ArenaActor).DrawBigWindow(Main.spriteBatch); int boss = -1; var drawCache = new List(); diff --git a/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs b/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs index 98ce5d897..852e59edb 100644 --- a/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs +++ b/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs @@ -115,6 +115,7 @@ private static void DrawAuroraTarget(SpriteBatch sb) private static void DrawAuroraBackTarget(SpriteBatch sb) { Asset asset = Assets.Misc.AuroraWaterMap; + Asset asset2 = Assets.Noise.SwirlyNoiseLooping; if (asset.IsLoaded) { @@ -124,6 +125,8 @@ private static void DrawAuroraBackTarget(SpriteBatch sb) Main.graphics.GraphicsDevice.Clear(Color.Transparent); Texture2D tex = asset.Value; + Texture2D tex2 = asset2.Value; + Texture2D tex3 = Assets.GradientV.Value; Vector2 layer1Pivot = Main.GameUpdateCount * new Vector2(-0.55f, 0.3f); Vector2 layer2Pivot = Main.GameUpdateCount * new Vector2(0.75f, -0.4f); @@ -134,7 +137,7 @@ private static void DrawAuroraBackTarget(SpriteBatch sb) (int)(Main.screenPosition.Y + layer1Pivot.Y) % tex.Height, Main.screenWidth, Main.screenHeight), - Color.White * 0.7f); + Color.Red * 0.7f); sb.Draw(tex, Vector2.Zero, new Rectangle( @@ -142,7 +145,33 @@ private static void DrawAuroraBackTarget(SpriteBatch sb) (int)(Main.screenPosition.Y + layer2Pivot.Y) % tex.Height, Main.screenWidth, Main.screenHeight), - Color.White); + Color.Red); + + sb.Draw(tex2, + Vector2.Zero, + new Rectangle( + (int)(Main.screenPosition.X + layer1Pivot.X) % tex2.Width, + (int)(Main.screenPosition.Y + layer1Pivot.Y) % tex2.Height, + Main.screenWidth, + Main.screenHeight), + Color.Green * 0.7f); + sb.Draw(tex2, + Vector2.Zero, + new Rectangle( + (int)(Main.screenPosition.X + layer2Pivot.X) % tex2.Width, + (int)(Main.screenPosition.Y + layer2Pivot.Y) % tex2.Height, + Main.screenWidth, + Main.screenHeight), + Color.Green); + + sb.Draw(tex3, + Vector2.Zero, + new Rectangle( + (int)(Main.screenPosition.X) % tex3.Width, + (int)(Main.screenPosition.Y) % tex3.Height, + Main.screenWidth, + Main.screenHeight), + Color.Blue); sb.End(); sb.Begin(); diff --git a/Effects/Source/Waves.fx b/Effects/Source/Waves.fx index 78d83a2bd..e15ebbb74 100644 --- a/Effects/Source/Waves.fx +++ b/Effects/Source/Waves.fx @@ -15,6 +15,7 @@ float2 uImageSize0; float2 uImageSize1; float power; float speed; +float4x4 transform; texture sampleTexture; sampler2D samplerTex = sampler_state { texture = ; magfilter = LINEAR; minfilter = LINEAR; mipfilter = LINEAR; AddressU = wrap; AddressV = wrap; }; @@ -22,22 +23,74 @@ sampler2D samplerTex = sampler_state { texture = ; magfilter = LI texture lightTexture; sampler2D lightTex = sampler_state { texture = ; magfilter = LINEAR; minfilter = LINEAR; mipfilter = LINEAR; AddressU = wrap; AddressV = wrap; }; +texture gameTexture; +sampler2D gameTex = sampler_state { texture = ; magfilter = LINEAR; minfilter = LINEAR; mipfilter = LINEAR; AddressU = clamp; AddressV = clamp; }; + float2 offset; -float4 PixelShaderFunction(float2 coords : TEXCOORD0) : COLOR0 +struct VertexShaderInput +{ + float4 Position : POSITION0; + float2 TexCoords : TEXCOORD0; + float4 Color : COLOR0; +}; + +struct VertexShaderOutput +{ + float4 Position : SV_POSITION; + float2 TexCoords : TEXCOORD0; + float4 Color : COLOR0; +}; + +VertexShaderOutput VertexShaderFunction(VertexShaderInput input) { - float4 color = tex2D(uImage0, coords).a * tex2D(uImage0, coords).r * tex2D(lightTex, coords * 2.0); - float map = tex2D(samplerTex, coords * 2).r; - float map2 = map * map * map; - float bright = min((color.r + color.g + color.b) * 2.5, 0.005); + VertexShaderOutput output; + + output.Color = input.Color; + output.TexCoords = input.TexCoords; + output.Position = mul(input.Position, transform); + + return output; +} + +float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0 +{ + float2 coords = input.TexCoords; + float2 pixCoord = coords - coords % (1.0 / uImageSize1) + float2(1.0 / uImageSize1); + + float4 mapSample = tex2D(samplerTex, coords * 2.0); + float swirl = sin((mapSample.g + uTime * 0.3) * 6.28); + + float4 light = tex2D(lightTex, coords * 2.0); + + float2 underCoord = coords * 2.0 + (swirl) * 0.005 * tex2D(uImage0, coords).a; + float2 pixUnderCoord = underCoord - underCoord % (2.0 / uImageSize1); + + float4 distortLight = tex2D(lightTex, pixUnderCoord); + float shapeMask = tex2D(uImage0, coords).a; + + float lum = ((light.r + light.g + light.b) / 3.0); + + float caustics = tex2D(samplerTex, pixUnderCoord).r; + caustics = max(0.0, caustics - 0.1); + float speculars = tex2D(uImage0, pixCoord).g * 0.4 * (caustics + pow(caustics, 3.0) * 1.2 * lum); + speculars += tex2D(uImage0, coords).r * (0.5 + light * 0.5); + + float bright = pow(speculars, 6.0) * 200.0 * pow(lum, 2.0); + float4 color = distortLight * (pow(speculars, 2.0) * 3.0 + bright); + color.a = shapeMask; + + float4 underColor = tex2D(gameTex, underCoord); + underColor += distortLight * distortLight * shapeMask * abs(swirl); - return float4(color.xyz * map * 3.0, color.a * map); + return underColor + color; } technique Technique1 { pass Pass1 { - PixelShader = compile ps_2_0 PixelShaderFunction(); + //VertexShader = compile vs_2_0 VertexShaderFunction(); + PixelShader = compile ps_3_0 PixelShaderFunction(); } } \ No newline at end of file From cf32188d7ace738f25084f42d5c4be61447b071a Mon Sep 17 00:00:00 2001 From: bobfishkins23 Date: Fri, 19 Dec 2025 21:11:55 -0500 Subject: [PATCH 02/13] Scaling fix --- .../SquidBoss/Misc.AuroraWaterMetaballs.cs | 10 ++-- Effects/Source/Waves.fx | 50 +++---------------- 2 files changed, 13 insertions(+), 47 deletions(-) diff --git a/Content/Bosses/SquidBoss/Misc.AuroraWaterMetaballs.cs b/Content/Bosses/SquidBoss/Misc.AuroraWaterMetaballs.cs index 23287c9d1..4e81f3f0d 100644 --- a/Content/Bosses/SquidBoss/Misc.AuroraWaterMetaballs.cs +++ b/Content/Bosses/SquidBoss/Misc.AuroraWaterMetaballs.cs @@ -85,16 +85,16 @@ public override bool PostDraw(SpriteBatch spriteBatch, Texture2D target) Main.graphics.GraphicsDevice.SetRenderTarget(Main.screenTargetSwap); effect.Parameters["uTime"].SetValue((float)Main.timeForVisualEffects * 0.02f); - effect.Parameters["power"].SetValue(0.01f); effect.Parameters["offset"].SetValue(new Vector2(Main.screenPosition.X / Main.screenWidth * -0.5f, Main.screenPosition.Y / Main.screenHeight * -0.5f)); effect.Parameters["sampleTexture"].SetValue(AuroraWaterSystem.auroraBackTarget.RenderTarget); effect.Parameters["uImageSize1"].SetValue(new Vector2(Main.screenWidth, Main.screenHeight)); - effect.Parameters["speed"].SetValue(50f); effect.Parameters["lightTexture"].SetValue(LightingBuffer.screenLightingTarget.RenderTarget); effect.Parameters["gameTexture"].SetValue(Main.screenTarget); - effect.Parameters["transform"].SetValue(Main.GameViewMatrix.TransformationMatrix); + effect.Parameters["transform"].SetValue(Matrix.Invert(Main.GameViewMatrix.TransformationMatrix)); + + var inv = Matrix.Invert(Main.GameViewMatrix.TransformationMatrix); - Main.spriteBatch.Begin(default, default, SamplerState.PointClamp, default, Main.Rasterizer, effect, Matrix.Identity); + Main.spriteBatch.Begin(default, default, SamplerState.PointClamp, default, RasterizerState.CullNone, effect, Matrix.Identity); Main.spriteBatch.Draw(target, Vector2.Zero, null, Color.White, 0, Vector2.Zero, 2, 0, 0); @@ -102,7 +102,7 @@ public override bool PostDraw(SpriteBatch spriteBatch, Texture2D target) Main.graphics.GraphicsDevice.SetRenderTarget(Main.screenTarget); - Main.spriteBatch.Begin(default, default, SamplerState.PointClamp, default, Main.Rasterizer, default, Matrix.Identity); + Main.spriteBatch.Begin(default, default, SamplerState.PointClamp, default, RasterizerState.CullNone, default, Matrix.Identity); Main.spriteBatch.Draw(Main.screenTargetSwap, Vector2.Zero, null, Color.White, 0, Vector2.Zero, 1, 0, 0); } diff --git a/Effects/Source/Waves.fx b/Effects/Source/Waves.fx index e15ebbb74..f7c233dda 100644 --- a/Effects/Source/Waves.fx +++ b/Effects/Source/Waves.fx @@ -1,20 +1,7 @@ sampler uImage0 : register(s0); -sampler uImage1 : register(s1); -sampler uImage2 : register(s2); -float3 uColor; -float3 uSecondaryColor; -float uOpacity; -float uSaturation; -float uRotation; float uTime; -float4 uSourceRect; -float2 uWorldPosition; -float uDirection; -float3 uLightSource; float2 uImageSize0; float2 uImageSize1; -float power; -float speed; float4x4 transform; texture sampleTexture; @@ -28,34 +15,13 @@ sampler2D gameTex = sampler_state { texture = ; magfilter = LINEAR; float2 offset; -struct VertexShaderInput -{ - float4 Position : POSITION0; - float2 TexCoords : TEXCOORD0; - float4 Color : COLOR0; -}; - -struct VertexShaderOutput -{ - float4 Position : SV_POSITION; - float2 TexCoords : TEXCOORD0; - float4 Color : COLOR0; -}; - -VertexShaderOutput VertexShaderFunction(VertexShaderInput input) -{ - VertexShaderOutput output; - - output.Color = input.Color; - output.TexCoords = input.TexCoords; - output.Position = mul(input.Position, transform); - - return output; -} - -float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0 +float4 PixelShaderFunction(float2 coords : TEXCOORD0) : COLOR0 { - float2 coords = input.TexCoords; + float2 originalCoords = coords; + + float2 pixel = coords * uImageSize1 * 2.0; + coords = mul(float4(pixel, 0.0, 1.0), transform).xy / (uImageSize1 * 2.0); + float2 pixCoord = coords - coords % (1.0 / uImageSize1) + float2(1.0 / uImageSize1); float4 mapSample = tex2D(samplerTex, coords * 2.0); @@ -80,7 +46,8 @@ float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0 float4 color = distortLight * (pow(speculars, 2.0) * 3.0 + bright); color.a = shapeMask; - float4 underColor = tex2D(gameTex, underCoord); + float2 originalUnderCoord = originalCoords * 2.0 + (swirl) * 0.005 * tex2D(uImage0, coords).a; + float4 underColor = tex2D(gameTex, originalUnderCoord); underColor += distortLight * distortLight * shapeMask * abs(swirl); return underColor + color; @@ -90,7 +57,6 @@ technique Technique1 { pass Pass1 { - //VertexShader = compile vs_2_0 VertexShaderFunction(); PixelShader = compile ps_3_0 PixelShaderFunction(); } } \ No newline at end of file From c5acc55921e58557ff4c4c369696f46a92256a29 Mon Sep 17 00:00:00 2001 From: bobfishkins23 Date: Fri, 19 Dec 2025 21:17:10 -0500 Subject: [PATCH 03/13] Final update --- Effects/Source/Waves.fx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Effects/Source/Waves.fx b/Effects/Source/Waves.fx index f7c233dda..803b54cc6 100644 --- a/Effects/Source/Waves.fx +++ b/Effects/Source/Waves.fx @@ -48,7 +48,7 @@ float4 PixelShaderFunction(float2 coords : TEXCOORD0) : COLOR0 float2 originalUnderCoord = originalCoords * 2.0 + (swirl) * 0.005 * tex2D(uImage0, coords).a; float4 underColor = tex2D(gameTex, originalUnderCoord); - underColor += distortLight * distortLight * shapeMask * abs(swirl); + underColor += shapeMask * distortLight * distortLight * (1.0 - abs(swirl)); return underColor + color; } From 8cc87a03a7a1b052b7cfde26bce900af791b1e19 Mon Sep 17 00:00:00 2001 From: bobfishkins23 Date: Sat, 20 Dec 2025 11:54:40 -0500 Subject: [PATCH 04/13] Floating water --- Assets/Misc/AuroraWater.png | Bin 615 -> 385 bytes Content/NPCs/Permafrost/WaterCube.cs | 2 +- .../AuroraWaterSystem/AuroraWaterSystem.cs | 50 +++++++++++- Effects/Source/AuroraWaterShader.fx | 71 ++++++++++++++---- 4 files changed, 104 insertions(+), 19 deletions(-) diff --git a/Assets/Misc/AuroraWater.png b/Assets/Misc/AuroraWater.png index 7c26549d84d2d95a2b2b993283251a3ce4715fb7..8d9e38e7bc672af3f9c26798e2fd22fcf358b132 100644 GIT binary patch delta 359 zcmV-t0hs>h1c3vPBYy!%NklfGa2T}-c4 z5Q@!ewYBT{#Y*J+yt-bL$a49Wz7oDty(_b)R(ueO5&Da{TgH!|7~y;|NlI}PBODi# ztQ1Evf-WX$DUM=Nm0WX5AhzGm4Sg!BCEw zQH-Pqle`>?5sn9wv>b{N&JQM8ITRy|zdmNRW3&y$2yZY2NS$tnJ6Qk#002ovPDHLk FV1gZ{tH%HU delta 591 zcmV-V0Px%AxT6*RCr$Po6(koFbG8T|3A9>Q1!GZ z3j>oAEA&+*(%{HJD0`~heq8Sosje=Y9|b4A8?Np>VTYp zj5uoVHi~I5BD6A+t(Xl^gE5q{UoNj0tr(UCW33JiMrl~efq$`-Qnto480YGvwf<#N z$*Ytyse}R<4TiNjMd!6=z_E!$4U_@HiqKQ+gpVDb0^pxT<$WoeO8WpTJF~&lYRqH7 zL?@O#d1DoEmLDJfe2W%M1(rkEMv>)*3I;W5ejEKfrojx4+1vr>ikUkd-sme!`cXThYE0Unr~%e$^cXO#Z{4Kmv!JujpZq}; z(_jQb4M?`*)lw-NF!cGbVj2vnl(LGklu{0i7f6FKnt#f4u@iriK3t0Q;48Z|IKB+mUbUi@*RZfFx#at5@-Kl0z1nHfxx6^Gf2B~ahytT_4F!p`ZKO90E dNj3n@-XCyDz#hY@)t&$V002ovPDHLkV1hSk4ub#y diff --git a/Content/NPCs/Permafrost/WaterCube.cs b/Content/NPCs/Permafrost/WaterCube.cs index f279c183e..bf31196a2 100644 --- a/Content/NPCs/Permafrost/WaterCube.cs +++ b/Content/NPCs/Permafrost/WaterCube.cs @@ -49,7 +49,7 @@ public void DrawToTarget(SpriteBatch spriteBatch) Vector2 pos = (NPC.position - Main.screenPosition) / 2f; var target = new Rectangle((int)pos.X, (int)pos.Y, NPC.width / 2, NPC.height / 2); - spriteBatch.Draw(tex, target, Color.Red); + spriteBatch.Draw(tex, target, Color.Green); } } } \ No newline at end of file diff --git a/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs b/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs index 852e59edb..d303da5ac 100644 --- a/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs +++ b/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs @@ -2,6 +2,7 @@ using StarlightRiver.Content.Dusts; using StarlightRiver.Content.NPCs.Permafrost; using StarlightRiver.Core.Loaders; +using StarlightRiver.Core.Systems.LightingSystem; using StarlightRiver.Core.Systems.MetaballSystem; using StarlightRiver.Core.Systems.ScreenTargetSystem; using System; @@ -320,7 +321,12 @@ class AuroraWaterGlobalTile : GlobalTile public override void NearbyEffects(int i, int j, int type, bool closer) { if (Main.tile[i, j].Get().HasAuroraWater) + { AuroraWaterSystem.visCounter = 30; + + if (i % 2 == 0 && j % 2 == 0 && !Main.tile[i, j].IsSquareSolidTile()) + Lighting.AddLight(new Vector2(i, j) * 16, new Vector3(0.4f, 0.8f, 1f)); + } } } @@ -328,7 +334,7 @@ class AuroraWaterTileMetaballs : MetaballActor { public override bool Active => AuroraWaterSystem.Visible && !Main.LocalPlayer.InModBiome(ModContent.GetInstance()); - public override Color OutlineColor => new(255, 0, 255); + public override Color OutlineColor => new(255, 0, 0); public override void DrawShapes(SpriteBatch spriteBatch) { @@ -348,7 +354,7 @@ public override void DrawShapes(SpriteBatch spriteBatch) foreach (Dust dust in Main.dust) { if (dust.active && dust.type == ModContent.DustType()) - spriteBatch.Draw(tex, (dust.position - Main.screenPosition) / 2, null, Color.Red, 0f, Vector2.One * 256f, dust.scale * 0.05f, SpriteEffects.None, 0); + spriteBatch.Draw(tex, (dust.position - Main.screenPosition) / 2, null, Color.Green, 0f, Vector2.One * 256f, dust.scale * 0.05f, SpriteEffects.None, 0); } spriteBatch.End(); @@ -365,7 +371,7 @@ public static void DrawSpecial() return; } - Effect shader = ShaderLoader.GetShader("AuroraWaterShader").Value; + /*Effect shader = ShaderLoader.GetShader("AuroraWaterShader").Value; if (shader is null) { @@ -386,6 +392,44 @@ public static void DrawSpecial() Main.spriteBatch.End(); Main.spriteBatch.Begin(0, BlendState.AlphaBlend, Main.DefaultSamplerState, DepthStencilState.None, Main.Rasterizer, null, Main.GameViewMatrix.TransformationMatrix); + */ + + Effect effect = ShaderLoader.GetShader("AuroraWaterShader").Value; + + if (effect is null) + { + MetaballSystem.MetaballSystem.actorsSem.Release(); + return; + } + + if (effect != null) + { + Main.spriteBatch.End(); + Main.graphics.GraphicsDevice.SetRenderTarget(Main.screenTargetSwap); + + effect.Parameters["uTime"].SetValue((float)Main.timeForVisualEffects * 0.02f); + effect.Parameters["offset"].SetValue(new Vector2(Main.screenPosition.X / Main.screenWidth * -0.5f, Main.screenPosition.Y / Main.screenHeight * -0.5f)); + effect.Parameters["sampleTexture"].SetValue(AuroraWaterSystem.auroraBackTarget.RenderTarget); + effect.Parameters["uImageSize1"].SetValue(new Vector2(Main.screenWidth, Main.screenHeight)); + //effect.Parameters["lightTexture"].SetValue(LightingBuffer.screenLightingTarget.RenderTarget); + effect.Parameters["gameTexture"].SetValue(Main.screenTarget); + effect.Parameters["transform"].SetValue(Matrix.Invert(Main.GameViewMatrix.TransformationMatrix)); + effect.Parameters["offset"].SetValue(new Vector2(Main.screenPosition.X % Main.screenWidth / Main.screenWidth, Main.screenPosition.Y % Main.screenHeight / Main.screenHeight)); + + var inv = Matrix.Invert(Main.GameViewMatrix.TransformationMatrix); + + Main.spriteBatch.Begin(default, default, SamplerState.PointClamp, default, RasterizerState.CullNone, effect, Matrix.Identity); + + Texture2D target = MetaballSystem.MetaballSystem.actors.FirstOrDefault(n => n is AuroraWaterTileMetaballs).Target.RenderTarget; + Main.spriteBatch.Draw(target, Vector2.Zero, null, Color.White, 0, Vector2.Zero, 2, 0, 0); + + Main.spriteBatch.End(); + + Main.graphics.GraphicsDevice.SetRenderTarget(Main.screenTarget); + + Main.spriteBatch.Begin(default, default, SamplerState.PointClamp, default, RasterizerState.CullNone, default, Matrix.Identity); + Main.spriteBatch.Draw(Main.screenTargetSwap, Vector2.Zero, null, Color.White, 0, Vector2.Zero, 1, 0, 0); + } MetaballSystem.MetaballSystem.actorsSem.Release(); } diff --git a/Effects/Source/AuroraWaterShader.fx b/Effects/Source/AuroraWaterShader.fx index 8b2cc98a1..1b2fa7925 100644 --- a/Effects/Source/AuroraWaterShader.fx +++ b/Effects/Source/AuroraWaterShader.fx @@ -1,8 +1,10 @@ #include "Common.fxh" -float time; -float2 screenSize; -float2 offset; +sampler uImage0 : register(s0); +float uTime; +float2 uImageSize0; +float2 uImageSize1; +float4x4 transform; texture sampleTexture; sampler2D samplerTex = sampler_state { texture = ; magfilter = LINEAR; minfilter = LINEAR; mipfilter = LINEAR; AddressU = wrap; AddressV = wrap; }; @@ -10,24 +12,63 @@ sampler2D samplerTex = sampler_state { texture = ; magfilter = LI texture sampleTexture2; sampler2D samplerTex2 = sampler_state { texture = ; magfilter = LINEAR; minfilter = LINEAR; mipfilter = LINEAR; AddressU = wrap; AddressV = wrap; }; -float4 PixelShaderFunction(float4 screenSpace : TEXCOORD0) : COLOR0 -{ - float2 st = screenSpace.xy; - float2 off = float2(sin(time + st.y * 200.0 + offset.y * 100.0), sin(time + st.x * 200.0 + offset.x * 100.0)) / screenSize; +texture gameTexture; +sampler2D gameTex = sampler_state { texture = ; magfilter = LINEAR; minfilter = LINEAR; mipfilter = LINEAR; AddressU = clamp; AddressV = clamp; }; - float map = tex2D(samplerTex2, st * 2 + off).r; - float4 color = tex2D(samplerTex, st + off); +float2 offset; - float progress = (st.x + st.y) * 10.0; +float4 GetRainbow(float2 coords) +{ + float progress = (coords.x + coords.y) * 10.0; - float r = 40.0 * (1.0 + sin(time + progress * 0.2)); - float g = 46.0 * (1.0 + sin(HALF_PI + time + progress)); + float r = 40.0 * (1.0 + sin(uTime + progress * 0.2)); + float g = 46.0 * (1.0 + sin(HALF_PI + uTime + progress)); float b = 72.0; + + return float4(r, g, b, 0.0) * 0.005; +} - float3 colorB = float3(r, g, b); - float3 color2 = colorB * 0.015 * map * (color.r + color.b * 4.0); +float4 PixelShaderFunction(float4 screenSpace : TEXCOORD0) : COLOR0 +{ + float2 coords = screenSpace.xy; + float2 off = float2(sin(uTime + coords.y * 200.0 + offset.y * 100.0), sin(uTime + coords.x * 200.0 + offset.x * 100.0)) / uImageSize1; + + float2 originalCoords = coords; + + coords += off; + + float2 pixel = coords * uImageSize1 * 2.0; + coords = mul(float4(pixel, 0.0, 1.0), transform).xy / (uImageSize1 * 2.0); + + float2 pixCoord = coords - coords % (1.0 / uImageSize1) + float2(1.0 / uImageSize1); + + float4 mapSample = tex2D(samplerTex, coords * 2.0); + float swirl = sin((mapSample.g + uTime * 0.3) * 6.28); + + float4 light = GetRainbow(coords); + + float2 underCoord = coords * 2.0 + (swirl) * 0.005 * tex2D(uImage0, coords).a; + float2 pixUnderCoord = underCoord - underCoord % (2.0 / uImageSize1); + + float4 distortLight = GetRainbow(pixUnderCoord); + float shapeMask = tex2D(uImage0, coords).a; + + float lum = ((light.r + light.g + light.b) / 3.0); + + float caustics = tex2D(samplerTex, pixUnderCoord).r; + caustics = max(0.0, caustics - 0.1); + float speculars = tex2D(uImage0, pixCoord).g * 0.4 * (caustics + pow(caustics, 3.0) * 1.2 * lum); + speculars += tex2D(uImage0, coords).r * (0.5 + light * 0.5); + + float bright = pow(speculars, 6.0) * 200.0 * pow(lum, 2.0); + float4 color = distortLight * (pow(speculars, 2.0) * 3.0 + bright); + color.a = shapeMask; + + float2 originalUnderCoord = originalCoords * 2.0 + (swirl) * 0.005 * tex2D(uImage0, coords).a; + float4 underColor = tex2D(gameTex, originalUnderCoord); + underColor += shapeMask * distortLight * distortLight * (1.0 - abs(swirl)); - return float4(color2, color.a) * 0.5; + return underColor + color; } technique Technique1 From c5b5ccba0543fe1d7cc29e7ac73f7f42aba12b03 Mon Sep 17 00:00:00 2001 From: bobfishkins23 Date: Sat, 20 Dec 2025 15:01:56 -0500 Subject: [PATCH 05/13] Adjust swimming behavior --- .../Items/Permafrost/Accessories.SquidFins.cs | 2 +- .../AuroraWaterSystem/AuroraWaterSystem.cs | 62 ++++------- Core/Systems/AuroraWaterSystem/SwimPlayer.cs | 102 ++++++++++++++---- 3 files changed, 99 insertions(+), 67 deletions(-) diff --git a/Content/Items/Permafrost/Accessories.SquidFins.cs b/Content/Items/Permafrost/Accessories.SquidFins.cs index c456dfa9e..223856350 100644 --- a/Content/Items/Permafrost/Accessories.SquidFins.cs +++ b/Content/Items/Permafrost/Accessories.SquidFins.cs @@ -28,7 +28,7 @@ public override void SafeUpdateEquip(Player player) { bool canSwim = player.grapCount <= 0 && player.wet && !player.mount.Active; player.GetModPlayer().ShouldSwim = canSwim; - player.GetModPlayer().SwimSpeed = 1.33f + player.moveSpeed * 1.33f; + player.GetModPlayer().SwimSpeed += 3f + player.moveSpeed * 1.33f; } private void DrawSquidFins(ref PlayerDrawSet drawInfo) diff --git a/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs b/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs index d303da5ac..d7c2bfa1f 100644 --- a/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs +++ b/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs @@ -371,29 +371,6 @@ public static void DrawSpecial() return; } - /*Effect shader = ShaderLoader.GetShader("AuroraWaterShader").Value; - - if (shader is null) - { - MetaballSystem.MetaballSystem.actorsSem.Release(); - return; - } - - shader.Parameters["time"].SetValue(StarlightWorld.visualTimer); - shader.Parameters["screenSize"].SetValue(new Vector2(Main.screenWidth, Main.screenHeight)); - shader.Parameters["offset"].SetValue(new Vector2(Main.screenPosition.X % Main.screenWidth / Main.screenWidth, Main.screenPosition.Y % Main.screenHeight / Main.screenHeight)); - shader.Parameters["sampleTexture2"].SetValue(AuroraWaterSystem.auroraBackTarget.RenderTarget); - - Main.spriteBatch.End(); - Main.spriteBatch.Begin(default, BlendState.Additive, Main.DefaultSamplerState, default, Main.Rasterizer, shader, Main.GameViewMatrix.TransformationMatrix); - - Texture2D target = MetaballSystem.MetaballSystem.actors.FirstOrDefault(n => n is AuroraWaterTileMetaballs).Target.RenderTarget; - Main.spriteBatch.Draw(target, Vector2.Zero, null, Color.White, 0, Vector2.Zero, 2, 0, 0); - - Main.spriteBatch.End(); - Main.spriteBatch.Begin(0, BlendState.AlphaBlend, Main.DefaultSamplerState, DepthStencilState.None, Main.Rasterizer, null, Main.GameViewMatrix.TransformationMatrix); - */ - Effect effect = ShaderLoader.GetShader("AuroraWaterShader").Value; if (effect is null) @@ -402,34 +379,31 @@ public static void DrawSpecial() return; } - if (effect != null) - { - Main.spriteBatch.End(); - Main.graphics.GraphicsDevice.SetRenderTarget(Main.screenTargetSwap); + Main.spriteBatch.End(); + Main.graphics.GraphicsDevice.SetRenderTarget(Main.screenTargetSwap); - effect.Parameters["uTime"].SetValue((float)Main.timeForVisualEffects * 0.02f); - effect.Parameters["offset"].SetValue(new Vector2(Main.screenPosition.X / Main.screenWidth * -0.5f, Main.screenPosition.Y / Main.screenHeight * -0.5f)); - effect.Parameters["sampleTexture"].SetValue(AuroraWaterSystem.auroraBackTarget.RenderTarget); - effect.Parameters["uImageSize1"].SetValue(new Vector2(Main.screenWidth, Main.screenHeight)); - //effect.Parameters["lightTexture"].SetValue(LightingBuffer.screenLightingTarget.RenderTarget); - effect.Parameters["gameTexture"].SetValue(Main.screenTarget); - effect.Parameters["transform"].SetValue(Matrix.Invert(Main.GameViewMatrix.TransformationMatrix)); - effect.Parameters["offset"].SetValue(new Vector2(Main.screenPosition.X % Main.screenWidth / Main.screenWidth, Main.screenPosition.Y % Main.screenHeight / Main.screenHeight)); + effect.Parameters["uTime"].SetValue((float)Main.timeForVisualEffects * 0.02f); + effect.Parameters["offset"].SetValue(new Vector2(Main.screenPosition.X / Main.screenWidth * -0.5f, Main.screenPosition.Y / Main.screenHeight * -0.5f)); + effect.Parameters["sampleTexture"].SetValue(AuroraWaterSystem.auroraBackTarget.RenderTarget); + effect.Parameters["uImageSize1"].SetValue(new Vector2(Main.screenWidth, Main.screenHeight)); + //effect.Parameters["lightTexture"].SetValue(LightingBuffer.screenLightingTarget.RenderTarget); + effect.Parameters["gameTexture"].SetValue(Main.screenTarget); + effect.Parameters["transform"].SetValue(Matrix.Invert(Main.GameViewMatrix.TransformationMatrix)); + effect.Parameters["offset"].SetValue(new Vector2(Main.screenPosition.X % Main.screenWidth / Main.screenWidth, Main.screenPosition.Y % Main.screenHeight / Main.screenHeight)); - var inv = Matrix.Invert(Main.GameViewMatrix.TransformationMatrix); + var inv = Matrix.Invert(Main.GameViewMatrix.TransformationMatrix); - Main.spriteBatch.Begin(default, default, SamplerState.PointClamp, default, RasterizerState.CullNone, effect, Matrix.Identity); + Main.spriteBatch.Begin(default, default, SamplerState.PointClamp, default, RasterizerState.CullNone, effect, Matrix.Identity); - Texture2D target = MetaballSystem.MetaballSystem.actors.FirstOrDefault(n => n is AuroraWaterTileMetaballs).Target.RenderTarget; - Main.spriteBatch.Draw(target, Vector2.Zero, null, Color.White, 0, Vector2.Zero, 2, 0, 0); + Texture2D target = MetaballSystem.MetaballSystem.actors.FirstOrDefault(n => n is AuroraWaterTileMetaballs).Target.RenderTarget; + Main.spriteBatch.Draw(target, Vector2.Zero, null, Color.White, 0, Vector2.Zero, 2, 0, 0); - Main.spriteBatch.End(); + Main.spriteBatch.End(); - Main.graphics.GraphicsDevice.SetRenderTarget(Main.screenTarget); + Main.graphics.GraphicsDevice.SetRenderTarget(Main.screenTarget); - Main.spriteBatch.Begin(default, default, SamplerState.PointClamp, default, RasterizerState.CullNone, default, Matrix.Identity); - Main.spriteBatch.Draw(Main.screenTargetSwap, Vector2.Zero, null, Color.White, 0, Vector2.Zero, 1, 0, 0); - } + Main.spriteBatch.Begin(default, default, SamplerState.PointClamp, default, RasterizerState.CullNone, default, Matrix.Identity); + Main.spriteBatch.Draw(Main.screenTargetSwap, Vector2.Zero, null, Color.White, 0, Vector2.Zero, 1, 0, 0); MetaballSystem.MetaballSystem.actorsSem.Release(); } diff --git a/Core/Systems/AuroraWaterSystem/SwimPlayer.cs b/Core/Systems/AuroraWaterSystem/SwimPlayer.cs index 5d086a27f..6bc95170d 100644 --- a/Core/Systems/AuroraWaterSystem/SwimPlayer.cs +++ b/Core/Systems/AuroraWaterSystem/SwimPlayer.cs @@ -11,7 +11,12 @@ class SwimPlayer : ModPlayer float targetRotation = 0; float realRotation = 0; float armRotation; + int emergeTime = 0; + float emergeRotatio = 0; + + int emergeBoostTime = 0; + Vector2 emergeBoostSpeed = default; public bool wasSwimming; @@ -62,7 +67,6 @@ class SwimPlayer : ModPlayer } ShouldSwim = true; - SwimSpeed *= 0.7f; } } } @@ -71,11 +75,40 @@ public override void PreUpdate() { CheckAuroraSwimming(); + if (emergeBoostTime > 0) + { + // Special effects for when we re-enter out of an exit boost + if (ShouldSwim) + { + emergeBoostTime = 0; + Player.velocity = Vector2.Normalize(Player.velocity) * 0.5f; + + SoundHelper.PlayPitched("Magic/WaterWoosh", 1f, -0.3f, Player.Center); + + for (int k = 0; k < 20; k++) + { + Dust.NewDustPerfect(Player.Center, DustType(), -Vector2.Normalize(Player.velocity).RotatedByRandom(0.5f) * Main.rand.NextFloat(15), 0, new Color(200, 220, 255) * 0.4f, Main.rand.NextFloat(0.2f, 0.8f)); + } + } + else + { + // Makes the exit boost "flat" + emergeBoostTime--; + Player.velocity = emergeBoostSpeed * (0.1f + (emergeBoostTime / 20f)); + + for (int k = 0; k < 5; k++) + { + Dust.NewDustPerfect(Player.Center + Main.rand.NextVector2Circular(16, 16), DustType(), -Vector2.Normalize(Player.velocity).RotatedByRandom(0.5f) * Main.rand.NextFloat(5), 0, new Color(100, Main.rand.Next(150, 255), 255, 0), Main.rand.NextFloat(0.1f, 0.2f)); + } + } + } + if (emergeTime == 18) //reset jumps { Player.RefreshExtraJumps(); Player.rocketTime = Player.rocketTimeMax; Player.wingTime = Player.wingTimeMax; + emergeRotatio = realRotation; SoundHelper.PlayPitched("Magic/WaterWoosh", 0.8f, 0, Player.Center); @@ -84,6 +117,21 @@ public override void PreUpdate() Dust.NewDustPerfect(Player.Center, DustType(), Main.rand.NextVector2Circular(2, 2), 0, new Color(200, 220, 255) * 0.4f, Main.rand.NextFloat(0.2f, 0.8f)); } + if (boostCD > 20 && Player.velocity.Length() > 0) + { + SoundHelper.PlayPitched("SquidBoss/LightSplash", 1f, 0.2f, Player.Center); + + for (int k = 0; k < 20; k++) + { + Dust.NewDustPerfect(Player.Center, DustType(), Vector2.Normalize(Player.velocity).RotatedByRandom(0.5f) * Main.rand.NextFloat(15), 0, new Color(200, 220, 255) * 0.4f, Main.rand.NextFloat(0.2f, 0.8f)); + } + + emergeBoostTime = 20; + emergeBoostSpeed = Vector2.Normalize(Player.velocity) * 20; + + boostCD = 0; + } + wasSwimming = false; } @@ -91,7 +139,7 @@ public override void PreUpdate() { if (boostCD > 0) { - boostCD = 0; + //boostCD = 0; Player.UpdateRotation(0); } @@ -101,10 +149,6 @@ public override void PreUpdate() targetRotation = ShouldSwim ? Player.velocity.ToRotation() : 1.57f + 3.14f; - // Forces the rotation target to be upright if the player is emerging - if (emergeTime < 19) - targetRotation = -MathHelper.PiOver2; - realRotation %= 6.28f; //handles the rotation, ensures the Player wont randomly snap to rotation when entering/leaving swimming if (Math.Abs(targetRotation - realRotation) % 6.28f > 0.21f) @@ -124,6 +168,10 @@ static float Mod(float a, float b) realRotation = targetRotation; } + // Forces the rotation target to be upright if the player is emerging + if (emergeTime < 18) + realRotation = -MathHelper.PiOver2 + (emergeRotatio + MathHelper.PiOver2 ) * (emergeTime - 1) / 19f; + Player.fullRotationOrigin = Player.Size / 2; //so the Player rotates around their center... why is this not the default? Player.fullRotation = realRotation + MathHelper.PiOver2; @@ -154,53 +202,63 @@ static float Mod(float a, float b) Player.legFrame = new Rectangle(0, 56 * (int)(5 + Main.GameUpdateCount / 7 % 3), 40, 56); - float speed = 0.2f * SwimSpeed; + float speed = 0.02f * SwimSpeed; + Vector2 dir = Vector2.Zero; if (Player.controlRight) - Player.velocity.X += speed; //there should probably be a better way of doing this? + dir.X += 1; if (Player.controlLeft) - Player.velocity.X -= speed; + dir.X -= 1; if (Player.controlDown) - Player.velocity.Y += speed; + dir.Y += 1; if (Player.controlUp) - Player.velocity.Y -= speed; + dir.Y -= 1; + + if (dir.Length() > 0) + Player.velocity += Vector2.Normalize(dir) * speed; Player.gravity = 0; - Player.velocity *= 0.95f; + + float slow = Player.velocity.Length() > SwimSpeed ? 0.5f : 0.95f; + Player.velocity *= slow; if (Player.controlJump && boostCD <= 0) { - SoundHelper.PlayPitched("SquidBoss/MagicSplash", 1f, -0.5f, Player.Center); - SoundHelper.PlayPitched("SquidBoss/MagicSplash", 1f, 0f, Player.Center); + SoundHelper.PlayPitched("SquidBoss/LightSplash", Main.rand.NextFloat(0.5f, 0.8f), Main.rand.NextFloat(-0.9f, -0.6f), Player.Center); + SoundHelper.PlayPitched("Magic/WaterWoosh", Main.rand.NextFloat(0.3f, 0.6f), Main.rand.NextFloat(-0.5f, -0.2f), Player.Center); boostCD = 60; } - if (boostCD > 40) + if (boostCD > 20) { - float timer = (boostCD - 40) / 20f; - float angle = timer * 6.28f; - Vector2 vel = -Player.velocity * 0f; + float timer = (boostCD - 20) / 40f; + float angle = timer * 6.28f * 2f; + Vector2 vel = Vector2.One.RotatedByRandom(6.28f) * Main.rand.NextFloat(0.15f); Player.UpdateRotation(angle); for (int k = 0; k < 2; k++) { float prog = k / 2f; var off = new Vector2((float)Math.Cos(angle + 1 / 20f * 6.28f * prog) * 18, (float)Math.Sin(angle + 1 / 20f * 6.28f * prog) * 4); + var color = new Color(timer, 1 - timer, 0.5f + 0.5f * MathF.Sin(timer * 3.14f), 0) * MathF.Sin(timer * 3.14f) * 0.3f; - var l = Dust.NewDustPerfect(Player.Center + Player.velocity * prog + off.RotatedBy(Player.fullRotation), DustType(), vel, 0, new Color(1 - timer, timer, 1), Main.rand.NextFloat(0.4f, 0.7f)); - var r = Dust.NewDustPerfect(Player.Center + Player.velocity * prog - off.RotatedBy(Player.fullRotation), DustType(), vel, 0, new Color(1 - timer, timer, 1), Main.rand.NextFloat(0.4f, 0.7f)); + var l = Dust.NewDustPerfect(Player.Center + Player.velocity * prog + off.RotatedBy(Player.fullRotation), DustType(), vel, 0, color, Main.rand.NextFloat(0.1f, 0.23f)); + var r = Dust.NewDustPerfect(Player.Center + Player.velocity * prog - off.RotatedBy(Player.fullRotation), DustType(), vel, 0, color, Main.rand.NextFloat(0.1f, 0.23f)); l.noGravity = true; r.noGravity = true; } + } + if (boostCD > 40) + { if (Player.velocity == Vector2.Zero) Player.velocity = new Vector2(0, -0.01f); - Player.velocity += Vector2.Normalize(Player.velocity) * 0.8f * SwimSpeed; + Player.velocity += Vector2.Normalize(Player.velocity) * 0.08f * SwimSpeed; Player.AddBuff(Terraria.ID.BuffID.Cursed, 1, true); } else @@ -231,7 +289,7 @@ public override void PostUpdate() public override void ResetEffects() { ShouldSwim = false; - SwimSpeed = 1f; + SwimSpeed = 10f; } } } \ No newline at end of file From 424fa8f231e14cbc186989feb62d3892be1a1b35 Mon Sep 17 00:00:00 2001 From: bobfishkins23 Date: Sat, 20 Dec 2025 15:23:13 -0500 Subject: [PATCH 06/13] Distortion bubble --- Content/NPCs/Permafrost/WaterCube.cs | 4 +++- .../Systems/AuroraWaterSystem/AuroraWaterSystem.cs | 14 +++++--------- Effects/Source/AuroraWaterShader.fx | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Content/NPCs/Permafrost/WaterCube.cs b/Content/NPCs/Permafrost/WaterCube.cs index bf31196a2..7ad75056e 100644 --- a/Content/NPCs/Permafrost/WaterCube.cs +++ b/Content/NPCs/Permafrost/WaterCube.cs @@ -28,6 +28,8 @@ public override void AI() { AuroraWaterSystem.visCounter = 30; NPC.velocity.X = 1; + + Lighting.AddLight(NPC.Center, new Vector3(0.4f, 0.8f, 1f)); } public override bool CanHitPlayer(Player target, ref int cooldownSlot) @@ -49,7 +51,7 @@ public void DrawToTarget(SpriteBatch spriteBatch) Vector2 pos = (NPC.position - Main.screenPosition) / 2f; var target = new Rectangle((int)pos.X, (int)pos.Y, NPC.width / 2, NPC.height / 2); - spriteBatch.Draw(tex, target, Color.Green); + spriteBatch.Draw(tex, target, Color.Lime); } } } \ No newline at end of file diff --git a/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs b/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs index d7c2bfa1f..4a650a3df 100644 --- a/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs +++ b/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs @@ -127,7 +127,7 @@ private static void DrawAuroraBackTarget(SpriteBatch sb) Texture2D tex = asset.Value; Texture2D tex2 = asset2.Value; - Texture2D tex3 = Assets.GradientV.Value; + Texture2D tex3 = Assets.Masks.Glow.Value; Vector2 layer1Pivot = Main.GameUpdateCount * new Vector2(-0.55f, 0.3f); Vector2 layer2Pivot = Main.GameUpdateCount * new Vector2(0.75f, -0.4f); @@ -166,13 +166,9 @@ private static void DrawAuroraBackTarget(SpriteBatch sb) Color.Green); sb.Draw(tex3, - Vector2.Zero, - new Rectangle( - (int)(Main.screenPosition.X) % tex3.Width, - (int)(Main.screenPosition.Y) % tex3.Height, - Main.screenWidth, - Main.screenHeight), - Color.Blue); + Main.LocalPlayer.Center - Main.screenPosition, + null, + Color.Blue, 0, tex3.Size() / 2f, 3f, 0, 0); sb.End(); sb.Begin(); @@ -354,7 +350,7 @@ public override void DrawShapes(SpriteBatch spriteBatch) foreach (Dust dust in Main.dust) { if (dust.active && dust.type == ModContent.DustType()) - spriteBatch.Draw(tex, (dust.position - Main.screenPosition) / 2, null, Color.Green, 0f, Vector2.One * 256f, dust.scale * 0.05f, SpriteEffects.None, 0); + spriteBatch.Draw(tex, (dust.position - Main.screenPosition) / 2, null, Color.Lime, 0f, Vector2.One * 256f, dust.scale * 0.05f, SpriteEffects.None, 0); } spriteBatch.End(); diff --git a/Effects/Source/AuroraWaterShader.fx b/Effects/Source/AuroraWaterShader.fx index 1b2fa7925..aca3f0e1c 100644 --- a/Effects/Source/AuroraWaterShader.fx +++ b/Effects/Source/AuroraWaterShader.fx @@ -64,7 +64,7 @@ float4 PixelShaderFunction(float4 screenSpace : TEXCOORD0) : COLOR0 float4 color = distortLight * (pow(speculars, 2.0) * 3.0 + bright); color.a = shapeMask; - float2 originalUnderCoord = originalCoords * 2.0 + (swirl) * 0.005 * tex2D(uImage0, coords).a; + float2 originalUnderCoord = originalCoords * 2.0 + (swirl) * 0.005 * tex2D(uImage0, coords).a * (1.0 - mapSample.b); float4 underColor = tex2D(gameTex, originalUnderCoord); underColor += shapeMask * distortLight * distortLight * (1.0 - abs(swirl)); From 9187f4693c61888e7d217a112078123647e647e7 Mon Sep 17 00:00:00 2001 From: bobfishkins23 Date: Sat, 20 Dec 2025 16:24:52 -0500 Subject: [PATCH 07/13] Add ripples --- Assets/Masks/RingGlow.png | Bin 0 -> 13963 bytes Assets/Masks/RingGlowInner.png | Bin 0 -> 20854 bytes Assets/Masks/RingGlowInnerTwo.png | Bin 0 -> 22495 bytes .../AuroraWaterSystem/AuroraWaterSystem.cs | 42 ++++++++++++++++++ Core/Systems/AuroraWaterSystem/SwimPlayer.cs | 6 +++ 5 files changed, 48 insertions(+) create mode 100644 Assets/Masks/RingGlow.png create mode 100644 Assets/Masks/RingGlowInner.png create mode 100644 Assets/Masks/RingGlowInnerTwo.png diff --git a/Assets/Masks/RingGlow.png b/Assets/Masks/RingGlow.png new file mode 100644 index 0000000000000000000000000000000000000000..8833cf304f96f339539a651d530d7914b3eb12c1 GIT binary patch literal 13963 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 BPP_mB literal 0 HcmV?d00001 diff --git a/Assets/Masks/RingGlowInnerTwo.png b/Assets/Masks/RingGlowInnerTwo.png new file mode 100644 index 0000000000000000000000000000000000000000..a1df4ff044faa672d489bcf2de907f3dd89d801a GIT binary patch literal 22495 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

Z*C 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 ripplePoints = new(); + public float Priority => 1; public override void Load() @@ -128,6 +146,7 @@ private static void DrawAuroraBackTarget(SpriteBatch sb) Texture2D tex = asset.Value; Texture2D tex2 = asset2.Value; Texture2D tex3 = Assets.Masks.Glow.Value; + Texture2D rippleTex = Assets.Masks.RingGlowInnerTwo.Value; Vector2 layer1Pivot = Main.GameUpdateCount * new Vector2(-0.55f, 0.3f); Vector2 layer2Pivot = Main.GameUpdateCount * new Vector2(0.75f, -0.4f); @@ -170,11 +189,34 @@ private static void DrawAuroraBackTarget(SpriteBatch sb) null, Color.Blue, 0, tex3.Size() / 2f, 3f, 0, 0); + foreach(var ripple in ripplePoints) + { + var col = Color.Lime * (1f - ripple.prog) * ripple.scale; + var col2 = Color.Red * (1f - ripple.prog) * ripple.scale; + sb.Draw(rippleTex, ripple.pos - Main.screenPosition, null, col, 0, rippleTex.Size() / 2f, ripple.scale * ripple.prog, 0, 0); + sb.Draw(rippleTex, ripple.pos - Main.screenPosition, null, col2, 0, rippleTex.Size() / 2f, ripple.scale * ripple.prog, 0, 0); + } + sb.End(); sb.Begin(); } } + public override void PostUpdateEverything() + { + for(int k = 0; k < ripplePoints.Count; k++) + { + ripplePoints[k].prog += ripplePoints[k].speed; + } + + ripplePoints.RemoveAll(n => n.prog >= 1f); + } + + public static void AddRipple(Vector2 pos, float scale, float speed) + { + ripplePoints.Add(new(pos, scale, speed)); + } + private void DrawAuroraWater(On_Main.orig_DrawInfernoRings orig, Main self) { orig(self); diff --git a/Core/Systems/AuroraWaterSystem/SwimPlayer.cs b/Core/Systems/AuroraWaterSystem/SwimPlayer.cs index 6bc95170d..a44cb991b 100644 --- a/Core/Systems/AuroraWaterSystem/SwimPlayer.cs +++ b/Core/Systems/AuroraWaterSystem/SwimPlayer.cs @@ -56,6 +56,8 @@ class SwimPlayer : ModPlayer { if (!wasSwimming) { + AuroraWaterSystem.AddRipple(Player.Center, 1.5f, 0.03f); + SoundHelper.PlayPitched("Magic/WaterWoosh", 0.8f, 0, Player.Center); for (int k = 0; k < 20; k++) @@ -225,10 +227,14 @@ static float Mod(float a, float b) float slow = Player.velocity.Length() > SwimSpeed ? 0.5f : 0.95f; Player.velocity *= slow; + if (Main.GameUpdateCount % 10 == 0) + AuroraWaterSystem.AddRipple(Player.Center, 0.5f + Player.velocity.Length() * 0.05f, 0.02f); + if (Player.controlJump && boostCD <= 0) { SoundHelper.PlayPitched("SquidBoss/LightSplash", Main.rand.NextFloat(0.5f, 0.8f), Main.rand.NextFloat(-0.9f, -0.6f), Player.Center); SoundHelper.PlayPitched("Magic/WaterWoosh", Main.rand.NextFloat(0.3f, 0.6f), Main.rand.NextFloat(-0.5f, -0.2f), Player.Center); + AuroraWaterSystem.AddRipple(Player.Center, 1.5f, 0.03f); boostCD = 60; } From 3e3efa29a19d1e5a42607dd12c09e9474bcebb8d Mon Sep 17 00:00:00 2001 From: ScalarVector Date: Fri, 26 Dec 2025 10:26:33 -0500 Subject: [PATCH 08/13] Seperate scan for water --- .../AuroraWaterSystem/AuroraWaterSystem.cs | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs b/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs index 1a6d79f02..8c5b9662d 100644 --- a/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs +++ b/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs @@ -8,7 +8,9 @@ using System; using System.Collections.Generic; using System.Linq; +using Terraria.ID; using Terraria.ModLoader.IO; +using Terraria.WorldBuilding; namespace StarlightRiver.Core.Systems.AuroraWaterSystem @@ -202,9 +204,25 @@ private static void DrawAuroraBackTarget(SpriteBatch sb) } } - public override void PostUpdateEverything() + public override void PostUpdateNPCs() { - for(int k = 0; k < ripplePoints.Count; k++) + Rectangle rectangle = WorldUtils.ClampToWorld(new Rectangle((int)Main.screenPosition.X / 16, (int)Main.screenPosition.Y / 16, Main.screenWidth / 16, Main.screenHeight / 16)); + for (int k = rectangle.Left; k < rectangle.Right; k++) + { + for (int l = rectangle.Top; l < rectangle.Bottom; l++) + { + Tile tile = Main.tile[k, l]; + if (tile.Get().HasAuroraWater) + { + AuroraWaterSystem.visCounter = 30; + + if (l % 2 == 0 && k % 2 == 0 && !tile.IsSquareSolidTile()) + Lighting.AddLight(new Vector2(k, l) * 16, new Vector3(0.4f, 0.8f, 1f)); + } + } + } + + for (int k = 0; k < ripplePoints.Count; k++) { ripplePoints[k].prog += ripplePoints[k].speed; } @@ -354,20 +372,6 @@ public override unsafe void LoadWorldData(TagCompound tag) } } - class AuroraWaterGlobalTile : GlobalTile - { - public override void NearbyEffects(int i, int j, int type, bool closer) - { - if (Main.tile[i, j].Get().HasAuroraWater) - { - AuroraWaterSystem.visCounter = 30; - - if (i % 2 == 0 && j % 2 == 0 && !Main.tile[i, j].IsSquareSolidTile()) - Lighting.AddLight(new Vector2(i, j) * 16, new Vector3(0.4f, 0.8f, 1f)); - } - } - } - class AuroraWaterTileMetaballs : MetaballActor { public override bool Active => AuroraWaterSystem.Visible && !Main.LocalPlayer.InModBiome(ModContent.GetInstance()); From 8c2cd9db75c8f493be7174654cb069e48e5e0f24 Mon Sep 17 00:00:00 2001 From: bobfishkins23 Date: Sun, 22 Feb 2026 15:07:36 -0500 Subject: [PATCH 09/13] Run format --- Content/Bosses/SquidBoss/Misc.AuroraWaterMetaballs.cs | 4 ++-- Content/Bosses/SquidBoss/NPCs.IcePlatform.cs | 2 +- Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs | 10 +++++----- Core/Systems/AuroraWaterSystem/SwimPlayer.cs | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Content/Bosses/SquidBoss/Misc.AuroraWaterMetaballs.cs b/Content/Bosses/SquidBoss/Misc.AuroraWaterMetaballs.cs index 4e81f3f0d..2c5fc40fb 100644 --- a/Content/Bosses/SquidBoss/Misc.AuroraWaterMetaballs.cs +++ b/Content/Bosses/SquidBoss/Misc.AuroraWaterMetaballs.cs @@ -99,9 +99,9 @@ public override bool PostDraw(SpriteBatch spriteBatch, Texture2D target) Main.spriteBatch.Draw(target, Vector2.Zero, null, Color.White, 0, Vector2.Zero, 2, 0, 0); Main.spriteBatch.End(); - + Main.graphics.GraphicsDevice.SetRenderTarget(Main.screenTarget); - + Main.spriteBatch.Begin(default, default, SamplerState.PointClamp, default, RasterizerState.CullNone, default, Matrix.Identity); Main.spriteBatch.Draw(Main.screenTargetSwap, Vector2.Zero, null, Color.White, 0, Vector2.Zero, 1, 0, 0); } diff --git a/Content/Bosses/SquidBoss/NPCs.IcePlatform.cs b/Content/Bosses/SquidBoss/NPCs.IcePlatform.cs index 9beacb0f8..eb8889796 100644 --- a/Content/Bosses/SquidBoss/NPCs.IcePlatform.cs +++ b/Content/Bosses/SquidBoss/NPCs.IcePlatform.cs @@ -47,7 +47,7 @@ public override void SafeAI() if (Main.npc.Any(n => n.active && n.type == ModContent.NPCType())) { - var actor = ArenaActor.latestActor; + ArenaActor actor = ArenaActor.latestActor; if (NPC.position.Y >= HomeYPosition) { diff --git a/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs b/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs index 1a6d79f02..7ff14dbca 100644 --- a/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs +++ b/Core/Systems/AuroraWaterSystem/AuroraWaterSystem.cs @@ -48,7 +48,7 @@ public AuroraRipple(Vector2 pos, float scale, float speed) this.pos = pos; this.scale = scale; this.speed = speed; - } + } } class AuroraWaterSystem : ModSystem @@ -189,10 +189,10 @@ private static void DrawAuroraBackTarget(SpriteBatch sb) null, Color.Blue, 0, tex3.Size() / 2f, 3f, 0, 0); - foreach(var ripple in ripplePoints) + foreach (AuroraRipple ripple in ripplePoints) { - var col = Color.Lime * (1f - ripple.prog) * ripple.scale; - var col2 = Color.Red * (1f - ripple.prog) * ripple.scale; + Color col = Color.Lime * (1f - ripple.prog) * ripple.scale; + Color col2 = Color.Red * (1f - ripple.prog) * ripple.scale; sb.Draw(rippleTex, ripple.pos - Main.screenPosition, null, col, 0, rippleTex.Size() / 2f, ripple.scale * ripple.prog, 0, 0); sb.Draw(rippleTex, ripple.pos - Main.screenPosition, null, col2, 0, rippleTex.Size() / 2f, ripple.scale * ripple.prog, 0, 0); } @@ -204,7 +204,7 @@ private static void DrawAuroraBackTarget(SpriteBatch sb) public override void PostUpdateEverything() { - for(int k = 0; k < ripplePoints.Count; k++) + for (int k = 0; k < ripplePoints.Count; k++) { ripplePoints[k].prog += ripplePoints[k].speed; } diff --git a/Core/Systems/AuroraWaterSystem/SwimPlayer.cs b/Core/Systems/AuroraWaterSystem/SwimPlayer.cs index a44cb991b..5ce50dc95 100644 --- a/Core/Systems/AuroraWaterSystem/SwimPlayer.cs +++ b/Core/Systems/AuroraWaterSystem/SwimPlayer.cs @@ -96,7 +96,7 @@ public override void PreUpdate() { // Makes the exit boost "flat" emergeBoostTime--; - Player.velocity = emergeBoostSpeed * (0.1f + (emergeBoostTime / 20f)); + Player.velocity = emergeBoostSpeed * (0.1f + emergeBoostTime / 20f); for (int k = 0; k < 5; k++) { @@ -172,7 +172,7 @@ static float Mod(float a, float b) // Forces the rotation target to be upright if the player is emerging if (emergeTime < 18) - realRotation = -MathHelper.PiOver2 + (emergeRotatio + MathHelper.PiOver2 ) * (emergeTime - 1) / 19f; + realRotation = -MathHelper.PiOver2 + (emergeRotatio + MathHelper.PiOver2) * (emergeTime - 1) / 19f; Player.fullRotationOrigin = Player.Size / 2; //so the Player rotates around their center... why is this not the default? Player.fullRotation = realRotation + MathHelper.PiOver2; @@ -250,7 +250,7 @@ static float Mod(float a, float b) { float prog = k / 2f; var off = new Vector2((float)Math.Cos(angle + 1 / 20f * 6.28f * prog) * 18, (float)Math.Sin(angle + 1 / 20f * 6.28f * prog) * 4); - var color = new Color(timer, 1 - timer, 0.5f + 0.5f * MathF.Sin(timer * 3.14f), 0) * MathF.Sin(timer * 3.14f) * 0.3f; + Color color = new Color(timer, 1 - timer, 0.5f + 0.5f * MathF.Sin(timer * 3.14f), 0) * MathF.Sin(timer * 3.14f) * 0.3f; var l = Dust.NewDustPerfect(Player.Center + Player.velocity * prog + off.RotatedBy(Player.fullRotation), DustType(), vel, 0, color, Main.rand.NextFloat(0.1f, 0.23f)); var r = Dust.NewDustPerfect(Player.Center + Player.velocity * prog - off.RotatedBy(Player.fullRotation), DustType(), vel, 0, color, Main.rand.NextFloat(0.1f, 0.23f)); From cc323bdc4151a36af092022dbe45f206a30a493e Mon Sep 17 00:00:00 2001 From: bobfishkins23 Date: Wed, 4 Mar 2026 18:38:23 -0500 Subject: [PATCH 10/13] Run format --- Content/Items/Haunted/Weapons.SpiritSeal.cs | 4 ++-- Content/Items/MechBoss/ViewFinder.cs | 2 +- Content/Tiles/Starlight/DreamingOnyx.cs | 2 +- Content/Tiles/Starlight/GlowingOracleGlass.cs | 2 +- Content/Tiles/Starlight/ObservatoryDoodad.cs | 2 +- .../Vitric/Temple/SoundPuzzle/SoundPuzzleHandler.cs | 10 +++++----- Content/WorldGeneration/GenerateVitric.cs | 5 ++--- StarlightRiver.csproj | 1 - 8 files changed, 13 insertions(+), 15 deletions(-) diff --git a/Content/Items/Haunted/Weapons.SpiritSeal.cs b/Content/Items/Haunted/Weapons.SpiritSeal.cs index 5a34e5cea..2b70c6d60 100644 --- a/Content/Items/Haunted/Weapons.SpiritSeal.cs +++ b/Content/Items/Haunted/Weapons.SpiritSeal.cs @@ -141,8 +141,8 @@ private void DrawPainShare(NPC npc, SpriteBatch spriteBatch, Vector2 screenPos, { if (Inflicted(npc)) { - var tex = Assets.Items.Haunted.SpiritSealBuff.Value; - var glow = Assets.Masks.GlowAlpha.Value; + Texture2D tex = Assets.Items.Haunted.SpiritSealBuff.Value; + Texture2D glow = Assets.Masks.GlowAlpha.Value; spriteBatch.Draw(tex, npc.Center - Main.screenPosition, null, new Color(0.4f, 0.5f, 0.25f) * 0.8f, 0, tex.Size() / 2f, 2f + (float)Math.Sin(Main.GameUpdateCount * 0.1f) * 0.5f, 0, 0); spriteBatch.Draw(glow, npc.Center - Main.screenPosition, null, new Color(0.3f, 0.5f, 0.2f, 0.0f) * 0.8f, 0, glow.Size() / 2f, 0.5f + (float)Math.Sin(Main.GameUpdateCount * 0.1f) * 0.1f, 0, 0); diff --git a/Content/Items/MechBoss/ViewFinder.cs b/Content/Items/MechBoss/ViewFinder.cs index 7ec92e626..0cb1f40b3 100644 --- a/Content/Items/MechBoss/ViewFinder.cs +++ b/Content/Items/MechBoss/ViewFinder.cs @@ -202,7 +202,7 @@ public override void PostAI() public override bool PreDraw(ref Color lightColor) { - var spike = Assets.Misc.SpikeTell.Value; + Texture2D spike = Assets.Misc.SpikeTell.Value; var spikeFrame = new Rectangle(spike.Width / 2, 0, spike.Width / 2, spike.Height); float opacity = 1f; diff --git a/Content/Tiles/Starlight/DreamingOnyx.cs b/Content/Tiles/Starlight/DreamingOnyx.cs index f7a142f4c..4f7974f32 100644 --- a/Content/Tiles/Starlight/DreamingOnyx.cs +++ b/Content/Tiles/Starlight/DreamingOnyx.cs @@ -46,7 +46,7 @@ public override void PostDraw(int i, int j, SpriteBatch spriteBatch) { Tile tile = Main.tile[i, j]; - var tex = Assets.Tiles.Starlight.DreamingOnyxGlow.Value; + Texture2D tex = Assets.Tiles.Starlight.DreamingOnyxGlow.Value; var frame = new Rectangle(tile.TileFrameX, tile.TileFrameY, 16, 16); Vector2 target = new Vector2(i, j) * 16 + Vector2.One * Main.offScreenRange - Main.screenPosition + Vector2.One * 8; var color = new Color(255, 255, 255, 0); diff --git a/Content/Tiles/Starlight/GlowingOracleGlass.cs b/Content/Tiles/Starlight/GlowingOracleGlass.cs index 9a5b0e7b4..8762428c3 100644 --- a/Content/Tiles/Starlight/GlowingOracleGlass.cs +++ b/Content/Tiles/Starlight/GlowingOracleGlass.cs @@ -42,7 +42,7 @@ public override void PostDraw(int i, int j, SpriteBatch spriteBatch) { Tile tile = Main.tile[i, j]; - var tex = Assets.Tiles.Starlight.OracleGlassGlow.Value; + Texture2D tex = Assets.Tiles.Starlight.OracleGlassGlow.Value; var frame = new Rectangle(tile.TileFrameX, tile.TileFrameY, 16, 16); Vector2 target = new Vector2(i, j) * 16 + Vector2.One * Main.offScreenRange - Main.screenPosition + Vector2.One * 8; var color = new Color(255, 255, 255, 0); diff --git a/Content/Tiles/Starlight/ObservatoryDoodad.cs b/Content/Tiles/Starlight/ObservatoryDoodad.cs index 3f0ac2eaa..d28ca43a4 100644 --- a/Content/Tiles/Starlight/ObservatoryDoodad.cs +++ b/Content/Tiles/Starlight/ObservatoryDoodad.cs @@ -35,7 +35,7 @@ public override void Update() public override void DrawBehindTiles() { - var tex = Assets.Tiles.Starlight.ObervatoryDoodadBack.Value; + Texture2D tex = Assets.Tiles.Starlight.ObervatoryDoodadBack.Value; LightingBufferRenderer.DrawWithLighting(tex, Center + Vector2.UnitY * height / 2f - Main.screenPosition, null, Color.White, 0, new Vector2(tex.Width / 2f, tex.Height), 1); } } diff --git a/Content/Tiles/Vitric/Temple/SoundPuzzle/SoundPuzzleHandler.cs b/Content/Tiles/Vitric/Temple/SoundPuzzle/SoundPuzzleHandler.cs index ca2300149..9564c4963 100644 --- a/Content/Tiles/Vitric/Temple/SoundPuzzle/SoundPuzzleHandler.cs +++ b/Content/Tiles/Vitric/Temple/SoundPuzzle/SoundPuzzleHandler.cs @@ -70,11 +70,11 @@ public override void PreUpdateEntities() public override void PostDrawTiles() { - var one = Assets.Tiles.Vitric.OldCeirosOrnament0.Value; - var two = Assets.Tiles.Vitric.OldCeirosOrnament3.Value; - var three = Assets.Tiles.Vitric.OldCeirosOrnament1.Value; - var four = Assets.Tiles.Vitric.OldCeirosOrnament2.Value; - var blank = Assets.Bosses.VitricBoss.VitricBossCrystal.Value; + Texture2D one = Assets.Tiles.Vitric.OldCeirosOrnament0.Value; + Texture2D two = Assets.Tiles.Vitric.OldCeirosOrnament3.Value; + Texture2D three = Assets.Tiles.Vitric.OldCeirosOrnament1.Value; + Texture2D four = Assets.Tiles.Vitric.OldCeirosOrnament2.Value; + Texture2D blank = Assets.Bosses.VitricBoss.VitricBossCrystal.Value; Vector2 pos = StarlightWorld.VitricBossArena.BottomLeft() * 16 + new Vector2(-762, 1424) - Main.screenPosition; diff --git a/Content/WorldGeneration/GenerateVitric.cs b/Content/WorldGeneration/GenerateVitric.cs index 31b507ff9..4a07511a4 100644 --- a/Content/WorldGeneration/GenerateVitric.cs +++ b/Content/WorldGeneration/GenerateVitric.cs @@ -1,7 +1,6 @@ using StarlightRiver.Content.CustomHooks; using StarlightRiver.Content.Tiles.Vitric; using StarlightRiver.Content.Tiles.Vitric.Temple.GearPuzzle; -using StarlightRiver.Helpers; using StarlightRiver.Noise; using System; using System.Collections.Generic; @@ -73,7 +72,7 @@ public static void VitricGen(GenerationProgress progress, GameConfiguration conf PlaceTile(vitricBiome.X + vitricBiome.Width / 2 + 41, y, StarlightRiver.Instance.Find("VitricBossBarrier").Type, false, false); } - VitricIslandLocations = new List(); //List for island positions + VitricIslandLocations = []; //List for island positions int fail = 0; for (int i = 0; i < vitricBiome.Width / 40 - 1; ++i) @@ -199,7 +198,7 @@ public static void VitricGen(GenerationProgress progress, GameConfiguration conf GenConsistentMiniIslands(); GenSandstonePillars(); - RuinedPillarPositions = new List(); + RuinedPillarPositions = []; GenRuins(); GenForge(); GenDecoration(); diff --git a/StarlightRiver.csproj b/StarlightRiver.csproj index 462b61e36..36a18203e 100644 --- a/StarlightRiver.csproj +++ b/StarlightRiver.csproj @@ -28,7 +28,6 @@ - From 47a56e3ed2ad589483e0cb1c0a2dd56fc25584f8 Mon Sep 17 00:00:00 2001 From: bobfishkins23 Date: Wed, 4 Mar 2026 18:40:20 -0500 Subject: [PATCH 11/13] Misc warning fixes --- Content/Bosses/SquidBoss/NPCs.SquidBoss.cs | 2 +- Content/Bosses/VitricBoss/NPCs.VitricBoss.cs | 2 +- Content/Items/Magnet/Weapons.Thunderbus.cs | 3 --- Core/Systems/ArmatureSystem/Arm.cs | 2 +- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Content/Bosses/SquidBoss/NPCs.SquidBoss.cs b/Content/Bosses/SquidBoss/NPCs.SquidBoss.cs index cc9da770c..158e6ee08 100644 --- a/Content/Bosses/SquidBoss/NPCs.SquidBoss.cs +++ b/Content/Bosses/SquidBoss/NPCs.SquidBoss.cs @@ -202,7 +202,7 @@ public override void ModifyNPCLoot(NPCLoot npcLoot) npcLoot.Add(ItemDropRule.MasterModeCommonDrop(Mod.Find("AuroracleRelicItem").Type)); } - public override void BossLoot(ref string name, ref int potionType) + public override void BossLoot(ref int potionType) { for (int k = 0; k < Main.maxPlayers; k++) { diff --git a/Content/Bosses/VitricBoss/NPCs.VitricBoss.cs b/Content/Bosses/VitricBoss/NPCs.VitricBoss.cs index daefc2e52..2790e846a 100644 --- a/Content/Bosses/VitricBoss/NPCs.VitricBoss.cs +++ b/Content/Bosses/VitricBoss/NPCs.VitricBoss.cs @@ -360,7 +360,7 @@ public override void ModifyNPCLoot(NPCLoot npcLoot) npcLoot.Add(ItemDropRule.MasterModeCommonDrop(Mod.Find("CeirosRelicItem").Type)); } - public override void BossLoot(ref string name, ref int potionType) + public override void BossLoot(ref int potionType) { BossRushDataStore.DefeatBoss(BossrushUnlockFlag.Ceiros); StarlightWorld.Flag(WorldFlags.VitricBossDowned); diff --git a/Content/Items/Magnet/Weapons.Thunderbus.cs b/Content/Items/Magnet/Weapons.Thunderbus.cs index 8b4f436bc..8d5c07fba 100644 --- a/Content/Items/Magnet/Weapons.Thunderbus.cs +++ b/Content/Items/Magnet/Weapons.Thunderbus.cs @@ -209,9 +209,6 @@ internal class ThunderbussShot : ModProjectile, IDrawPrimitive private List cache; private Trail trail; - private readonly float dist1; - private readonly float dist2; - readonly List nodes = new(); public ref float TargetID => ref Projectile.ai[0]; diff --git a/Core/Systems/ArmatureSystem/Arm.cs b/Core/Systems/ArmatureSystem/Arm.cs index 80b47a532..ea41abe8d 100644 --- a/Core/Systems/ArmatureSystem/Arm.cs +++ b/Core/Systems/ArmatureSystem/Arm.cs @@ -109,7 +109,7 @@ public void IKToPoint(Vector2 target) Vector2 toTarget = target - currentSegment.start; float targetRotation = toTarget.ToRotation(); - if (targetRotation != targetRotation) // == NaN + if (float.IsNaN(targetRotation)) targetRotation = 0; segments[i].rotation = targetRotation; From ecb6f4166077f6ca1895ff5a8fe457bc7872de08 Mon Sep 17 00:00:00 2001 From: bobfishkins23 Date: Wed, 4 Mar 2026 19:31:08 -0500 Subject: [PATCH 12/13] Update to preview lang version --- Content/Abilities/AbilityHandler.cs | 9 +++---- Content/Abilities/Hint/HintAbility.cs | 3 +-- .../Abilities/InfusionItem.ModItemMethods.cs | 3 +-- .../VitricBoss/NPCs.VitricBoss.Attacks.cs | 3 +-- .../Items/Forest/Armors.SlimePrinceMinion.cs | 3 +-- .../Gravedigger/Weapons.RadculasRapier.cs | 3 +-- Content/NPCs/Actors/StarlightWaterActor.cs | 3 +-- Content/NPCs/Moonstone/DreambeastSystems.cs | 3 +-- Content/Noise/FastNoise.NoiseCellular.cs | 8 +++---- Content/Noise/FastNoise.NoiseCubic.cs | 24 +++++++++---------- Content/Noise/FastNoise.NoisePerlin.cs | 24 +++++++++---------- Content/Noise/FastNoise.NoiseSimplex.cs | 24 +++++++++---------- Content/Noise/FastNoise.NoiseValue.cs | 24 +++++++++---------- Content/Noise/FastNoise.cs | 21 +++++++--------- .../Vitric/Temple/GearPuzzle/GearTile.cs | 12 ++++------ Content/WorldGeneration/GenerateVitric.cs | 6 ++--- Core/ParticleSystem.cs | 3 +-- Core/PrimitiveDrawing.cs | 6 ++--- Core/Systems/CameraSystem/ZoomHandler.cs | 12 ++++------ Core/Systems/DummyTileSystem/Dummy.cs | 3 +-- Helpers/DustHelper.cs | 6 ++--- StarlightRiver.csproj | 2 +- 22 files changed, 89 insertions(+), 116 deletions(-) diff --git a/Content/Abilities/AbilityHandler.cs b/Content/Abilities/AbilityHandler.cs index d4de3332d..aa4a1dac4 100644 --- a/Content/Abilities/AbilityHandler.cs +++ b/Content/Abilities/AbilityHandler.cs @@ -16,8 +16,6 @@ public class AbilityHandler : ModPlayer, IOrderedLoadable private InfusionItem[] infusions = new InfusionItem[Infusion.InfusionSlots]; public Dictionary unlockedAbilities = new(); - - private float stamina; private float staminaMaxBonus; private int staminaRegenCD; @@ -99,9 +97,9 @@ public float StaminaMaxBonus /// public float Stamina { - get => stamina; + get; // Can't have less than 0 or more than max stamina. - set => stamina = MathHelper.Clamp(value, 0, StaminaMax); + set => field = MathHelper.Clamp(value, 0, StaminaMax); } //for some reason without specifically setting these values to zero with cloneNewInstances => false and contructor, @@ -400,8 +398,7 @@ public override void PreUpdate() // To ensure fusions always have their owner set to a valid Player. for (int i = 0; i < infusions.Length; i++) { - if (infusions[i] != null) - infusions[i].Item.playerIndexTheItemIsReservedFor = Player.whoAmI; + infusions[i]?.Item.playerIndexTheItemIsReservedFor = Player.whoAmI; } } diff --git a/Content/Abilities/Hint/HintAbility.cs b/Content/Abilities/Hint/HintAbility.cs index e2ca75bf0..3c87523f6 100644 --- a/Content/Abilities/Hint/HintAbility.cs +++ b/Content/Abilities/Hint/HintAbility.cs @@ -153,8 +153,7 @@ public override void UpdateActive() int i = Projectile.NewProjectile(Player.GetSource_FromThis(), Main.MouseWorld + Vector2.UnitY * -32, Vector2.Zero, ModContent.ProjectileType(), 0, 0, Main.myPlayer); var proj = Main.projectile[i].ModProjectile as HintText; - if (proj != null) - proj.text = hintToDisplay; + proj?.text = hintToDisplay; } Deactivate(); diff --git a/Content/Abilities/InfusionItem.ModItemMethods.cs b/Content/Abilities/InfusionItem.ModItemMethods.cs index 482490336..cd63f8f49 100644 --- a/Content/Abilities/InfusionItem.ModItemMethods.cs +++ b/Content/Abilities/InfusionItem.ModItemMethods.cs @@ -33,8 +33,7 @@ public void Draw(SpriteBatch spriteBatch, Vector2 position, float opacity, float public override void UpdateInventory(Player player) { - if (ability != null) - ability.User = player.GetHandler(); + ability?.User = player.GetHandler(); } public override void Update(ref float gravity, ref float maxFallSpeed) diff --git a/Content/Bosses/VitricBoss/NPCs.VitricBoss.Attacks.cs b/Content/Bosses/VitricBoss/NPCs.VitricBoss.Attacks.cs index 2f5e6f7d4..3dfc91a89 100644 --- a/Content/Bosses/VitricBoss/NPCs.VitricBoss.Attacks.cs +++ b/Content/Bosses/VitricBoss/NPCs.VitricBoss.Attacks.cs @@ -108,8 +108,7 @@ private void MakeCrystalVulnerable() { NPC crystal = crystals.FirstOrDefault(n => n.ai[0] == 2); - if (crystal != null) - crystal.ai[0] = 0; + crystal?.ai[0] = 0; } if (AttackTimer > 180 && AttackTimer % 25 == 0 && Main.netMode != NetmodeID.MultiplayerClient) diff --git a/Content/Items/Forest/Armors.SlimePrinceMinion.cs b/Content/Items/Forest/Armors.SlimePrinceMinion.cs index fa19beec3..04e5d17b6 100644 --- a/Content/Items/Forest/Armors.SlimePrinceMinion.cs +++ b/Content/Items/Forest/Armors.SlimePrinceMinion.cs @@ -194,8 +194,7 @@ public void FuseAnimation() { var helm = Owner.armor[0].ModItem as SlimePrinceHead; - if (helm != null) - helm.targetVel = new Vector2(0, -10); + helm?.targetVel = new Vector2(0, -10); State = 3; Timer = 0; diff --git a/Content/Items/Gravedigger/Weapons.RadculasRapier.cs b/Content/Items/Gravedigger/Weapons.RadculasRapier.cs index 5a27f3610..144eafcc3 100644 --- a/Content/Items/Gravedigger/Weapons.RadculasRapier.cs +++ b/Content/Items/Gravedigger/Weapons.RadculasRapier.cs @@ -424,8 +424,7 @@ public override void OnHitNPC(NPC target, NPC.HitInfo hit, int damageDone) RadculasRapierBleed buff = InstancedBuffNPC.GetInstance(target); - if (buff != null) - buff.lastHitPos = Owner.Center; + buff?.lastHitPos = Owner.Center; Vector2 pos = Owner.Center - (Owner.Center - target.Center); diff --git a/Content/NPCs/Actors/StarlightWaterActor.cs b/Content/NPCs/Actors/StarlightWaterActor.cs index a64d9c03a..893f2b668 100644 --- a/Content/NPCs/Actors/StarlightWaterActor.cs +++ b/Content/NPCs/Actors/StarlightWaterActor.cs @@ -48,8 +48,7 @@ public override void SetBestiary(BestiaryDatabase database, BestiaryEntry bestia public void ResetConversion() { - if (targetItem != null) - targetItem.GetGlobalItem().starlightWaterActor = null; + targetItem?.GetGlobalItem().starlightWaterActor = null; targetItem = null; targetItemTransformType = 0; diff --git a/Content/NPCs/Moonstone/DreambeastSystems.cs b/Content/NPCs/Moonstone/DreambeastSystems.cs index 5ab6a1f05..c9c41426c 100644 --- a/Content/NPCs/Moonstone/DreambeastSystems.cs +++ b/Content/NPCs/Moonstone/DreambeastSystems.cs @@ -186,8 +186,7 @@ public override void PostUpdateBuffs() { SoundEngine.TryGetActiveSound((SlotId)insaneChargeSound, out ActiveSound sound); - if (sound != null) - sound.Volume = 0; + sound?.Volume = 0; insaneChargeSound = null; } diff --git a/Content/Noise/FastNoise.NoiseCellular.cs b/Content/Noise/FastNoise.NoiseCellular.cs index 857b8c6fd..ecfdbfb73 100644 --- a/Content/Noise/FastNoise.NoiseCellular.cs +++ b/Content/Noise/FastNoise.NoiseCellular.cs @@ -66,10 +66,10 @@ public void GradientPerturbFractal(ref DECIMAL x, ref DECIMAL y) SingleGradientPerturb(seed, amp, Frequency, ref x, ref y); - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { freq *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; SingleGradientPerturb(++seed, amp, freq, ref x, ref y); } } @@ -81,10 +81,10 @@ public void GradientPerturbFractal(ref DECIMAL x, ref DECIMAL y, ref DECIMAL z) SingleGradientPerturb(seed, amp, Frequency, ref x, ref y, ref z); - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { freq *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; SingleGradientPerturb(++seed, amp, freq, ref x, ref y, ref z); } } diff --git a/Content/Noise/FastNoise.NoiseCubic.cs b/Content/Noise/FastNoise.NoiseCubic.cs index ce7ded098..069086488 100644 --- a/Content/Noise/FastNoise.NoiseCubic.cs +++ b/Content/Noise/FastNoise.NoiseCubic.cs @@ -132,12 +132,12 @@ private DECIMAL SingleCubicFractalFBM(DECIMAL x, DECIMAL y) DECIMAL amp = 1; int i = 0; - while (++i < octaves) + while (++i < FractalOctaves) { x *= FractalLacunarity; y *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum += SingleCubic(++seed, x, y) * amp; } @@ -150,13 +150,13 @@ private DECIMAL SingleCubicFractalFBM(DECIMAL x, DECIMAL y, DECIMAL z) DECIMAL amp = 1; int i = 0; - while (++i < octaves) + while (++i < FractalOctaves) { x *= FractalLacunarity; y *= FractalLacunarity; z *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum += SingleCubic(++seed, x, y, z) * amp; } @@ -169,12 +169,12 @@ private DECIMAL SingleCubicFractalBillow(DECIMAL x, DECIMAL y) DECIMAL amp = 1; int i = 0; - while (++i < octaves) + while (++i < FractalOctaves) { x *= FractalLacunarity; y *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum += (Math.Abs(SingleCubic(++seed, x, y)) * 2 - 1) * amp; } @@ -187,13 +187,13 @@ private DECIMAL SingleCubicFractalBillow(DECIMAL x, DECIMAL y, DECIMAL z) DECIMAL amp = 1; int i = 0; - while (++i < octaves) + while (++i < FractalOctaves) { x *= FractalLacunarity; y *= FractalLacunarity; z *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum += (Math.Abs(SingleCubic(++seed, x, y, z)) * 2 - 1) * amp; } @@ -206,12 +206,12 @@ private DECIMAL SingleCubicFractalRigidMulti(DECIMAL x, DECIMAL y) DECIMAL amp = 1; int i = 0; - while (++i < octaves) + while (++i < FractalOctaves) { x *= FractalLacunarity; y *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum -= (1 - Math.Abs(SingleCubic(++seed, x, y))) * amp; } @@ -224,13 +224,13 @@ private DECIMAL SingleCubicFractalRigidMulti(DECIMAL x, DECIMAL y, DECIMAL z) DECIMAL amp = 1; int i = 0; - while (++i < octaves) + while (++i < FractalOctaves) { x *= FractalLacunarity; y *= FractalLacunarity; z *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum -= (1 - Math.Abs(SingleCubic(++seed, x, y, z))) * amp; } diff --git a/Content/Noise/FastNoise.NoisePerlin.cs b/Content/Noise/FastNoise.NoisePerlin.cs index a5c28e198..5cd0d7156 100644 --- a/Content/Noise/FastNoise.NoisePerlin.cs +++ b/Content/Noise/FastNoise.NoisePerlin.cs @@ -134,12 +134,12 @@ private DECIMAL SinglePerlinFractalFBM(DECIMAL x, DECIMAL y) DECIMAL sum = SinglePerlin(seed, x, y); DECIMAL amp = 1; - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { x *= FractalLacunarity; y *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum += SinglePerlin(++seed, x, y) * amp; } @@ -151,13 +151,13 @@ private DECIMAL SinglePerlinFractalFBM(DECIMAL x, DECIMAL y, DECIMAL z) DECIMAL sum = SinglePerlin(seed, x, y, z); DECIMAL amp = 1; - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { x *= FractalLacunarity; y *= FractalLacunarity; z *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum += SinglePerlin(++seed, x, y, z) * amp; } @@ -169,12 +169,12 @@ private DECIMAL SinglePerlinFractalBillow(DECIMAL x, DECIMAL y) DECIMAL sum = Math.Abs(SinglePerlin(seed, x, y)) * 2 - 1; DECIMAL amp = 1; - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { x *= FractalLacunarity; y *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum += (Math.Abs(SinglePerlin(++seed, x, y)) * 2 - 1) * amp; } @@ -186,13 +186,13 @@ private DECIMAL SinglePerlinFractalBillow(DECIMAL x, DECIMAL y, DECIMAL z) DECIMAL sum = Math.Abs(SinglePerlin(seed, x, y, z)) * 2 - 1; DECIMAL amp = 1; - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { x *= FractalLacunarity; y *= FractalLacunarity; z *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum += (Math.Abs(SinglePerlin(++seed, x, y, z)) * 2 - 1) * amp; } @@ -204,12 +204,12 @@ private DECIMAL SinglePerlinFractalRigidMulti(DECIMAL x, DECIMAL y) DECIMAL sum = 1 - Math.Abs(SinglePerlin(seed, x, y)); DECIMAL amp = 1; - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { x *= FractalLacunarity; y *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum -= (1 - Math.Abs(SinglePerlin(++seed, x, y))) * amp; } @@ -221,13 +221,13 @@ private DECIMAL SinglePerlinFractalRigidMulti(DECIMAL x, DECIMAL y, DECIMAL z) DECIMAL sum = 1 - Math.Abs(SinglePerlin(seed, x, y, z)); DECIMAL amp = 1; - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { x *= FractalLacunarity; y *= FractalLacunarity; z *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum -= (1 - Math.Abs(SinglePerlin(++seed, x, y, z))) * amp; } diff --git a/Content/Noise/FastNoise.NoiseSimplex.cs b/Content/Noise/FastNoise.NoiseSimplex.cs index 54ef8f6a4..b8f0dbda7 100644 --- a/Content/Noise/FastNoise.NoiseSimplex.cs +++ b/Content/Noise/FastNoise.NoiseSimplex.cs @@ -397,12 +397,12 @@ private DECIMAL SingleSimplexFractalBillow(DECIMAL x, DECIMAL y) DECIMAL sum = Math.Abs(SingleSimplex(seed, x, y)) * 2 - 1; DECIMAL amp = 1; - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { x *= FractalLacunarity; y *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum += (Math.Abs(SingleSimplex(++seed, x, y)) * 2 - 1) * amp; } @@ -414,13 +414,13 @@ private DECIMAL SingleSimplexFractalBillow(DECIMAL x, DECIMAL y, DECIMAL z) DECIMAL sum = Math.Abs(SingleSimplex(seed, x, y, z)) * 2 - 1; DECIMAL amp = 1; - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { x *= FractalLacunarity; y *= FractalLacunarity; z *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum += (Math.Abs(SingleSimplex(++seed, x, y, z)) * 2 - 1) * amp; } @@ -432,12 +432,12 @@ private DECIMAL SingleSimplexFractalFBM(DECIMAL x, DECIMAL y) DECIMAL sum = SingleSimplex(seed, x, y); DECIMAL amp = 1; - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { x *= FractalLacunarity; y *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum += SingleSimplex(++seed, x, y) * amp; } @@ -449,13 +449,13 @@ private DECIMAL SingleSimplexFractalFBM(DECIMAL x, DECIMAL y, DECIMAL z) DECIMAL sum = SingleSimplex(seed, x, y, z); DECIMAL amp = 1; - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { x *= FractalLacunarity; y *= FractalLacunarity; z *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum += SingleSimplex(++seed, x, y, z) * amp; } @@ -467,12 +467,12 @@ private DECIMAL SingleSimplexFractalRigidMulti(DECIMAL x, DECIMAL y) DECIMAL sum = 1 - Math.Abs(SingleSimplex(seed, x, y)); DECIMAL amp = 1; - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { x *= FractalLacunarity; y *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum -= (1 - Math.Abs(SingleSimplex(++seed, x, y))) * amp; } @@ -484,13 +484,13 @@ private DECIMAL SingleSimplexFractalRigidMulti(DECIMAL x, DECIMAL y, DECIMAL z) DECIMAL sum = 1 - Math.Abs(SingleSimplex(seed, x, y, z)); DECIMAL amp = 1; - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { x *= FractalLacunarity; y *= FractalLacunarity; z *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum -= (1 - Math.Abs(SingleSimplex(++seed, x, y, z))) * amp; } diff --git a/Content/Noise/FastNoise.NoiseValue.cs b/Content/Noise/FastNoise.NoiseValue.cs index e7e0cf709..161a50823 100644 --- a/Content/Noise/FastNoise.NoiseValue.cs +++ b/Content/Noise/FastNoise.NoiseValue.cs @@ -122,11 +122,11 @@ private DECIMAL SingleValueFractalBillow(DECIMAL x, DECIMAL y) DECIMAL sum = Math.Abs(SingleValue(seed, x, y)) * 2 - 1; DECIMAL amp = 1; - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { x *= FractalLacunarity; y *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum += (Math.Abs(SingleValue(++seed, x, y)) * 2 - 1) * amp; } @@ -138,13 +138,13 @@ private DECIMAL SingleValueFractalBillow(DECIMAL x, DECIMAL y, DECIMAL z) DECIMAL sum = Math.Abs(SingleValue(seed, x, y, z)) * 2 - 1; DECIMAL amp = 1; - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { x *= FractalLacunarity; y *= FractalLacunarity; z *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum += (Math.Abs(SingleValue(++seed, x, y, z)) * 2 - 1) * amp; } @@ -156,12 +156,12 @@ private DECIMAL SingleValueFractalFBM(DECIMAL x, DECIMAL y) DECIMAL sum = SingleValue(seed, x, y); DECIMAL amp = 1; - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { x *= FractalLacunarity; y *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum += SingleValue(++seed, x, y) * amp; } @@ -173,13 +173,13 @@ private DECIMAL SingleValueFractalFBM(DECIMAL x, DECIMAL y, DECIMAL z) DECIMAL sum = SingleValue(seed, x, y, z); DECIMAL amp = 1; - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { x *= FractalLacunarity; y *= FractalLacunarity; z *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum += SingleValue(++seed, x, y, z) * amp; } @@ -191,12 +191,12 @@ private DECIMAL SingleValueFractalRigidMulti(DECIMAL x, DECIMAL y) DECIMAL sum = 1 - Math.Abs(SingleValue(seed, x, y)); DECIMAL amp = 1; - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { x *= FractalLacunarity; y *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum -= (1 - Math.Abs(SingleValue(++seed, x, y))) * amp; } @@ -208,13 +208,13 @@ private DECIMAL SingleValueFractalRigidMulti(DECIMAL x, DECIMAL y, DECIMAL z) DECIMAL sum = 1 - Math.Abs(SingleValue(seed, x, y, z)); DECIMAL amp = 1; - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { x *= FractalLacunarity; y *= FractalLacunarity; z *= FractalLacunarity; - amp *= gain; + amp *= FractalGain; sum -= (1 - Math.Abs(SingleValue(++seed, x, y, z))) * amp; } diff --git a/Content/Noise/FastNoise.cs b/Content/Noise/FastNoise.cs index 43abc8bd5..f4a4fcb13 100644 --- a/Content/Noise/FastNoise.cs +++ b/Content/Noise/FastNoise.cs @@ -10,9 +10,6 @@ public partial class FastNoise { private const short Inline = (short)MethodImplOptions.AggressiveInlining; private const int CellularMaxIndex = 3; - - private int octaves = 3; - private DECIMAL gain = (DECIMAL)0.5; private DECIMAL fractalBounding; public int Seed { get; set; } @@ -24,24 +21,24 @@ public partial class FastNoise public int FractalOctaves { - get => octaves; + get; set { - octaves = value; + field = value; CalculateFractalBounding(); } - } + } = 3; public DECIMAL FractalGain { - get => gain; + get; set { - gain = value; + field = value; CalculateFractalBounding(); } - } + } = (DECIMAL)0.5; public FastNoise(int seed = 0) { @@ -150,13 +147,13 @@ public DECIMAL GetNoise(DECIMAL x, DECIMAL y, DECIMAL z) private void CalculateFractalBounding() { - DECIMAL amp = gain; + DECIMAL amp = FractalGain; DECIMAL ampFractal = 1; - for (int i = 1; i < octaves; i++) + for (int i = 1; i < FractalOctaves; i++) { ampFractal += amp; - amp *= gain; + amp *= FractalGain; } fractalBounding = 1 / ampFractal; diff --git a/Content/Tiles/Vitric/Temple/GearPuzzle/GearTile.cs b/Content/Tiles/Vitric/Temple/GearPuzzle/GearTile.cs index 477d5ae2c..886737de2 100644 --- a/Content/Tiles/Vitric/Temple/GearPuzzle/GearTile.cs +++ b/Content/Tiles/Vitric/Temple/GearPuzzle/GearTile.cs @@ -309,8 +309,7 @@ protected bool Engaged } set { - if (GearEntity != null) - GearEntity.engaged = value; + GearEntity?.engaged = value; } } @@ -325,8 +324,7 @@ protected float RotationVelocity } set { - if (GearEntity != null) - GearEntity.rotationVelocity = value; + GearEntity?.rotationVelocity = value; } } @@ -341,8 +339,7 @@ protected float RotationOffset } set { - if (GearEntity != null) - GearEntity.rotationOffset = value; + GearEntity?.rotationOffset = value; } } @@ -364,8 +361,7 @@ public int GearSize get => GearEntity?.size ?? 0; set { - if (GearEntity != null) - GearEntity.size = value % 4; + GearEntity?.size = value % 4; } } diff --git a/Content/WorldGeneration/GenerateVitric.cs b/Content/WorldGeneration/GenerateVitric.cs index 4a07511a4..c2783e61d 100644 --- a/Content/WorldGeneration/GenerateVitric.cs +++ b/Content/WorldGeneration/GenerateVitric.cs @@ -36,8 +36,7 @@ public partial class StarlightWorld : ModSystem /// public static void VitricGen(GenerationProgress progress, GameConfiguration configuration) { - if (progress != null) - progress.Message = "Digging the Vitric Desert"; + progress?.Message = "Digging the Vitric Desert"; int vitricHeight = 140; ValidGround = new int[] { instance.Find("VitricSand").Type, instance.Find("VitricSoftSand").Type }; @@ -193,8 +192,7 @@ public static void VitricGen(GenerationProgress progress, GameConfiguration conf } } - if (progress != null) - progress.Message = "Melting Glass"; + progress?.Message = "Melting Glass"; GenConsistentMiniIslands(); GenSandstonePillars(); diff --git a/Core/ParticleSystem.cs b/Core/ParticleSystem.cs index dac6b0d36..14dbfc60f 100644 --- a/Core/ParticleSystem.cs +++ b/Core/ParticleSystem.cs @@ -293,8 +293,7 @@ public void SetTexture(Texture2D texture) { this.texture = texture; - if (effect != null) - effect.Texture = texture; + effect?.Texture = texture; } } diff --git a/Core/PrimitiveDrawing.cs b/Core/PrimitiveDrawing.cs index 061e91685..4daa16b92 100644 --- a/Core/PrimitiveDrawing.cs +++ b/Core/PrimitiveDrawing.cs @@ -95,7 +95,7 @@ public class Trail : IDisposable /// public Vector2[] Positions { - get => positions; + get; set { if (value.Length != maxPointCount) @@ -103,12 +103,10 @@ public Vector2[] Positions throw new ArgumentException("Array of positions was a different length than the expected result!"); } - positions = value; + field = value; } } - private Vector2[] positions; - ///

/// Used in order to calculate the normal from the frontmost position, because there isn't a point after it in the original list. /// diff --git a/Core/Systems/CameraSystem/ZoomHandler.cs b/Core/Systems/CameraSystem/ZoomHandler.cs index 98faf612a..152b271d8 100644 --- a/Core/Systems/CameraSystem/ZoomHandler.cs +++ b/Core/Systems/CameraSystem/ZoomHandler.cs @@ -15,19 +15,17 @@ public class ZoomHandler : ModSystem private static float flatZoomTarget = 0; private static float flatZoom = 0; - private static float extraZoomTarget = 1; - public static float ExtraZoomTarget { - get => extraZoomTarget; + get; private set { oldZoom = zoomOverride; zoomTimer = 0; - extraZoomTarget = value; + field = value; } - } + } = 1; public static float ClampedExtraZoomTarget => System.Math.Min(1, ExtraZoomTarget); @@ -83,12 +81,12 @@ public static void TickZoom() public static void UpdateZoom() { - zoomOverride = Vector2.SmoothStep(new Vector2(oldZoom, 0), new Vector2(extraZoomTarget, 0), zoomTimer / (float)maxTimer).X; + zoomOverride = Vector2.SmoothStep(new Vector2(oldZoom, 0), new Vector2(ExtraZoomTarget, 0), zoomTimer / (float)maxTimer).X; if (zoomOverride == Main.GameZoomTarget) oldZoom = Main.GameZoomTarget; - if (zoomTimer == maxTimer && extraZoomTarget == Main.GameZoomTarget) + if (zoomTimer == maxTimer && ExtraZoomTarget == Main.GameZoomTarget) maxTimer = 0; if (maxTimer == 0) diff --git a/Core/Systems/DummyTileSystem/Dummy.cs b/Core/Systems/DummyTileSystem/Dummy.cs index 9954227d2..9bd3f45e9 100644 --- a/Core/Systems/DummyTileSystem/Dummy.cs +++ b/Core/Systems/DummyTileSystem/Dummy.cs @@ -307,8 +307,7 @@ protected override void Receive() { Dummy dummy = DummyTile.GetDummy((int)(x / 16), (int)(y / 16), type); - if (dummy != null) - dummy.active = false; + dummy?.active = false; } } } \ No newline at end of file diff --git a/Helpers/DustHelper.cs b/Helpers/DustHelper.cs index 7f9d1419f..d4b7e204d 100644 --- a/Helpers/DustHelper.cs +++ b/Helpers/DustHelper.cs @@ -44,8 +44,7 @@ public static void SpawnImagePattern(Vector2 position, int dustType, float size, var d = Dust.NewDustPerfect(position, dustType, new Vector2((float)dustX, (float)dustY).RotatedBy(rotation), Alpha, (Color)color, dustSize); - if (d != null) - d.noGravity = noGravity; + d?.noGravity = noGravity; } } } @@ -92,8 +91,7 @@ public static void SpawnStillImagePattern(Vector2 position, int dustType, float var d = Dust.NewDustPerfect(position + new Vector2(dustX, dustY), dustType, Vector2.UnitX.RotatedByRandom(6.28f) * randomVel, Alpha, (Color)color, dustSize); - if (d != null) - d.noGravity = noGravity; + d?.noGravity = noGravity; } } } diff --git a/StarlightRiver.csproj b/StarlightRiver.csproj index 36a18203e..31120a097 100644 --- a/StarlightRiver.csproj +++ b/StarlightRiver.csproj @@ -4,7 +4,7 @@ StarlightRiver net8.0 - latest + preview true AnyCPU;x64;x86 From 56b7fadfa0d12e71f0ee576175b7436ed6d5a085 Mon Sep 17 00:00:00 2001 From: bobfishkins23 Date: Wed, 4 Mar 2026 19:36:06 -0500 Subject: [PATCH 13/13] Remove unused content --- Content/Alchemy/AlchemyIngredient.cs | 134 ---------- Content/Alchemy/AlchemyModifier.cs | 6 - Content/Alchemy/AlchemyRecipe.cs | 171 ------------- Content/Alchemy/AlchemyRecipeSystem.cs | 79 ------ Content/Alchemy/AlchemyWrapper.cs | 28 --- Content/Alchemy/Cauldron.cs | 70 ------ Content/Alchemy/CauldronDummyAbstract.cs | 238 ------------------ Content/Alchemy/GenericAlchemyIngredient.cs | 21 -- Content/Alchemy/Ingredients/DirtIngredient.cs | 34 --- .../Ingredients/DullBladeIngredient.cs | 31 --- .../Ingredients/LivingFireIngredient.cs | 19 -- .../Ingredients/VitricOreIngredient.cs | 38 --- Content/Alchemy/MixingStick.cs | 35 --- Content/Alchemy/Recipes/BloodCrystalRecipe.cs | 116 --------- .../Alchemy/Recipes/TaintedGreataxeRecipe.cs | 70 ------ .../Vitric/Temple/GearPuzzle/GearTile.cs | 24 +- 16 files changed, 7 insertions(+), 1107 deletions(-) delete mode 100644 Content/Alchemy/AlchemyIngredient.cs delete mode 100644 Content/Alchemy/AlchemyModifier.cs delete mode 100644 Content/Alchemy/AlchemyRecipe.cs delete mode 100644 Content/Alchemy/AlchemyRecipeSystem.cs delete mode 100644 Content/Alchemy/AlchemyWrapper.cs delete mode 100644 Content/Alchemy/Cauldron.cs delete mode 100644 Content/Alchemy/CauldronDummyAbstract.cs delete mode 100644 Content/Alchemy/GenericAlchemyIngredient.cs delete mode 100644 Content/Alchemy/Ingredients/DirtIngredient.cs delete mode 100644 Content/Alchemy/Ingredients/DullBladeIngredient.cs delete mode 100644 Content/Alchemy/Ingredients/LivingFireIngredient.cs delete mode 100644 Content/Alchemy/Ingredients/VitricOreIngredient.cs delete mode 100644 Content/Alchemy/MixingStick.cs delete mode 100644 Content/Alchemy/Recipes/BloodCrystalRecipe.cs delete mode 100644 Content/Alchemy/Recipes/TaintedGreataxeRecipe.cs diff --git a/Content/Alchemy/AlchemyIngredient.cs b/Content/Alchemy/AlchemyIngredient.cs deleted file mode 100644 index e94682959..000000000 --- a/Content/Alchemy/AlchemyIngredient.cs +++ /dev/null @@ -1,134 +0,0 @@ -using Terraria.DataStructures; -using Terraria.ID; - -namespace StarlightRiver.Content.Alchemy -{ - public abstract class AlchemyIngredient - { - /// - /// When instantiated by the cauldron dummy we may need to store exactly the Item being used as an ingredient so we don't lose properties on the ingredient like modifiers etc - /// - public Item storedItem; - - /// - /// Item type ID of the ingredient, use ItemType() to get Mod Item IDs and Terraria.ID.ItemID for vanilla Items - /// - public readonly int ItemType; - - /// - /// if not overriding default visuals this will be used to lerp the overall color towards this value. defaults to a sort of light blue - /// - public Color ingredientColor = new(3, 127, 252); - - protected int timeSinceAdded; - - public AlchemyIngredient() { } - - public abstract int GetItemID(); - - /// - /// for instantiating the actual Item into the ingredient - /// - /// - public void PutIngredient(Item ingredientItem) - { - this.storedItem = ingredientItem; - timeSinceAdded = 0; - } - - /// - /// called at the end of every frame that this is in the cauldron to increment the timer - /// 0 on first frame inserted - /// - public void IncrementTimer() - { - timeSinceAdded++; - } - - /// - /// performs logic and visuals while this is the most recent Item added to the cauldron. return true if visual updates should be skipped for other ingredents currently in cauldron - /// - public virtual bool MostRecentUpdate(AlchemyWrapper wrapper) - { - return false; - } - - /// - /// performs logic and visuals that occur AFTER ALL other ingredient visuals / logic are run while this is the most recent Item added to the cauldron - /// executes even if mostRecentUpdate returns true - /// by default just adds cauldron lighting for the resulting bubble color - /// - /// - public virtual void MostRecentPostUpdate(AlchemyWrapper wrapper) - { - Lighting.AddLight(wrapper.cauldronRect.TopLeft() + new Vector2(wrapper.cauldronRect.Width / 2, 0), wrapper.bubbleColor.ToVector3()); - } - - /// - /// perform logic updates while this is added to the cauldron, executed by both client and server. runs even if mostRecentUpdate returned true. - /// runs after the most recent ingredient executes mostRecentUpdate and executes in order of oldest ingredient to newest. also executes for most recent ingredient. - /// designed for the idea of "dangerous" ingredients that may damage nearby Players or have other tangible effects on the world and Players outside of just visuals - /// - public virtual void Update(AlchemyWrapper wrapper) - { - - } - - /// - /// Perform client-only updates while this is added to the cauldron runs after Update, skipped if mostRecentUpdate returned true. - /// Executes in order of the oldest ingredient to newest immediately after running Update for this ingredient - /// - public virtual void VisualUpdate(AlchemyWrapper wrapper) - { - wrapper.bubbleAnimationTimer += 0.1f; //slightly increase bubbling speed - - if (timeSinceAdded == 0) - { - for (int k = 0; k < 10; k++) - Dust.NewDust(wrapper.cauldronRect.TopLeft() + new Vector2(wrapper.cauldronRect.Width / 4, 0), wrapper.cauldronRect.Width / 2, 0, DustID.Water, 0, -6, 0, default, 1f); - - Terraria.Audio.SoundEngine.PlaySound(SoundID.Splash, wrapper.cauldronRect.Center.ToVector2()); - } - - wrapper.bubbleColor = Color.Lerp(wrapper.bubbleColor, ingredientColor, 0.7f); - - if (timeSinceAdded < 15) - { - wrapper.bubbleAnimationTimer += 2; - //lerp towards a white flash when freshly added - wrapper.bubbleColor = Color.Lerp(Color.White, wrapper.bubbleColor, timeSinceAdded / 15f); - } - } - - /// - /// spawns this Item into the world randomized in the cauldron's rectangle subtracting the consumedCount from the stack or doing nothing if 0 after subtracting - /// - /// - /// - public virtual void Dump(Rectangle cauldronRect) - { - if (storedItem.stack > 0) - { - //TODO: rework this to handle exact clone dropping like keeping modifiers, maybe look into calling newItem to get an open Main.item index and then replace it with the clone and net send it - Item.NewItem(new EntitySource_WorldEvent(), cauldronRect, storedItem.type, storedItem.stack); - } - - storedItem = null; - } - - /// - /// PRECONDITION: Item type matches this ingredient's Item type - /// Attempts to add the Item stack to the ingredient stack - /// return false if this is an ingredient that should not stack and instead create another AlchemyIngredient instance - /// by default adds the stack counts together, resets timeSinceAdded to 0 and returns true - /// - /// - /// - public virtual bool AddToStack(Item Item) - { - timeSinceAdded = 0; - storedItem.stack += Item.stack; - return true; - } - } -} \ No newline at end of file diff --git a/Content/Alchemy/AlchemyModifier.cs b/Content/Alchemy/AlchemyModifier.cs deleted file mode 100644 index c033f9717..000000000 --- a/Content/Alchemy/AlchemyModifier.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace StarlightRiver.Content.Alchemy -{ - class AlchemyModifier - { - } -} \ No newline at end of file diff --git a/Content/Alchemy/AlchemyRecipe.cs b/Content/Alchemy/AlchemyRecipe.cs deleted file mode 100644 index 60c058e93..000000000 --- a/Content/Alchemy/AlchemyRecipe.cs +++ /dev/null @@ -1,171 +0,0 @@ -using System; -using System.Collections.Generic; -using Terraria.DataStructures; - -namespace StarlightRiver.Content.Alchemy -{ - /// - /// base alchemy class, can be directly created if no unique visuals / logic is needed for the recipe - /// otherwise override and use provided hooks for more advanced logic and visuals - /// - public class AlchemyRecipe - { - - protected Dictionary requiredIngredientsMap = new(); - protected List requiredModifiers = new(); - - protected List outputItemList = new(); - - /// - /// adds this recipe to the recipe cache now that it is done - /// make sure to call this after adding all the modifiers / ingredients - /// - public void AddRecipe() - { - AlchemyRecipeSystem.recipeList.Add(this); - } - - public void AddOutputById(int outputItemId, int outputCount = 1) - { - var newOutput = new Item(); - newOutput.SetDefaults(outputItemId); - newOutput.stack = outputCount; - outputItemList.Add(newOutput); - } - - /// - /// creats an output by a clone of provided Item for potential exact matching - /// - /// - public void AddOutputByItem(Item Item) - { - outputItemList.Add(Item.Clone()); - } - - public void AddIngredientById(int requiredIngredientId, int inputCount = 1) - { - var newIngredient = new Item(); - newIngredient.SetDefaults(requiredIngredientId); - newIngredient.stack = inputCount; - requiredIngredientsMap.Add(requiredIngredientId, newIngredient); - } - - /// - /// creates an ingredient by a clone of provided Item for potential exact matching - /// - /// - public void AddIngredientByItem(Item Item) - { - requiredIngredientsMap.Add(Item.type, Item.Clone()); - } - - public void AddRequiredModifier(int requiredModifierTileId) - { - requiredModifiers.Add(requiredModifierTileId); - } - - /// - /// Runs when this recipe is the only possible remaining recipe from the current set of ingredients and has enough of each ingredient to be valid. - /// return true to block any individual ingredient code from running. - /// executes on client and server. - /// by default does no logic and returns false. - /// - /// - public virtual bool UpdateReady(AlchemyWrapper wrapper) - { - return false; - } - - /// - /// runs when this recipe is the only possible remaining recipe but the current set of ingredients is NOT valid for atleast one craft. - /// return true to block any individual ingredient code from running. - /// executes on client and server. - /// by default does not logic and returns false. - /// - /// - public virtual bool UpdateAlmostReady(AlchemyWrapper wrapper) - { - //TODO: maybe default to some kind of way to indicate to the Player they are on the right track but missing quantity / certain Items - return false; - } - - /// - /// Runs when Player has initiated crafting this recipe with all ingredients added. return true to skip individual ingredient code from running. - /// responsible for spawning in Items and visuals. - /// executes on client and server. return true to stop individual ingredient code from running. - /// by default consumes ingredients and spawns output instantly - /// - /// - public virtual bool UpdateCrafting(AlchemyWrapper wrapper, List currentingredients, CauldronDummyAbstract cauldronDummy) - { - foreach (Item eachOutputItem in outputItemList) - { - Item.NewItem(new EntitySource_WorldEvent(), wrapper.cauldronRect, eachOutputItem.type, eachOutputItem.stack * wrapper.currentBatchSize); - } - - foreach (AlchemyIngredient eachIngredient in currentingredients) - { - requiredIngredientsMap.TryGetValue(eachIngredient.storedItem.type, out Item requiredItem); - - eachIngredient.storedItem.stack -= requiredItem.stack * wrapper.currentBatchSize; - } - - cauldronDummy.DumpIngredients(); - - return false; - } - - /// - /// returns true if an Item is part of this recipe, false otherwise. - /// by default only checks Item Id, override for stricter checking (like weapon modifier, ensuring minimum amount at insertion time, fields on the Item, etc). - /// ignores minimum amounts by default under the assumption that Player can add the rest at a later step - /// - /// - public virtual bool CheckItem(Item Item) - { - return requiredIngredientsMap.ContainsKey(Item.type); - } - - /// - /// returns a number for the amount of times this ingredient can be batched in the recipe 0 if invalid/insufficient. - /// Used for ensuring the ingredient is valid and in proper stack size right before initializing the craft. - /// By default only checks id and stack. override if needs stricter checking (like weapon modifier, maximums, split Item stacks etc.). - /// - /// - /// - public virtual int CheckIngredientBatch(AlchemyIngredient ingredient) - { - if (requiredIngredientsMap.ContainsKey(ingredient.storedItem.type)) - { - requiredIngredientsMap.TryGetValue(ingredient.storedItem.type, out Item requiredItem); - - return ingredient.storedItem.stack / requiredItem.stack; - } - - return 0; - } - - /// - /// Returns number of times this recipe can craft if all the conditions are correct for the this recipe, otherwise 0 - /// - /// - /// - /// - public virtual int GetCraftBatchSize(List currentIngredients, List currentModifiers) - { - //if they don't match in count its not possible for it to be complete so we short circuit and avoid needing to iterate through lists multiple times - if (currentIngredients.Count != requiredIngredientsMap.Count) - return 0; - if (currentModifiers.Count != requiredModifiers.Count) - return 0; - - int batchSize = int.MaxValue; - foreach (AlchemyIngredient eachCurrentIngredient in currentIngredients) - { - batchSize = Math.Min(batchSize, CheckIngredientBatch(eachCurrentIngredient)); - } - - return batchSize; - } - } -} \ No newline at end of file diff --git a/Content/Alchemy/AlchemyRecipeSystem.cs b/Content/Alchemy/AlchemyRecipeSystem.cs deleted file mode 100644 index c18ef72b1..000000000 --- a/Content/Alchemy/AlchemyRecipeSystem.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace StarlightRiver.Content.Alchemy -{ - public static class AlchemyRecipeSystem - { - //static class to handle recipe loading / unloading as well as helper functions for codex integration and determining result of a list of ingredients - - public static List recipeList; - - /// - /// cache Types of all the alchemy ingredients in use, indexed by ItemId, - /// done this way since we want to instantiate new instances b/c there can be multiple cauldrons and we don't want to use reflection every time an ingredient needs to be created - /// - public static Dictionary allIngredientMap; - - public static void Load() - { - allIngredientMap = new Dictionary(); - recipeList = new List(); - //reflection to discover and cache AlchemyIngredient override types - Mod Mod = StarlightRiver.Instance; - foreach (Type type in Mod.Code.GetTypes().Where(t => !t.IsAbstract && t.IsSubclassOf(typeof(AlchemyIngredient)) && t != typeof(GenericAlchemyIngredient))) - { - var tempIngredient = (AlchemyIngredient)Activator.CreateInstance(type); - allIngredientMap.Add(tempIngredient.GetItemID(), type); - } - } - - public static void Unload() - { - if (allIngredientMap != null) - { - allIngredientMap.Clear(); - allIngredientMap = null; - } - - if (recipeList != null) - { - recipeList.Clear(); - recipeList = null; - } - } - - public static List GetRemainingPossiblities(Item addedItem, List previousPossibilities) - { - var remainingPossibilities = new List(); - foreach (AlchemyRecipe eachRecipe in previousPossibilities) - { - if (eachRecipe.CheckItem(addedItem)) - remainingPossibilities.Add(eachRecipe); - } - - return remainingPossibilities; - } - - /// - /// Creates an instance of AlchemyIngredient based on provided Item and puts the Item itself into the ingredient object - /// - /// - /// - public static AlchemyIngredient InstantiateIngredient(Item Item) - { - bool inMap = allIngredientMap.TryGetValue(Item.type, out Type ingredientClassType); - - AlchemyIngredient instantiatedIngredient; - - if (inMap) - instantiatedIngredient = (AlchemyIngredient)Activator.CreateInstance(ingredientClassType); - else - instantiatedIngredient = new GenericAlchemyIngredient(Item.type); - - instantiatedIngredient.PutIngredient(Item); - return instantiatedIngredient; - } - } -} \ No newline at end of file diff --git a/Content/Alchemy/AlchemyWrapper.cs b/Content/Alchemy/AlchemyWrapper.cs deleted file mode 100644 index b0760d8b6..000000000 --- a/Content/Alchemy/AlchemyWrapper.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace StarlightRiver.Content.Alchemy -{ - public class AlchemyWrapper - { - //used to pass around to all the alchemy components to maintain context about bubble color, position, modifiers etc - //add variables to this for more data - //cauldron should be resetting any relevant fields every frame otherwise keeps context between frames - - public Rectangle cauldronRect; - - public Color bubbleColor; - public Color bloomColor; - - /// - /// opacity of the bubbling fluid in the cauldron 1f is fully opaque, 0f is fully transparent - /// - public float bubbleOpacity = 1f; - - public float bubbleAnimationTimer; //float for % multipliers potentially - - public int bubbleAnimationFrame; - - public int timeSinceCraftStarted; - public int timeSinceCraftReady; - - public int currentBatchSize = 0; //when this has a value greater than 0, the recipe is ready - } -} \ No newline at end of file diff --git a/Content/Alchemy/Cauldron.cs b/Content/Alchemy/Cauldron.cs deleted file mode 100644 index bccfd8d97..000000000 --- a/Content/Alchemy/Cauldron.cs +++ /dev/null @@ -1,70 +0,0 @@ -using StarlightRiver.Content.Dusts; -using StarlightRiver.Core.Systems.DummyTileSystem; -using Terraria.ID; -using static Terraria.ModLoader.ModContent; - -namespace StarlightRiver.Content.Alchemy -{ - public class CauldronItem : ModItem - { - public override string Texture => AssetDirectory.Alchemy + Name; - - public override void SetStaticDefaults() - { - Tooltip.SetDefault("Places an Alchemic Cauldron"); - } - - public override void SetDefaults() - { - Item.width = 26; - Item.height = 22; - Item.maxStack = 99; - Item.useTurn = true; - Item.autoReuse = true; - Item.useAnimation = 15; - Item.useTime = 15; - Item.useStyle = ItemUseStyleID.Swing; - Item.consumable = true; - Item.value = 500; - Item.createTile = ModContent.TileType(); - } - } - - internal class CauldronTile : DummyTile - { - public override int DummyType => DummySystem.DummyType(); - - public override string Texture => AssetDirectory.Alchemy + Name; - - public override void SafeNearbyEffects(int i, int j, bool closer) - { - } - - public override void SetStaticDefaults() - { - this.QuickSetFurniture(3, 2, DustType(), SoundID.Tink, true, new Color(50, 50, 50), false, false, "Alchemic Cauldron"); - } - - public override bool RightClick(int i, int j) - { - int x = i - Main.tile[i, j].TileFrameX / 16 % 3; - int y = j - Main.tile[i, j].TileFrameY / 16 % 2; - if (DummyExists(x, y, DummyType)) - { - var cauldronDummy = (CauldronDummyAbstract)Dummy(x, y); - - if (Main.LocalPlayer.HeldItem.type == ModContent.ItemType()) - cauldronDummy.AttemptStartCraft(); - else - cauldronDummy.DumpIngredients(); - } - - return false; - } - } - - public class CauldronDummy : CauldronDummyAbstract - { - public CauldronDummy() : base(TileType(), 48, 32) { } - } -} \ No newline at end of file diff --git a/Content/Alchemy/CauldronDummyAbstract.cs b/Content/Alchemy/CauldronDummyAbstract.cs deleted file mode 100644 index 347a65f12..000000000 --- a/Content/Alchemy/CauldronDummyAbstract.cs +++ /dev/null @@ -1,238 +0,0 @@ -using StarlightRiver.Core.Systems.DummyTileSystem; -using System.Collections.Generic; -using static Terraria.ModLoader.ModContent; - -namespace StarlightRiver.Content.Alchemy -{ - public abstract class CauldronDummyAbstract : Dummy - { - //This serves as the core logic driver of the alchemy system - //any inputs and outputs will be routed through here - //and this will execute the calls to any ingredient logic and visuals - //Abstract so this can be overridden by more specific cauldrons if later there are multiple cauldrons with similar logic but different visuals - - protected List currentIngredients = new(); - protected List currentModifiers = new(); - - List possibleRecipes = AlchemyRecipeSystem.recipeList; - - AlchemyRecipe currentRecipe = null; - - AlchemyIngredient mostRecentIngredient = null; - readonly AlchemyWrapper wrapper = new(); - - protected bool isCrafting = false; //true when the ingredients are finalized and recipe is doing visuals/crafting - - public const int bubbleAnimationFrameTime = 8; - public const int bubbleAnimationFrames = 10; - public const int bubbleYOffset = 10; //bubble animation is centered in their frames so we need an offset to find bottom - - public int inputCooldown = 0; //if this is greater than 0, the cauldron will not take inputs until it reaches 0 again - - protected CauldronDummyAbstract(int validType, int width, int height) : base(validType, width, height) - { - } - - public override void Update() - { - if (!isCrafting && inputCooldown <= 0) - { - foreach (Item eachWorldItem in Main.item) - { - if (eachWorldItem.active && Hitbox.Contains(eachWorldItem.Center.ToPoint())) - { - if (AttemptAddItem(eachWorldItem.Clone())) - { - //todo: mp logic - eachWorldItem.active = false; - eachWorldItem.TurnToAir(); - } - } - } - } - - wrapper.bubbleColor = new Color(127, 127, 127); - wrapper.cauldronRect = Hitbox; - - bool skipIngredientLogic = false; - if (currentRecipe != null) - { - if (isCrafting) - { - skipIngredientLogic = currentRecipe.UpdateCrafting(wrapper, currentIngredients, this); - } - else if (wrapper.currentBatchSize > 0) - { - skipIngredientLogic = currentRecipe.UpdateReady(wrapper); - } - else - { - skipIngredientLogic = currentRecipe.UpdateAlmostReady(wrapper); - } - } - - if (mostRecentIngredient != null && !skipIngredientLogic) - { - bool ignoreRegularVisuals = mostRecentIngredient.MostRecentUpdate(wrapper); - - foreach (AlchemyIngredient ingredient in currentIngredients) - { - ingredient.Update(wrapper); - if (!ignoreRegularVisuals) - ingredient.VisualUpdate(wrapper); - ingredient.IncrementTimer(); - } - - mostRecentIngredient.MostRecentPostUpdate(wrapper); - } - - IncrementWrapperTimers(); - - if (inputCooldown > 0) - inputCooldown--; - } - - protected virtual void IncrementWrapperTimers() - { - wrapper.bubbleAnimationTimer++; - wrapper.timeSinceCraftStarted++; - wrapper.timeSinceCraftReady++; - - if (wrapper.bubbleAnimationTimer >= bubbleAnimationFrameTime) - { - wrapper.bubbleAnimationTimer = 0; - wrapper.bubbleAnimationFrame++; - wrapper.bubbleAnimationFrame %= bubbleAnimationFrames; - } - } - - public override void PostDraw(Color lightColor) - { - if (mostRecentIngredient != null && wrapper.bubbleOpacity > 0f) - { - Texture2D bubbleSheet = Request(AssetDirectory.Alchemy + "BubbleSheet").Value; - Texture2D bubbleGlow = Request(AssetDirectory.Alchemy + "BubbleSheetGlow").Value; - int frameHeight = bubbleSheet.Height / bubbleAnimationFrames; - - if (wrapper.bubbleOpacity > 1f) - wrapper.bubbleOpacity = 1f; - - wrapper.bubbleColor.A = (byte)(wrapper.bubbleColor.A * wrapper.bubbleOpacity); - SpriteBatch spriteBatch = Main.spriteBatch; - spriteBatch.Draw(bubbleSheet, position - Main.screenPosition - new Vector2(0, frameHeight - bubbleYOffset), new Rectangle(0, frameHeight * wrapper.bubbleAnimationFrame, bubbleSheet.Width, frameHeight), wrapper.bubbleColor); - - spriteBatch.End(); - spriteBatch.Begin(default, BlendState.Additive, SamplerState.PointClamp, default, Main.Rasterizer, default, Main.GameViewMatrix.TransformationMatrix); - - spriteBatch.Draw(bubbleGlow, position - Main.screenPosition - new Vector2(0, frameHeight - bubbleYOffset), new Rectangle(0, frameHeight * wrapper.bubbleAnimationFrame, bubbleSheet.Width, frameHeight), wrapper.bubbleColor * wrapper.bubbleOpacity); - - spriteBatch.End(); - spriteBatch.Begin(default, default, SamplerState.PointClamp, default, Main.Rasterizer, default, Main.GameViewMatrix.TransformationMatrix); - } - } - - /// - /// empties out cauldron and dumps Items into the world and resets any data like possible recipes - /// - public void DumpIngredients() - { - possibleRecipes = AlchemyRecipeSystem.recipeList; - mostRecentIngredient = null; - currentRecipe = null; - isCrafting = false; - wrapper.currentBatchSize = 0; - - foreach (AlchemyIngredient ingredient in currentIngredients) - { - ingredient.Dump(wrapper.cauldronRect); - } - - currentIngredients.Clear(); - inputCooldown = 120; - } - - public void ConsumeAndDumpIngredients() - { - - } - - /// - /// attempts to insert a specific Item into the cauldron. if cannot be added returns false and performs no additional logic. - /// if can be added will create and add ingredient to the current ingredients, and update possibleRecipes, returning true - /// - /// - /// - public bool AttemptAddItem(Item Item) - { - List newPossibilities = AlchemyRecipeSystem.GetRemainingPossiblities(Item, possibleRecipes); - if (newPossibilities != null && newPossibilities.Count >= 1) - { - //first attempts to stack into an existing ingredient stack - bool hasStack = false; - for (int i = 0; i < currentIngredients.Count; i++) - { - AlchemyIngredient eachIngredient = currentIngredients[i]; - if (eachIngredient.GetItemID() == Item.type) - { - if (eachIngredient.AddToStack(Item)) - { - mostRecentIngredient = eachIngredient; - - //move to end of list - currentIngredients.RemoveAt(i); - currentIngredients.Add(eachIngredient); - - hasStack = true; - break; - } - else - { - //if an ingredient stack is found but not stackable we can skip and return false - return false; - } - } - } - - if (!hasStack) - { - AlchemyIngredient newIngredient = AlchemyRecipeSystem.InstantiateIngredient(Item); - - mostRecentIngredient = newIngredient; - - currentIngredients.Add(newIngredient); - } - - possibleRecipes = newPossibilities; - - //TODO: mp logic here ? - //if it reaches here, means that Items were successfully added to the cauldron, so we check for full validation on the recipes to see if theres only 1 and its ready - if (possibleRecipes.Count == 1) - { - currentRecipe = possibleRecipes[0]; - wrapper.currentBatchSize = currentRecipe.GetCraftBatchSize(currentIngredients, currentModifiers); - } - else - { - currentRecipe = null; - wrapper.currentBatchSize = 0; - } - - return true; - } - - return false; - } - - public bool AttemptStartCraft() - { - if (currentRecipe != null && wrapper.currentBatchSize > 0 && !isCrafting) - { - wrapper.timeSinceCraftStarted = 0; - isCrafting = true; - return true; - } - - return false; - } - } -} \ No newline at end of file diff --git a/Content/Alchemy/GenericAlchemyIngredient.cs b/Content/Alchemy/GenericAlchemyIngredient.cs deleted file mode 100644 index 6c4c00808..000000000 --- a/Content/Alchemy/GenericAlchemyIngredient.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace StarlightRiver.Content.Alchemy -{ - public class GenericAlchemyIngredient : AlchemyIngredient - { - //this class is for instantiating generic ingredients that do not have any custom logic / visuals assigned to them - //defaults to using this for new ingredients if chosen Item Id is not in the AlchemyRecipeSystem cache - //ideally every alchemy ingredient will have its own awesome visuals eventually but this is a nice stopgap - - private readonly int ItemId; - - public GenericAlchemyIngredient(int ItemId) - { - ingredientColor = new Color(Main.rand.Next(255), Main.rand.Next(255), Main.rand.Next(255)); //just randomize it if its not a defined ingredient - this.ItemId = ItemId; - } - public override int GetItemID() - { - return ItemId; - } - } -} \ No newline at end of file diff --git a/Content/Alchemy/Ingredients/DirtIngredient.cs b/Content/Alchemy/Ingredients/DirtIngredient.cs deleted file mode 100644 index 4e21287e2..000000000 --- a/Content/Alchemy/Ingredients/DirtIngredient.cs +++ /dev/null @@ -1,34 +0,0 @@ -using StarlightRiver.Content.Dusts; -using Terraria.ID; - -namespace StarlightRiver.Content.Alchemy.Ingredients -{ - internal class DirtIngredient : AlchemyIngredient - { - //TODO: this is being treated as though it is the tarnished ring that does not exist yet, replace with tarnished ring - public DirtIngredient() - { - ingredientColor = Color.DarkRed; - } - - public override int GetItemID() - { - return ItemID.DirtBlock; - } - - public override void VisualUpdate(AlchemyWrapper wrapper) - { - base.VisualUpdate(wrapper); - - if (Main.rand.NextBool(20)) - { - Dust.NewDust(wrapper.cauldronRect.TopLeft() - new Vector2(0, 20), wrapper.cauldronRect.Width, 0, ModContent.DustType(), 0, -2, 120, Color.Black, 0.5f); - } - } - - public override bool AddToStack(Item Item) - { - return false; //unstackable equipment - } - } -} \ No newline at end of file diff --git a/Content/Alchemy/Ingredients/DullBladeIngredient.cs b/Content/Alchemy/Ingredients/DullBladeIngredient.cs deleted file mode 100644 index 6187fa93d..000000000 --- a/Content/Alchemy/Ingredients/DullBladeIngredient.cs +++ /dev/null @@ -1,31 +0,0 @@ -using StarlightRiver.Content.Dusts; -using StarlightRiver.Content.Items.Misc; - -namespace StarlightRiver.Content.Alchemy.Ingredients -{ - internal class DullBladeIngredient : AlchemyIngredient - { - public DullBladeIngredient() - { - ingredientColor = new Color(200, 200, 205); - } - - public override int GetItemID() - { - return ModContent.ItemType(); - } - - public override void VisualUpdate(AlchemyWrapper wrapper) - { - base.VisualUpdate(wrapper); - - if (Main.rand.NextBool(20)) - Dust.NewDust(wrapper.cauldronRect.TopLeft() + new Vector2(0, 20), wrapper.cauldronRect.Width, 0, ModContent.DustType(), 0, -2, 0, new Color(200, 200, 205) * 0.8f, 0.75f); - } - - public override bool AddToStack(Item Item) - { - return false; //unstackable equipment - } - } -} \ No newline at end of file diff --git a/Content/Alchemy/Ingredients/LivingFireIngredient.cs b/Content/Alchemy/Ingredients/LivingFireIngredient.cs deleted file mode 100644 index e40d78d4f..000000000 --- a/Content/Alchemy/Ingredients/LivingFireIngredient.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Terraria.ID; - -namespace StarlightRiver.Content.Alchemy.Ingredients -{ - class LivingFireIngredient : AlchemyIngredient - { - - //TODO: this is a placeholder for Blood replace with that once added - public LivingFireIngredient() - { - ingredientColor = Color.Red; - } - - public override int GetItemID() - { - return ItemID.LivingFireBlock; - } - } -} \ No newline at end of file diff --git a/Content/Alchemy/Ingredients/VitricOreIngredient.cs b/Content/Alchemy/Ingredients/VitricOreIngredient.cs deleted file mode 100644 index cc3beec5c..000000000 --- a/Content/Alchemy/Ingredients/VitricOreIngredient.cs +++ /dev/null @@ -1,38 +0,0 @@ -using StarlightRiver.Content.Dusts; - -namespace StarlightRiver.Content.Alchemy.Ingredients -{ - class VitricOreIngredient : AlchemyIngredient - { - public VitricOreIngredient() - { - ingredientColor = Color.Aquamarine; - } - - public override int GetItemID() - { - return ModContent.ItemType(); - } - - public override void VisualUpdate(AlchemyWrapper wrapper) - { - base.VisualUpdate(wrapper); - if (timeSinceAdded == 0) - { - for (int i = 0; i < 3; i++) - { - Dust.NewDust(wrapper.cauldronRect.TopLeft() - new Vector2(0, 25), wrapper.cauldronRect.Width, 25, ModContent.DustType(), 0, 0); - Dust.NewDust(wrapper.cauldronRect.TopLeft() - new Vector2(0, 25), wrapper.cauldronRect.Width, 25, ModContent.DustType(), 0, 0); - } - } - - if (Main.rand.NextBool(50)) - { - if (Main.rand.NextBool()) - Dust.NewDust(wrapper.cauldronRect.TopLeft() - new Vector2(0, 25), wrapper.cauldronRect.Width, 25, ModContent.DustType(), 0, 0); - else - Dust.NewDust(wrapper.cauldronRect.TopLeft() - new Vector2(0, 25), wrapper.cauldronRect.Width, 25, ModContent.DustType(), 0, 0); - } - } - } -} \ No newline at end of file diff --git a/Content/Alchemy/MixingStick.cs b/Content/Alchemy/MixingStick.cs deleted file mode 100644 index 8fc3954c8..000000000 --- a/Content/Alchemy/MixingStick.cs +++ /dev/null @@ -1,35 +0,0 @@ -using StarlightRiver.Core.Systems; -using Terraria.ID; - -namespace StarlightRiver.Content.Alchemy -{ - [SLRDebug] - public class MixingStick : ModItem - { - public override string Texture => AssetDirectory.Alchemy + Name; - - public override bool AltFunctionUse(Player Player) - { - return true; - } - - public override void SetStaticDefaults() - { - Tooltip.SetDefault("Mixing Stick\nUse this to finalize alchemy recipes to craft them."); - } - - public override void SetDefaults() - { - Item.width = 26; - Item.height = 22; - Item.maxStack = 99; - Item.useTurn = true; - Item.autoReuse = true; - Item.useAnimation = 15; - Item.useTime = 15; - Item.useStyle = ItemUseStyleID.Shoot; - Item.consumable = true; - Item.value = 500; - } - } -} \ No newline at end of file diff --git a/Content/Alchemy/Recipes/BloodCrystalRecipe.cs b/Content/Alchemy/Recipes/BloodCrystalRecipe.cs deleted file mode 100644 index a68a4af1e..000000000 --- a/Content/Alchemy/Recipes/BloodCrystalRecipe.cs +++ /dev/null @@ -1,116 +0,0 @@ -using StarlightRiver.Content.Dusts; -using StarlightRiver.Content.Items.Misc; -using StarlightRiver.Content.Items.Vitric; -using System.Collections.Generic; -using Terraria.DataStructures; -using Terraria.ID; - -namespace StarlightRiver.Content.Alchemy.Recipes -{ - public class BloodCrystalRecipe : AlchemyRecipe, IPostLoadable - { - public void PostLoad() - { - //todo: update with real components blood crystal, tarnished ring, blood when they are implemented - - AddIngredientById(ItemID.DirtBlock); //placeholder for "tarnished ring" - AddIngredientById(ItemID.LivingFireBlock); //placeholder for "blood" - AddIngredientById(ModContent.ItemType(), 16); - - AddOutputById(ModContent.ItemType()); //placeholder for "blood crystal" - - AddRecipe(); - } - - public void PostLoadUnload() - { - } - - public override bool UpdateCrafting(AlchemyWrapper wrapper, List currentingredients, CauldronDummyAbstract cauldronDummy) - { - if (wrapper.timeSinceCraftStarted < 60) - { - for (int i = 0; i < wrapper.timeSinceCraftStarted / 3; i++) - { - Dust.NewDust(wrapper.cauldronRect.TopLeft() + new Vector2(5, -30), wrapper.cauldronRect.Width - 10, 30, ModContent.DustType(), 0, -10, Scale: 0.3f); - } - } - - wrapper.bubbleColor = Color.Red; - - if (Main.rand.NextBool(10)) - { - if (Main.rand.NextBool()) - Dust.NewDust(wrapper.cauldronRect.TopLeft() - new Vector2(0, wrapper.timeSinceCraftStarted / 2), wrapper.cauldronRect.Width, 20, ModContent.DustType(), 0, 0, newColor: Color.Red); - else - Dust.NewDust(wrapper.cauldronRect.TopLeft() - new Vector2(0, wrapper.timeSinceCraftStarted / 2), wrapper.cauldronRect.Width, 20, ModContent.DustType(), 0, 0, newColor: Color.Red); - } - - if (wrapper.timeSinceCraftStarted > 60) - { - wrapper.bubbleOpacity = 1f - (wrapper.timeSinceCraftStarted - 60) * 0.025f; - } - - if (wrapper.timeSinceCraftStarted >= 200) - { - foreach (Item eachOutputItem in outputItemList) - { - Item.NewItem(new EntitySource_WorldEvent(), wrapper.cauldronRect.Center() - new Vector2(0, 100), Vector2.Zero, eachOutputItem.type, Stack: eachOutputItem.stack, prefixGiven: eachOutputItem.prefix); - } - - foreach (AlchemyIngredient eachIngredient in currentingredients) - { - requiredIngredientsMap.TryGetValue(eachIngredient.storedItem.type, out Item requiredItem); - - eachIngredient.storedItem.stack -= requiredItem.stack * wrapper.currentBatchSize; - } - - cauldronDummy.DumpIngredients(); - } - - return true; - } - } - public class BloodCrystalRecipeDust : ModDust - { - public override string Texture => AssetDirectory.Dust + "NeedlerDust"; - - public override void OnSpawn(Dust dust) - { - dust.noGravity = true; - dust.scale *= Main.rand.NextFloat(0.8f, 2f); - dust.frame = new Rectangle(0, 0, 34, 36); - } - - public override Color? GetAlpha(Dust dust, Color lightColor) - { - var gray = new Color(25, 25, 25); - return gray * ((255 - dust.alpha) / 255f); - } - - public override bool Update(Dust dust) - { - if (dust.velocity.Length() > 3) - dust.velocity *= 0.85f; - else - dust.velocity *= 0.92f; - - if (dust.alpha > 130) - { - dust.scale *= 0.92f; - dust.alpha += 8; - } - else - { - dust.alpha += 1; - } - - dust.position += dust.velocity; - - if (dust.alpha >= 255) - dust.active = false; - - return false; - } - } -} \ No newline at end of file diff --git a/Content/Alchemy/Recipes/TaintedGreataxeRecipe.cs b/Content/Alchemy/Recipes/TaintedGreataxeRecipe.cs deleted file mode 100644 index b9c9cd54a..000000000 --- a/Content/Alchemy/Recipes/TaintedGreataxeRecipe.cs +++ /dev/null @@ -1,70 +0,0 @@ -using StarlightRiver.Content.Dusts; -using StarlightRiver.Content.Items.Haunted; -using StarlightRiver.Content.Items.Misc; -using System.Collections.Generic; -using Terraria.Audio; -using Terraria.DataStructures; -using Terraria.ID; - -namespace StarlightRiver.Content.Alchemy.Recipes -{ - public class TaintedGreataxeRecipe : AlchemyRecipe, IPostLoadable - { - public void PostLoad() - { - AddIngredientById(ModContent.ItemType()); - AddIngredientById(ItemID.LivingFireBlock); //placeholder for "blood" - AddOutputById(ModContent.ItemType()); - AddRecipe(); - } - - public void PostLoadUnload() - { - } - - public override bool UpdateCrafting(AlchemyWrapper wrapper, List currentingredients, CauldronDummyAbstract cauldronDummy) - { - if (wrapper.timeSinceCraftStarted < 180) - { - if (wrapper.timeSinceCraftStarted % 3 == 0) - { - Dust.NewDust(wrapper.cauldronRect.TopLeft() + new Vector2(5, 20), wrapper.cauldronRect.Width - 10, 30, ModContent.DustType(), 0, -5, newColor: new Color(200, 200, 205) * 0.8f); - if (Main.rand.NextBool(3)) - Dust.NewDust(wrapper.cauldronRect.TopLeft() - new Vector2(0, 20), wrapper.cauldronRect.Width - 10, 30, ModContent.DustType(), 0, -3.5f, newColor: new Color(200, 200, 205), Scale: 0.35f); - - if (Main.rand.NextBool(3)) - Dust.NewDust(wrapper.cauldronRect.TopLeft() - new Vector2(0, 20), wrapper.cauldronRect.Width - 10, 30, ModContent.DustType(), 0, -3.5f, newColor: new Color(85, 220, 55), Scale: 0.35f); - } - } - - wrapper.bubbleColor = new Color(200, 200, 205); - - if (wrapper.timeSinceCraftStarted >= 200) - { - foreach (Item eachOutputItem in outputItemList) - { - Item.NewItem(new EntitySource_WorldEvent(), wrapper.cauldronRect.Center(), Vector2.Zero, eachOutputItem.type, Stack: eachOutputItem.stack, prefixGiven: eachOutputItem.prefix); - } - - foreach (AlchemyIngredient eachIngredient in currentingredients) - { - requiredIngredientsMap.TryGetValue(eachIngredient.storedItem.type, out Item requiredItem); - - eachIngredient.storedItem.stack -= requiredItem.stack * wrapper.currentBatchSize; - } - - for (int i = 0; i < 13; i++) - { - Dust.NewDust(wrapper.cauldronRect.TopLeft() + new Vector2(0, 5), wrapper.cauldronRect.Width - 10, 30, ModContent.DustType(), 0, -3.5f, newColor: new Color(200, 200, 205), Scale: 0.4f); - - Dust.NewDust(wrapper.cauldronRect.TopLeft() + new Vector2(0, 5), wrapper.cauldronRect.Width - 10, 30, ModContent.DustType(), 0, -3f, newColor: new Color(200, 200, 205), Scale: 0.45f); - } - - SoundEngine.PlaySound(SoundID.Splash, wrapper.cauldronRect.Center()); - cauldronDummy.DumpIngredients(); - } - - return true; - } - } -} \ No newline at end of file diff --git a/Content/Tiles/Vitric/Temple/GearPuzzle/GearTile.cs b/Content/Tiles/Vitric/Temple/GearPuzzle/GearTile.cs index 886737de2..9eebd9e73 100644 --- a/Content/Tiles/Vitric/Temple/GearPuzzle/GearTile.cs +++ b/Content/Tiles/Vitric/Temple/GearPuzzle/GearTile.cs @@ -307,10 +307,8 @@ protected bool Engaged return false; } - set - { - GearEntity?.engaged = value; - } + + set => GearEntity?.engaged = value; } protected float RotationVelocity @@ -322,10 +320,8 @@ protected float RotationVelocity return 0; } - set - { - GearEntity?.rotationVelocity = value; - } + + set => GearEntity?.rotationVelocity = value; } protected float RotationOffset @@ -337,10 +333,8 @@ protected float RotationOffset return 0; } - set - { - GearEntity?.rotationOffset = value; - } + + set => GearEntity?.rotationOffset = value; } protected GearTileEntity GearEntity @@ -358,11 +352,7 @@ protected GearTileEntity GearEntity public int GearSize { - get => GearEntity?.size ?? 0; - set - { - GearEntity?.size = value % 4; - } + get => GearEntity?.size ?? 0; set => GearEntity?.size = value % 4; } public float Rotation