mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-15 13:14:17 +01:00
feat: condition changed event, expose condition address
This commit is contained in:
parent
b0f2486215
commit
37fc6ffc73
4 changed files with 116 additions and 26 deletions
|
|
@ -153,6 +153,19 @@ namespace Dalamud
|
||||||
Service<NetworkHandlers>.Set();
|
Service<NetworkHandlers>.Set();
|
||||||
Log.Information("[T2] NH OK!");
|
Log.Information("[T2] NH OK!");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Service<DataManager>.Set().Initialize(this.AssetDirectory.FullName);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Error(e, "Could not initialize DataManager.");
|
||||||
|
this.Unload();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Information("[T2] Data OK!");
|
||||||
|
|
||||||
var clientState = Service<ClientState>.Set();
|
var clientState = Service<ClientState>.Set();
|
||||||
Log.Information("[T2] CS OK!");
|
Log.Information("[T2] CS OK!");
|
||||||
|
|
||||||
|
|
@ -192,19 +205,6 @@ namespace Dalamud
|
||||||
Log.Information(e, "Could not init IME.");
|
Log.Information(e, "Could not init IME.");
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Service<DataManager>.Set().Initialize(this.AssetDirectory.FullName);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Log.Error(e, "Could not initialize DataManager.");
|
|
||||||
this.Unload();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.Information("[T2] Data OK!");
|
|
||||||
|
|
||||||
#pragma warning disable CS0618 // Type or member is obsolete
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
Service<SeStringManager>.Set();
|
Service<SeStringManager>.Set();
|
||||||
#pragma warning restore CS0618 // Type or member is obsolete
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,7 @@ namespace Dalamud.Game.ClientState
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Enable()
|
public void Enable()
|
||||||
{
|
{
|
||||||
|
Service<Condition>.Get().Enable();
|
||||||
Service<GamepadState>.Get().Enable();
|
Service<GamepadState>.Get().Enable();
|
||||||
this.setupTerritoryTypeHook.Enable();
|
this.setupTerritoryTypeHook.Enable();
|
||||||
}
|
}
|
||||||
|
|
@ -135,6 +136,7 @@ namespace Dalamud.Game.ClientState
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
this.setupTerritoryTypeHook.Dispose();
|
this.setupTerritoryTypeHook.Dispose();
|
||||||
|
Service<Condition>.Get().Dispose();
|
||||||
Service<GamepadState>.Get().Dispose();
|
Service<GamepadState>.Get().Dispose();
|
||||||
Service<Framework>.Get().Update -= this.FrameworkOnOnUpdateEvent;
|
Service<Framework>.Get().Update -= this.FrameworkOnOnUpdateEvent;
|
||||||
Service<NetworkHandlers>.Get().CfPop -= this.NetworkHandlersOnCfPop;
|
Service<NetworkHandlers>.Get().CfPop -= this.NetworkHandlersOnCfPop;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
|
|
||||||
using Dalamud.IoC;
|
using Dalamud.IoC;
|
||||||
using Dalamud.IoC.Internal;
|
using Dalamud.IoC.Internal;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
namespace Dalamud.Game.ClientState.Conditions
|
namespace Dalamud.Game.ClientState.Conditions
|
||||||
{
|
{
|
||||||
|
|
@ -10,45 +11,61 @@ namespace Dalamud.Game.ClientState.Conditions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PluginInterface]
|
[PluginInterface]
|
||||||
[InterfaceVersion("1.0")]
|
[InterfaceVersion("1.0")]
|
||||||
public class Condition
|
public sealed partial class Condition
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current max number of conditions. You can get this just by looking at the condition sheet and how many rows it has.
|
/// The current max number of conditions. You can get this just by looking at the condition sheet and how many rows it has.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int MaxConditionEntries = 100;
|
public const int MaxConditionEntries = 100;
|
||||||
|
|
||||||
|
private readonly bool[] cache = new bool[MaxConditionEntries];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="Condition"/> class.
|
/// Initializes a new instance of the <see cref="Condition"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="resolver">The ClientStateAddressResolver instance.</param>
|
/// <param name="resolver">The ClientStateAddressResolver instance.</param>
|
||||||
internal Condition(ClientStateAddressResolver resolver)
|
internal Condition(ClientStateAddressResolver resolver)
|
||||||
{
|
{
|
||||||
this.ConditionArrayBase = resolver.ConditionFlags;
|
this.Address = resolver.ConditionFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the condition array base pointer.
|
/// A delegate type used with the <see cref="ConditionChange"/> event.
|
||||||
/// Would typically be private but is used in /xldata windows.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal IntPtr ConditionArrayBase { get; private set; }
|
/// <param name="flag">The changed condition.</param>
|
||||||
|
/// <param name="value">The value the condition is set to.</param>
|
||||||
|
public delegate void ConditionChangeDelegate(ConditionFlag flag, bool value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event that gets fired when a condition is set.
|
||||||
|
/// Should only get fired for actual changes, so the previous value will always be !value.
|
||||||
|
/// </summary>
|
||||||
|
public event ConditionChangeDelegate? ConditionChange;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the condition array base pointer.
|
||||||
|
/// </summary>
|
||||||
|
public IntPtr Address { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check the value of a specific condition/state flag.
|
/// Check the value of a specific condition/state flag.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="flag">The condition flag to check.</param>
|
/// <param name="flag">The condition flag to check.</param>
|
||||||
public unsafe bool this[ConditionFlag flag]
|
public unsafe bool this[int flag]
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var idx = (int)flag;
|
if (flag < 0 || flag >= MaxConditionEntries)
|
||||||
|
|
||||||
if (idx < 0 || idx >= MaxConditionEntries)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return *(bool*)(this.ConditionArrayBase + idx);
|
return *(bool*)(this.Address + flag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="this[int]"/>
|
||||||
|
public unsafe bool this[ConditionFlag flag]
|
||||||
|
=> this[(int)flag];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if any condition flags are set.
|
/// Check if any condition flags are set.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -57,8 +74,7 @@ namespace Dalamud.Game.ClientState.Conditions
|
||||||
{
|
{
|
||||||
for (var i = 0; i < MaxConditionEntries; i++)
|
for (var i = 0; i < MaxConditionEntries; i++)
|
||||||
{
|
{
|
||||||
var typedCondition = (ConditionFlag)i;
|
var cond = this[i];
|
||||||
var cond = this[typedCondition];
|
|
||||||
|
|
||||||
if (cond)
|
if (cond)
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -66,5 +82,77 @@ namespace Dalamud.Game.ClientState.Conditions
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables the hooks of the Condition class function.
|
||||||
|
/// </summary>
|
||||||
|
public void Enable()
|
||||||
|
{
|
||||||
|
// Initialization
|
||||||
|
for (var i = 0; i < MaxConditionEntries; i++)
|
||||||
|
this.cache[i] = this[i];
|
||||||
|
|
||||||
|
Service<Framework>.Get().Update += this.FrameworkUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FrameworkUpdate(Framework framework)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < MaxConditionEntries; i++)
|
||||||
|
{
|
||||||
|
var value = this[i];
|
||||||
|
|
||||||
|
if (value != this.cache[i])
|
||||||
|
{
|
||||||
|
this.cache[i] = value;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.ConditionChange?.Invoke((ConditionFlag)i, value);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error(ex, $"While invoking {nameof(this.ConditionChange)}, an exception was thrown.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides access to conditions (generally player state). You can check whether a player is in combat, mounted, etc.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class Condition : IDisposable
|
||||||
|
{
|
||||||
|
private bool isDisposed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finalizes an instance of the <see cref="Condition" /> class.
|
||||||
|
/// </summary>
|
||||||
|
~Condition()
|
||||||
|
{
|
||||||
|
this.Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disposes this instance, alongside its hooks.
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
this.Dispose(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (this.isDisposed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
Service<Framework>.Get().Update -= this.FrameworkUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isDisposed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -674,7 +674,7 @@ namespace Dalamud.Interface.Internal.Windows
|
||||||
var condition = Service<Condition>.Get();
|
var condition = Service<Condition>.Get();
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
ImGui.Text($"ptr: 0x{condition.ConditionArrayBase.ToInt64():X}");
|
ImGui.Text($"ptr: 0x{condition.Address.ToInt64():X}");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ImGui.Text("Current Conditions:");
|
ImGui.Text("Current Conditions:");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue