Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ExampleNewMod/ExampleNewMod.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="FortRise.Configuration" Version="1.5.0" />
<PackageReference Include="FortRise.Configuration" Version="1.5.6" />
</ItemGroup>
</Project>

Expand Down
132 changes: 132 additions & 0 deletions MiasmaColors/ColorUtils.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
Binary file not shown.

This file was deleted.

Binary file not shown.

This file was deleted.

Binary file not shown.

This file was deleted.

Binary file not shown.

This file was deleted.

Binary file not shown.

This file was deleted.

Binary file not shown.

This file was deleted.

Binary file not shown.

This file was deleted.

Binary file not shown.

This file was deleted.

Binary file not shown.

This file was deleted.

Binary file not shown.

This file was deleted.

Binary file not shown.

This file was deleted.

Binary file not shown.

This file was deleted.

Binary file not shown.

This file was deleted.

Binary file not shown.

This file was deleted.

128 changes: 89 additions & 39 deletions MiasmaColors/MiasmaColorsModule.cs
Original file line number Diff line number Diff line change
@@ -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>("Color");
originalLightColor = miasmaData.Get<Color>("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<string> tag)
{
for (int i = 0; i < tag.Count; i++)
Expand Down
44 changes: 44 additions & 0 deletions MiasmaColors/SubTextureModifier.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
2 changes: 1 addition & 1 deletion MiasmaColors/meta.json
Original file line number Diff line number Diff line change
@@ -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": [
Expand Down