mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
Merge pull request #466 from lmcintyre/flytext
This commit is contained in:
commit
ad1aa8d5eb
6 changed files with 625 additions and 0 deletions
|
|
@ -49,6 +49,7 @@
|
|||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EFormat_002ESettingsUpgrade_002EAlignmentTabFillStyleMigration/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=clientopcode/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Dalamud/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Flytext/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Gpose/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=lumina/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Materia/@EntryIndexedValue">True</s:Boolean>
|
||||
|
|
|
|||
312
Dalamud/Game/Gui/FlyText/FlyTextGui.cs
Normal file
312
Dalamud/Game/Gui/FlyText/FlyTextGui.cs
Normal file
|
|
@ -0,0 +1,312 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Hooking;
|
||||
using Dalamud.Memory;
|
||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||
using Serilog;
|
||||
|
||||
namespace Dalamud.Game.Gui.FlyText
|
||||
{
|
||||
/// <summary>
|
||||
/// This class facilitates interacting with and creating native in-game "fly text".
|
||||
/// </summary>
|
||||
public sealed class FlyTextGui : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The native function responsible for adding fly text to the UI. See <see cref="FlyTextGuiAddressResolver.AddFlyText"/>.
|
||||
/// </summary>
|
||||
private readonly AddFlyTextDelegate addFlyTextNative;
|
||||
|
||||
/// <summary>
|
||||
/// The hook that fires when the game creates a fly text element. See <see cref="FlyTextGuiAddressResolver.CreateFlyText"/>.
|
||||
/// </summary>
|
||||
private readonly Hook<CreateFlyTextDelegate> createFlyTextHook;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FlyTextGui"/> class.
|
||||
/// </summary>
|
||||
/// <param name="scanner">The SigScanner instance.</param>
|
||||
/// <param name="dalamud">The Dalamud instance.</param>
|
||||
internal FlyTextGui(SigScanner scanner, Dalamud dalamud)
|
||||
{
|
||||
this.Dalamud = dalamud;
|
||||
|
||||
this.Address = new FlyTextGuiAddressResolver();
|
||||
this.Address.Setup(scanner);
|
||||
|
||||
this.addFlyTextNative = Marshal.GetDelegateForFunctionPointer<AddFlyTextDelegate>(this.Address.AddFlyText);
|
||||
this.createFlyTextHook = new Hook<CreateFlyTextDelegate>(this.Address.CreateFlyText, this.CreateFlyTextDetour);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The delegate defining the type for the FlyText event.
|
||||
/// </summary>
|
||||
/// <param name="kind">The FlyTextKind. See <see cref="FlyTextKind"/>.</param>
|
||||
/// <param name="val1">Value1 passed to the native flytext function.</param>
|
||||
/// <param name="val2">Value2 passed to the native flytext function. Seems unused.</param>
|
||||
/// <param name="text1">Text1 passed to the native flytext function.</param>
|
||||
/// <param name="text2">Text2 passed to the native flytext function.</param>
|
||||
/// <param name="color">Color passed to the native flytext function. Changes flytext color.</param>
|
||||
/// <param name="icon">Icon ID passed to the native flytext function. Only displays with select FlyTextKind.</param>
|
||||
/// <param name="yOffset">The vertical offset to place the flytext at. 0 is default. Negative values result
|
||||
/// in text appearing higher on the screen. This does not change where the element begins to fade.</param>
|
||||
/// <param name="handled">Whether this flytext has been handled. If a subscriber sets this to true, the FlyText will not appear.</param>
|
||||
public delegate void OnFlyTextCreatedDelegate(
|
||||
ref FlyTextKind kind,
|
||||
ref int val1,
|
||||
ref int val2,
|
||||
ref SeString text1,
|
||||
ref SeString text2,
|
||||
ref uint color,
|
||||
ref uint icon,
|
||||
ref float yOffset,
|
||||
ref bool handled);
|
||||
|
||||
/// <summary>
|
||||
/// Private delegate for the native CreateFlyText function's hook.
|
||||
/// </summary>
|
||||
private delegate IntPtr CreateFlyTextDelegate(
|
||||
IntPtr addonFlyText,
|
||||
int kind,
|
||||
int val1,
|
||||
int val2,
|
||||
IntPtr text2,
|
||||
uint color,
|
||||
uint icon,
|
||||
IntPtr text1,
|
||||
float yOffset);
|
||||
|
||||
/// <summary>
|
||||
/// Private delegate for the native AddFlyText function pointer.
|
||||
/// </summary>
|
||||
private delegate void AddFlyTextDelegate(
|
||||
IntPtr addonFlyText,
|
||||
uint actorIndex,
|
||||
uint messageMax,
|
||||
IntPtr numbers,
|
||||
uint offsetNum,
|
||||
uint offsetNumMax,
|
||||
IntPtr strings,
|
||||
uint offsetStr,
|
||||
uint offsetStrMax,
|
||||
int unknown);
|
||||
|
||||
/// <summary>
|
||||
/// The FlyText event that can be subscribed to.
|
||||
/// </summary>
|
||||
public event OnFlyTextCreatedDelegate? FlyTextCreated;
|
||||
|
||||
private Dalamud Dalamud { get; }
|
||||
|
||||
private FlyTextGuiAddressResolver Address { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Disposes of managed and unmanaged resources.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
this.createFlyTextHook.Disable();
|
||||
this.createFlyTextHook.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays a fly text in-game on the local player.
|
||||
/// </summary>
|
||||
/// <param name="kind">The FlyTextKind. See <see cref="FlyTextKind"/>.</param>
|
||||
/// <param name="actorIndex">The index of the actor to place flytext on. Indexing unknown. 1 places flytext on local player.</param>
|
||||
/// <param name="val1">Value1 passed to the native flytext function.</param>
|
||||
/// <param name="val2">Value2 passed to the native flytext function. Seems unused.</param>
|
||||
/// <param name="text1">Text1 passed to the native flytext function.</param>
|
||||
/// <param name="text2">Text2 passed to the native flytext function.</param>
|
||||
/// <param name="color">Color passed to the native flytext function. Changes flytext color.</param>
|
||||
/// <param name="icon">Icon ID passed to the native flytext function. Only displays with select FlyTextKind.</param>
|
||||
public unsafe void AddFlyText(FlyTextKind kind, uint actorIndex, uint val1, uint val2, SeString text1, SeString text2, uint color, uint icon)
|
||||
{
|
||||
// Known valid flytext region within the atk arrays
|
||||
int numIndex = 28;
|
||||
int strIndex = 25;
|
||||
uint numOffset = 147;
|
||||
uint strOffset = 28;
|
||||
|
||||
// Get the UI module and flytext addon pointers
|
||||
var ui = (UIModule*)this.Dalamud.Framework.Gui.GetUIModule();
|
||||
var flytext = this.Dalamud.Framework.Gui.GetUiObjectByName("_FlyText", 1);
|
||||
|
||||
if (ui == null || flytext == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
// Get the number and string arrays we need
|
||||
var atkArrayDataHolder = ui->RaptureAtkModule.AtkModule.AtkArrayDataHolder;
|
||||
var numArray = atkArrayDataHolder._NumberArrays[numIndex];
|
||||
var strArray = atkArrayDataHolder._StringArrays[strIndex];
|
||||
|
||||
// Write the values to the arrays using a known valid flytext region
|
||||
numArray->IntArray[numOffset + 0] = 1; // Some kind of "Enabled" flag for this section
|
||||
numArray->IntArray[numOffset + 1] = (int)kind;
|
||||
numArray->IntArray[numOffset + 2] = unchecked((int)val1);
|
||||
numArray->IntArray[numOffset + 3] = unchecked((int)val2);
|
||||
numArray->IntArray[numOffset + 4] = 5; // Unknown
|
||||
numArray->IntArray[numOffset + 5] = unchecked((int)color);
|
||||
numArray->IntArray[numOffset + 6] = unchecked((int)icon);
|
||||
numArray->IntArray[numOffset + 7] = 0; // Unknown
|
||||
numArray->IntArray[numOffset + 8] = 0; // Unknown, has something to do with yOffset
|
||||
|
||||
fixed (byte* pText1 = text1.Encode())
|
||||
{
|
||||
fixed (byte* pText2 = text2.Encode())
|
||||
{
|
||||
strArray->StringArray[strOffset + 0] = pText1;
|
||||
strArray->StringArray[strOffset + 1] = pText2;
|
||||
|
||||
this.addFlyTextNative(
|
||||
flytext,
|
||||
actorIndex,
|
||||
1,
|
||||
(IntPtr)numArray,
|
||||
numOffset,
|
||||
9,
|
||||
(IntPtr)strArray,
|
||||
strOffset,
|
||||
2,
|
||||
0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables this module.
|
||||
/// </summary>
|
||||
internal void Enable()
|
||||
{
|
||||
this.createFlyTextHook.Enable();
|
||||
}
|
||||
|
||||
private IntPtr CreateFlyTextDetour(
|
||||
IntPtr addonFlyText,
|
||||
int kind,
|
||||
int val1,
|
||||
int val2,
|
||||
IntPtr text2,
|
||||
uint color,
|
||||
uint icon,
|
||||
IntPtr text1,
|
||||
float yOffset)
|
||||
{
|
||||
var retVal = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
Log.Verbose("[FlyText] Enter CreateFlyText detour!");
|
||||
|
||||
var handled = false;
|
||||
|
||||
var tmpKind = (FlyTextKind)kind;
|
||||
var tmpVal1 = val1;
|
||||
var tmpVal2 = val2;
|
||||
var tmpText1 = MemoryHelper.ReadSeString(text1);
|
||||
var tmpText2 = MemoryHelper.ReadSeString(text2);
|
||||
var tmpColor = color;
|
||||
var tmpIcon = icon;
|
||||
var tmpYOffset = yOffset;
|
||||
|
||||
var cmpText1 = tmpText1.ToString();
|
||||
var cmpText2 = tmpText2.ToString();
|
||||
|
||||
Log.Verbose($"[FlyText] Called with addonFlyText({addonFlyText.ToInt64():X}) " +
|
||||
$"kind({((FlyTextKind)kind).ToString()}) val1({val1}) val2({val2}) " +
|
||||
$"text1({text1.ToInt64():X}, \"{tmpText1}\") text2({text2.ToInt64():X}, \"{tmpText2}\") " +
|
||||
$"color({color:X}) icon({icon}) yOffset({yOffset})");
|
||||
Log.Verbose("[FlyText] Calling flytext events!");
|
||||
this.FlyTextCreated?.Invoke(
|
||||
ref tmpKind,
|
||||
ref tmpVal1,
|
||||
ref tmpVal2,
|
||||
ref tmpText1,
|
||||
ref tmpText2,
|
||||
ref tmpColor,
|
||||
ref tmpIcon,
|
||||
ref tmpYOffset,
|
||||
ref handled);
|
||||
|
||||
// If handled, ignore the original call
|
||||
if (handled)
|
||||
{
|
||||
Log.Verbose("[FlyText] FlyText was handled.");
|
||||
|
||||
// Returning null to AddFlyText from CreateFlyText will result
|
||||
// in the operation being dropped entirely.
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
// Check if any values have changed
|
||||
var dirty = tmpKind != (FlyTextKind)kind ||
|
||||
tmpVal1 != val1 ||
|
||||
tmpVal2 != val2 ||
|
||||
tmpText1.ToString() != cmpText1 ||
|
||||
tmpText2.ToString() != cmpText2 ||
|
||||
tmpColor != color ||
|
||||
tmpIcon != icon ||
|
||||
Math.Abs(tmpYOffset - yOffset) > float.Epsilon;
|
||||
|
||||
// If not dirty, make the original call
|
||||
if (!dirty)
|
||||
{
|
||||
Log.Verbose("[FlyText] Calling flytext with original args.");
|
||||
return this.createFlyTextHook.Original(addonFlyText, kind, val1, val2, text2, color, icon, text1, yOffset);
|
||||
}
|
||||
|
||||
var terminated1 = Terminate(tmpText1.Encode());
|
||||
var terminated2 = Terminate(tmpText2.Encode());
|
||||
var pText1 = Marshal.AllocHGlobal(terminated1.Length);
|
||||
var pText2 = Marshal.AllocHGlobal(terminated2.Length);
|
||||
Marshal.Copy(terminated1, 0, pText1, terminated1.Length);
|
||||
Marshal.Copy(terminated2, 0, pText2, terminated2.Length);
|
||||
Log.Verbose("[FlyText] Allocated and set strings.");
|
||||
|
||||
retVal = this.createFlyTextHook.Original(
|
||||
addonFlyText,
|
||||
(int)tmpKind,
|
||||
tmpVal1,
|
||||
tmpVal2,
|
||||
pText2,
|
||||
tmpColor,
|
||||
tmpIcon,
|
||||
pText1,
|
||||
tmpYOffset);
|
||||
|
||||
Log.Verbose("[FlyText] Returned from original. Delaying free task.");
|
||||
|
||||
Task.Delay(2000).ContinueWith(_ =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Marshal.FreeHGlobal(pText1);
|
||||
Marshal.FreeHGlobal(pText2);
|
||||
Log.Verbose("[FlyText] Freed strings.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Verbose(e, "[FlyText] Exception occurred freeing strings in task.");
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, "Exception occurred in CreateFlyTextDetour!");
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private static byte[] Terminate(byte[] source)
|
||||
{
|
||||
var terminated = new byte[source.Length + 1];
|
||||
Array.Copy(source, 0, terminated, 0, source.Length);
|
||||
terminated[^1] = 0;
|
||||
|
||||
return terminated;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Dalamud/Game/Gui/FlyText/FlyTextGuiAddressResolver.cs
Normal file
32
Dalamud/Game/Gui/FlyText/FlyTextGuiAddressResolver.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
|
||||
namespace Dalamud.Game.Gui.FlyText
|
||||
{
|
||||
/// <summary>
|
||||
/// An address resolver for the <see cref="FlyTextGui"/> class.
|
||||
/// </summary>
|
||||
public class FlyTextGuiAddressResolver : BaseAddressResolver
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the address of the native AddFlyText method, which occurs
|
||||
/// when the game adds fly text elements to the UI. Multiple fly text
|
||||
/// elements can be added in a single AddFlyText call.
|
||||
/// </summary>
|
||||
public IntPtr AddFlyText { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the address of the native CreateFlyText method, which occurs
|
||||
/// when the game creates a new fly text element. This method is called
|
||||
/// once per fly text element, and can be called multiple times per
|
||||
/// AddFlyText call.
|
||||
/// </summary>
|
||||
public IntPtr CreateFlyText { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Setup64Bit(SigScanner sig)
|
||||
{
|
||||
this.AddFlyText = sig.ScanText("E8 ?? ?? ?? ?? FF C7 41 D1 C7");
|
||||
this.CreateFlyText = sig.ScanText("48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 83 EC 40 48 63 FA");
|
||||
}
|
||||
}
|
||||
}
|
||||
214
Dalamud/Game/Gui/FlyText/FlyTextKind.cs
Normal file
214
Dalamud/Game/Gui/FlyText/FlyTextKind.cs
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
namespace Dalamud.Game.Gui.FlyText
|
||||
{
|
||||
/// <summary>
|
||||
/// Enum of FlyTextKind values. Members suffixed with
|
||||
/// a number seem to be a duplicate, or perform duplicate behavior.
|
||||
/// </summary>
|
||||
public enum FlyTextKind
|
||||
{
|
||||
/// <summary>
|
||||
/// Val1 in serif font, Text2 in sans-serif as subtitle.
|
||||
/// Used for autos and incoming DoTs.
|
||||
/// </summary>
|
||||
AutoAttack = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Val1 in serif font, Text2 in sans-serif as subtitle.
|
||||
/// Does a bounce effect on appearance.
|
||||
/// </summary>
|
||||
DirectHit = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Val1 in larger serif font with exclamation, with Text2
|
||||
/// in sans-serif as subtitle. Does a bigger bounce effect on appearance.
|
||||
/// </summary>
|
||||
CriticalHit = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Val1 in even larger serif font with 2 exclamations, Text2 in
|
||||
/// sans-serif as subtitle. Does a large bounce effect on appearance.
|
||||
/// Does not scroll up or down the screen.
|
||||
/// </summary>
|
||||
CriticalDirectHit = 3,
|
||||
|
||||
/// <summary>
|
||||
/// AutoAttack with sans-serif Text1 to the left of the Val1.
|
||||
/// </summary>
|
||||
NamedAttack = 4,
|
||||
|
||||
/// <summary>
|
||||
/// DirectHit with sans-serif Text1 to the left of the Val1.
|
||||
/// </summary>
|
||||
NamedDirectHit = 5,
|
||||
|
||||
/// <summary>
|
||||
/// CriticalHit with sans-serif Text1 to the left of the Val1.
|
||||
/// </summary>
|
||||
NamedCriticalHit = 6,
|
||||
|
||||
/// <summary>
|
||||
/// CriticalDirectHit with sans-serif Text1 to the left of the Val1.
|
||||
/// </summary>
|
||||
NamedCriticalDirectHit = 7,
|
||||
|
||||
/// <summary>
|
||||
/// All caps, serif MISS.
|
||||
/// </summary>
|
||||
Miss = 8,
|
||||
|
||||
/// <summary>
|
||||
/// Sans-serif Text1 next to all caps serif MISS.
|
||||
/// </summary>
|
||||
NamedMiss = 9,
|
||||
|
||||
/// <summary>
|
||||
/// All caps serif DODGE.
|
||||
/// </summary>
|
||||
Dodge = 10,
|
||||
|
||||
/// <summary>
|
||||
/// Sans-serif Text1 next to all caps serif DODGE.
|
||||
/// </summary>
|
||||
NamedDodge = 11,
|
||||
|
||||
/// <summary>
|
||||
/// Icon next to sans-serif Text1.
|
||||
/// </summary>
|
||||
NamedIcon = 12,
|
||||
NamedIcon2 = 13,
|
||||
|
||||
/// <summary>
|
||||
/// Serif Val1 with all caps condensed font EXP with Text2 in sans-serif as subtitle.
|
||||
/// </summary>
|
||||
Exp = 14,
|
||||
|
||||
/// <summary>
|
||||
/// Sans-serif Text1 next to serif Val1 with all caps condensed font MP with Text2 in sans-serif as subtitle.
|
||||
/// </summary>
|
||||
NamedMp = 15,
|
||||
|
||||
/// <summary>
|
||||
/// Sans-serif Text1 next to serif Val1 with all caps condensed font TP with Text2 in sans-serif as subtitle.
|
||||
/// </summary>
|
||||
NamedTp = 16,
|
||||
|
||||
NamedAttack2 = 17,
|
||||
NamedMp2 = 18,
|
||||
NamedTp2 = 19,
|
||||
|
||||
/// <summary>
|
||||
/// Sans-serif Text1 next to serif Val1 with all caps condensed font EP with Text2 in sans-serif as subtitle.
|
||||
/// </summary>
|
||||
NamedEp = 20,
|
||||
|
||||
/// <summary>
|
||||
/// Displays nothing.
|
||||
/// </summary>
|
||||
None = 21,
|
||||
|
||||
/// <summary>
|
||||
/// All caps serif INVULNERABLE.
|
||||
/// </summary>
|
||||
Invulnerable = 22,
|
||||
|
||||
/// <summary>
|
||||
/// All caps sans-serif condensed font INTERRUPTED!
|
||||
/// Does a large bounce effect on appearance.
|
||||
/// Does not scroll up or down the screen.
|
||||
/// </summary>
|
||||
Interrupted = 23,
|
||||
|
||||
/// <summary>
|
||||
/// AutoAttack with no Text2.
|
||||
/// </summary>
|
||||
AutoAttackNoText = 24,
|
||||
AutoAttackNoText2 = 25,
|
||||
CriticalHit2 = 26,
|
||||
AutoAttackNoText3 = 27,
|
||||
NamedCriticalHit2 = 28,
|
||||
|
||||
/// <summary>
|
||||
/// Same as NamedCriticalHit with a green (cannot change) MP in condensed font to the right of Val1.
|
||||
/// Does a jiggle effect to the right on appearance.
|
||||
/// </summary>
|
||||
NamedCriticalHitWithMp = 29,
|
||||
|
||||
/// <summary>
|
||||
/// Same as NamedCriticalHit with a yellow (cannot change) TP in condensed font to the right of Val1.
|
||||
/// Does a jiggle effect to the right on appearance.
|
||||
/// </summary>
|
||||
NamedCriticalHitWithTp = 30,
|
||||
|
||||
/// <summary>
|
||||
/// Same as NamedIcon with sans-serif "has no effect!" to the right.
|
||||
/// </summary>
|
||||
NamedIconHasNoEffect = 31,
|
||||
|
||||
/// <summary>
|
||||
/// Same as NamedIcon but Text1 is slightly faded. Used for buff expiration.
|
||||
/// </summary>
|
||||
NamedIconFaded = 32,
|
||||
NamedIconFaded2 = 33,
|
||||
|
||||
/// <summary>
|
||||
/// Text1 in sans-serif font.
|
||||
/// </summary>
|
||||
Named = 34,
|
||||
|
||||
/// <summary>
|
||||
/// Same as NamedIcon with sans-serif "(fully resisted)" to the right.
|
||||
/// </summary>
|
||||
NamedIconFullyResisted = 35,
|
||||
|
||||
/// <summary>
|
||||
/// All caps serif 'INCAPACITATED!'.
|
||||
/// </summary>
|
||||
Incapacitated = 36,
|
||||
|
||||
/// <summary>
|
||||
/// Text1 with sans-serif "(fully resisted)" to the right.
|
||||
/// </summary>
|
||||
NamedFullyResisted = 37,
|
||||
|
||||
/// <summary>
|
||||
/// Text1 with sans-serif "has no effect!" to the right.
|
||||
/// </summary>
|
||||
NamedHasNoEffect = 38,
|
||||
|
||||
NamedAttack3 = 39,
|
||||
NamedMp3 = 40,
|
||||
NamedTp3 = 41,
|
||||
|
||||
/// <summary>
|
||||
/// Same as NamedIcon with serif "INVULNERABLE!" beneath the Text1.
|
||||
/// </summary>
|
||||
NamedIconInvulnerable = 42,
|
||||
|
||||
/// <summary>
|
||||
/// All caps serif RESIST.
|
||||
/// </summary>
|
||||
Resist = 43,
|
||||
|
||||
/// <summary>
|
||||
/// Same as NamedIcon but places the given icon in the item icon outline.
|
||||
/// </summary>
|
||||
NamedIconWithItemOutline = 44,
|
||||
|
||||
AutoAttackNoText4 = 45,
|
||||
CriticalHit3 = 46,
|
||||
|
||||
/// <summary>
|
||||
/// All caps serif REFLECT.
|
||||
/// </summary>
|
||||
Reflect = 47,
|
||||
|
||||
/// <summary>
|
||||
/// All caps serif REFLECTED.
|
||||
/// </summary>
|
||||
Reflected = 48,
|
||||
|
||||
DirectHit2 = 49,
|
||||
CriticalHit5 = 50,
|
||||
CriticalDirectHit2 = 51,
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ using System.Numerics;
|
|||
using System.Runtime.InteropServices;
|
||||
|
||||
using Dalamud.Game.Gui.Addons;
|
||||
using Dalamud.Game.Gui.FlyText;
|
||||
using Dalamud.Game.Gui.PartyFinder;
|
||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||
using Dalamud.Hooking;
|
||||
|
|
@ -66,6 +67,7 @@ namespace Dalamud.Game.Gui
|
|||
this.Chat = new ChatGui(this.address.ChatManager, scanner, dalamud);
|
||||
this.PartyFinder = new PartyFinderGui(scanner, dalamud);
|
||||
this.Toast = new ToastGui(scanner, dalamud);
|
||||
this.FlyText = new FlyTextGui(scanner, dalamud);
|
||||
|
||||
this.setGlobalBgmHook = new Hook<SetGlobalBgmDelegate>(this.address.SetGlobalBgm, this.HandleSetGlobalBgmDetour);
|
||||
|
||||
|
|
@ -172,6 +174,11 @@ namespace Dalamud.Game.Gui
|
|||
/// </summary>
|
||||
public ToastGui Toast { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="FlyText"/> instance.
|
||||
/// </summary>
|
||||
public FlyTextGui FlyText { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the game UI is hidden.
|
||||
/// </summary>
|
||||
|
|
@ -498,6 +505,7 @@ namespace Dalamud.Game.Gui
|
|||
{
|
||||
this.Chat.Enable();
|
||||
this.Toast.Enable();
|
||||
this.FlyText.Enable();
|
||||
this.PartyFinder.Enable();
|
||||
this.setGlobalBgmHook.Enable();
|
||||
this.handleItemHoverHook.Enable();
|
||||
|
|
@ -515,6 +523,7 @@ namespace Dalamud.Game.Gui
|
|||
{
|
||||
this.Chat.Dispose();
|
||||
this.Toast.Dispose();
|
||||
this.FlyText.Dispose();
|
||||
this.PartyFinder.Dispose();
|
||||
this.setGlobalBgmHook.Dispose();
|
||||
this.handleItemHoverHook.Dispose();
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ using Dalamud.Game.ClientState.JobGauge.Types;
|
|||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||
using Dalamud.Game.ClientState.Objects.Types;
|
||||
using Dalamud.Game.Gui.Addons;
|
||||
using Dalamud.Game.Gui.FlyText;
|
||||
using Dalamud.Game.Gui.Toast;
|
||||
using Dalamud.Game.Text;
|
||||
using Dalamud.Interface.Windowing;
|
||||
|
|
@ -53,6 +54,7 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
|
||||
private UIDebug addonInspector = null;
|
||||
|
||||
// Toast fields
|
||||
private string inputTextToast = string.Empty;
|
||||
private int toastPosition = 0;
|
||||
private int toastSpeed = 0;
|
||||
|
|
@ -61,6 +63,17 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
private int questToastIconId = 0;
|
||||
private bool questToastCheckmark = false;
|
||||
|
||||
// Fly text fields
|
||||
private int flyActor;
|
||||
private FlyTextKind flyKind;
|
||||
private int flyVal1;
|
||||
private int flyVal2;
|
||||
private string flyText1 = string.Empty;
|
||||
private string flyText2 = string.Empty;
|
||||
private int flyIcon;
|
||||
private Vector4 flyColor = new(1, 0, 0, 1);
|
||||
|
||||
// ImGui fields
|
||||
private string inputTexPath = string.Empty;
|
||||
private TextureWrap debugTex = null;
|
||||
private Vector2 inputTexUv0 = Vector2.Zero;
|
||||
|
|
@ -103,6 +116,7 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
StartInfo,
|
||||
Target,
|
||||
Toast,
|
||||
FlyText,
|
||||
ImGui,
|
||||
Tex,
|
||||
Gamepad,
|
||||
|
|
@ -251,6 +265,10 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
this.DrawToast();
|
||||
break;
|
||||
|
||||
case DataKind.FlyText:
|
||||
this.DrawFlyText();
|
||||
break;
|
||||
|
||||
case DataKind.ImGui:
|
||||
this.DrawImGui();
|
||||
break;
|
||||
|
|
@ -954,6 +972,45 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
}
|
||||
}
|
||||
|
||||
private void DrawFlyText()
|
||||
{
|
||||
if (ImGui.BeginCombo("Kind", this.flyKind.ToString()))
|
||||
{
|
||||
var names = Enum.GetNames(typeof(FlyTextKind));
|
||||
for (int i = 0; i < names.Length; i++)
|
||||
{
|
||||
if (ImGui.Selectable($"{names[i]} ({i})"))
|
||||
this.flyKind = (FlyTextKind)i;
|
||||
}
|
||||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
ImGui.InputText("Text1", ref this.flyText1, 200);
|
||||
ImGui.InputText("Text2", ref this.flyText2, 200);
|
||||
|
||||
ImGui.InputInt("Val1", ref this.flyVal1);
|
||||
ImGui.InputInt("Val2", ref this.flyVal2);
|
||||
|
||||
ImGui.InputInt("Icon ID", ref this.flyIcon);
|
||||
ImGui.ColorEdit4("Color", ref this.flyColor);
|
||||
ImGui.InputInt("Actor Index", ref this.flyActor);
|
||||
var sendColor = ImGui.ColorConvertFloat4ToU32(this.flyColor);
|
||||
|
||||
if (ImGui.Button("Send"))
|
||||
{
|
||||
this.dalamud.Framework.Gui.FlyText.AddFlyText(
|
||||
this.flyKind,
|
||||
unchecked((uint)this.flyActor),
|
||||
unchecked((uint)this.flyVal1),
|
||||
unchecked((uint)this.flyVal2),
|
||||
this.flyText1,
|
||||
this.flyText2,
|
||||
sendColor,
|
||||
unchecked((uint)this.flyIcon));
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawImGui()
|
||||
{
|
||||
ImGui.Text("Monitor count: " + ImGui.GetPlatformIO().Monitors.Size);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue