|
5 | 5 | using FFXIVClientStructs.FFXIV.Client.Game.UI;
|
6 | 6 | using Lumina.Excel;
|
7 | 7 | using Lumina.Excel.Sheets;
|
| 8 | +using System; |
8 | 9 |
|
9 | 10 | namespace RotationSolver.Basic.Rotations;
|
10 | 11 | public partial class CustomRotation
|
@@ -113,6 +114,156 @@ public static IReadOnlyList<RowRef<ClassJob>> PartyComposition
|
113 | 114 | }
|
114 | 115 | }
|
115 | 116 |
|
| 117 | + /// <summary> |
| 118 | + /// |
| 119 | + /// </summary> |
| 120 | + public static bool HasBuffs |
| 121 | + { |
| 122 | + get |
| 123 | + { |
| 124 | + StatusList(); |
| 125 | + |
| 126 | + if (Buffs.Count == 0) return false; |
| 127 | + |
| 128 | + bool playerHasBuffs = true; |
| 129 | + if (Player == null) |
| 130 | + { |
| 131 | + playerHasBuffs = false; |
| 132 | + } |
| 133 | + else |
| 134 | + { |
| 135 | + for (int i = 0; i < Buffs.Count; i++) |
| 136 | + { |
| 137 | + var buff = Buffs[i]; |
| 138 | + if (buff.Type != StatusType.Buff) continue; |
| 139 | + |
| 140 | + if (!Player.HasStatus(false, buff.Ids) || Player.WillStatusEnd(0, false, buff.Ids)) |
| 141 | + { |
| 142 | + playerHasBuffs = false; |
| 143 | + break; |
| 144 | + } |
| 145 | + } |
| 146 | + } |
| 147 | + |
| 148 | + bool targetHasDebuffs = HostileTarget != null; |
| 149 | + if (targetHasDebuffs) |
| 150 | + { |
| 151 | + var target = HostileTarget!; |
| 152 | + for (int i = 0; i < Buffs.Count; i++) |
| 153 | + { |
| 154 | + var buff = Buffs[i]; |
| 155 | + if (buff.Type != StatusType.Debuff) continue; |
| 156 | + |
| 157 | + if (!target.HasStatus(false, buff.Ids) || target.WillStatusEnd(0, false, buff.Ids)) |
| 158 | + { |
| 159 | + targetHasDebuffs = false; |
| 160 | + break; |
| 161 | + } |
| 162 | + } |
| 163 | + } |
| 164 | + |
| 165 | + return playerHasBuffs || targetHasDebuffs; |
| 166 | + } |
| 167 | + } |
| 168 | + |
| 169 | + /// <summary> |
| 170 | + /// |
| 171 | + /// </summary> |
| 172 | + public static List<StatusInfo> Buffs { get; } = []; |
| 173 | + |
| 174 | + /// <summary> |
| 175 | + /// |
| 176 | + /// </summary> |
| 177 | + public static void StatusList() |
| 178 | + { |
| 179 | + Buffs.Clear(); |
| 180 | + var processedJobs = new HashSet<string>(); |
| 181 | + |
| 182 | + if (CustomRotation.PartyComposition == null) |
| 183 | + { |
| 184 | + var abbr = Player.ClassJob.Value.Abbreviation.ToString(); |
| 185 | + AddJobBuffs(abbr, processedJobs); |
| 186 | + } |
| 187 | + else |
| 188 | + { |
| 189 | + foreach (var job in CustomRotation.PartyComposition) |
| 190 | + { |
| 191 | + var abbr = job.Value.Abbreviation.ToString(); |
| 192 | + AddJobBuffs(abbr, processedJobs); |
| 193 | + } |
| 194 | + } |
| 195 | + } |
| 196 | + |
| 197 | + private static readonly Dictionary<string, List<StatusInfo>> JobBuffs = new() |
| 198 | + { |
| 199 | + { "AST", [new StatusInfo("Divination", "AST", StatusType.Buff, StatusID.Divination)] }, |
| 200 | + { "BRD", [new StatusInfo("Battle Voice", "BRD", StatusType.Buff, StatusID.BattleVoice), |
| 201 | + new StatusInfo("Radiant Finale", "BRD", StatusType.Buff, StatusID.RadiantFinale_2964, |
| 202 | + StatusID.RadiantFinale)] }, |
| 203 | + { "DNC", [new StatusInfo("Technical Finish", "DNC", StatusType.Buff, StatusID.TechnicalFinish)] }, |
| 204 | + { "DRG", [new StatusInfo("Battle Litany", "DRG", StatusType.Buff, StatusID.BattleLitany)] }, |
| 205 | + { "MNK", [new StatusInfo("Brotherhood", "MNK", StatusType.Buff, StatusID.Brotherhood)] }, |
| 206 | + { "NIN", [new StatusInfo("Mug", "NIN", StatusType.Debuff, StatusID.Mug), |
| 207 | + new StatusInfo("Dokumori", "NIN", StatusType.Debuff, StatusID.Dokumori, StatusID.Dokumori_4303)] }, |
| 208 | + { "PCT", [new StatusInfo("Starry Muse", "PCT", StatusType.Buff, StatusID.StarryMuse)] }, |
| 209 | + { "RPR", [new StatusInfo("Arcane Circle", "RPR", StatusType.Buff, StatusID.ArcaneCircle)] }, |
| 210 | + { "RDM", [new StatusInfo("Embolden", "RDM", StatusType.Buff, StatusID.Embolden, StatusID.Embolden_1297)] }, |
| 211 | + { "SCH", [new StatusInfo("Chain Stratagem", "SCH", StatusType.Debuff, StatusID.ChainStratagem, StatusID.ChainStratagem_1406)] }, |
| 212 | + { "SMN", [new StatusInfo("Searing Light", "SMN", StatusType.Buff, StatusID.SearingLight)] } |
| 213 | + }; |
| 214 | + |
| 215 | + private static void AddJobBuffs(string abbr, HashSet<string> processedJobs) |
| 216 | + { |
| 217 | + if (!processedJobs.Add(abbr)) return; |
| 218 | + |
| 219 | + if (JobBuffs.TryGetValue(abbr, out var buffs)) |
| 220 | + { |
| 221 | + Buffs.AddRange(buffs); |
| 222 | + } |
| 223 | + } |
| 224 | + |
| 225 | + /// <summary> |
| 226 | + /// |
| 227 | + /// </summary> |
| 228 | + public enum StatusType |
| 229 | + { |
| 230 | + /// <summary> |
| 231 | + /// |
| 232 | + /// </summary> |
| 233 | + Buff, |
| 234 | + |
| 235 | + /// <summary> |
| 236 | + /// |
| 237 | + /// </summary> |
| 238 | + Debuff |
| 239 | + } |
| 240 | + |
| 241 | + /// <summary> |
| 242 | + /// |
| 243 | + /// </summary> |
| 244 | + public class StatusInfo(string name, string jobAbbr, StatusType type, params StatusID[] ids) |
| 245 | + { |
| 246 | + /// <summary> |
| 247 | + /// |
| 248 | + /// </summary> |
| 249 | + public StatusID[] Ids { get; } = ids; |
| 250 | + |
| 251 | + /// <summary> |
| 252 | + /// |
| 253 | + /// </summary> |
| 254 | + public string Name { get; } = name; |
| 255 | + |
| 256 | + /// <summary> |
| 257 | + /// |
| 258 | + /// </summary> |
| 259 | + public string JobAbbr { get; } = jobAbbr; |
| 260 | + |
| 261 | + /// <summary> |
| 262 | + /// |
| 263 | + /// </summary> |
| 264 | + public StatusType Type { get; } = type; |
| 265 | + } |
| 266 | + |
116 | 267 | /// <summary>
|
117 | 268 | /// Determines if the current combat time is within the first 15 seconds of an even minute.
|
118 | 269 | /// WARNING: Do not use as a main function of your rotation, hardcoding timers is begging for everything to fuck up.
|
@@ -159,7 +310,23 @@ public static bool IsWithinFirst15SecondsOfEvenMinute()
|
159 | 310 | /// Whether the number of party members is 8.
|
160 | 311 | /// </summary>
|
161 | 312 | [Description("Is Full Party")]
|
162 |
| - public static bool IsFullParty => PartyMembers.Count() is 8 or 9; |
| 313 | + public static bool IsFullParty |
| 314 | + { |
| 315 | + get |
| 316 | + { |
| 317 | + int count = 0; |
| 318 | + var members = PartyMembers; |
| 319 | + if (members != null) |
| 320 | + { |
| 321 | + foreach (var _ in members) |
| 322 | + { |
| 323 | + count++; |
| 324 | + if (count > 9) break; |
| 325 | + } |
| 326 | + } |
| 327 | + return count == 8 || count == 9; |
| 328 | + } |
| 329 | + } |
163 | 330 |
|
164 | 331 | /// <summary>
|
165 | 332 | /// party members HP.
|
|
0 commit comments