Подписывайтесь на наш Telegram и не пропускайте важные новости! Перейти

Визуальная часть TargetHud || Relake Client || 1.21.10 Fabric

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
24 Фев 2025
Сообщения
3
Реакции
1
Выберите загрузчик игры
  1. Fabric
Первая тема, не срите пж

Сделал этот тх за 15 - 20 с чем то минут

TargetHUD:
Expand Collapse Copy
package idk.relake.hud.impl;

import idk.relake.hud.HudElement;
import idk.relake.themes.ThemeManager;
import idk.relake.ui.UIRenderContext;
import idk.relake.utilities.ColorUtility;
import idk.relake.utilities.RenderUtility;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Identifier;

public final class TargetHUD extends HudElement {
    private LivingEntity target;
    private float lastHealth = 20f;
    private float animatedHealth = 20f;
    private float displayHealth = 20f;
    private long lastHealthChangeTime = 0;
    
    private float lastAbsorption = 0f;
    private float animatedAbsorption = 0f;
    private float displayAbsorption = 0f;
    private long lastAbsorptionChangeTime = 0;
    
    private float displayedHpNumber = 20f;
    private float targetHpNumber = 20f;
    private long lastHpNumberChange = 0;
    
    private float displayedAbsorptionNumber = 0f;
    private float targetAbsorptionNumber = 0f;
    private long lastAbsorptionNumberChange = 0;
    
    private String lastDisplayedName = "";
    private boolean wasNameTruncated = false;
    private long nameChangeTime = 0;
    private float nameAlphaAnimation = 1f;
    
    private boolean tookDamage = false;
    private long damageTime = 0;
    private final java.util.List<TearParticle> tears = new java.util.ArrayList<>();
    
    private static class TearParticle {
        float x, y;
        float velocityY;
        long spawnTime;
        
        TearParticle(float x, float y) {
            this.x = x;
            this.y = y;
            this.velocityY = 0.5f + (float) Math.random() * 0.5f;
            this.spawnTime = System.currentTimeMillis();
        }
        
        void update() {
            y += velocityY;
            velocityY += 0.05f;
        }
        
        boolean isExpired() {
            return System.currentTimeMillis() - spawnTime > 1000;
        }
    }
    
    public TargetHUD() {
        super("TargetHUD", 10, 30);
    }

