mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-30 12:23:39 +01:00
[Fools-YesHealMePlugin] Finished implementation.
This commit is contained in:
parent
dd2b842723
commit
b91ce2c46f
7 changed files with 335 additions and 19 deletions
|
|
@ -139,7 +139,7 @@ internal class FoolsManager : IDisposable, IServiceType
|
||||||
{
|
{
|
||||||
Name = "YesHealMe",
|
Name = "YesHealMe",
|
||||||
InternalName = "YesHealMePlugin",
|
InternalName = "YesHealMePlugin",
|
||||||
Description = "The only warning you need.",
|
Description = "As the saying goes: it's the first missing HP that matters. And the second. And the third...",
|
||||||
Author = "MidoriKami",
|
Author = "MidoriKami",
|
||||||
RealAuthor = "Berna",
|
RealAuthor = "Berna",
|
||||||
Type = typeof(YesHealMePlugin),
|
Type = typeof(YesHealMePlugin),
|
||||||
|
|
|
||||||
31
Dalamud/Fools/Helper/YesHealMe/Colors.cs
Normal file
31
Dalamud/Fools/Helper/YesHealMe/Colors.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System.Numerics;
|
||||||
|
using ImGuiNET;
|
||||||
|
|
||||||
|
namespace Dalamud.Fools.Helper.YesHealMe;
|
||||||
|
|
||||||
|
public static class Colors
|
||||||
|
{
|
||||||
|
public static Vector4 Purple = new(176 / 255.0f, 38 / 255.0f, 236 / 255.0f, 1.0f);
|
||||||
|
public static Vector4 Blue = new(37 / 255.0f, 168 / 255.0f, 1.0f, 1.0f);
|
||||||
|
public static Vector4 ForestGreen = new(0.133f, 0.545f, 0.1333f, 1.0f);
|
||||||
|
public static Vector4 White = new(1.0f, 1.0f, 1.0f,1.0f);
|
||||||
|
public static Vector4 Red = new(1.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
public static Vector4 Green = new(0.0f, 1.0f, 0.0f, 1.0f);
|
||||||
|
public static Vector4 Black = new(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
public static Vector4 HealerGreen = new(33 / 255f, 193 / 255f, 0, 1.0f);
|
||||||
|
public static Vector4 DPSRed = new(210/255f, 42/255f, 43/255f, 1.0f);
|
||||||
|
public static Vector4 SoftRed = new(0.8f, 0.2f, 0.2f, 1.0f);
|
||||||
|
public static Vector4 Grey = new(0.6f, 0.6f, 0.6f, 1.0f);
|
||||||
|
public static Vector4 LightGrey = new(220/250.0f, 220/250.0f, 220/250f, 1.0f);
|
||||||
|
public static Vector4 Orange = new(1.0f, 165.0f / 255.0f, 0.0f, 1.0f);
|
||||||
|
public static Vector4 SoftGreen = new(0.2f, 0.8f, 0.2f, 1.0f);
|
||||||
|
public static Vector4 FatePink = new(0.58f, 0.388f, 0.827f, 0.33f);
|
||||||
|
public static Vector4 FateDarkPink = new(0.58f, 0.388f, 0.827f, 1.0f);
|
||||||
|
public static Vector4 MapTextBrown = new(0.655f, 0.396f, 0.149f, 1.0f);
|
||||||
|
public static Vector4 BabyBlue = new(0.537f, 0.812f, 0.941f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ColorExtensions
|
||||||
|
{
|
||||||
|
public static uint ToU32(this Vector4 color) => ImGui.GetColorU32(color);
|
||||||
|
}
|
||||||
99
Dalamud/Fools/Helper/YesHealMe/DrawUtilities.cs
Normal file
99
Dalamud/Fools/Helper/YesHealMe/DrawUtilities.cs
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
using System;
|
||||||
|
using System.Numerics;
|
||||||
|
using ImGuiNET;
|
||||||
|
using KamiLib.Caching;
|
||||||
|
|
||||||
|
namespace Dalamud.Fools.Helper.YesHealMe;
|
||||||
|
|
||||||
|
internal static class DrawUtilities
|
||||||
|
{
|
||||||
|
public static void TextOutlined(FontManager fontManager, Vector2 startingPosition, string text, float scale, Vector4 color)
|
||||||
|
{
|
||||||
|
startingPosition = startingPosition.Ceil();
|
||||||
|
|
||||||
|
var outlineThickness = (int)MathF.Ceiling(1 * scale);
|
||||||
|
|
||||||
|
for (var x = -outlineThickness; x <= outlineThickness; ++x)
|
||||||
|
{
|
||||||
|
for (var y = -outlineThickness; y <= outlineThickness; ++y)
|
||||||
|
{
|
||||||
|
if (x == 0 && y == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawText(fontManager, startingPosition + new Vector2(x, y), text, Colors.Black, scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawText(fontManager, startingPosition, text, color, scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DrawIconWithName(FontManager fontManager, Vector2 drawPosition, uint iconID, string name, float iconScale, float textScale, bool drawText = true)
|
||||||
|
{
|
||||||
|
if (!fontManager.GameFont.Available) return;
|
||||||
|
|
||||||
|
var icon = IconCache.Instance.GetIcon(iconID);
|
||||||
|
if (icon != null)
|
||||||
|
{
|
||||||
|
var drawList = ImGui.GetBackgroundDrawList();
|
||||||
|
|
||||||
|
var imagePadding = new Vector2(20.0f, 10.0f) * iconScale;
|
||||||
|
var imageSize = new Vector2(50.0f, 50.0f) * iconScale;
|
||||||
|
|
||||||
|
drawPosition += imagePadding;
|
||||||
|
|
||||||
|
drawList.AddImage(icon.ImGuiHandle, drawPosition, drawPosition + imageSize);
|
||||||
|
|
||||||
|
if (drawText)
|
||||||
|
{
|
||||||
|
drawPosition.X += imageSize.X / 2.0f;
|
||||||
|
drawPosition.Y += imageSize.Y + 2.0f * iconScale;
|
||||||
|
|
||||||
|
var textSize = CalculateTextSize(fontManager, name, textScale / 2.75f);
|
||||||
|
var textOffset = new Vector2(0.0f, 5.0f) * iconScale;
|
||||||
|
|
||||||
|
drawPosition.X -= textSize.X / 2.0f;
|
||||||
|
|
||||||
|
TextOutlined(fontManager, drawPosition + textOffset, name, textScale / 2.75f, Colors.White);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector2 CalculateTextSize(FontManager fontManager, string text, float scale)
|
||||||
|
{
|
||||||
|
if(!fontManager.GameFont.Available) return Vector2.Zero;
|
||||||
|
|
||||||
|
var fontSize = fontManager.GameFont.ImFont.FontSize;
|
||||||
|
var textSize = ImGui.CalcTextSize(text);
|
||||||
|
var fontScalar = 62.0f / textSize.Y;
|
||||||
|
|
||||||
|
var textWidth = textSize.X * fontScalar;
|
||||||
|
|
||||||
|
return new Vector2(textWidth, fontSize) * scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawText(FontManager fontManager, Vector2 drawPosition, string text, Vector4 color, float scale, bool debug = false)
|
||||||
|
{
|
||||||
|
if (!fontManager.GameFont.Available) return;
|
||||||
|
var font = fontManager.GameFont.ImFont;
|
||||||
|
|
||||||
|
var drawList = ImGui.GetBackgroundDrawList();
|
||||||
|
var stringSize = CalculateTextSize(fontManager, text, scale);
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
drawList.AddRect(drawPosition, drawPosition + stringSize, ImGui.GetColorU32(Colors.Green));
|
||||||
|
}
|
||||||
|
|
||||||
|
drawList.AddText(font, font.FontSize * scale, drawPosition, ImGui.GetColorU32(color), text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class VectorExtensions
|
||||||
|
{
|
||||||
|
public static Vector2 Ceil(this Vector2 data)
|
||||||
|
{
|
||||||
|
return new Vector2(MathF.Ceiling(data.X), MathF.Ceiling(data.Y));
|
||||||
|
}
|
||||||
|
}
|
||||||
20
Dalamud/Fools/Helper/YesHealMe/FontManager.cs
Normal file
20
Dalamud/Fools/Helper/YesHealMe/FontManager.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System;
|
||||||
|
using Dalamud.Interface;
|
||||||
|
using Dalamud.Interface.GameFonts;
|
||||||
|
|
||||||
|
namespace Dalamud.Fools.Helper.YesHealMe;
|
||||||
|
|
||||||
|
public class FontManager : IDisposable
|
||||||
|
{
|
||||||
|
public GameFontHandle GameFont { get; }
|
||||||
|
|
||||||
|
public FontManager(UiBuilder uiBuilder)
|
||||||
|
{
|
||||||
|
this.GameFont = uiBuilder.GetGameFontHandle( new GameFontStyle( GameFontFamily.Axis, 52.0f ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
this.GameFont.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
70
Dalamud/Fools/Helper/YesHealMe/IconCache.cs
Normal file
70
Dalamud/Fools/Helper/YesHealMe/IconCache.cs
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Dalamud;
|
||||||
|
using Dalamud.Data;
|
||||||
|
using Dalamud.Logging;
|
||||||
|
using Dalamud.Utility;
|
||||||
|
using ImGuiScene;
|
||||||
|
|
||||||
|
namespace KamiLib.Caching;
|
||||||
|
|
||||||
|
public class IconCache : IDisposable
|
||||||
|
{
|
||||||
|
private readonly Dictionary<uint, TextureWrap?> iconTextures = new();
|
||||||
|
|
||||||
|
private const string IconFilePath = "ui/icon/{0:D3}000/{1:D6}_hr1.tex";
|
||||||
|
|
||||||
|
private static IconCache? _instance;
|
||||||
|
public static IconCache Instance => _instance ??= new IconCache();
|
||||||
|
|
||||||
|
public static void Cleanup()
|
||||||
|
{
|
||||||
|
_instance?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
foreach (var texture in iconTextures.Values)
|
||||||
|
{
|
||||||
|
texture?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
iconTextures.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadIconTexture(uint iconId)
|
||||||
|
{
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var path = IconFilePath.Format(iconId / 1000, iconId);
|
||||||
|
var tex = Service<DataManager>.Get().GetImGuiTexture(path);
|
||||||
|
|
||||||
|
if (tex is not null && tex.ImGuiHandle != nint.Zero)
|
||||||
|
{
|
||||||
|
iconTextures[iconId] = tex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tex?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
PluginLog.LogError($"Failed loading texture for icon {iconId} - {ex.Message}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextureWrap? GetIcon(uint iconId)
|
||||||
|
{
|
||||||
|
if (iconTextures.TryGetValue(iconId, out var value)) return value;
|
||||||
|
|
||||||
|
iconTextures.Add(iconId, null);
|
||||||
|
LoadIconTexture(iconId);
|
||||||
|
|
||||||
|
return iconTextures[iconId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,32 +1,31 @@
|
||||||
using System.Linq;
|
using Dalamud.Fools.Helper.YesHealMe;
|
||||||
using Dalamud.Logging;
|
using Dalamud.Interface;
|
||||||
using NoTankYou.System;
|
using NoTankYou.System;
|
||||||
|
|
||||||
namespace Dalamud.Fools.Plugins;
|
namespace Dalamud.Fools.Plugins;
|
||||||
|
|
||||||
public class YesHealMePlugin: IFoolsPlugin
|
public class YesHealMePlugin : IFoolsPlugin
|
||||||
{
|
{
|
||||||
private PartyListAddon partyListAddon;
|
private readonly FontManager fontManager;
|
||||||
|
private readonly PartyListAddon partyListAddon = new();
|
||||||
|
private int iconId = 1;
|
||||||
|
|
||||||
public YesHealMePlugin()
|
public YesHealMePlugin()
|
||||||
{
|
{
|
||||||
partyListAddon = new PartyListAddon();
|
const string nameSpace = "fools+YesHealMe";
|
||||||
|
var uiBuilder = new UiBuilder(nameSpace);
|
||||||
|
this.fontManager = new FontManager(uiBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
this.fontManager.Dispose();
|
||||||
|
this.partyListAddon.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawUi()
|
public void DrawUi()
|
||||||
{
|
{
|
||||||
foreach (var partyMember in this.partyListAddon.Select(pla => pla.PlayerCharacter).Where(pc => pc is not null))
|
YesHealMePluginWindow.Draw(this.partyListAddon, this.fontManager, ref this.iconId);
|
||||||
{
|
|
||||||
if (partyMember.CurrentHp < partyMember.MaxHp)
|
|
||||||
{
|
|
||||||
// Do things here
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
this.partyListAddon.Dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
97
Dalamud/Fools/Plugins/YesHealMePluginWindow.cs
Normal file
97
Dalamud/Fools/Plugins/YesHealMePluginWindow.cs
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Numerics;
|
||||||
|
using Dalamud.Data;
|
||||||
|
using Dalamud.Fools.Helper.YesHealMe;
|
||||||
|
using Dalamud.Game.ClientState;
|
||||||
|
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||||
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
|
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||||
|
using Dalamud.Interface.Components;
|
||||||
|
using Dalamud.Interface.Internal;
|
||||||
|
using ImGuiNET;
|
||||||
|
using NoTankYou.System;
|
||||||
|
|
||||||
|
namespace Dalamud.Fools.Plugins;
|
||||||
|
|
||||||
|
public static class YesHealMePluginWindow
|
||||||
|
{
|
||||||
|
private const string WindowName = "##foolsYesHealMeBanner";
|
||||||
|
private const string WarningText = "HEAL ME";
|
||||||
|
private const int Length = 300;
|
||||||
|
private const int SectionHeight = 100;
|
||||||
|
private const float Scale = 1f;
|
||||||
|
private static readonly Vector2 Position = new(200, 200);
|
||||||
|
private static readonly Vector2 Size = new(Length, SectionHeight);
|
||||||
|
|
||||||
|
private static IEnumerable<PlayerCharacter> Characters(PartyListAddon partyListAddon)
|
||||||
|
{
|
||||||
|
return partyListAddon.Any() ? partyListAddon.Select(pla => pla.PlayerCharacter) : new[] { Service<ClientState>.Get().LocalPlayer };
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<PlayerCharacter> HurtingCharacters(IEnumerable<PlayerCharacter> characters)
|
||||||
|
{
|
||||||
|
return characters
|
||||||
|
.Where(pc => pc.CurrentHp < pc.MaxHp ||
|
||||||
|
Service<DalamudInterface>.Get()
|
||||||
|
.IsDevMenuOpen)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Draw(PartyListAddon partyListAddon, FontManager fontManager, ref int iconId)
|
||||||
|
{
|
||||||
|
ImGui.SetNextWindowPos(Position, ImGuiCond.FirstUseEver);
|
||||||
|
ImGui.SetNextWindowSize(Size);
|
||||||
|
ImGui.SetNextWindowSizeConstraints(Size, Size);
|
||||||
|
ImGui.Begin(WindowName, ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoBackground);
|
||||||
|
var playersDrawn = 0;
|
||||||
|
var hurtingCharacters = HurtingCharacters(Characters(partyListAddon));
|
||||||
|
if (hurtingCharacters.Count > 0)
|
||||||
|
{
|
||||||
|
var windowPos = ImGui.GetCursorScreenPos();
|
||||||
|
foreach (var hurtingCharacter in hurtingCharacters)
|
||||||
|
{
|
||||||
|
var position = windowPos + new Vector2(0, playersDrawn * SectionHeight);
|
||||||
|
var healMeTextSize = DrawUtilities.CalculateTextSize(fontManager, WarningText, Scale);
|
||||||
|
var healMePosition = position with
|
||||||
|
{
|
||||||
|
X = position.X + healMeTextSize.X,
|
||||||
|
};
|
||||||
|
DrawHealMeText(fontManager, position);
|
||||||
|
DrawPlayerName(fontManager, hurtingCharacter, healMePosition);
|
||||||
|
DrawIcon(fontManager, healMePosition);
|
||||||
|
playersDrawn += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.End();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawIcon(FontManager fontManager, Vector2 healMePosition)
|
||||||
|
{
|
||||||
|
DrawUtilities.DrawIconWithName(fontManager, healMePosition, 62582, "pls? owo", 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawHealMeText(FontManager fontManager, Vector2 position)
|
||||||
|
{
|
||||||
|
// HEAL ME text
|
||||||
|
DrawUtilities.TextOutlined(fontManager, position, WarningText, 1, Colors.White);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawPlayerName(
|
||||||
|
FontManager fontManager, PlayerCharacter hurtingCharacter, Vector2 healMePosition)
|
||||||
|
{
|
||||||
|
var textSize = DrawUtilities.CalculateTextSize(fontManager, hurtingCharacter.Name.TextValue, Scale);
|
||||||
|
var namePosition = new Vector2
|
||||||
|
{
|
||||||
|
X = healMePosition.X - textSize.X / 2.0f,
|
||||||
|
Y = healMePosition.Y + textSize.Y,
|
||||||
|
};
|
||||||
|
DrawUtilities.TextOutlined(
|
||||||
|
fontManager,
|
||||||
|
namePosition,
|
||||||
|
hurtingCharacter.Name.TextValue,
|
||||||
|
Scale / 2f,
|
||||||
|
Colors.White);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue