Add visual affects to Developer and Singularity items

This commit is contained in:
2025-11-10 22:32:20 +00:00
parent 46390b8f80
commit 7038741693
2 changed files with 177 additions and 0 deletions
@@ -0,0 +1,36 @@
using Microsoft.Xna.Framework;
using System;
using Terraria;
using Terraria.ModLoader;
using Terraria.ID;
using System.Collections.Generic;
namespace ForgottenWawiTech.Content.Items.Global
{
// Appends a rainbow developer marker line to items with the Developer rarity
public class DeveloperRarityTooltip : GlobalItem
{
public override bool InstancePerEntity => false;
private static int DevRarityId => ModContent.RarityType<Content.Rarities.FWTDeveloperItem>();
public override void ModifyTooltips(Item item, List<TooltipLine> tooltips)
{
if (item.rare != DevRarityId)
return;
// Build a hue-cycling color for the tooltip text
float time = Main.GlobalTimeWrappedHourly;
// Cycle hue 0..1 over 5 seconds
float hue = (time / 5f) % 1f;
Color rainbow = Main.hslToRgb(hue, 1f, 0.5f);
var line = new TooltipLine(Mod, "DeveloperMarker", "-Developer Based Item-")
{
OverrideColor = rainbow
};
tooltips.Add(line);
}
}
}
@@ -0,0 +1,141 @@
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using ReLogic.Content;
using Terraria;
using Terraria.GameContent;
using Terraria.ID;
using Terraria.ModLoader;
namespace ForgottenWawiTech.Content.Items.Global
{
// Visual effects for items that use the Singularity rarity
public class SingularityRarityVisuals : GlobalItem
{
public override bool InstancePerEntity => false;
private static int SingularityRarityId => ModContent.RarityType<Content.Rarities.SingularityItem>();
private static bool IsSingularity(Item item) => item.rare == SingularityRarityId;
private static Color GetSingularityColor()
{
// Reuse the rarity's animated color so visuals stay in sync
var rarity = ModContent.GetInstance<Content.Rarities.SingularityItem>();
return rarity.RarityColor;
}
private static float GetBreathing(float hz, float minScale = 0.85f, float maxScale = 1.15f)
{
float t = Main.GlobalTimeWrappedHourly * hz * MathHelper.TwoPi;
float s = (float)(Math.Sin(t) * 0.5 + 0.5); // 0..1
return MathHelper.Lerp(minScale, maxScale, s);
}
public override void PostDrawInInventory(Item item, SpriteBatch spriteBatch, Vector2 position, Rectangle frame, Color drawColor, Color itemColor, Vector2 origin, float scale)
{
if (!IsSingularity(item))
return;
Texture2D texture = TextureAssets.Item[item.type].Value;
// Subtle chromatic aberration: red and blue edge offsets
float aberrPixels = 1f;
Color redTint = new Color(255, 60, 60) * 0.25f;
Color blueTint = new Color(60, 60, 255) * 0.25f;
spriteBatch.Draw(texture, position + new Vector2(aberrPixels, 0f), frame, redTint, 0f, origin, scale, SpriteEffects.None, 0f);
spriteBatch.Draw(texture, position + new Vector2(-aberrPixels, 0f), frame, blueTint, 0f, origin, scale, SpriteEffects.None, 0f);
// Optional glow overlay if a _Glow texture exists
if (TryGetGlowTexture(item, out var glowTex))
{
Color glowColor = GetSingularityColor();
float breathe = GetBreathing(0.5f, 0.9f, 1.2f);
spriteBatch.Draw(glowTex, position, frame, glowColor * 0.6f, 0f, origin, scale * breathe, SpriteEffects.None, 0f);
}
}
public override bool PreDrawInWorld(Item item, SpriteBatch spriteBatch, Color lightColor, Color alphaColor, ref float rotation, ref float scale, int whoAmI)
{
if (!IsSingularity(item))
return true; // not ours, let vanilla draw
Texture2D texture = TextureAssets.Item[item.type].Value;
Rectangle frame = Main.itemAnimations[item.type] != null
? Main.itemAnimations[item.type].GetFrame(texture)
: texture.Frame();
Vector2 drawPos = item.Center - Main.screenPosition;
Vector2 origin = frame.Size() / 2f;
// Sync light with rarity color (subtle)
Color pulse = GetSingularityColor();
Lighting.AddLight(item.Center, pulse.ToVector3() * 0.35f);
// Subtle chromatic aberration edges
float aberrPixels = 1f;
Color redTint = new Color(255, 60, 60) * 0.20f;
Color blueTint = new Color(60, 60, 255) * 0.20f;
spriteBatch.Draw(texture, drawPos + new Vector2(aberrPixels, 0f), frame, redTint, rotation, origin, scale, SpriteEffects.None, 0f);
spriteBatch.Draw(texture, drawPos + new Vector2(-aberrPixels, 0f), frame, blueTint, rotation, origin, scale, SpriteEffects.None, 0f);
// Optional glow overlay if a _Glow texture exists
if (TryGetGlowTexture(item, out var glowTex))
{
float breathe = GetBreathing(0.5f, 0.9f, 1.15f);
spriteBatch.Draw(glowTex, drawPos, frame, pulse * 0.7f, rotation, origin, scale * breathe, SpriteEffects.None, 0f);
}
return true; // continue with default draw
}
public override void HoldItem(Item item, Player player)
{
if (!IsSingularity(item))
return;
Color pulse = GetSingularityColor();
// Add light at the player's hand
Lighting.AddLight(player.MountedCenter, pulse.ToVector3() * 0.45f);
// Faint rotating dust ring to simulate an event horizon while held
int points = 8;
float radius = 10f;
float speed = 2.2f; // rotations per second
float t = Main.GlobalTimeWrappedHourly * speed * MathHelper.TwoPi;
for (int i = 0; i < points; i++)
{
float angle = t + (i / (float)points) * MathHelper.TwoPi;
Vector2 pos = player.MountedCenter + angle.ToRotationVector2() * radius;
Dust d = Dust.NewDustPerfect(pos, DustID.PurpleTorch, Vector2.Zero, 150, pulse, 0.9f);
if (d != null)
{
d.noGravity = true;
d.velocity = Vector2.Zero;
}
}
}
private static bool TryGetGlowTexture(Item item, out Texture2D texture)
{
texture = null;
// Only attempt for modded items that likely follow the _Glow convention
if (item.ModItem == null)
return false;
string path = item.ModItem.Texture + "_Glow";
if (ModContent.HasAsset(path))
{
Asset<Texture2D> asset = ModContent.Request<Texture2D>(path, AssetRequestMode.AsyncLoad);
if (asset.IsLoaded)
{
texture = asset.Value;
return true;
}
}
return false;
}
}
}