    @Override
    public void render(UIRenderContext ctx) {
        MinecraftClient mc = MinecraftClient.getInstance();
        if (mc.player == null) {
            return;
        }

        this.target = mc.player;
        
        if (this.target == null) {
            return;
        }

        float width = 115f;
        float height = 34f;
        float headSize = 22f;
        float padding = 6f;
        
        this.width = width;
        this.height = height;

        int accent = ThemeManager.INSTANCE.getCurrentColor();
        
        ctx.rectangles().add(
                this.x, this.y, width, height,
                RenderUtility.vectorFromSingle(6),
                0xFF1A1D22, 0xFF3A3D42, 1);

        float headX = this.x + padding;
        float headY = this.y + (height - headSize) / 2f;
        
        ctx.images().add(Identifier.of("relake", "images/head.png"),
                        headX, headY, headSize, headSize, -1);
        
        long timeSinceDamage = System.currentTimeMillis() - damageTime;
        if (tookDamage && timeSinceDamage < 500) {
            float damageProgress = timeSinceDamage / 500f;
            
            float c1 = 1.70158f;
            float c3 = c1 + 1f;
            float easedProgress = 1f + c3 * (float) Math.pow(damageProgress - 1, 3) + c1 * (float) Math.pow(damageProgress - 1, 2);
            
            int redAlpha = (int) ((1f - easedProgress) * 100);
            if (redAlpha > 0) {
                int redOverlay = ColorUtility.withAlpha(0xFFFF0000, redAlpha);
                ctx.rectangles().add(
                        headX, headY, headSize, headSize,
                        RenderUtility.vectorFromSingle(0f),
                        redOverlay);
            }
        }

        String name = target.getName().getString();
        float textStartX = headX + headSize + padding;
        float nameY = this.y + 8f;
        
        float hp = target.getHealth();
        float absorption = 0f;
        
        if (target instanceof PlayerEntity player) {
            absorption = player.getAbsorptionAmount();
        }
        
        if (Math.abs(hp - targetHpNumber) > 0.1f) {
            targetHpNumber = hp;
            lastHpNumberChange = System.currentTimeMillis();
        }
        
        if (Math.abs(absorption - targetAbsorptionNumber) > 0.1f) {
            targetAbsorptionNumber = absorption;
            lastAbsorptionNumberChange = System.currentTimeMillis();
        }
        
        long hpTimeSinceChange = System.currentTimeMillis() - lastHpNumberChange;
        float hpAnimDuration = 400f;
        
        if (hpTimeSinceChange < hpAnimDuration) {
            float progress = hpTimeSinceChange / hpAnimDuration;
            float easedProgress = 1f - (float) Math.pow(1 - progress, 3);
            displayedHpNumber = displayedHpNumber + (targetHpNumber - displayedHpNumber) * easedProgress;
        } else {
            displayedHpNumber = targetHpNumber;
        }
        
        long absTimeSinceChange = System.currentTimeMillis() - lastAbsorptionNumberChange;
        float absAnimDuration = 400f;
        
        if (absTimeSinceChange < absAnimDuration) {
            float progress = absTimeSinceChange / absAnimDuration;
            float easedProgress = 1f - (float) Math.pow(1 - progress, 3);
            displayedAbsorptionNumber = displayedAbsorptionNumber + (targetAbsorptionNumber - displayedAbsorptionNumber) * easedProgress;
        } else {
            displayedAbsorptionNumber = targetAbsorptionNumber;
        }
        
        String hpMainText = String.valueOf((int) displayedHpNumber);
        String hpAbsorptionText = "";
        
        if (displayedAbsorptionNumber > 0.05f) {
            if (displayedAbsorptionNumber % 1 < 0.1f) {
                hpAbsorptionText = String.format(" + %d AB", (int) displayedAbsorptionNumber);
            } else {
                hpAbsorptionText = String.format(" + %.1f AB", displayedAbsorptionNumber);
            }
        }
        
        String fullHpText = hpMainText + hpAbsorptionText;
        float hpTextWidth = ctx.fontsMedium().getTextWidth(fullHpText, 8f);
        
        float maxNameWidth = width - (headSize + padding * 3) - hpTextWidth - 5f;
        String displayName = name;
        boolean isNameTruncated = false;
        
        if (ctx.fontsMedium().getTextWidth(name, 8f) > maxNameWidth) {
            isNameTruncated = true;
            while (ctx.fontsMedium().getTextWidth(displayName + "...", 8f) > maxNameWidth && displayName.length() > 0) {
                displayName = displayName.substring(0, displayName.length() - 1);
            }
            displayName += "...";
        }
        
        if (!displayName.equals(lastDisplayedName)) {
            lastDisplayedName = displayName;
            nameChangeTime = System.currentTimeMillis();
        }
        
        long nameTimeSinceChange = System.currentTimeMillis() - nameChangeTime;
        float nameAnimDuration = 300f;
        
        if (nameTimeSinceChange < nameAnimDuration) {
            float progress = nameTimeSinceChange / nameAnimDuration;
            nameAlphaAnimation = 1f - (float) Math.pow(1 - progress, 3);
        } else {
            nameAlphaAnimation = 1f;
        }
        
        if (isNameTruncated) {
            String mainPart = displayName.substring(0, displayName.length() - 3);
            String dotsPart = "...";
            
            ctx.fontsMedium().add(mainPart, textStartX, nameY, 8f, 0xFFFFFFFF);
            
            float dotsX = textStartX + ctx.fontsMedium().getTextWidth(mainPart, 8f);
            int dotsAlpha = (int) (nameAlphaAnimation * 255);
            int dotsColor = (dotsAlpha << 24) | 0x00FFFFFF;
            ctx.fontsMedium().add(dotsPart, dotsX, nameY, 8f, dotsColor);
        } else {
            ctx.fontsMedium().add(displayName, textStartX, nameY, 8f, 0xFFFFFFFF);
        }
        
        wasNameTruncated = isNameTruncated;
        
        float hpX = this.x + width - padding - hpTextWidth;
        
        int hpAlpha = 255;
        if (hpTimeSinceChange < 100) {
            float fadeProgress = hpTimeSinceChange / 100f;
            hpAlpha = (int) (200 + fadeProgress * 55);
        }
        
        int hpColor = (hpAlpha << 24) | 0x00FFFFFF;
        ctx.fontsMedium().add(hpMainText, hpX, nameY, 8f, hpColor);
        
        if (!hpAbsorptionText.isEmpty()) {
            float mainTextWidth = ctx.fontsMedium().getTextWidth(hpMainText, 8f);
            float currentX = hpX + mainTextWidth;
            
            int absBaseAlpha = 255;
            if (absTimeSinceChange < 100) {
                float fadeProgress = absTimeSinceChange / 100f;
                absBaseAlpha = (int) (200 + fadeProgress * 55);
            }
            
            for (int glowLayer = 5; glowLayer >= 1; glowLayer--) {
                int glowAlpha = (20 / glowLayer);
                int glowColor = (glowAlpha << 24) | 0x00FFD700;
                ctx.fontsMedium().add(hpAbsorptionText, currentX, nameY, 8f, glowColor);
            }
            
            int mainColor = (absBaseAlpha << 24) | 0x00FFD700;
            ctx.fontsMedium().add(hpAbsorptionText, currentX, nameY, 8f, mainColor);
        }

        float maxHp = target.getMaxHealth();
        float currentHp = hp;
        
        if (currentHp < lastHealth - 0.5f) {
            if (!tookDamage) {
                tookDamage = true;
                damageTime = System.currentTimeMillis();
                
                int tearCount = 3 + (int) (Math.random() * 3);
                for (int i = 0; i < tearCount; i++) {
                    float tearX = headX + headSize / 2f + (float) (Math.random() * 6 - 3);
                    float tearY = headY + headSize * 0.7f;
                    tears.add(new TearParticle(tearX, tearY));
                }
            }
        } else if (currentHp >= lastHealth) {
            tookDamage = false;
        }
        
        tears.removeIf(TearParticle::isExpired);
        for (TearParticle tear : tears) {
            tear.update();
            
            float tearSize = 2f;
            ctx.rectangles().add(
                    tear.x - tearSize / 2f,
                    tear.y - tearSize / 2f,
                    tearSize, tearSize,
                    RenderUtility.vectorFromSingle(tearSize / 2f),
                    0xFF87CEEB);
        }
        
        if (Math.abs(currentHp - lastHealth) > 0.1f) {
            lastHealth = currentHp;
            lastHealthChangeTime = System.currentTimeMillis();
        }
        
        long timeSinceChange = System.currentTimeMillis() - lastHealthChangeTime;
        float animationDuration = 500f;
        
        if (timeSinceChange < animationDuration) {
            float progress = timeSinceChange / animationDuration;
            
            float c1 = 1.70158f;
            float c3 = c1 + 1f;
            float easedProgress = 1f + c3 * (float) Math.pow(progress - 1, 3) + c1 * (float) Math.pow(progress - 1, 2);
            
            animatedHealth = animatedHealth + (currentHp - animatedHealth) * easedProgress;
        } else {
            animatedHealth = currentHp;
        }
        
        displayHealth = displayHealth + (animatedHealth - displayHealth) * 0.15f;
        
        float healthPercent = Math.min(1f, Math.max(0f, displayHealth / maxHp));
        
        float barY = this.y + height - 13f;
        float barHeight = 6f;
        float barWidth = width - (headSize + padding * 3);
        float barX = textStartX;
        
        ctx.rectangles().add(
                barX, barY, barWidth, barHeight,
                RenderUtility.vectorFromSingle(2f),
                0xFF1A1D22);
        
        if (healthPercent > 0f) {
            float pulseScale = 1f;
            if (timeSinceChange < 200) {
                float pulseProgress = timeSinceChange / 200f;
                pulseScale = 1f + (1f - pulseProgress) * 0.15f;
            }
            
            float animatedBarHeight = barHeight * pulseScale;
            float barOffsetY = (barHeight - animatedBarHeight) / 2f;
            float barFilledWidth = barWidth * healthPercent;
            
            for (int glowLayer = 5; glowLayer >= 1; glowLayer--) {
                float glowSize = glowLayer * 1.5f;
                int glowAlpha = 20 / glowLayer;
                int glowColor = ColorUtility.withAlpha(0xFFFFFFFF, glowAlpha);
                
                ctx.rectangles().add(
                        barX - glowSize / 2f,
                        barY + barOffsetY - glowSize / 2f,
                        barFilledWidth + glowSize,
                        animatedBarHeight + glowSize,
                        RenderUtility.vectorFromSingle(2f + glowSize / 2f),
                        glowColor);
            }
            
            ctx.rectangles().add(
                    barX, barY + barOffsetY, barFilledWidth, animatedBarHeight,
                    RenderUtility.vectorFromSingle(2f),
                    0xFFB0B0B0, 0xFFFFFFFF);
        }
        
        if (target instanceof PlayerEntity player) {
            float absorptionAmount = player.getAbsorptionAmount();
            
            if (absorptionAmount > 0f) {
                if (Math.abs(absorptionAmount - lastAbsorption) > 0.1f) {
                    lastAbsorption = absorptionAmount;
                    lastAbsorptionChangeTime = System.currentTimeMillis();
                }
                
                long absorptionTimeSinceChange = System.currentTimeMillis() - lastAbsorptionChangeTime;
                float absorptionAnimDuration = 500f;
                
                if (absorptionTimeSinceChange < absorptionAnimDuration) {
                    float progress = absorptionTimeSinceChange / absorptionAnimDuration;
                    float c1 = 1.70158f;
                    float c3 = c1 + 1f;
                    float easedProgress = 1f + c3 * (float) Math.pow(progress - 1, 3) + c1 * (float) Math.pow(progress - 1, 2);
                    animatedAbsorption = animatedAbsorption + (absorptionAmount - animatedAbsorption) * easedProgress;
                } else {
                    animatedAbsorption = absorptionAmount;
                }
                
                displayAbsorption = displayAbsorption + (animatedAbsorption - displayAbsorption) * 0.15f;
                
                float absorptionPercent = Math.min(1f, displayAbsorption / 20f);
                
                float absorptionPulseScale = 1f;
                if (absorptionTimeSinceChange < 200) {
                    float pulseProgress = absorptionTimeSinceChange / 200f;
                    absorptionPulseScale = 1f + (1f - pulseProgress) * 0.15f;
                }
                
                float absorptionBarHeight = barHeight * absorptionPulseScale;
                float absorptionBarOffsetY = (barHeight - absorptionBarHeight) / 2f;
                float absorptionBarWidth = barWidth * absorptionPercent;
                
                int absorptionColorFull = 0xFFFFD700;
                int absorptionColorFade = 0x00FFD700;
                
                float absorptionBarX = this.x + width - padding - absorptionBarWidth;
                float absorptionBarY = barY;
                
                for (int glowLayer = 3; glowLayer >= 1; glowLayer--) {
                    float glowSize = glowLayer * 1.5f;
                    int glowAlpha = 20 / glowLayer;
                    int glowColor = ColorUtility.withAlpha(absorptionColorFull, glowAlpha);
                    
                    ctx.rectangles().add(
                            absorptionBarX - glowSize / 2f,
                            absorptionBarY + absorptionBarOffsetY - glowSize / 2f,
                            absorptionBarWidth + glowSize,
                            absorptionBarHeight + glowSize,
                            RenderUtility.vectorFromSingle(2f + glowSize / 2f),
                            glowColor);
                }
                
                ctx.rectangles().add(
                        absorptionBarX, absorptionBarY + absorptionBarOffsetY, absorptionBarWidth, absorptionBarHeight,
                        RenderUtility.vectorFromSingle(2f),
                        absorptionColorFade, absorptionColorFull);
            }
        }
    }
    
