Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hide cooldowns of locked skills #205

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions JobBars/Cooldowns/CooldownPartyMember.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
namespace JobBars.Cooldowns {
public unsafe class CooldownPartyMember {
private JobIds PartyMemberCurrentJob = JobIds.OTHER;
private byte PartyMemberLevel = 0;
private readonly List<CooldownTracker> Trackers = new();
private readonly uint ObjectId;

Expand All @@ -15,8 +16,9 @@ public CooldownPartyMember(uint objectId) {
}

public void Tick(AtkCooldown ui, CurrentPartyMember partyMember, float percent) {
if (PartyMemberCurrentJob != partyMember.Job) {
if (PartyMemberCurrentJob != partyMember.Job || PartyMemberLevel != partyMember.Level) {
PartyMemberCurrentJob = partyMember.Job;
PartyMemberLevel = partyMember.Level;
SetupTrackers();
}

Expand Down Expand Up @@ -53,7 +55,7 @@ public void ProcessAction(Item action, uint objectId) {
private void SetupTrackers() {
Trackers.Clear();

var trackerProps = JobBars.CooldownManager.GetCooldownConfigs(PartyMemberCurrentJob);
var trackerProps = JobBars.CooldownManager.GetCooldownConfigs(PartyMemberCurrentJob, PartyMemberLevel);
var count = 0;
foreach (var prop in trackerProps.OrderBy(x => x.Order)) {
if (!prop.Enabled) continue;
Expand Down
5 changes: 5 additions & 0 deletions JobBars/Cooldowns/Manager/CooldownManager.UI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ protected override void DrawSettings() {
ResetUi();
}

if (ImGui.Checkbox("Hide cooldowns of unavailable actions" + Id, ref JobBars.Configuration.CooldownsHideUnavailableActions)) {
JobBars.Configuration.Save();
ResetUi();
}

ImGui.SetNextItemWidth(50f);
if (ImGui.InputFloat("Opacity when on cooldown" + Id, ref JobBars.Configuration.CooldownsOnCDOpacity)) JobBars.Configuration.Save();
}
Expand Down
8 changes: 7 additions & 1 deletion JobBars/Cooldowns/Manager/CooldownManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,16 @@ public CooldownManager() : base( "##JobBars_Cooldowns" ) {
}
}

public CooldownConfig[] GetCooldownConfigs( JobIds job ) {
public CooldownConfig[] GetCooldownConfigs( JobIds job, byte level ) {
List<CooldownConfig> configs = new();
if( JobToValue.TryGetValue( job, out var props ) ) configs.AddRange( props );
if( CustomCooldowns.TryGetValue( job, out var customProps ) ) configs.AddRange( customProps );
if( JobBars.Configuration.CooldownsHideUnavailableActions ) {
configs = configs.FindAll( config => config.Triggers.Any( item => {
if( item.Type != ItemType.Action ) return true;
return AtkHelper.IsActionAvailableAtLevel(item.Id, level);
} ) );
}
return configs.ToArray();
}

Expand Down
1 change: 1 addition & 0 deletions JobBars/Data/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ public class Configuration : IPluginConfiguration {
public bool CooldownsHideWeaponSheathed = false;
public bool CooldownsHideActiveBuffDuration = false;
public bool CooldownsShowPartyMembers = true;
public bool CooldownsHideUnavailableActions = true;
public float CooldownsOnCDOpacity = 1.0f;

public bool CooldownsStateShowDefault = true;
Expand Down
94 changes: 92 additions & 2 deletions JobBars/Helper/UiHelper.Data.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,25 @@ public override readonly int GetHashCode() {
}
}

public struct ClassJobActionInfo {
public uint ActionId;
public byte Level;
public bool IsRoleAction;
}

public struct ClassJobActionEvolution {
public uint ActionId;
/// <summary>
/// Action ID of the greatest ancestor.
/// </summary>
public uint BaseActionId;
}

public class ClassJobActionLevelRange {
public byte MinLevel;
public byte ReplacedLevel;
}

public unsafe partial class AtkHelper {
public static bool OutOfCombat => !Dalamud.Condition[ConditionFlag.InCombat];
public static bool WeaponSheathed => Dalamud.ClientState.LocalPlayer != null && !Dalamud.ClientState.LocalPlayer.StatusFlags.HasFlag(StatusFlags.WeaponOut);
Expand Down Expand Up @@ -71,6 +90,17 @@ public static void ZoneChanged(ushort e) {
public static int GetIcon(ActionIds action) => GetIcon((uint)action);
public static int GetIcon(uint action) => (int)ActionToIcon[action];

public static bool IsActionAvailableAtLevel(ActionIds action, byte level) => IsActionAvailableAtLevel((uint)action, level);
public static bool IsActionAvailableAtLevel(uint action, byte level) {
if (level == 0) return true;
var actionInfo = ClassJobActionIdToInfo.GetValueOrDefault(action);
if (actionInfo.IsRoleAction) return true;
if (ClassJobActionToLevelRange.TryGetValue(action, out var levelRange)) {
return level >= levelRange.MinLevel && (levelRange.ReplacedLevel == 0 || level < levelRange.ReplacedLevel);
}
return level >= actionInfo.Level;
}

public static JobIds IdToJob(uint job) => job < 19 ? JobIds.OTHER : (JobIds)job;

private static IEnumerable<ClassJob> JobSheet;
Expand All @@ -80,6 +110,8 @@ public static void ZoneChanged(ushort e) {
// Cache converted strings
private static Dictionary<JobIds, string> JobToString;
private static Dictionary<Item, string> ItemToString;
private static Dictionary<uint, ClassJobActionInfo> ClassJobActionIdToInfo = new();
private static Dictionary<uint, ClassJobActionLevelRange> ClassJobActionToLevelRange = new();

public static string Localize(JobIds job) {
if (JobToString.TryGetValue(job, out var jobString)) return jobString;
Expand Down Expand Up @@ -136,17 +168,18 @@ private static void SetupSheets() {
ItemToString = new();
ActionList.Clear();
StatusList.Clear();
ClassJobActionIdToInfo.Clear();

ActionSheet = Dalamud.DataManager.GetExcelSheet<Lumina.Excel.GeneratedSheets.Action>().Where(
x => !string.IsNullOrEmpty(x.Name) && (x.IsPlayerAction || x.ClassJob.Value != null) && !x.IsPvP // weird conditions to catch things like enchanted RDM spells
);
foreach (var item in ActionSheet) {
var name = item.Name.ToString();
var attackType = item.ActionCategory.Value.Name.ToString();
var actionId = item.ActionCategory.Value.RowId;
var categoryId = item.ActionCategory.Value.RowId;
if (item.Icon != 405 && item.Icon != 0) ActionToIcon[item.RowId] = item.Icon;

if (actionId == 2 || actionId == 3) { // spell or weaponskill
if (categoryId == 2 || categoryId == 3) { // spell or weaponskill
if (item.CooldownGroup == 58 || item.AdditionalCooldownGroup == 58) GCDs.Add(item.RowId); // not actually a gcd
}

Expand All @@ -158,6 +191,12 @@ private static void SetupSheets() {
Type = ItemType.Action
}
});

ClassJobActionIdToInfo.Add(item.RowId, new ClassJobActionInfo {
ActionId = item.RowId,
Level = item.ClassJobLevel,
IsRoleAction = item.IsRoleAction
});
}

StatusSheet = Dalamud.DataManager.GetExcelSheet<Lumina.Excel.GeneratedSheets.Status>().Where(x => !string.IsNullOrEmpty(x.Name));
Expand All @@ -173,6 +212,57 @@ private static void SetupSheets() {
}

JobSheet = Dalamud.DataManager.GetExcelSheet<ClassJob>().Where(x => x.Name != null);

SetupClassJobActionLevelRanges(ClassJobActionIdToInfo);
}

private static void SetupClassJobActionLevelRanges(Dictionary<uint, ClassJobActionInfo> classJobActionIdToInfo) {
ClassJobActionToLevelRange.Clear();

var actionEvoBases = Dalamud.DataManager.GetExcelSheet<ClassJobActionSort>()
.Where(row =>
row.Unknown1/*BaseActionId*/ != 0 &&
classJobActionIdToInfo.ContainsKey(row.Unknown0/*ActionId*/))
.Select(row => row.Unknown1/*BaseActionId*/)
.ToHashSet();

var actionEvos = Dalamud.DataManager.GetExcelSheet<ClassJobActionSort>()
.Where(row => actionEvoBases.Contains(row.Unknown1/*BaseActionId*/))
.Select(row => new ClassJobActionEvolution {
ActionId = row.Unknown0,
BaseActionId = row.Unknown1
})
.ToList();

Dictionary<uint, List<uint>> baseActionToActionGroup = new();
foreach (var evo in actionEvos) {
if (!classJobActionIdToInfo.ContainsKey(evo.ActionId)) continue;
if (!baseActionToActionGroup.TryGetValue(evo.BaseActionId, out var actionGroup)) {
actionGroup = new();
baseActionToActionGroup.Add(evo.BaseActionId, actionGroup);
}
actionGroup.Add(evo.ActionId);
}

foreach (var actionGroup in baseActionToActionGroup.Values) {
actionGroup.Sort((a1, a2) => {
var a1Level = classJobActionIdToInfo.GetValueOrDefault(a1).Level;
var a2Level = classJobActionIdToInfo.GetValueOrDefault(a2).Level;
return a1Level - a2Level;
});

for (int i=0; i < actionGroup.Count; i++) {
byte minLevel = classJobActionIdToInfo.GetValueOrDefault(actionGroup[i]).Level;
byte replacedLevel = 0;
if (i < actionGroup.Count - 1) {
replacedLevel = classJobActionIdToInfo.GetValueOrDefault(actionGroup[i+1]).Level;
}
ClassJobActionToLevelRange.Add(actionGroup[i], new ClassJobActionLevelRange {
MinLevel = minLevel,
ReplacedLevel = replacedLevel
});
}
}
}

public static float TimeLeft(float defaultDuration, Dictionary<Item, Status> buffDict, Item lastActiveTrigger, DateTime lastActiveTime) {
Expand Down
3 changes: 3 additions & 0 deletions JobBars/JobBars.Party.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace JobBars {
public class CurrentPartyMember {
public uint ObjectId;
public JobIds Job;
public byte Level;
public uint CurrentHP;
public uint MaxHP;
public Dictionary<Item, Status> BuffDict;
Expand Down Expand Up @@ -55,6 +56,7 @@ private static List<CurrentPartyMember> GetPartyMembers() {
ObjectId = localPlayer.ObjectId,
CurrentHP = localPlayer.CurrentHp,
MaxHP = localPlayer.MaxHp,
Level = localPlayer.Level,
Job = AtkHelper.IdToJob(localPlayer.ClassJob.Id),
BuffDict = new()
};
Expand All @@ -76,6 +78,7 @@ private static List<CurrentPartyMember> GetPartyMembers() {
ObjectId = info->ObjectID,
CurrentHP = info->CurrentHP,
MaxHP = info->MaxHP,
Level = info->Level,
Job = AtkHelper.IdToJob(info->ClassJob),
BuffDict = new()
};
Expand Down