private static async Task <string> GetExtraSkelbPath(XivDependencyRootInfo root, XivRace race = XivRace.All_Races) { var type = Est.GetEstType(root); // Type doesn't use extra skels. if (type == Est.EstType.Invalid) { return(null); } var id = (ushort)root.PrimaryId; if (type == Est.EstType.Face || type == Est.EstType.Hair) { id = (ushort)root.SecondaryId; } // Hair and face types have a race defined at root level. if ((type == Est.EstType.Face || type == Est.EstType.Hair) && race == XivRace.All_Races) { var ret = new Dictionary <XivRace, ExtraSkeletonEntry>(); race = XivRaces.GetXivRace(root.PrimaryId); } var entry = await Est.GetExtraSkeletonEntry(type, race, id); var skelId = entry.SkelId; if (skelId == 0) { if (race == XivRace.Hyur_Midlander_Male) { return(null); } // Okay, this model, *as defined* has no EX Skeleton. _HOWEVER_ its parent skeleton could. // So we need to re-call and check up the chain until we hit Hyur M. var parent = XivRaceTree.GetNode(race).Parent; if (parent == null) { return(null); } // It's worth noting in these cases, the Skeletal bones themselves will still be using the matrices appropriate // for their parent race in this method, but that should be sufficient for now. return(await GetExtraSkelbPath(root, parent.Race)); } var prefix = Est.GetSystemPrefix(type); var slot = Est.GetSystemSlot(type); var raceCode = XivRaces.GetRaceCode(race); var skelCode = skelId.ToString().PadLeft(4, '0'); var path = $"chara/human/c{raceCode}/skeleton/{slot}/{prefix}{skelCode}/skl_c{raceCode}{prefix}{skelCode}.sklb"; return(path); }
/// <summary> /// Retrieves the Ex skeleton file for a given model file, parsing it from the base /// game files to generate it, if necessary. /// </summary> /// <param name="fullMdlPath"></param> /// <returns></returns> public static async Task <string> GetExtraSkeletonFile(string fullMdlPath) { var root = await XivCache.GetFirstRoot(fullMdlPath); var estType = Est.GetEstType(root); if (estType == Est.EstType.Invalid) { return(null); } // This is a hair/hat/face/body model at this point so this is a safe pull. var race = XivRaces.GetXivRace(fullMdlPath.Substring(1, 4)); return(await GetExtraSkeletonFile(root.Info, race)); }