    public void setTarget(LivingEntity target) {
        this.target = target;
    }
}
SS:
 

Вложения

  • Screenshot 2026-02-25 213938.png
    Screenshot 2026-02-25 213938.png
    25.5 KB · Просмотры: 155
Первая тема, не срите пж

Сделал этот тх за 15 - 20 с чем то минут

TargetHUD:
Expand Collapse Copy
package idk.relake.hud.impl;

import idk.relake.hud.HudElement;
import idk.relake.themes.ThemeManager;
import idk.relake.ui.UIRenderContext;
import idk.relake.utilities.ColorUtility;
import idk.relake.utilities.RenderUtility;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Identifier;

public final class TargetHUD extends HudElement {
    private LivingEntity target;
    private float lastHealth = 20f;
    private float animatedHealth = 20f;
    private float displayHealth = 20f;
    private long lastHealthChangeTime = 0;
   
    private float lastAbsorption = 0f;
    private float animatedAbsorption = 0f;
    private float displayAbsorption = 0f;
    private long lastAbsorptionChangeTime = 0;
   
    private float displayedHpNumber = 20f;
    private float targetHpNumber = 20f;
    private long lastHpNumberChange = 0;
   
    private float displayedAbsorptionNumber = 0f;
    private float targetAbsorptionNumber = 0f;
    private long lastAbsorptionNumberChange = 0;
   
    private String lastDisplayedName = "";
    private boolean wasNameTruncated = false;
    private long nameChangeTime = 0;
    private float nameAlphaAnimation = 1f;
   
    private boolean tookDamage = false;
    private long damageTime = 0;
    private final java.util.List<TearParticle> tears = new java.util.ArrayList<>();
   
    private static class TearParticle {
        float x, y;
        float velocityY;
        long spawnTime;
       
        TearParticle(float x, float y) {
            this.x = x;
            this.y = y;
            this.velocityY = 0.5f + (float) Math.random() * 0.5f;
            this.spawnTime = System.currentTimeMillis();
        }
       
        void update() {
            y += velocityY;
            velocityY += 0.05f;
        }
       
        boolean isExpired() {
            return System.currentTimeMillis() - spawnTime > 1000;
        }
    }
   
    public TargetHUD() {
        super("TargetHUD", 10, 30);
    }

