194 lines
6.3 KiB
C#
194 lines
6.3 KiB
C#
using Dalamud.Game.ClientState.Objects.Types;
|
|
using Dalamud.Plugin;
|
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
|
using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
|
using ImGuiNET;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Numerics;
|
|
using Dalamud.Interface.Utility;
|
|
using Dalamud.Plugin.Services;
|
|
|
|
namespace ZodiacFinder
|
|
{
|
|
public class Plugin : IDalamudPlugin
|
|
{
|
|
private readonly DalamudPluginInterface pluginInterface;
|
|
private readonly IChatGui chat;
|
|
private readonly IClientState clientState;
|
|
private readonly IObjectTable objectTable;
|
|
private readonly IDataManager dataManager;
|
|
private readonly IGameGui gameGui;
|
|
|
|
private readonly IDictionary<uint, Book> books = new Dictionary<uint, Book>();
|
|
|
|
private ISet<uint> atmaWeapons = new HashSet<uint> {
|
|
7824, // Curtana Atma
|
|
7825, // Sphairai Atma
|
|
7826, // Bravura Atma
|
|
7827, // Gae Bolg Atma
|
|
7828, // Artemis Bow Atma
|
|
7829, // Thyrus Atma
|
|
7830, // Stardust Rod Atma
|
|
7831, // Veil of Wiyu Atma
|
|
7832, // Omnilex Atma
|
|
7833, // Holy Shield Atma
|
|
9251, // Yoshimitsu Atma
|
|
};
|
|
|
|
public string Name => "ZodiacFinder";
|
|
|
|
public Plugin(
|
|
DalamudPluginInterface pi,
|
|
ICommandManager commands,
|
|
IChatGui chat,
|
|
IClientState clientState,
|
|
IObjectTable objectTable,
|
|
IDataManager dataManager,
|
|
IGameGui gameGui)
|
|
{
|
|
this.pluginInterface = pi;
|
|
this.chat = chat;
|
|
this.clientState = clientState;
|
|
this.objectTable = objectTable;
|
|
this.dataManager = dataManager;
|
|
this.gameGui = gameGui;
|
|
|
|
this.pluginInterface.UiBuilder.Draw += this.Draw;
|
|
|
|
this.PopulateBooks();
|
|
}
|
|
|
|
#region IDisposable Support
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (!disposing) return;
|
|
|
|
this.pluginInterface.UiBuilder.Draw -= this.Draw;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
#endregion
|
|
|
|
private unsafe void Draw()
|
|
{
|
|
if (!clientState.IsLoggedIn || clientState.IsPvP || objectTable == null || !HasAtmaWeaponEquipped())
|
|
return;
|
|
|
|
var bookId = GetCurrentBook();
|
|
if (bookId == 0)
|
|
return;
|
|
|
|
var relicNote = RelicNote.Instance();
|
|
if (relicNote == null)
|
|
return;
|
|
|
|
var book = books[bookId];
|
|
for (int index = 0; index < objectTable.Length; ++index)
|
|
{
|
|
GameObject obj = objectTable[index];
|
|
if (!(obj is BattleNpc npc) || npc.CurrentHp == 0)
|
|
continue;
|
|
|
|
var indexInBook = book.Enemies.IndexOf(npc.NameId);
|
|
if (indexInBook == -1)
|
|
continue;
|
|
|
|
if (relicNote->GetMonsterProgress(indexInBook) >= 3)
|
|
continue;
|
|
|
|
if (!gameGui.WorldToScreen(new Vector3(obj.Position.X, obj.Position.Y, obj.Position.Z), out var pos))
|
|
continue;
|
|
|
|
ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, new Vector2(0, 0));
|
|
ImGuiHelpers.ForceNextWindowMainViewport();
|
|
ImGuiHelpers.SetNextWindowPosRelativeMainViewport(new Vector2(0, 0));
|
|
ImGui.Begin($"zodiac###{index}",
|
|
ImGuiWindowFlags.NoInputs | ImGuiWindowFlags.NoNav | ImGuiWindowFlags.NoTitleBar |
|
|
ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoBackground | ImGuiWindowFlags.NoSavedSettings);
|
|
ImGui.SetWindowSize(ImGui.GetIO().DisplaySize);
|
|
|
|
ImGui.GetWindowDrawList().AddCircleFilled(new Vector2(pos.X, pos.Y), 5f, ImGui.GetColorU32(0xff0000ff), 100);
|
|
//ImGui.GetWindowDrawList().AddText(new Vector2(pos.X, pos.Y), ImGui.GetColorU32(0xffffffff), $"{npc.NameId} - {obj.Name.TextValue}");
|
|
|
|
ImGui.End();
|
|
ImGui.PopStyleVar();
|
|
}
|
|
}
|
|
|
|
private bool HasAtmaWeaponEquipped()
|
|
{
|
|
return atmaWeapons.Contains(GetEquippedItem(0)) || atmaWeapons.Contains(GetEquippedItem(1));
|
|
}
|
|
|
|
private unsafe uint GetCurrentBook()
|
|
{
|
|
var im = InventoryManager.Instance();
|
|
if (im == null)
|
|
return 0;
|
|
|
|
var keyItems = im->GetInventoryContainer(InventoryType.KeyItems);
|
|
for (int i = 0; i < keyItems->Size; ++i)
|
|
{
|
|
var slot = keyItems->GetInventorySlot(i);
|
|
if (slot == null)
|
|
continue;
|
|
|
|
uint itemId = slot->ItemID;
|
|
if (books.ContainsKey(itemId))
|
|
return itemId;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
private unsafe uint GetEquippedItem(int index)
|
|
{
|
|
var im = InventoryManager.Instance();
|
|
if (im == null)
|
|
return 0;
|
|
|
|
var equipped = im->GetInventoryContainer(InventoryType.EquippedItems);
|
|
if (equipped == null)
|
|
return 0;
|
|
|
|
var slot = equipped->GetInventorySlot(index);
|
|
if (slot == null)
|
|
return 0;
|
|
|
|
return slot->ItemID;
|
|
}
|
|
|
|
private void PopulateBooks()
|
|
{
|
|
var relicNoteSheet = this.dataManager.GetExcelSheet<Excel.RelicNote>()!;
|
|
foreach (var row in relicNoteSheet)
|
|
{
|
|
if (row.EventItem == null || row.EventItem.Row == 0)
|
|
continue;
|
|
|
|
var book = new Book();
|
|
for (int i = 0; i < row.MonsterNoteTargetCommon.Length; i++)
|
|
{
|
|
book.Enemies.Add(row.MonsterNoteTargetCommon[i].MonsterNoteTargetCommon.Value!.BNpcName.Row);
|
|
}
|
|
//chat.Print($"{row.EventItem.Row} - {book}");
|
|
books.Add(row.EventItem.Row, book);
|
|
}
|
|
}
|
|
|
|
internal sealed class Book
|
|
{
|
|
public IList<uint> Enemies = new List<uint>();
|
|
public override string ToString()
|
|
{
|
|
return string.Join(",", Enemies);
|
|
}
|
|
}
|
|
}
|
|
}
|