private static async Task SaveEstFile(EstType type, Dictionary <XivRace, Dictionary <ushort, ExtraSkeletonEntry> > entries, IItem referenceItem = null, IndexFile cachedIndexFile = null, ModList cachedModList = null) { var count = entries.Select(x => x.Value.Count).Aggregate((x, y) => x + y); var data = new byte[4 + (count * 6)]; IOUtil.ReplaceBytesAt(data, BitConverter.GetBytes(count), 0); var races = entries.Keys.ToList(); races.Sort(); var index = 0; foreach (var race in races) { var sets = entries[race].Keys.ToList(); sets.Sort(); foreach (var set in sets) { var entry = entries[race][set]; ExtraSkeletonEntry.Write(data, entry, count, index); index++; } } var _dat = new Dat(_gameDirectory); await _dat.ImportType2Data(data, EstFiles[type], Constants.InternalModSourceName, referenceItem, cachedIndexFile, cachedModList); }
/// <summary> /// Saves a given set of modified entries to the EST file. /// Entries with a SkeletonID of 0 will be removed. /// </summary> /// <param name="type"></param> /// <param name="modifiedEntries"></param> /// <returns></returns> public static async Task SaveExtraSkeletonEntries(EstType type, List <ExtraSkeletonEntry> modifiedEntries, IItem referenceItem = null, IndexFile cachedIndexFile = null, ModList cachedModList = null) { var entries = await GetEstFile(type, false); // Add/Remove entries. foreach (var entry in modifiedEntries) { if (entry.SkelId == 0) { // Remove this entry. if (entries[entry.Race].ContainsKey(entry.SetId)) { entries[entry.Race].Remove(entry.SetId); } } else { // Add or update this entry. if (entries[entry.Race].ContainsKey(entry.SetId)) { entries[entry.Race][entry.SetId] = entry; } else { entries[entry.Race].Add(entry.SetId, entry); } } } // Save file. await SaveEstFile(type, entries, referenceItem, cachedIndexFile, cachedModList); }
/// <summary> /// Retrieves the extra skeleton entry for a given Type/Race/Equipment Set. /// </summary> /// <param name="type"></param> /// <param name="race"></param> /// <param name="setId"></param> /// <param name="forceDefault"></param> /// <returns></returns> public static async Task <ExtraSkeletonEntry> GetExtraSkeletonEntry(EstType type, XivRace race, ushort setId, bool forceDefault = false) { var entries = await GetEstFile(type, forceDefault); if (!entries.ContainsKey(race)) { return(new ExtraSkeletonEntry(race, setId)); } if (!entries[race].ContainsKey(setId)) { return(new ExtraSkeletonEntry(race, setId)); } return(entries[race][setId]); }
public static char GetSystemPrefix(EstType type) { switch (type) { case EstType.Head: return('m'); case EstType.Body: return('t'); case EstType.Face: return('f'); case EstType.Hair: return('h'); default: throw new Exception("Cannot get prefix for Invalid EST Type."); } }
public static string GetSystemSlot(EstType type) { switch (type) { case EstType.Head: return("met"); case EstType.Body: return("top"); case EstType.Face: return("face"); case EstType.Hair: return("hair"); default: throw new Exception("Cannot get slot for Invalid EST Type."); } }
private static async Task <Dictionary <XivRace, Dictionary <ushort, ExtraSkeletonEntry> > > GetEstFile(EstType type, bool forceDefault = false) { var _dat = new Dat(_gameDirectory); var data = await _dat.GetType2Data(EstFiles[type], forceDefault); var count = BitConverter.ToUInt32(data, 0); Dictionary <XivRace, Dictionary <ushort, ExtraSkeletonEntry> > entries = new Dictionary <XivRace, Dictionary <ushort, ExtraSkeletonEntry> >(); for (int i = 0; i < count; i++) { var entry = ExtraSkeletonEntry.Read(data, count, (uint)i); if (!entries.ContainsKey(entry.Race)) { entries.Add(entry.Race, new Dictionary <ushort, ExtraSkeletonEntry>()); } if (!entries[entry.Race].ContainsKey(entry.SetId)) { // For whatever reason there is exactly one dupe in the game files, where a Lalafell M face has two identical entries. // Doesn't seem to matter to SE, so shouldn't matter to us. entries[entry.Race].Add(entry.SetId, entry); } } return(entries); }
/// <summary> /// Retrieves the skeleton information for a given set for all races. /// </summary> /// <param name=""></param> /// <param name="setId"></param> /// <param name="forceDefault"></param> /// <returns></returns> public static async Task <Dictionary <XivRace, ExtraSkeletonEntry> > GetExtraSkeletonEntries(EstType type, ushort setId, bool forceDefault = false, bool includeNpcs = false) { if (type == EstType.Invalid) { return(new Dictionary <XivRace, ExtraSkeletonEntry>()); } var entries = await GetEstFile(type, forceDefault); var races = Eqp.PlayableRaces; if (includeNpcs) { races = Eqp.PlayableRacesWithNPCs; } var ret = new Dictionary <XivRace, ExtraSkeletonEntry>(); foreach (var race in races) { var dict = entries[race]; if (dict.ContainsKey(setId)) { ret.Add(race, dict[setId]); } else { ret.Add(race, new ExtraSkeletonEntry(race, setId)); } } return(ret); }
/// <summary> /// Retrieve the list of all possible skeletal selections for a given type. /// </summary> /// <param name="type"></param> /// <returns></returns> public static async Task <Dictionary <XivRace, HashSet <int> > > GetAllExtraSkeletons(EstType type, XivRace raceFilter = XivRace.All_Races, bool includeNpcs = false) { var ret = new Dictionary <XivRace, HashSet <int> >(); var races = includeNpcs ? Eqp.PlayableRacesWithNPCs : Eqp.PlayableRaces; if (raceFilter != XivRace.All_Races) { races = new List <XivRace>(); races.Add(raceFilter); } var entries = await GetEstFile(type, true); foreach (var race in races) { ret.Add(race, new HashSet <int>()); if (!entries.ContainsKey(race)) { continue; } var dict = entries[race]; foreach (var kv in dict) { ret[race].Add(kv.Value.SkelId); } } return(ret); }