    @Override
    public void render(UIRenderContext ctx) {
        MinecraftClient mc = MinecraftClient.getInstance();
        if (mc.player == null) {
            return;
        }

        this.target = mc.player;
       
        if (this.target == null) {
            return;
        }

        float width = 115f;
        float height = 34f;
        float headSize = 22f;
        float padding = 6f;
       
        this.width = width;
        this.height = height;

        int accent = ThemeManager.INSTANCE.getCurrentColor();
       
        ctx.rectangles().add(
                this.x, this.y, width, height,
                RenderUtility.vectorFromSingle(6),
                0xFF1A1D22, 0xFF3A3D42, 1);

        float headX = this.x + padding;
        float headY = this.y + (height - headSize) / 2f;
       
        ctx.images().add(Identifier.of("relake", "images/head.png"),
                        headX, headY, headSize, headSize, -1);
       
        long timeSinceDamage = System.currentTimeMillis() - damageTime;
        if (tookDamage && timeSinceDamage < 500) {
            float damageProgress = timeSinceDamage / 500f;
           
            float c1 = 1.70158f;
            float c3 = c1 + 1f;
            float easedProgress = 1f + c3 * (float) Math.pow(damageProgress - 1, 3) + c1 * (float) Math.pow(damageProgress - 1, 2);
           
            int redAlpha = (int) ((1f - easedProgress) * 100);
            if (redAlpha > 0) {
                int redOverlay = ColorUtility.withAlpha(0xFFFF0000, redAlpha);
                ctx.rectangles().add(
                        headX, headY, headSize, headSize,
                        RenderUtility.vectorFromSingle(0f),
                        redOverlay);
            }
        }

        String name = target.getName().getString();
        float textStartX = headX + headSize + padding;
        float nameY = this.y + 8f;
       
        float hp = target.getHealth();
        float absorption = 0f;
       
        if (target instanceof PlayerEntity player) {
            absorption = player.getAbsorptionAmount();
        }
       
        if (Math.abs(hp - targetHpNumber) > 0.1f) {
            targetHpNumber = hp;
            lastHpNumberChange = System.currentTimeMillis();
        }
       
        if (Math.abs(absorption - targetAbsorptionNumber) > 0.1f) {
            targetAbsorptionNumber = absorption;
            lastAbsorptionNumberChange = System.currentTimeMillis();
        }
       
        long hpTimeSinceChange = System.currentTimeMillis() - lastHpNumberChange;
        float hpAnimDuration = 400f;
       
        if (hpTimeSinceChange < hpAnimDuration) {
            float progress = hpTimeSinceChange / hpAnimDuration;
            float easedProgress = 1f - (float) Math.pow(1 - progress, 3);
            displayedHpNumber = displayedHpNumber + (targetHpNumber - displayedHpNumber) * easedProgress;
        } else {
            displayedHpNumber = targetHpNumber;
        }
       
        long absTimeSinceChange = System.currentTimeMillis() - lastAbsorptionNumberChange;
        float absAnimDuration = 400f;
       
        if (absTimeSinceChange < absAnimDuration) {
            float progress = absTimeSinceChange / absAnimDuration;
            float easedProgress = 1f - (float) Math.pow(1 - progress, 3);
            displayedAbsorptionNumber = displayedAbsorptionNumber + (targetAbsorptionNumber - displayedAbsorptionNumber) * easedProgress;
        } else {
            displayedAbsorptionNumber = targetAbsorptionNumber;
        }
       
        String hpMainText = String.valueOf((int) displayedHpNumber);
        String hpAbsorptionText = "";
       
        if (displayedAbsorptionNumber > 0.05f) {
            if (displayedAbsorptionNumber % 1 < 0.1f) {
                hpAbsorptionText = String.format(" + %d AB", (int) displayedAbsorptionNumber);
            } else {
                hpAbsorptionText = String.format(" + %.1f AB", displayedAbsorptionNumber);
            }
        }
       
        String fullHpText = hpMainText + hpAbsorptionText;
        float hpTextWidth = ctx.fontsMedium().getTextWidth(fullHpText, 8f);
       
        float maxNameWidth = width - (headSize + padding * 3) - hpTextWidth - 5f;
        String displayName = name;
        boolean isNameTruncated = false;
       
        if (ctx.fontsMedium().getTextWidth(name, 8f) > maxNameWidth) {
            isNameTruncated = true;
            while (ctx.fontsMedium().getTextWidth(displayName + "...", 8f) > maxNameWidth && displayName.length() > 0) {
                displayName = displayName.substring(0, displayName.length() - 1);
            }
            displayName += "...";
        }
       
        if (!displayName.equals(lastDisplayedName)) {
            lastDisplayedName = displayName;
            nameChangeTime = System.currentTimeMillis();
        }
       
        long nameTimeSinceChange = System.currentTimeMillis() - nameChangeTime;
        float nameAnimDuration = 300f;
       
        if (nameTimeSinceChange < nameAnimDuration) {
            float progress = nameTimeSinceChange / nameAnimDuration;
            nameAlphaAnimation = 1f - (float) Math.pow(1 - progress, 3);
        } else {
            nameAlphaAnimation = 1f;
        }
       
        if (isNameTruncated) {
            String mainPart = displayName.substring(0, displayName.length() - 3);
            String dotsPart = "...";
           
            ctx.fontsMedium().add(mainPart, textStartX, nameY, 8f, 0xFFFFFFFF);
           
            float dotsX = textStartX + ctx.fontsMedium().getTextWidth(mainPart, 8f);
            int dotsAlpha = (int) (nameAlphaAnimation * 255);
            int dotsColor = (dotsAlpha << 24) | 0x00FFFFFF;
            ctx.fontsMedium().add(dotsPart, dotsX, nameY, 8f, dotsColor);
        } else {
            ctx.fontsMedium().add(displayName, textStartX, nameY, 8f, 0xFFFFFFFF);
        }
       
        wasNameTruncated = isNameTruncated;
       
        float hpX = this.x + width - padding - hpTextWidth;
       
        int hpAlpha = 255;
        if (hpTimeSinceChange < 100) {
            float fadeProgress = hpTimeSinceChange / 100f;
            hpAlpha = (int) (200 + fadeProgress * 55);
        }
       
        int hpColor = (hpAlpha << 24) | 0x00FFFFFF;
        ctx.fontsMedium().add(hpMainText, hpX, nameY, 8f, hpColor);
       
        if (!hpAbsorptionText.isEmpty()) {
            float mainTextWidth = ctx.fontsMedium().getTextWidth(hpMainText, 8f);
            float currentX = hpX + mainTextWidth;
           
            int absBaseAlpha = 255;
            if (absTimeSinceChange < 100) {
                float fadeProgress = absTimeSinceChange / 100f;
                absBaseAlpha = (int) (200 + fadeProgress * 55);
            }
           
            for (int glowLayer = 5; glowLayer >= 1; glowLayer--) {
                int glowAlpha = (20 / glowLayer);
                int glowColor = (glowAlpha << 24) | 0x00FFD700;
                ctx.fontsMedium().add(hpAbsorptionText, currentX, nameY, 8f, glowColor);
            }
           
            int mainColor = (absBaseAlpha << 24) | 0x00FFD700;
            ctx.fontsMedium().add(hpAbsorptionText, currentX, nameY, 8f, mainColor);
        }

        float maxHp = target.getMaxHealth();
        float currentHp = hp;
       
        if (currentHp < lastHealth - 0.5f) {
            if (!tookDamage) {
                tookDamage = true;
                damageTime = System.currentTimeMillis();
               
                int tearCount = 3 + (int) (Math.random() * 3);
                for (int i = 0; i < tearCount; i++) {
                    float tearX = headX + headSize / 2f + (float) (Math.random() * 6 - 3);
                    float tearY = headY + headSize * 0.7f;
                    tears.add(new TearParticle(tearX, tearY));
                }
            }
        } else if (currentHp >= lastHealth) {
            tookDamage = false;
        }
       
        tears.removeIf(TearParticle::isExpired);
        for (TearParticle tear : tears) {
            tear.update();
           
            float tearSize = 2f;
            ctx.rectangles().add(
                    tear.x - tearSize / 2f,
                    tear.y - tearSize / 2f,
                    tearSize, tearSize,
                    RenderUtility.vectorFromSingle(tearSize / 2f),
                    0xFF87CEEB);
        }
       
        if (Math.abs(currentHp - lastHealth) > 0.1f) {
            lastHealth = currentHp;
            lastHealthChangeTime = System.currentTimeMillis();
        }
       
        long timeSinceChange = System.currentTimeMillis() - lastHealthChangeTime;
        float animationDuration = 500f;
       
        if (timeSinceChange < animationDuration) {
            float progress = timeSinceChange / animationDuration;
           
            float c1 = 1.70158f;
            float c3 = c1 + 1f;
            float easedProgress = 1f + c3 * (float) Math.pow(progress - 1, 3) + c1 * (float) Math.pow(progress - 1, 2);
           
            animatedHealth = animatedHealth + (currentHp - animatedHealth) * easedProgress;
        } else {
            animatedHealth = currentHp;
        }
       
        displayHealth = displayHealth + (animatedHealth - displayHealth) * 0.15f;
       
        float healthPercent = Math.min(1f, Math.max(0f, displayHealth / maxHp));
       
        float barY = this.y + height - 13f;
        float barHeight = 6f;
        float barWidth = width - (headSize + padding * 3);
        float barX = textStartX;
       
        ctx.rectangles().add(
                barX, barY, barWidth, barHeight,
                RenderUtility.vectorFromSingle(2f),
                0xFF1A1D22);
       
        if (healthPercent > 0f) {
            float pulseScale = 1f;
            if (timeSinceChange < 200) {
                float pulseProgress = timeSinceChange / 200f;
                pulseScale = 1f + (1f - pulseProgress) * 0.15f;
            }
           
            float animatedBarHeight = barHeight * pulseScale;
            float barOffsetY = (barHeight - animatedBarHeight) / 2f;
            float barFilledWidth = barWidth * healthPercent;
           
            for (int glowLayer = 5; glowLayer >= 1; glowLayer--) {
                float glowSize = glowLayer * 1.5f;
                int glowAlpha = 20 / glowLayer;
                int glowColor = ColorUtility.withAlpha(0xFFFFFFFF, glowAlpha);
               
                ctx.rectangles().add(
                        barX - glowSize / 2f,
                        barY + barOffsetY - glowSize / 2f,
                        barFilledWidth + glowSize,
                        animatedBarHeight + glowSize,
                        RenderUtility.vectorFromSingle(2f + glowSize / 2f),
                        glowColor);
            }
           
            ctx.rectangles().add(
                    barX, barY + barOffsetY, barFilledWidth, animatedBarHeight,
                    RenderUtility.vectorFromSingle(2f),
                    0xFFB0B0B0, 0xFFFFFFFF);
        }
       
        if (target instanceof PlayerEntity player) {
            float absorptionAmount = player.getAbsorptionAmount();
           
            if (absorptionAmount > 0f) {
                if (Math.abs(absorptionAmount - lastAbsorption) > 0.1f) {
                    lastAbsorption = absorptionAmount;
                    lastAbsorptionChangeTime = System.currentTimeMillis();
                }
               
                long absorptionTimeSinceChange = System.currentTimeMillis() - lastAbsorptionChangeTime;
                float absorptionAnimDuration = 500f;
               
                if (absorptionTimeSinceChange < absorptionAnimDuration) {
                    float progress = absorptionTimeSinceChange / absorptionAnimDuration;
                    float c1 = 1.70158f;
                    float c3 = c1 + 1f;
                    float easedProgress = 1f + c3 * (float) Math.pow(progress - 1, 3) + c1 * (float) Math.pow(progress - 1, 2);
                    animatedAbsorption = animatedAbsorption + (absorptionAmount - animatedAbsorption) * easedProgress;
                } else {
                    animatedAbsorption = absorptionAmount;
                }
               
                displayAbsorption = displayAbsorption + (animatedAbsorption - displayAbsorption) * 0.15f;
               
                float absorptionPercent = Math.min(1f, displayAbsorption / 20f);
               
                float absorptionPulseScale = 1f;
                if (absorptionTimeSinceChange < 200) {
                    float pulseProgress = absorptionTimeSinceChange / 200f;
                    absorptionPulseScale = 1f + (1f - pulseProgress) * 0.15f;
                }
               
                float absorptionBarHeight = barHeight * absorptionPulseScale;
                float absorptionBarOffsetY = (barHeight - absorptionBarHeight) / 2f;
                float absorptionBarWidth = barWidth * absorptionPercent;
               
                int absorptionColorFull = 0xFFFFD700;
                int absorptionColorFade = 0x00FFD700;
               
                float absorptionBarX = this.x + width - padding - absorptionBarWidth;
                float absorptionBarY = barY;
               
                for (int glowLayer = 3; glowLayer >= 1; glowLayer--) {
                    float glowSize = glowLayer * 1.5f;
                    int glowAlpha = 20 / glowLayer;
                    int glowColor = ColorUtility.withAlpha(absorptionColorFull, glowAlpha);
                   
                    ctx.rectangles().add(
                            absorptionBarX - glowSize / 2f,
                            absorptionBarY + absorptionBarOffsetY - glowSize / 2f,
                            absorptionBarWidth + glowSize,
                            absorptionBarHeight + glowSize,
                            RenderUtility.vectorFromSingle(2f + glowSize / 2f),
                            glowColor);
                }
               
                ctx.rectangles().add(
                        absorptionBarX, absorptionBarY + absorptionBarOffsetY, absorptionBarWidth, absorptionBarHeight,
                        RenderUtility.vectorFromSingle(2f),
                        absorptionColorFade, absorptionColorFull);
            }
        }
    }
   
