using Dalamud.Memory; using HSUI.Helpers; using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Component.GUI; using System; using System.Collections.Generic; using FFXIVClientStructs.FFXIV.Client.UI.Arrays; using StructsFramework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework; namespace HSUI.Interface.EnemyList { public unsafe class EnemyListHelper { private List _enemiesData = new List(); public IReadOnlyCollection EnemiesData => _enemiesData.AsReadOnly(); public int EnemyCount => _enemiesData.Count; public void Update() { _enemiesData.Clear(); var enemyListNumberInstance = EnemyListNumberArray.Instance(); var enemyNumberArrayEnemies = enemyListNumberInstance->Enemies; int enemyCount = *(int*)((byte*)enemyListNumberInstance + 0x04); //TODO: Change it to the correct property when it lands in CS //int enemyCount = enemyListNumberInstance->Unk1; if(enemyCount == 0) { return; } for (int i = 0; i < enemyCount; i++) { int entityId = enemyNumberArrayEnemies[i].EntityId; int? letter = GetEnemyLetter(entityId, i); int enmityLevel = GetEnmityLevelForIndex(i); _enemiesData.Add(new EnemyListData(entityId, letter, enmityLevel)); } } private int? GetEnemyLetter(int objectId, int index) { var enemyStringArrayMembers = EnemyListStringArray.Instance()->Members; if (enemyStringArrayMembers.IsEmpty || enemyStringArrayMembers.Length <= index) { return null; } string name = enemyStringArrayMembers[index].EnemyName; bool isMarked = Utils.SignIconIDForObjectID((uint)objectId) != null; char letterSymbol = isMarked && name.Length > 1 ? name[2] : name[0]; return letterSymbol - 57457; } private int GetEnmityLevelForIndex(int index) { // gets enmity level by checking texture in enemy list addon AtkUnitBase* enemyList = (AtkUnitBase*)Plugin.GameGui.GetAddonByName("_EnemyList", 1).Address; if (enemyList == null || enemyList->RootNode == null) { return 0; } int id = index == 0 ? 2 : 20000 + index; // makes no sense but it is what it is (blame SE) AtkResNode* node = enemyList->GetNodeById((uint)id); if (node == null || node->GetComponent() == null) { return 0; } AtkImageNode* imageNode = (AtkImageNode*)node->GetComponent()->UldManager.SearchNodeById(13); if (imageNode == null) { return 0; } return Math.Min(4, imageNode->PartId + 1); } } public struct EnemyListData { public int EntityId; public int? LetterIndex; public int EnmityLevel; public EnemyListData(int entityId, int? letterIndex, int enmityLevel) { EntityId = entityId; LetterIndex = letterIndex; EnmityLevel = enmityLevel; } } }