ZodiacFinder/Plugin.cs

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);
}
}
}
}