    public void setTarget(LivingEntity target) {
        this.target = target;
    }
}
SS:
хз мне зашло +rep
 
Первая тема, не срите пж

Сделал этот тх за 15 - 20 с чем то минут

TargetHUD:
Expand Collapse Copy
package idk.relake.hud.impl;

import idk.relake.hud.HudElement;
import idk.relake.themes.ThemeManager;
import idk.relake.ui.UIRenderContext;
import idk.relake.utilities.ColorUtility;
import idk.relake.utilities.RenderUtility;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Identifier;

public final class TargetHUD extends HudElement {
    private LivingEntity target;
    private float lastHealth = 20f;
    private float animatedHealth = 20f;
    private float displayHealth = 20f;
    private long lastHealthChangeTime = 0;
   
    private float lastAbsorption = 0f;
    private float animatedAbsorption = 0f;
    private float displayAbsorption = 0f;
    private long lastAbsorptionChangeTime = 0;
   
    private float displayedHpNumber = 20f;
    private float targetHpNumber = 20f;
    private long lastHpNumberChange = 0;
   
    private float displayedAbsorptionNumber = 0f;
    private float targetAbsorptionNumber = 0f;
    private long lastAbsorptionNumberChange = 0;
   
    private String lastDisplayedName = "";
    private boolean wasNameTruncated = false;
    private long nameChangeTime = 0;
    private float nameAlphaAnimation = 1f;
   
    private boolean tookDamage = false;
    private long damageTime = 0;
    private final java.util.List<TearParticle> tears = new java.util.ArrayList<>();
   
    private static class TearParticle {
        float x, y;
        float velocityY;
        long spawnTime;
       
        TearParticle(float x, float y) {
            this.x = x;
            this.y = y;
            this.velocityY = 0.5f + (float) Math.random() * 0.5f;
            this.spawnTime = System.currentTimeMillis();
        }
       
        void update() {
            y += velocityY;
            velocityY += 0.05f;
        }
       
        boolean isExpired() {
            return System.currentTimeMillis() - spawnTime > 1000;
        }
    }
   
    public TargetHUD() {
        super("TargetHUD", 10, 30);
    }

