100 lines
3.8 KiB
C#
100 lines
3.8 KiB
C#
using System;
|
|
using System.Numerics;
|
|
using System.Runtime.InteropServices;
|
|
using Dalamud.Game.ClientState.Objects.SubKinds;
|
|
using Dalamud.Game.ClientState.Objects.Types;
|
|
using Dalamud.Plugin;
|
|
using Dalamud.Plugin.Services;
|
|
using ImGuiNET;
|
|
|
|
namespace Pal.Client.Floors;
|
|
|
|
/// <summary>
|
|
/// This isn't very useful for running deep dungeons normally, but it is for plugin dev.
|
|
///
|
|
/// Needs the corresponding beta feature to be enabled.
|
|
/// </summary>
|
|
internal sealed class ObjectTableDebug : IDisposable
|
|
{
|
|
public const string FeatureName = nameof(ObjectTableDebug);
|
|
|
|
private readonly DalamudPluginInterface _pluginInterface;
|
|
private readonly IObjectTable _objectTable;
|
|
private readonly IGameGui _gameGui;
|
|
private readonly IClientState _clientState;
|
|
|
|
public ObjectTableDebug(DalamudPluginInterface pluginInterface, IObjectTable objectTable, IGameGui gameGui,
|
|
IClientState clientState)
|
|
{
|
|
_pluginInterface = pluginInterface;
|
|
_objectTable = objectTable;
|
|
_gameGui = gameGui;
|
|
_clientState = clientState;
|
|
|
|
_pluginInterface.UiBuilder.Draw += Draw;
|
|
}
|
|
|
|
private void Draw()
|
|
{
|
|
int index = 0;
|
|
foreach (GameObject obj in _objectTable)
|
|
{
|
|
if (obj is EventObj eventObj && string.IsNullOrEmpty(eventObj.Name.ToString()))
|
|
{
|
|
++index;
|
|
int model = Marshal.ReadInt32(obj.Address + 128);
|
|
|
|
if (_gameGui.WorldToScreen(obj.Position, out var screenCoords))
|
|
{
|
|
// So, while WorldToScreen will return false if the point is off of game client screen, to
|
|
// to avoid performance issues, we have to manually determine if creating a window would
|
|
// produce a new viewport, and skip rendering it if so
|
|
float distance = DistanceToPlayer(obj.Position);
|
|
var objectText =
|
|
$"{obj.Address.ToInt64():X}:{obj.ObjectId:X}[{index}]\nkind: {obj.ObjectKind} sub: {obj.SubKind}\nmodel: {model}\nname: {obj.Name}\ndata id: {obj.DataId}";
|
|
|
|
var screenPos = ImGui.GetMainViewport().Pos;
|
|
var screenSize = ImGui.GetMainViewport().Size;
|
|
|
|
var windowSize = ImGui.CalcTextSize(objectText);
|
|
|
|
// Add some extra safety padding
|
|
windowSize.X += ImGui.GetStyle().WindowPadding.X + 10;
|
|
windowSize.Y += ImGui.GetStyle().WindowPadding.Y + 10;
|
|
|
|
if (screenCoords.X + windowSize.X > screenPos.X + screenSize.X ||
|
|
screenCoords.Y + windowSize.Y > screenPos.Y + screenSize.Y)
|
|
continue;
|
|
|
|
if (distance > 50f)
|
|
continue;
|
|
|
|
ImGui.SetNextWindowPos(new Vector2(screenCoords.X, screenCoords.Y));
|
|
|
|
ImGui.SetNextWindowBgAlpha(Math.Max(1f - (distance / 50f), 0.2f));
|
|
if (ImGui.Begin(
|
|
$"PalacePal_{nameof(ObjectTableDebug)}_{index}",
|
|
ImGuiWindowFlags.NoDecoration |
|
|
ImGuiWindowFlags.AlwaysAutoResize |
|
|
ImGuiWindowFlags.NoSavedSettings |
|
|
ImGuiWindowFlags.NoMove |
|
|
ImGuiWindowFlags.NoMouseInputs |
|
|
ImGuiWindowFlags.NoDocking |
|
|
ImGuiWindowFlags.NoFocusOnAppearing |
|
|
ImGuiWindowFlags.NoNav))
|
|
ImGui.Text(objectText);
|
|
ImGui.End();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private float DistanceToPlayer(Vector3 center)
|
|
=> Vector3.Distance(_clientState.LocalPlayer?.Position ?? Vector3.Zero, center);
|
|
|
|
public void Dispose()
|
|
{
|
|
_pluginInterface.UiBuilder.Draw -= Draw;
|
|
}
|
|
}
|