namespace BardFrontline.Core; public enum BattlefieldMode { None, Frontline, RivalWings } public static class Battlefield { // BNpcName row IDs from local client reference data, never localized display-name matching. public static ObjectiveKind Classify(BattlefieldMode mode, bool npc, bool warmachina, uint nameId) { if (warmachina && mode == BattlefieldMode.RivalWings) return ObjectiveKind.Mech; if (!npc) return ObjectiveKind.Other; if (mode == BattlefieldMode.Frontline && nameId is >= 4822 and <= 4837 or >= 4840 and <= 4845) return ObjectiveKind.Ice; if (mode != BattlefieldMode.RivalWings) return ObjectiveKind.Other; return nameId switch { 6857 or 6858 => ObjectiveKind.Core, >= 6859 and <= 6862 => ObjectiveKind.Tower, >= 6863 and <= 6868 => ObjectiveKind.Mech, >= 6869 and <= 6872 or 7889 or 7890 or 14252 or 14253 => ObjectiveKind.Infantry, 7891 or 7892 or 7906 => ObjectiveKind.Mercenary, _ => ObjectiveKind.Other, }; } public static string KindName(ObjectiveKind kind) => kind switch { ObjectiveKind.Mech => "机甲", ObjectiveKind.Infantry => "兵线", ObjectiveKind.Mercenary => "佣兵", ObjectiveKind.Tower => "防御塔", ObjectiveKind.Core => "核心", ObjectiveKind.Ice => "冰块", _ => "其他目标", }; // TerritoryIntendedUse values from the client sheet / FFXIVClientStructs enum. public static BattlefieldMode Identify(uint intendedUse, bool pvp) => !pvp ? BattlefieldMode.None : intendedUse switch { 18 => BattlefieldMode.Frontline, 39 => BattlefieldMode.RivalWings, _ => BattlefieldMode.None, }; public static string Name(BattlefieldMode mode) => mode switch { BattlefieldMode.Frontline => "纷争前线", BattlefieldMode.RivalWings => "烈羽争锋", _ => "不支持的区域", }; // Content key 1 is the Rival Wings ManeuversArmor row. Check both it and the // warmachina status to cover transitions without relying on an ordinary mount flag. public static bool IsPiloting(BattlefieldMode mode, bool pilotingCondition, bool warmachinaStatus, uint armor) => mode == BattlefieldMode.RivalWings && (pilotingCondition || warmachinaStatus || armor != 0); public static bool IsBattleNpcCandidate(byte subKind, uint owner) => subKind is 0 or 1 or 5 && owner is 0 or 0xE0000000; }