    @Override
    public void render(UIRenderContext ctx) {
        MinecraftClient mc = MinecraftClient.getInstance();
        if (mc.player == null) {
            return;
        }

        this.target = mc.player;
       
        if (this.target == null) {
            return;
        }

        float width = 115f;
        float height = 34f;
        float headSize = 22f;
        float padding = 6f;
       
        this.width = width;
        this.height = height;

        int accent = ThemeManager.INSTANCE.getCurrentColor();
       
        ctx.rectangles().add(
                this.x, this.y, width, height,
                RenderUtility.vectorFromSingle(6),
                0xFF1A1D22, 0xFF3A3D42, 1);

        float headX = this.x + padding;
        float headY = this.y + (height - headSize) / 2f;
       
        ctx.images().add(Identifier.of("relake", "images/head.png"),
                        headX, headY, headSize, headSize, -1);
       
        long timeSinceDamage = System.currentTimeMillis() - damageTime;
        if (tookDamage && timeSinceDamage < 500) {
            float damageProgress = timeSinceDamage / 500f;
           
            float c1 = 1.70158f;
            float c3 = c1 + 1f;
            float easedProgress = 1f + c3 * (float) Math.pow(damageProgress - 1, 3) + c1 * (float) Math.pow(damageProgress - 1, 2);
           
            int redAlpha = (int) ((1f - easedProgress) * 100);
            if (redAlpha > 0) {
                int redOverlay = ColorUtility.withAlpha(0xFFFF0000, redAlpha);
                ctx.rectangles().add(
                        headX, headY, headSize, headSize,
                        RenderUtility.vectorFromSingle(0f),
                        redOverlay);
            }
        }

        String name = target.getName().getString();
        float textStartX = headX + headSize + padding;
        float nameY = this.y + 8f;
       
        float hp = target.getHealth();
        float absorption = 0f;
       
        if (target instanceof PlayerEntity player) {
            absorption = player.getAbsorptionAmount();
        }
       
        if (Math.abs(hp - targetHpNumber) > 0.1f) {
            targetHpNumber = hp;
            lastHpNumberChange = System.currentTimeMillis();
        }
       
        if (Math.abs(absorption - targetAbsorptionNumber) > 0.1f) {
            targetAbsorptionNumber = absorption;
            lastAbsorptionNumberChange = System.currentTimeMillis();
        }
       
        long hpTimeSinceChange = System.currentTimeMillis() - lastHpNumberChange;
        float hpAnimDuration = 400f;
       
        if (hpTimeSinceChange < hpAnimDuration) {
            float progress = hpTimeSinceChange / hpAnimDuration;
            float easedProgress = 1f - (float) Math.pow(1 - progress, 3);
            displayedHpNumber = displayedHpNumber + (targetHpNumber - displayedHpNumber) * easedProgress;
        } else {
            displayedHpNumber = targetHpNumber;
        }
       
        long absTimeSinceChange = System.currentTimeMillis() - lastAbsorptionNumberChange;
        float absAnimDuration = 400f;
       
        if (absTimeSinceChange < absAnimDuration) {
            float progress = absTimeSinceChange / absAnimDuration;
            float easedProgress = 1f - (float) Math.pow(1 - progress, 3);
            displayedAbsorptionNumber = displayedAbsorptionNumber + (targetAbsorptionNumber - displayedAbsorptionNumber) * easedProgress;
        } else {
            displayedAbsorptionNumber = targetAbsorptionNumber;
        }
       
        String hpMainText = String.valueOf((int) displayedHpNumber);
        String hpAbsorptionText = "";
       
        if (displayedAbsorptionNumber > 0.05f) {
            if (displayedAbsorptionNumber % 1 < 0.1f) {
                hpAbsorptionText = String.format(" + %d AB", (int) displayedAbsorptionNumber);
            } else {
                hpAbsorptionText = String.format(" + %.1f AB", displayedAbsorptionNumber);
            }
        }
       
        String fullHpText = hpMainText + hpAbsorptionText;
        float hpTextWidth = ctx.fontsMedium().getTextWidth(fullHpText, 8f);
       
        float maxNameWidth = width - (headSize + padding * 3) - hpTextWidth - 5f;
        String displayName = name;
        boolean isNameTruncated = false;
       
        if (ctx.fontsMedium().getTextWidth(name, 8f) > maxNameWidth) {
            isNameTruncated = true;
            while (ctx.fontsMedium().getTextWidth(displayName + "...", 8f) > maxNameWidth && displayName.length() > 0) {
                displayName = displayName.substring(0, displayName.length() - 1);
            }
            displayName += "...";
        }
       
        if (!displayName.equals(lastDisplayedName)) {
            lastDisplayedName = displayName;
            nameChangeTime = System.currentTimeMillis();
        }
       
        long nameTimeSinceChange = System.currentTimeMillis() - nameChangeTime;
        float nameAnimDuration = 300f;
       
        if (nameTimeSinceChange < nameAnimDuration) {
            float progress = nameTimeSinceChange / nameAnimDuration;
            nameAlphaAnimation = 1f - (float) Math.pow(1 - progress, 3);
        } else {
            nameAlphaAnimation = 1f;
        }
       
        if (isNameTruncated) {
            String mainPart = displayName.substring(0, displayName.length() - 3);
            String dotsPart = "...";
           
            ctx.fontsMedium().add(mainPart, textStartX, nameY, 8f, 0xFFFFFFFF);
           
            float dotsX = textStartX + ctx.fontsMedium().getTextWidth(mainPart, 8f);
            int dotsAlpha = (int) (nameAlphaAnimation * 255);
            int dotsColor = (dotsAlpha << 24) | 0x00FFFFFF;
            ctx.fontsMedium().add(dotsPart, dotsX, nameY, 8f, dotsColor);
        } else {
            ctx.fontsMedium().add(displayName, textStartX, nameY, 8f, 0xFFFFFFFF);
        }
       
        wasNameTruncated = isNameTruncated;
       
        float hpX = this.x + width - padding - hpTextWidth;
       
        int hpAlpha = 255;
        if (hpTimeSinceChange < 100) {
            float fadeProgress = hpTimeSinceChange / 100f;
            hpAlpha = (int) (200 + fadeProgress * 55);
        }
       
        int hpColor = (hpAlpha << 24) | 0x00FFFFFF;
        ctx.fontsMedium().add(hpMainText, hpX, nameY, 8f, hpColor);
       
        if (!hpAbsorptionText.isEmpty()) {
            float mainTextWidth = ctx.fontsMedium().getTextWidth(hpMainText, 8f);
            float currentX = hpX + mainTextWidth;
           
            int absBaseAlpha = 255;
            if (absTimeSinceChange < 100) {
                float fadeProgress = absTimeSinceChange / 100f;
                absBaseAlpha = (int) (200 + fadeProgress * 55);
            }
           
            for (int glowLayer = 5; glowLayer >= 1; glowLayer--) {
                int glowAlpha = (20 / glowLayer);
                int glowColor = (glowAlpha << 24) | 0x00FFD700;
                ctx.fontsMedium().add(hpAbsorptionText, currentX, nameY, 8f, glowColor);
            }
           
            int mainColor = (absBaseAlpha << 24) | 0x00FFD700;
            ctx.fontsMedium().add(hpAbsorptionText, currentX, nameY, 8f, mainColor);
        }

        float maxHp = target.getMaxHealth();
        float currentHp = hp;
       
        if (currentHp < lastHealth - 0.5f) {
            if (!tookDamage) {
                tookDamage = true;
                damageTime = System.currentTimeMillis();
               
                int tearCount = 3 + (int) (Math.random() * 3);
                for (int i = 0; i < tearCount; i++) {
                    float tearX = headX + headSize / 2f + (float) (Math.random() * 6 - 3);
                    float tearY = headY + headSize * 0.7f;
                    tears.add(new TearParticle(tearX, tearY));
                }
            }
        } else if (currentHp >= lastHealth) {
            tookDamage = false;
        }
       
        tears.removeIf(TearParticle::isExpired);
        for (TearParticle tear : tears) {
            tear.update();
           
            float tearSize = 2f;
            ctx.rectangles().add(
                    tear.x - tearSize / 2f,
                    tear.y - tearSize / 2f,
                    tearSize, tearSize,
                    RenderUtility.vectorFromSingle(tearSize / 2f),
                    0xFF87CEEB);
        }
       
        if (Math.abs(currentHp - lastHealth) > 0.1f) {
            lastHealth = currentHp;
            lastHealthChangeTime = System.currentTimeMillis();
        }
       
        long timeSinceChange = System.currentTimeMillis() - lastHealthChangeTime;
        float animationDuration = 500f;
       
        if (timeSinceChange < animationDuration) {
            float progress = timeSinceChange / animationDuration;
           
            float c1 = 1.70158f;
            float c3 = c1 + 1f;
            float easedProgress = 1f + c3 * (float) Math.pow(progress - 1, 3) + c1 * (float) Math.pow(progress - 1, 2);
           
            animatedHealth = animatedHealth + (currentHp - animatedHealth) * easedProgress;
        } else {
            animatedHealth = currentHp;
        }
       
        displayHealth = displayHealth + (animatedHealth - displayHealth) * 0.15f;
       
        float healthPercent = Math.min(1f, Math.max(0f, displayHealth / maxHp));
       
        float barY = this.y + height - 13f;
        float barHeight = 6f;
        float barWidth = width - (headSize + padding * 3);
        float barX = textStartX;
       
        ctx.rectangles().add(
                barX, barY, barWidth, barHeight,
                RenderUtility.vectorFromSingle(2f),
                0xFF1A1D22);
       
        if (healthPercent > 0f) {
            float pulseScale = 1f;
            if (timeSinceChange < 200) {
                float pulseProgress = timeSinceChange / 200f;
                pulseScale = 1f + (1f - pulseProgress) * 0.15f;
            }
           
            float animatedBarHeight = barHeight * pulseScale;
            float barOffsetY = (barHeight - animatedBarHeight) / 2f;
            float barFilledWidth = barWidth * healthPercent;
           
            for (int glowLayer = 5; glowLayer >= 1; glowLayer--) {
                float glowSize = glowLayer * 1.5f;
                int glowAlpha = 20 / glowLayer;
                int glowColor = ColorUtility.withAlpha(0xFFFFFFFF, glowAlpha);
               
                ctx.rectangles().add(
                        barX - glowSize / 2f,
                        barY + barOffsetY - glowSize / 2f,
                        barFilledWidth + glowSize,
                        animatedBarHeight + glowSize,
                        RenderUtility.vectorFromSingle(2f + glowSize / 2f),
                        glowColor);
            }
           
            ctx.rectangles().add(
                    barX, barY + barOffsetY, barFilledWidth, animatedBarHeight,
                    RenderUtility.vectorFromSingle(2f),
                    0xFFB0B0B0, 0xFFFFFFFF);
        }
       
        if (target instanceof PlayerEntity player) {
            float absorptionAmount = player.getAbsorptionAmount();
           
            if (absorptionAmount > 0f) {
                if (Math.abs(absorptionAmount - lastAbsorption) > 0.1f) {
                    lastAbsorption = absorptionAmount;
                    lastAbsorptionChangeTime = System.currentTimeMillis();
                }
               
                long absorptionTimeSinceChange = System.currentTimeMillis() - lastAbsorptionChangeTime;
                float absorptionAnimDuration = 500f;
               
                if (absorptionTimeSinceChange < absorptionAnimDuration) {
                    float progress = absorptionTimeSinceChange / absorptionAnimDuration;
                    float c1 = 1.70158f;
                    float c3 = c1 + 1f;
                    float easedProgress = 1f + c3 * (float) Math.pow(progress - 1, 3) + c1 * (float) Math.pow(progress - 1, 2);
                    animatedAbsorption = animatedAbsorption + (absorptionAmount - animatedAbsorption) * easedProgress;
                } else {
                    animatedAbsorption = absorptionAmount;
                }
               
                displayAbsorption = displayAbsorption + (animatedAbsorption - displayAbsorption) * 0.15f;
               
                float absorptionPercent = Math.min(1f, displayAbsorption / 20f);
               
                float absorptionPulseScale = 1f;
                if (absorptionTimeSinceChange < 200) {
                    float pulseProgress = absorptionTimeSinceChange / 200f;
                    absorptionPulseScale = 1f + (1f - pulseProgress) * 0.15f;
                }
               
                float absorptionBarHeight = barHeight * absorptionPulseScale;
                float absorptionBarOffsetY = (barHeight - absorptionBarHeight) / 2f;
                float absorptionBarWidth = barWidth * absorptionPercent;
               
                int absorptionColorFull = 0xFFFFD700;
                int absorptionColorFade = 0x00FFD700;
               
                float absorptionBarX = this.x + width - padding - absorptionBarWidth;
                float absorptionBarY = barY;
               
                for (int glowLayer = 3; glowLayer >= 1; glowLayer--) {
                    float glowSize = glowLayer * 1.5f;
                    int glowAlpha = 20 / glowLayer;
                    int glowColor = ColorUtility.withAlpha(absorptionColorFull, glowAlpha);
                   
                    ctx.rectangles().add(
                            absorptionBarX - glowSize / 2f,
                            absorptionBarY + absorptionBarOffsetY - glowSize / 2f,
                            absorptionBarWidth + glowSize,
                            absorptionBarHeight + glowSize,
                            RenderUtility.vectorFromSingle(2f + glowSize / 2f),
                            glowColor);
                }
               
                ctx.rectangles().add(
                        absorptionBarX, absorptionBarY + absorptionBarOffsetY, absorptionBarWidth, absorptionBarHeight,
                        RenderUtility.vectorFromSingle(2f),
                        absorptionColorFade, absorptionColorFull);
            }
        }
    }
   
