diff --git a/Interface/GeneralElements/ActionBarsHud.cs b/Interface/GeneralElements/ActionBarsHud.cs index 99676b5..79b746a 100644 --- a/Interface/GeneralElements/ActionBarsHud.cs +++ b/Interface/GeneralElements/ActionBarsHud.cs @@ -1194,12 +1194,34 @@ namespace HSUI.Interface.GeneralElements slot.SlotType == RaptureHotbarModule.HotbarSlotType.CraftAction || slot.SlotType == RaptureHotbarModule.HotbarSlotType.PetAction) { - var row = Plugin.DataManager.GetExcelSheet()?.GetRow(slot.ActionId); + uint actionIdForLookup = slot.ActionId; + LuminaAction? actionRow = null; + + var actionSheet = Plugin.DataManager.GetExcelSheet(); + var actionRowOpt = actionSheet?.GetRow(slot.ActionId); + if (actionRowOpt.HasValue) + { + actionRow = actionRowOpt.Value; + } + else if (slot.SlotType == RaptureHotbarModule.HotbarSlotType.CraftAction) + { + // Crafting actions: hotbar may store CraftAction sheet row ID (1-based). Action sheet uses 100000+ range (100001 = Basic Synthesis). + const uint CraftActionToActionOffset = 100000; + uint mappedId = slot.ActionId + CraftActionToActionOffset; + var mappedRow = actionSheet?.GetRow(mappedId); + if (mappedRow.HasValue) + { + actionIdForLookup = mappedId; + actionRow = mappedRow.Value; + } + } + + var row = actionRow; if (row.HasValue) { string name = row.Value.Name.ToString(); string desc = ""; - var descRow = Plugin.DataManager.GetExcelSheet()?.GetRow(slot.ActionId); + var descRow = Plugin.DataManager.GetExcelSheet()?.GetRow(actionIdForLookup); string descRaw = ""; if (descRow.HasValue) { diff --git a/Interface/GeneralElements/VisibilityConfig.cs b/Interface/GeneralElements/VisibilityConfig.cs index a0d2c2f..b6d36ba 100644 --- a/Interface/GeneralElements/VisibilityConfig.cs +++ b/Interface/GeneralElements/VisibilityConfig.cs @@ -96,6 +96,9 @@ namespace HSUI.Interface if (element != null && element.GetType() == typeof(PlayerCastbarHud)) { return true; } if (element != null && !element.GetConfig().Enabled) { return false; } + // Alliance frames only matter in alliance raids (duty). HideInDuty would hide them exactly when needed. + bool isAllianceFrames = element != null && element.GetType() == typeof(AllianceFramesHud); + bool isInIslandSanctuary = IsInIslandSanctuary(); bool isInDuty = IsInDuty() && !isInIslandSanctuary; IPlayerCharacter? player = Plugin.ObjectTable.LocalPlayer; @@ -127,7 +130,8 @@ namespace HSUI.Interface if (HideOnFullHP && player != null && player.CurrentHp == player.MaxHp) { return false; } - if (HideInDuty && isInDuty) { return false; } + // Alliance frames only matter in alliance raids (duty). Skip HideInDuty for them. + if (HideInDuty && isInDuty && !isAllianceFrames) { return false; } if (HideInIslandSanctuary && isInIslandSanctuary) { return false; } diff --git a/Interface/Party/AllianceManager.cs b/Interface/Party/AllianceManager.cs index b80b968..578ddc8 100644 --- a/Interface/Party/AllianceManager.cs +++ b/Interface/Party/AllianceManager.cs @@ -280,34 +280,18 @@ namespace HSUI.Interface.Party bool anyChanged = false; ref var mainGroup = ref gm->MainGroup; + // GroupManager layout: _allianceMembers flat array (indices 0-19) has groups 0 and 1. + // Group 2 (our party) is stored in _partyMembers. GetAllianceMemberByGroupAndIndex(0/1, slot) + // returns empty in-instance for some game versions; use GetAllianceMemberByIndex with flat + // indices: group 0 = indices 0-7, group 1 = indices 8-15. for (int allianceIdx = 0; allianceIdx < 3; allianceIdx++) { int count = 0; var list = new List(); - for (int slot = 0; slot < 8; slot++) - { - var pm = mainGroup.GetAllianceMemberByGroupAndIndex(allianceIdx, slot); - if (pm == null || pm->EntityId == 0) continue; - var pfMember = new PartyFramesMember( - pm->EntityId, - count, - count, - EnmityLevel.Last, - PartyMemberStatus.None, - ReadyCheckStatus.None, - false, - false - ); - pfMember.Update(EnmityLevel.Last, PartyMemberStatus.None, ReadyCheckStatus.None, false, pm->ClassJob); - list.Add(pfMember); - count++; - } - - // GroupManager stores our party in _partyMembers, not GetAllianceMemberByGroupAndIndex. - // When group 2 is empty, it's our alliance—populate from GetPartyMemberByIndex. - if (count == 0 && allianceIdx == 2) + if (allianceIdx == 2) { + // Our party: _partyMembers via GetPartyMemberByIndex for (int slot = 0; slot < 8; slot++) { var pm = mainGroup.GetPartyMemberByIndex(slot); @@ -327,6 +311,29 @@ namespace HSUI.Interface.Party count++; } } + else + { + // Other alliances: _allianceMembers flat indices. Group 0 = 0-7, group 1 = 8-15. + int baseIdx = allianceIdx * 8; + for (int slot = 0; slot < 8; slot++) + { + var pm = mainGroup.GetAllianceMemberByIndex(baseIdx + slot); + if (pm == null || pm->EntityId == 0) continue; + var pfMember = new PartyFramesMember( + pm->EntityId, + count, + count, + EnmityLevel.Last, + PartyMemberStatus.None, + ReadyCheckStatus.None, + false, + false + ); + pfMember.Update(EnmityLevel.Last, PartyMemberStatus.None, ReadyCheckStatus.None, false, pm->ClassJob); + list.Add(pfMember); + count++; + } + } if (count != _lastMemberCounts[allianceIdx]) { @@ -340,9 +347,11 @@ namespace HSUI.Interface.Party int ourIdx = 0; for (int slot = 0; slot < 8 && ourIdx < _allianceMembers[allianceIdx].Count; slot++) { - PartyMember* pm = allianceIdx == 2 - ? mainGroup.GetPartyMemberByIndex(slot) - : mainGroup.GetAllianceMemberByGroupAndIndex(allianceIdx, slot); + PartyMember* pm; + if (allianceIdx == 2) + pm = mainGroup.GetPartyMemberByIndex(slot); + else + pm = mainGroup.GetAllianceMemberByIndex(allianceIdx * 8 + slot); if (pm == null || pm->EntityId == 0) continue; if (_allianceMembers[allianceIdx][ourIdx] is PartyFramesMember pfMember) pfMember.Update(EnmityLevel.Last, PartyMemberStatus.None, ReadyCheckStatus.None, false, pm->ClassJob);