feat: Color damage numbers by damage class

This commit is contained in:
VAC committed 2026-10-16 00:30:44 -03:00
1 parent 746ad799a0
commit 3195e7ba92
6 files changed
+198

No files matched your search

+9
View File
@@ -98,6 +98,15 @@ public static partial class Settings
[nameof(EspWaypoints)] = "Esp.Waypoints.Enabled", [nameof(EspWaypoints)] = "Esp.Waypoints.Enabled",
[nameof(ColWaypoint)] = "Esp.Waypoints.Color", [nameof(ColWaypoint)] = "Esp.Waypoints.Color",
[nameof(DamageMelee)] = "DamageNumbers.Melee.Enabled",
[nameof(ColDamageMelee)] = "DamageNumbers.Melee.Color",
[nameof(DamageRanged)] = "DamageNumbers.Ranged.Enabled",
[nameof(ColDamageRanged)] = "DamageNumbers.Ranged.Color",
[nameof(DamageMagic)] = "DamageNumbers.Magic.Enabled",
[nameof(ColDamageMagic)] = "DamageNumbers.Magic.Color",
[nameof(DamageSummon)] = "DamageNumbers.Summon.Enabled",
[nameof(ColDamageSummon)] = "DamageNumbers.Summon.Color",
[nameof(Spelunker)] = "Vision.Spelunker", [nameof(Spelunker)] = "Vision.Spelunker",
[nameof(Hunter)] = "Vision.Hunter", [nameof(Hunter)] = "Vision.Hunter",
[nameof(Shine)] = "Vision.Shine", [nameof(Shine)] = "Vision.Shine",
+2
View File
@@ -46,6 +46,8 @@ public static partial class Settings
public static EspBoxStyle EspStyle; public static EspBoxStyle EspStyle;
public static float EspThickness = 1f, EspMaxDistance; // tiles, 0 = unlimited public static float EspThickness = 1f, EspMaxDistance; // tiles, 0 = unlimited
public static Color ColLocal = Color.White, ColPlayers = new(70, 200, 255), ColHostile = new(235, 60, 60), ColCritters = new(200, 170, 120), ColTown = new(80, 220, 110), ColBoss = new(255, 120, 40), ColItems = new(255, 210, 70), ColProjHostile = new(255, 80, 200), ColProjFriendly = new(120, 160, 255), ColWaypoint = new(220, 90, 255); public static Color ColLocal = Color.White, ColPlayers = new(70, 200, 255), ColHostile = new(235, 60, 60), ColCritters = new(200, 170, 120), ColTown = new(80, 220, 110), ColBoss = new(255, 120, 40), ColItems = new(255, 210, 70), ColProjHostile = new(255, 80, 200), ColProjFriendly = new(120, 160, 255), ColWaypoint = new(220, 90, 255);
public static bool DamageMelee, DamageRanged, DamageMagic, DamageSummon;
public static Color ColDamageMelee = new(255, 110, 60), ColDamageRanged = new(120, 230, 90), ColDamageMagic = new(90, 150, 255), ColDamageSummon = new(200, 110, 255);
public static bool Spelunker, Hunter, Shine, NightOwl, DangerSense, BiomeSight; public static bool Spelunker, Hunter, Shine, NightOwl, DangerSense, BiomeSight;
public static bool FreezeTime, SpawnRateBoost; public static bool FreezeTime, SpawnRateBoost;
+76
View File
@@ -0,0 +1,76 @@
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using TerraSharp.Core;
#if TMODLOADER
using Terraria.ModLoader;
#endif
namespace TerraSharp.Features;
public enum DamageKind { None, Melee, Ranged, Magic, Summon }
// Hit paths set Current around StrikeNPC; CombatText.NewText reads it.
public static class DamageNumbers
{
public static DamageKind Current;
public static Color? Recolor(Color color)
{
bool crit = color == CombatText.DamagedHostileCrit;
if (!crit && color != CombatText.DamagedHostile)
return null;
(bool enabled, Color chosen) = Current switch
{
DamageKind.Melee => (Settings.DamageMelee, Settings.ColDamageMelee),
DamageKind.Ranged => (Settings.DamageRanged, Settings.ColDamageRanged),
DamageKind.Magic => (Settings.DamageMagic, Settings.ColDamageMagic),
DamageKind.Summon => (Settings.DamageSummon, Settings.ColDamageSummon),
_ => (false, default),
};
if (!enabled)
return null;
var opaque = new Color(chosen.R, chosen.G, chosen.B);
return crit ? Color.Lerp(opaque, Color.White, 0.4f) : opaque;
}
#if TMODLOADER
// Whips count as melee too, so summon is checked first.
public static DamageKind Of(DamageClass? damageClass)
{
if (damageClass is null)
return DamageKind.None;
if (damageClass.CountsAsClass(DamageClass.Summon))
return DamageKind.Summon;
if (damageClass.CountsAsClass(DamageClass.Magic))
return DamageKind.Magic;
if (damageClass.CountsAsClass(DamageClass.Ranged))
return DamageKind.Ranged;
return damageClass.CountsAsClass(DamageClass.Melee) ? DamageKind.Melee : DamageKind.None;
}
#else
public static DamageKind Of(Projectile projectile)
{
if (projectile.minion || projectile.sentry || ProjectileID.Sets.IsAWhip[projectile.type] || ProjectileID.Sets.MinionShot[projectile.type] || ProjectileID.Sets.SentryShot[projectile.type])
return DamageKind.Summon;
if (projectile.magic)
return DamageKind.Magic;
if (projectile.ranged)
return DamageKind.Ranged;
return projectile.melee ? DamageKind.Melee : DamageKind.None;
}
public static DamageKind Of(Item item)
{
if (item.summon || item.sentry)
return DamageKind.Summon;
if (item.magic)
return DamageKind.Magic;
if (item.ranged)
return DamageKind.Ranged;
return item.melee ? DamageKind.Melee : DamageKind.None;
}
#endif
}
@@ -0,0 +1,103 @@
using System;
using Microsoft.Xna.Framework;
using Terraria;
using TerraSharp.Core;
using TerraSharp.Features;
#if !TMODLOADER
using Terraria.GameContent;
using Terraria.ID;
#endif
namespace TerraSharp.Patches;
internal static class DamageNumberPatches
{
delegate int NewTextOriginal(Rectangle location, Color color, string text, bool dramatic, bool dot);
internal static void Install(HookRegistry hooks)
{
hooks.Add(HookRegistry.Method(typeof(CombatText), nameof(CombatText.NewText), [typeof(Rectangle), typeof(Color), typeof(string), typeof(bool), typeof(bool)]), (Func<NewTextOriginal, Rectangle, Color, string, bool, bool, int>)NewText);
#if TMODLOADER
hooks.Add(HookRegistry.Method(typeof(NPC), nameof(NPC.StrikeNPC), [typeof(NPC.HitInfo), typeof(bool), typeof(bool)]), (Func<StrikeOriginal, NPC, NPC.HitInfo, bool, bool, int>)Strike);
#else
hooks.Add(typeof(Projectile), nameof(Projectile.Damage), (Action<ProjectileDamageOriginal, Projectile>)ProjectileDamage);
hooks.Add(typeof(Player), "ProcessHitAgainstNPC", (Action<MeleeHitOriginal, Player, Item, Rectangle, int, float, int>)MeleeHit);
hooks.Add(HookRegistry.Method(typeof(Player), nameof(Player.ApplyDamageToNPC), [typeof(NPC), typeof(int), typeof(float), typeof(int), typeof(bool), typeof(PlayerNPCHitSource)]), (Action<ApplyDamageOriginal, Player, NPC, int, float, int, bool, PlayerNPCHitSource>)ApplyDamage);
#endif
}
static int NewText(NewTextOriginal original, Rectangle location, Color color, string text, bool dramatic, bool dot)
{
if (Plugin.Active && DamageNumbers.Current != DamageKind.None && DamageNumbers.Recolor(color) is { } recolored)
color = recolored;
return original(location, color, text, dramatic, dot);
}
#if TMODLOADER
delegate int StrikeOriginal(NPC self, NPC.HitInfo hit, bool fromNet, bool noPlayerInteraction);
static int Strike(StrikeOriginal original, NPC self, NPC.HitInfo hit, bool fromNet, bool noPlayerInteraction)
{
DamageKind previous = DamageNumbers.Current;
DamageNumbers.Current = DamageNumbers.Of(hit.DamageType);
try
{
return original(self, hit, fromNet, noPlayerInteraction);
}
finally
{
DamageNumbers.Current = previous;
}
}
#else
delegate void ProjectileDamageOriginal(Projectile self);
delegate void MeleeHitOriginal(Player self, Item item, Rectangle itemRectangle, int originalDamage, float knockBack, int npcIndex);
delegate void ApplyDamageOriginal(Player self, NPC npc, int damage, float knockback, int direction, bool crit, PlayerNPCHitSource source);
static void ProjectileDamage(ProjectileDamageOriginal original, Projectile self)
{
DamageKind previous = DamageNumbers.Current;
DamageNumbers.Current = DamageNumbers.Of(self);
try
{
original(self);
}
finally
{
DamageNumbers.Current = previous;
}
}
static void MeleeHit(MeleeHitOriginal original, Player self, Item item, Rectangle itemRectangle, int originalDamage, float knockBack, int npcIndex)
{
DamageKind previous = DamageNumbers.Current;
DamageNumbers.Current = DamageNumbers.Of(item);
try
{
original(self, item, itemRectangle, originalDamage, knockBack, npcIndex);
}
finally
{
DamageNumbers.Current = previous;
}
}
// Dashes, buffs and contact damage pass the item or projectile that caused the hit.
static void ApplyDamage(ApplyDamageOriginal original, Player self, NPC npc, int damage, float knockback, int direction, bool crit, PlayerNPCHitSource source)
{
DamageKind previous = DamageNumbers.Current;
if (source.ProjType > 0 && ContentSamples.ProjectilesByType.TryGetValue(source.ProjType, out Projectile? projectile))
DamageNumbers.Current = DamageNumbers.Of(projectile);
else if (source.ItemType > 0 && ContentSamples.ItemsByType.TryGetValue(source.ItemType, out Item? item))
DamageNumbers.Current = DamageNumbers.Of(item);
try
{
original(self, npc, damage, knockback, direction, crit, source);
}
finally
{
DamageNumbers.Current = previous;
}
}
#endif
}
+1
View File
@@ -21,6 +21,7 @@ internal sealed class HookRegistry : IDisposable
MainPatches.Install(hooks); MainPatches.Install(hooks);
PlayerPatches.Install(hooks); PlayerPatches.Install(hooks);
NpcPatches.Install(hooks); NpcPatches.Install(hooks);
DamageNumberPatches.Install(hooks);
SpawnRatePatch.Install(hooks); SpawnRatePatch.Install(hooks);
ItemCheckShootPatch.Install(hooks); ItemCheckShootPatch.Install(hooks);
SandboxGuards.Install(hooks); SandboxGuards.Install(hooks);
+7
View File
@@ -175,6 +175,13 @@ public sealed partial class MainWindow
Toggle("Night Owl", ref Settings.NightOwl); Toggle("Night Owl", ref Settings.NightOwl);
Toggle("Shine", ref Settings.Shine); Toggle("Shine", ref Settings.Shine);
Toggle("Spelunker", ref Settings.Spelunker); Toggle("Spelunker", ref Settings.Spelunker);
Group("Damage Numbers");
Note("Colors your hits by damage class. Crits are lighter.");
ToggleColor("Magic", ref Settings.DamageMagic, ref Settings.ColDamageMagic, nameof(Settings.ColDamageMagic));
ToggleColor("Melee", ref Settings.DamageMelee, ref Settings.ColDamageMelee, nameof(Settings.ColDamageMelee));
ToggleColor("Ranged", ref Settings.DamageRanged, ref Settings.ColDamageRanged, nameof(Settings.ColDamageRanged));
ToggleColor("Summon", ref Settings.DamageSummon, ref Settings.ColDamageSummon, nameof(Settings.ColDamageSummon));
} }
void WorldPage() void WorldPage()