    public void setTarget(LivingEntity target) {
        this.target = target;
    }
}
SS:
ну неплохо молодец
 
Первая тема, не срите пж

Сделал этот тх за 15 - 20 с чем то минут

TargetHUD:
Expand Collapse Copy
package idk.relake.hud.impl;

import idk.relake.hud.HudElement;
import idk.relake.themes.ThemeManager;
import idk.relake.ui.UIRenderContext;
import idk.relake.utilities.ColorUtility;
import idk.relake.utilities.RenderUtility;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Identifier;

public final class TargetHUD extends HudElement {
    private LivingEntity target;
    private float lastHealth = 20f;
    private float animatedHealth = 20f;
    private float displayHealth = 20f;
    private long lastHealthChangeTime = 0;
   
    private float lastAbsorption = 0f;
    private float animatedAbsorption = 0f;
    private float displayAbsorption = 0f;
    private long lastAbsorptionChangeTime = 0;
   
    private float displayedHpNumber = 20f;
    private float targetHpNumber = 20f;
    private long lastHpNumberChange = 0;
   
    private float displayedAbsorptionNumber = 0f;
    private float targetAbsorptionNumber = 0f;
    private long lastAbsorptionNumberChange = 0;
   
    private String lastDisplayedName = "";
    private boolean wasNameTruncated = false;
    private long nameChangeTime = 0;
    private float nameAlphaAnimation = 1f;
   
    private boolean tookDamage = false;
    private long damageTime = 0;
    private final java.util.List<TearParticle> tears = new java.util.ArrayList<>();
   
    private static class TearParticle {
        float x, y;
        float velocityY;
        long spawnTime;
       
        TearParticle(float x, float y) {
            this.x = x;
            this.y = y;
            this.velocityY = 0.5f + (float) Math.random() * 0.5f;
            this.spawnTime = System.currentTimeMillis();
        }
       
        void update() {
            y += velocityY;
            velocityY += 0.05f;
        }
       
        boolean isExpired() {
            return System.currentTimeMillis() - spawnTime > 1000;
        }
    }
   
    public TargetHUD() {
        super("TargetHUD", 10, 30);
    }

