diff --git a/ExampleNewMod/ExampleNewMod.csproj b/ExampleNewMod/ExampleNewMod.csproj index bf99f10..55dc13e 100644 --- a/ExampleNewMod/ExampleNewMod.csproj +++ b/ExampleNewMod/ExampleNewMod.csproj @@ -17,7 +17,7 @@ - + diff --git a/MiasmaColors/ColorUtils.cs b/MiasmaColors/ColorUtils.cs new file mode 100644 index 0000000..a534d8b --- /dev/null +++ b/MiasmaColors/ColorUtils.cs @@ -0,0 +1,132 @@ +using System; +using Microsoft.Xna.Framework; + +namespace MiasmaColors; + +public struct HSV +{ + public float H; + public float S; + public float V; + + public HSV(float h, float s, float v) + { + H = h; + S = s; + V = v; + } +} + +public static class ColorUtils +{ + public static HSV ColorToHSV(Color color) + { + // Normalize RGB to [0,1] + float r = color.R / 255f; + float g = color.G / 255f; + float b = color.B / 255f; + + float max = Math.Max(r, Math.Max(g, b)); + float min = Math.Min(r, Math.Min(g, b)); + float delta = max - min; + + float h = 0f; + + if (delta > 0f) + { + if (max == r) + { + h = 60f * (((g - b) / delta) % 6f); + } + else if (max == g) + { + h = 60f * (((b - r) / delta) + 2f); + } + else // max == b + { + h = 60f * (((r - g) / delta) + 4f); + } + } + + if (h < 0f) h += 360f; + + float s = (max == 0f) ? 0f : (delta / max); + float v = max; + + return new HSV(h, s, v); + } + + public static Color HSVToColor(HSV hsv, byte alpha = 255) + { + float h = hsv.H; + float s = hsv.S; + float v = hsv.V; + + float c = v * s; // Chroma + float x = c * (1 - Math.Abs((h / 60f) % 2 - 1)); + float m = v - c; + + float r1 = 0f, g1 = 0f, b1 = 0f; + + if (h < 60) + { + r1 = c; + g1 = x; + b1 = 0; + } + else if (h < 120) + { + r1 = x; + g1 = c; + b1 = 0; + } + else if (h < 180) + { + r1 = 0; + g1 = c; + b1 = x; + } + else if (h < 240) + { + r1 = 0; + g1 = x; + b1 = c; + } + else if (h < 300) + { + r1 = x; + g1 = 0; + b1 = c; + } + else + { + r1 = c; + g1 = 0; + b1 = x; + } + + byte r = (byte)((r1 + m) * 255f); + byte g = (byte)((g1 + m) * 255f); + byte b = (byte)((b1 + m) * 255f); + + return new Color(r, g, b, alpha); + } + + public static void HueShift(ref HSV hsv, float amount) + { + hsv.H += amount; + + // Wrap around 0-360 + if (hsv.H < 0f) + hsv.H += 360f; + else if (hsv.H >= 360f) + hsv.H -= 360f; + } + + public static Color HueShift(Color color, float amount) + { + HSV hsv = ColorToHSV(color); + HueShift(ref hsv, amount); + return HSVToColor(hsv, color.A); + } +} \ No newline at end of file diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Ascension.png b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Ascension.png deleted file mode 100644 index 1f8b63c..0000000 Binary files a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Ascension.png and /dev/null differ diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Ascension.tag b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Ascension.tag deleted file mode 100644 index 2a85ad5..0000000 --- a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Ascension.tag +++ /dev/null @@ -1 +0,0 @@ -level=Ascension diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Backfire.png b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Backfire.png deleted file mode 100644 index fa0dd2a..0000000 Binary files a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Backfire.png and /dev/null differ diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Backfire.tag b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Backfire.tag deleted file mode 100644 index 74af9be..0000000 --- a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Backfire.tag +++ /dev/null @@ -1 +0,0 @@ -level=Backfire diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Flight.png b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Flight.png deleted file mode 100644 index c490ffe..0000000 Binary files a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Flight.png and /dev/null differ diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Flight.tag b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Flight.tag deleted file mode 100644 index 18962ec..0000000 --- a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Flight.tag +++ /dev/null @@ -1 +0,0 @@ -level=Flight diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Frostfang Keep.png b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Frostfang Keep.png deleted file mode 100644 index ea22c06..0000000 Binary files a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Frostfang Keep.png and /dev/null differ diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Frostfang Keep.tag b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Frostfang Keep.tag deleted file mode 100644 index 9f91fef..0000000 --- a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Frostfang Keep.tag +++ /dev/null @@ -1 +0,0 @@ -level=Frostfang Keep diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Gauntlet II.png b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Gauntlet II.png deleted file mode 100644 index 1e88664..0000000 Binary files a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Gauntlet II.png and /dev/null differ diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Gauntlet II.tag b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Gauntlet II.tag deleted file mode 100644 index 4c2d9bc..0000000 --- a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Gauntlet II.tag +++ /dev/null @@ -1 +0,0 @@ -level=Gauntlet Ii diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Gauntlet.png b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Gauntlet.png deleted file mode 100644 index 59176e2..0000000 Binary files a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Gauntlet.png and /dev/null differ diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Gauntlet.tag b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Gauntlet.tag deleted file mode 100644 index 0df3488..0000000 --- a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Gauntlet.tag +++ /dev/null @@ -1 +0,0 @@ -level=Gauntlet diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--King's Court.png b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--King's Court.png deleted file mode 100644 index 8840f75..0000000 Binary files a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--King's Court.png and /dev/null differ diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--King's Court.tag b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--King's Court.tag deleted file mode 100644 index 3fd2f0b..0000000 --- a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--King's Court.tag +++ /dev/null @@ -1 +0,0 @@ -level=King's Court diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Mirage.png b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Mirage.png deleted file mode 100644 index 5eaadf6..0000000 Binary files a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Mirage.png and /dev/null differ diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Mirage.tag b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Mirage.tag deleted file mode 100644 index 37fc63c..0000000 --- a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Mirage.tag +++ /dev/null @@ -1 +0,0 @@ -level=Mirage diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Moonstone.png b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Moonstone.png deleted file mode 100644 index e805736..0000000 Binary files a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Moonstone.png and /dev/null differ diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Moonstone.tag b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Moonstone.tag deleted file mode 100644 index 96cc5ee..0000000 --- a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Moonstone.tag +++ /dev/null @@ -1 +0,0 @@ -level=Moonstone diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Sacred Ground.png b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Sacred Ground.png deleted file mode 100644 index 700fcae..0000000 Binary files a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Sacred Ground.png and /dev/null differ diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Sacred Ground.tag b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Sacred Ground.tag deleted file mode 100644 index 9fa4417..0000000 --- a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Sacred Ground.tag +++ /dev/null @@ -1 +0,0 @@ -level=Sacred Ground diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Sunken City.png b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Sunken City.png deleted file mode 100644 index 5ce9a67..0000000 Binary files a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Sunken City.png and /dev/null differ diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Sunken City.tag b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Sunken City.tag deleted file mode 100644 index 068fb58..0000000 --- a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Sunken City.tag +++ /dev/null @@ -1 +0,0 @@ -level=Sunken City diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Thornwood.png b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Thornwood.png deleted file mode 100644 index 8985cf2..0000000 Binary files a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Thornwood.png and /dev/null differ diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Thornwood.tag b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Thornwood.tag deleted file mode 100644 index c737f87..0000000 --- a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Thornwood.tag +++ /dev/null @@ -1 +0,0 @@ -level=Thornwood diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Towerforge.png b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Towerforge.png deleted file mode 100644 index 63f6c73..0000000 Binary files a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Towerforge.png and /dev/null differ diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Towerforge.tag b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Towerforge.tag deleted file mode 100644 index 0035984..0000000 --- a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Towerforge.tag +++ /dev/null @@ -1 +0,0 @@ -level=Towerforge diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Twilight Spire.png b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Twilight Spire.png deleted file mode 100644 index 405db23..0000000 Binary files a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Twilight Spire.png and /dev/null differ diff --git a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Twilight Spire.tag b/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Twilight Spire.tag deleted file mode 100644 index c88f366..0000000 --- a/MiasmaColors/Content/Atlas/atlas/quest/(floorMiasma)--Twilight Spire.tag +++ /dev/null @@ -1 +0,0 @@ -level=Twilight Spire diff --git a/MiasmaColors/MiasmaColorsModule.cs b/MiasmaColors/MiasmaColorsModule.cs index fe9ed3e..9312a5a 100644 --- a/MiasmaColors/MiasmaColorsModule.cs +++ b/MiasmaColors/MiasmaColorsModule.cs @@ -1,66 +1,116 @@ using System; using System.Collections.Generic; +using System.Reflection; using FortRise; +using HarmonyLib; +using Microsoft.Extensions.Logging; using Microsoft.Xna.Framework; -using Monocle; +using MonoMod.Utils; using TowerFall; namespace MiasmaColors; -public class MiasmaColorsModule : FortModule +public class MiasmaColorsModule : Mod { - public override void Load() - { - On.TowerFall.FloorMiasma.ctor += ApplyLightColorToMiasma; - } + public static MiasmaColorsModule Instance = null!; - public override void Unload() - { - On.TowerFall.FloorMiasma.ctor -= ApplyLightColorToMiasma; - } + private DynamicData miasmaData; + private DynamicData bottomMiasmaData; + private Color originalColor; + private Color originalLightColor; + + private SubTextureModifier surfaceModifier; + private SubTextureModifier tentaclesModifier; + private SubTextureModifier tentaclesHModifier; + private SubTextureModifier floorModfier; + + private bool colorsUpdated = false; - private void ApplyLightColorToMiasma(On.TowerFall.FloorMiasma.orig_ctor orig, FloorMiasma self, Vector2 position, int width, int group) + public MiasmaColorsModule(IModContent content, IModuleContext context, ILogger logger) : base(content, context, logger) { - orig(self, position, width, group); - self.Add(new MiasmaColorComponent()); + Instance = this; + + miasmaData = new DynamicData(typeof(Miasma)); + bottomMiasmaData = new DynamicData(typeof(BottomMiasma)); + + originalColor = miasmaData.Get("Color"); + originalLightColor = miasmaData.Get("Light"); + + OnInitialize = HandleInitialize; } -} -public class MiasmaColorComponent : Component -{ - public MiasmaColorComponent() : base(false, false) + private void HandleInitialize(IModuleContext context) { + floorModfier = new SubTextureModifier("quest/floorMiasma"); + surfaceModifier = new SubTextureModifier("miasma/surface"); + tentaclesModifier = new SubTextureModifier("miasma/tentacles"); + tentaclesHModifier = new SubTextureModifier("miasma/tentaclesH"); + + context.Events.OnLevelLoaded += HandleLevelLoaded; + context.Harmony.Patch(AccessTools.Method(typeof(LevelSystem), nameof(LevelSystem.Dispose)), postfix: new HarmonyMethod(LevelSystemDisposePostfix)); } - public override void EntityAdded() + private void HandleLevelLoaded(object sender, RoundLogic logic) { - base.EntityAdded(); - - var levelTag = ReadLevelTag(Scene.SceneTags); + if (!logic.CanMiasma || colorsUpdated) + return; + + var levelTag = ReadLevelTag(logic.Session.CurrentLevel.SceneTags); if (string.IsNullOrEmpty(levelTag)) return; - (Entity as LevelEntity).LightColor = (levelTag switch - { - "Sacred Ground" => Calc.HexToColor("ffd29e"), - "Twilight Spire" => Calc.HexToColor("e39eff"), - "Backfire" => Calc.HexToColor("9ecdff"), - "Flight" => Calc.HexToColor("ff9620"), - "Mirage" => Calc.HexToColor("ffff60"), - "Thornwood" => Calc.HexToColor("72ff66"), - "Frostfang Keep" => Calc.HexToColor("26fff5"), - "King's Court" => Calc.HexToColor("ff0000"), - "Sunken City" => Calc.HexToColor("50ffb1"), - "Moonstone" => Calc.HexToColor("7275dd"), - "Towerforge" => Calc.HexToColor("FF2000"), - "Ascension" => Calc.HexToColor("f8ffff"), - "Gauntlet" => Calc.HexToColor("616a9e"), - "Gauntlet II" => Calc.HexToColor("fbfcfc"), - _ => Calc.HexToColor("9ED1FF") - }).Invert(); + float shiftAmount = GetHueShiftForLevel(levelTag); + + surfaceModifier.ApplyHueShift(shiftAmount); + tentaclesModifier.ApplyHueShift(shiftAmount); + floorModfier.ApplyHueShift(shiftAmount); + + Color newColor = ColorUtils.HueShift(originalColor, shiftAmount); + miasmaData.Set("Color", newColor); + bottomMiasmaData.Set("Color", newColor); + + Color newLightColor = ColorUtils.HueShift(originalLightColor, shiftAmount); + miasmaData.Set("Light", newLightColor); + bottomMiasmaData.Set("Light", newLightColor); } + private static void LevelSystemDisposePostfix(LevelSystem __instance) + { + if (!Instance.colorsUpdated) + return; + + Instance.surfaceModifier.Reset(); + Instance.floorModfier.Reset(); + Instance.tentaclesModifier.Reset(); + Instance.tentaclesHModifier.Reset(); + } + private float GetHueShiftForLevel(string levelTag) + { + return levelTag switch + { + "SacredGround" => 132.8f, + "TwilightSpire" => 27.4f, + "Backfire" => -81.2f, + "Flight" => 113f, + "Mirage" => 143.8f, + "Thornwood" => -128.4f, + "FrostfangKeep" => -96.6f, + "KingsCourt" => 80f, + "SunkenCity" => -125f, + "Moonstone" => -62f, + "TowerForge" => 69.1f, + "Ascension" => -95.5f, + "GauntletA" => -63.7f, + "GauntletB" => -95.5f, + "TheAmaranth" => -152.6f, + "Dreadwood" => -180f, + "Darkfang" => -92.2f, + "Cataclysm" => 40.6f, + _ => 0 + }; + } + private static string ReadLevelTag(List tag) { for (int i = 0; i < tag.Count; i++) diff --git a/MiasmaColors/SubTextureModifier.cs b/MiasmaColors/SubTextureModifier.cs new file mode 100644 index 0000000..9c4041a --- /dev/null +++ b/MiasmaColors/SubTextureModifier.cs @@ -0,0 +1,44 @@ +using Microsoft.Xna.Framework; +using Monocle; +using TowerFall; + +namespace MiasmaColors; + +public class SubTextureModifier +{ + private string subtextureName; + + private Color[] originalColors; + private Subtexture texture; + + public SubTextureModifier(string subtextureName) + { + this.subtextureName = subtextureName; + texture = TFGame.Atlas[subtextureName]; + originalColors = new Color[texture.Width * texture.Height]; + TFGame.Atlas.Texture2D.GetData(0, texture.Rect, originalColors, 0, originalColors.Length); + } + + public void ApplyHueShift(float angle) + { + Color[] newColors = new Color[originalColors.Length]; + for (int i = 0; i < newColors.Length; i++) + { + if (originalColors[i].A == 0) + { + newColors[i] = originalColors[i]; + continue; + } + + HSV hsvColor = ColorUtils.ColorToHSV(originalColors[i]); + ColorUtils.HueShift(ref hsvColor, angle); + newColors[i] = ColorUtils.HSVToColor(hsvColor, originalColors[i].A); + } + TFGame.Atlas.Texture2D.SetData(0, texture.Rect, newColors, 0, newColors.Length); + } + + public void Reset() + { + TFGame.Atlas.Texture2D.SetData(0, texture.Rect, originalColors, 0, originalColors.Length); + } +} \ No newline at end of file diff --git a/MiasmaColors/meta.json b/MiasmaColors/meta.json index 26344d4..69ad46f 100644 --- a/MiasmaColors/meta.json +++ b/MiasmaColors/meta.json @@ -1,7 +1,7 @@ { "name": "Teuria.MiasmaColors", "version": "2.0.0", - "author": "Terria", + "author": "Terria, Lync", "description": "A mod that changes miasma colors in different level with different colors.", "dll": "MiasmaColors.dll", "dependencies": [