/// <summary> /// Gets the list to be displayed in the Minion category /// </summary> /// <remarks> /// The model data for the minion is held separately in modelchara_0.exd /// The data within companion_0 exd contains a reference to the index for lookup in modelchara /// </remarks> /// <returns>A list containing XivMinion data</returns> public async Task <List <XivMinion> > GetMinionList() { var minionLock = new object(); var minionList = new List <XivMinion>(); // These are the offsets to relevant data // These will need to be changed if data gets added or removed with a patch const int dataLength = 48; const int nameDataOffset = 6; const int modelCharaIndexOffset = 16; var minionEx = await _ex.ReadExData(XivEx.companion); var modelCharaEx = await XivModelChara.GetModelCharaData(_gameDirectory); // Loops through all available minions in the companion exd files // At present only one file exists (companion_0) await Task.Run(() => Parallel.ForEach(minionEx.Values, (minion) => { var xivMinion = new XivMinion { Category = XivStrings.Companions, ItemCategory = XivStrings.Minions }; int modelCharaIndex; // Big Endian Byte Order using (var br = new BinaryReaderBE(new MemoryStream(minion))) { br.BaseStream.Seek(nameDataOffset, SeekOrigin.Begin); var nameOffset = br.ReadInt16(); br.BaseStream.Seek(modelCharaIndexOffset, SeekOrigin.Begin); modelCharaIndex = br.ReadInt16(); br.BaseStream.Seek(dataLength, SeekOrigin.Begin); var nameString = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(Encoding.UTF8 .GetString(br.ReadBytes(nameOffset)).Replace("\0", "")); xivMinion.Name = new string(nameString.Where(c => !char.IsControl(c)).ToArray()); } if (modelCharaIndex == 0) { return; } // This will get the model data using the index obtained for the current minion xivMinion.ModelInfo = XivModelChara.GetModelInfo(modelCharaEx, modelCharaIndex); lock (minionLock) { minionList.Add(xivMinion); } })); minionList.Sort(); return(minionList); }
/// <summary> /// Gets the list to be displayed in the Pets category /// </summary> /// <remarks> /// The pet_0 exd does not contain the model ID or a reference to a modelchara, it contains names and other data /// Because of this, the Pet data is hardcoded until a better way of obtaining it is found. /// </remarks> /// <returns>A list containing XivMount data</returns> public async Task <List <XivPet> > GetPetList() { var petLock = new object(); var petList = new List <XivPet>(); // A list of indices in modelchara that contain Pet model data var petModelIndexList = new List <int>() { 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 537, 618, 1027, 1028, 1430, 1930, 2023 }; // A dictionary consisting of <model ID, Pet Name> // All pet IDs are in the 7000 range // This list does not contain Pets that are separate but share the same ID (Fairy, Turrets) var petModelDictionary = new Dictionary <int, string>() { { 7002, XivStrings.Carbuncle }, { 7003, XivStrings.Ifrit_Egi }, { 7004, XivStrings.Titan_Egi }, { 7005, XivStrings.Garuda_Egi }, { 7006, XivStrings.Ramuh_Egi }, { 7007, XivStrings.Sephirot_Egi }, { 7102, XivStrings.Bahamut_Egi }, { 7103, XivStrings.Placeholder_Egi }, }; var modelCharaEx = await XivModelChara.GetModelCharaData(_gameDirectory); // Loops through the list of indices containing Pet model data await Task.Run(() => Parallel.ForEach(petModelIndexList, (petIndex) => { var xivPet = new XivPet { Category = XivStrings.Companions, ItemCategory = XivStrings.Pets, }; // Gets the model info from modelchara for the given index var modelInfo = XivModelChara.GetModelInfo(modelCharaEx, petIndex); // Finds the name of the pet using the model ID and the above dictionary if (petModelDictionary.ContainsKey(modelInfo.ModelID)) { var petName = petModelDictionary[modelInfo.ModelID]; if (modelInfo.Variant > 1) { petName += $" {modelInfo.Variant - 1}"; } xivPet.Name = petName; } // For cases where there are separate pets under the same model ID with different body IDs else { switch (modelInfo.ModelID) { case 7001: xivPet.Name = modelInfo.Body == 1 ? XivStrings.Eos : XivStrings.Selene; break; case 7101: xivPet.Name = modelInfo.Body == 1 ? XivStrings.Rook_Autoturret : XivStrings.Bishop_Autoturret; break; default: xivPet.Name = "Unknown"; break; } } xivPet.ModelInfo = modelInfo; lock (petLock) { petList.Add(xivPet); } })); petList.Sort(); return(petList); }