    @Override
    public void render(UIRenderContext ctx) {
        MinecraftClient mc = MinecraftClient.getInstance();
        if (mc.player == null) {
            return;
        }

        this.target = mc.player;
       
        if (this.target == null) {
            return;
        }

        float width = 115f;
        float height = 34f;
        float headSize = 22f;
        float padding = 6f;
       
        this.width = width;
        this.height = height;

        int accent = ThemeManager.INSTANCE.getCurrentColor();
       
        ctx.rectangles().add(
                this.x, this.y, width, height,
                RenderUtility.vectorFromSingle(6),
                0xFF1A1D22, 0xFF3A3D42, 1);

        float headX = this.x + padding;
        float headY = this.y + (height - headSize) / 2f;
       
        ctx.images().add(Identifier.of("relake", "images/head.png"),
                        headX, headY, headSize, headSize, -1);
       
        long timeSinceDamage = System.currentTimeMillis() - damageTime;
        if (tookDamage && timeSinceDamage < 500) {
            float damageProgress = timeSinceDamage / 500f;
           
            float c1 = 1.70158f;
            float c3 = c1 + 1f;
            float easedProgress = 1f + c3 * (float) Math.pow(damageProgress - 1, 3) + c1 * (float) Math.pow(damageProgress - 1, 2);
           
            int redAlpha = (int) ((1f - easedProgress) * 100);
            if (redAlpha > 0) {
                int redOverlay = ColorUtility.withAlpha(0xFFFF0000, redAlpha);
                ctx.rectangles().add(
                        headX, headY, headSize, headSize,
                        RenderUtility.vectorFromSingle(0f),
                        redOverlay);
            }
        }

        String name = target.getName().getString();
        float textStartX = headX + headSize + padding;
        float nameY = this.y + 8f;
       
        float hp = target.getHealth();
        float absorption = 0f;
       
        if (target instanceof PlayerEntity player) {
            absorption = player.getAbsorptionAmount();
        }
       
        if (Math.abs(hp - targetHpNumber) > 0.1f) {
            targetHpNumber = hp;
            lastHpNumberChange = System.currentTimeMillis();
        }
       
        if (Math.abs(absorption - targetAbsorptionNumber) > 0.1f) {
            targetAbsorptionNumber = absorption;
            lastAbsorptionNumberChange = System.currentTimeMillis();
        }
       
        long hpTimeSinceChange = System.currentTimeMillis() - lastHpNumberChange;
        float hpAnimDuration = 400f;
       
        if (hpTimeSinceChange < hpAnimDuration) {
            float progress = hpTimeSinceChange / hpAnimDuration;
            float easedProgress = 1f - (float) Math.pow(1 - progress, 3);
            displayedHpNumber = displayedHpNumber + (targetHpNumber - displayedHpNumber) * easedProgress;
        } else {
            displayedHpNumber = targetHpNumber;
        }
       
        long absTimeSinceChange = System.currentTimeMillis() - lastAbsorptionNumberChange;
        float absAnimDuration = 400f;
       
        if (absTimeSinceChange < absAnimDuration) {
            float progress = absTimeSinceChange / absAnimDuration;
            float easedProgress = 1f - (float) Math.pow(1 - progress, 3);
            displayedAbsorptionNumber = displayedAbsorptionNumber + (targetAbsorptionNumber - displayedAbsorptionNumber) * easedProgress;
        } else {
            displayedAbsorptionNumber = targetAbsorptionNumber;
        }
       
        String hpMainText = String.valueOf((int) displayedHpNumber);
        String hpAbsorptionText = "";
       
        if (displayedAbsorptionNumber > 0.05f) {
            if (displayedAbsorptionNumber % 1 < 0.1f) {
                hpAbsorptionText = String.format(" + %d AB", (int) displayedAbsorptionNumber);
            } else {
                hpAbsorptionText = String.format(" + %.1f AB", displayedAbsorptionNumber);
            }
        }
       
        String fullHpText = hpMainText + hpAbsorptionText;
        float hpTextWidth = ctx.fontsMedium().getTextWidth(fullHpText, 8f);
       
        float maxNameWidth = width - (headSize + padding * 3) - hpTextWidth - 5f;
        String displayName = name;
        boolean isNameTruncated = false;
       
        if (ctx.fontsMedium().getTextWidth(name, 8f) > maxNameWidth) {
            isNameTruncated = true;
            while (ctx.fontsMedium().getTextWidth(displayName + "...", 8f) > maxNameWidth && displayName.length() > 0) {
                displayName = displayName.substring(0, displayName.length() - 1);
            }
            displayName += "...";
        }
       
        if (!displayName.equals(lastDisplayedName)) {
            lastDisplayedName = displayName;
            nameChangeTime = System.currentTimeMillis();
        }
       
        long nameTimeSinceChange = System.currentTimeMillis() - nameChangeTime;
        float nameAnimDuration = 300f;
       
        if (nameTimeSinceChange < nameAnimDuration) {
            float progress = nameTimeSinceChange / nameAnimDuration;
            nameAlphaAnimation = 1f - (float) Math.pow(1 - progress, 3);
        } else {
            nameAlphaAnimation = 1f;
        }
       
        if (isNameTruncated) {
            String mainPart = displayName.substring(0, displayName.length() - 3);
            String dotsPart = "...";
           
            ctx.fontsMedium().add(mainPart, textStartX, nameY, 8f, 0xFFFFFFFF);
           
            float dotsX = textStartX + ctx.fontsMedium().getTextWidth(mainPart, 8f);
            int dotsAlpha = (int) (nameAlphaAnimation * 255);
            int dotsColor = (dotsAlpha << 24) | 0x00FFFFFF;
            ctx.fontsMedium().add(dotsPart, dotsX, nameY, 8f, dotsColor);
        } else {
            ctx.fontsMedium().add(displayName, textStartX, nameY, 8f, 0xFFFFFFFF);
        }
       
        wasNameTruncated = isNameTruncated;
       
        float hpX = this.x + width - padding - hpTextWidth;
       
        int hpAlpha = 255;
        if (hpTimeSinceChange < 100) {
            float fadeProgress = hpTimeSinceChange / 100f;
            hpAlpha = (int) (200 + fadeProgress * 55);
        }
       
        int hpColor = (hpAlpha << 24) | 0x00FFFFFF;
        ctx.fontsMedium().add(hpMainText, hpX, nameY, 8f, hpColor);
       
        if (!hpAbsorptionText.isEmpty()) {
            float mainTextWidth = ctx.fontsMedium().getTextWidth(hpMainText, 8f);
            float currentX = hpX + mainTextWidth;
           
            int absBaseAlpha = 255;
            if (absTimeSinceChange < 100) {
                float fadeProgress = absTimeSinceChange / 100f;
                absBaseAlpha = (int) (200 + fadeProgress * 55);
            }
           
            for (int glowLayer = 5; glowLayer >= 1; glowLayer--) {
                int glowAlpha = (20 / glowLayer);
                int glowColor = (glowAlpha << 24) | 0x00FFD700;
                ctx.fontsMedium().add(hpAbsorptionText, currentX, nameY, 8f, glowColor);
            }
           
            int mainColor = (absBaseAlpha << 24) | 0x00FFD700;
            ctx.fontsMedium().add(hpAbsorptionText, currentX, nameY, 8f, mainColor);
        }

        float maxHp = target.getMaxHealth();
        float currentHp = hp;
       
        if (currentHp < lastHealth - 0.5f) {
            if (!tookDamage) {
                tookDamage = true;
                damageTime = System.currentTimeMillis();
               
                int tearCount = 3 + (int) (Math.random() * 3);
                for (int i = 0; i < tearCount; i++) {
                    float tearX = headX + headSize / 2f + (float) (Math.random() * 6 - 3);
                    float tearY = headY + headSize * 0.7f;
                    tears.add(new TearParticle(tearX, tearY));
                }
            }
        } else if (currentHp >= lastHealth) {
            tookDamage = false;
        }
       
        tears.removeIf(TearParticle::isExpired);
        for (TearParticle tear : tears) {
            tear.update();
           
            float tearSize = 2f;
            ctx.rectangles().add(
                    tear.x - tearSize / 2f,
                    tear.y - tearSize / 2f,
                    tearSize, tearSize,
                    RenderUtility.vectorFromSingle(tearSize / 2f),
                    0xFF87CEEB);
        }
       
        if (Math.abs(currentHp - lastHealth) > 0.1f) {
            lastHealth = currentHp;
            lastHealthChangeTime = System.currentTimeMillis();
        }
       
        long timeSinceChange = System.currentTimeMillis() - lastHealthChangeTime;
        float animationDuration = 500f;
       
        if (timeSinceChange < animationDuration) {
            float progress = timeSinceChange / animationDuration;
           
            float c1 = 1.70158f;
            float c3 = c1 + 1f;
            float easedProgress = 1f + c3 * (float) Math.pow(progress - 1, 3) + c1 * (float) Math.pow(progress - 1, 2);
           
            animatedHealth = animatedHealth + (currentHp - animatedHealth) * easedProgress;
        } else {
            animatedHealth = currentHp;
        }
       
        displayHealth = displayHealth + (animatedHealth - displayHealth) * 0.15f;
       
        float healthPercent = Math.min(1f, Math.max(0f, displayHealth / maxHp));
       
        float barY = this.y + height - 13f;
        float barHeight = 6f;
        float barWidth = width - (headSize + padding * 3);
        float barX = textStartX;
       
        ctx.rectangles().add(
                barX, barY, barWidth, barHeight,
                RenderUtility.vectorFromSingle(2f),
                0xFF1A1D22);
       
        if (healthPercent > 0f) {
            float pulseScale = 1f;
            if (timeSinceChange < 200) {
                float pulseProgress = timeSinceChange / 200f;
                pulseScale = 1f + (1f - pulseProgress) * 0.15f;
            }
           
            float animatedBarHeight = barHeight * pulseScale;
            float barOffsetY = (barHeight - animatedBarHeight) / 2f;
            float barFilledWidth = barWidth * healthPercent;
           
            for (int glowLayer = 5; glowLayer >= 1; glowLayer--) {
                float glowSize = glowLayer * 1.5f;
                int glowAlpha = 20 / glowLayer;
                int glowColor = ColorUtility.withAlpha(0xFFFFFFFF, glowAlpha);
               
                ctx.rectangles().add(
                        barX - glowSize / 2f,
                        barY + barOffsetY - glowSize / 2f,
                        barFilledWidth + glowSize,
                        animatedBarHeight + glowSize,
                        RenderUtility.vectorFromSingle(2f + glowSize / 2f),
                        glowColor);
            }
           
            ctx.rectangles().add(
                    barX, barY + barOffsetY, barFilledWidth, animatedBarHeight,
                    RenderUtility.vectorFromSingle(2f),
                    0xFFB0B0B0, 0xFFFFFFFF);
        }
       
        if (target instanceof PlayerEntity player) {
            float absorptionAmount = player.getAbsorptionAmount();
           
            if (absorptionAmount > 0f) {
                if (Math.abs(absorptionAmount - lastAbsorption) > 0.1f) {
                    lastAbsorption = absorptionAmount;
                    lastAbsorptionChangeTime = System.currentTimeMillis();
                }
               
                long absorptionTimeSinceChange = System.currentTimeMillis() - lastAbsorptionChangeTime;
                float absorptionAnimDuration = 500f;
               
                if (absorptionTimeSinceChange < absorptionAnimDuration) {
                    float progress = absorptionTimeSinceChange / absorptionAnimDuration;
                    float c1 = 1.70158f;
                    float c3 = c1 + 1f;
                    float easedProgress = 1f + c3 * (float) Math.pow(progress - 1, 3) + c1 * (float) Math.pow(progress - 1, 2);
                    animatedAbsorption = animatedAbsorption + (absorptionAmount - animatedAbsorption) * easedProgress;
                } else {
                    animatedAbsorption = absorptionAmount;
                }
               
                displayAbsorption = displayAbsorption + (animatedAbsorption - displayAbsorption) * 0.15f;
               
                float absorptionPercent = Math.min(1f, displayAbsorption / 20f);
               
                float absorptionPulseScale = 1f;
                if (absorptionTimeSinceChange < 200) {
                    float pulseProgress = absorptionTimeSinceChange / 200f;
                    absorptionPulseScale = 1f + (1f - pulseProgress) * 0.15f;
                }
               
                float absorptionBarHeight = barHeight * absorptionPulseScale;
                float absorptionBarOffsetY = (barHeight - absorptionBarHeight) / 2f;
                float absorptionBarWidth = barWidth * absorptionPercent;
               
                int absorptionColorFull = 0xFFFFD700;
                int absorptionColorFade = 0x00FFD700;
               
                float absorptionBarX = this.x + width - padding - absorptionBarWidth;
                float absorptionBarY = barY;
               
                for (int glowLayer = 3; glowLayer >= 1; glowLayer--) {
                    float glowSize = glowLayer * 1.5f;
                    int glowAlpha = 20 / glowLayer;
                    int glowColor = ColorUtility.withAlpha(absorptionColorFull, glowAlpha);
                   
                    ctx.rectangles().add(
                            absorptionBarX - glowSize / 2f,
                            absorptionBarY + absorptionBarOffsetY - glowSize / 2f,
                            absorptionBarWidth + glowSize,
                            absorptionBarHeight + glowSize,
                            RenderUtility.vectorFromSingle(2f + glowSize / 2f),
                            glowColor);
                }
               
                ctx.rectangles().add(
                        absorptionBarX, absorptionBarY + absorptionBarOffsetY, absorptionBarWidth, absorptionBarHeight,
                        RenderUtility.vectorFromSingle(2f),
                        absorptionColorFade, absorptionColorFull);
            }
        }
    }
   
    public void setTarget(LivingEntity target) {
        this.target = target;
    }
}
SS:
четко ваще
 
Назад
Сверху Снизу