Exemplo n.º 1
0
    private static Mesh[][][] GetMeshesForExteriorFixture(int fixtureId, ref FFXIVHSLib.Transform[][] transformsPerModel)
    {
        //A little different this time!
        if (_exteriorFixtureMeshes == null)
        {
            _exteriorFixtureMeshes = new Dictionary <int, Mesh[][][]>();
        }

        if (_exteriorFixtureMeshTransforms == null)
        {
            _exteriorFixtureMeshTransforms = new Dictionary <int, FFXIVHSLib.Transform[][]>();
        }

        Mesh[][][] modelMeshes;
        if (!_exteriorFixtureMeshes.TryGetValue(fixtureId, out modelMeshes))
        {
            string exteriorHousingObjectsFolder = FFXIVHSPaths.GetHousingExteriorObjectsDirectory();

            //Load the meshes if not found
            HousingExteriorFixture fixture = _exteriorFixtures[fixtureId];

            //Initialize variants dimensions
            int numVariants = HousingExteriorFixture.GetVariants(fixture.fixtureType);
            modelMeshes        = new Mesh[numVariants][][];
            transformsPerModel = new FFXIVHSLib.Transform[numVariants][];

            int i = 0;
            foreach (HousingExteriorFixtureVariant variant in fixture.variants)
            {
                //Initialize model dimensions for this variant
                int numModels = variant.models.Length;
                modelMeshes[i]        = new Mesh[numModels][];
                transformsPerModel[i] = new FFXIVHSLib.Transform[numModels];

                int j = 0;
                foreach (HousingExteriorFixtureModel model in variant.models)
                {
                    modelMeshes[i][j]        = new Mesh[model.numMeshes];
                    transformsPerModel[i][j] = model.transform;

                    for (int k = 0; k < model.numMeshes; k++)
                    {
                        string meshFileName = string.Format("{0}{1}_{2}.obj", exteriorHousingObjectsFolder, model.modelName, k);
                        modelMeshes[i][j][k] = FastObjImporter.Instance.ImportFile(meshFileName);
                    }
                    j++;
                }
                i++;
            }
            _exteriorFixtureMeshes.Add(fixtureId, modelMeshes);
            _exteriorFixtureMeshTransforms.Add(fixtureId, transformsPerModel);
        }
        else
        {
            //If the meshes are in the dictionary, so are the transforms :p
            transformsPerModel = _exteriorFixtureMeshTransforms[fixtureId];
        }
        return(modelMeshes);
    }
Exemplo n.º 2
0
        /// <summary>
        /// Adds the housing territory default fences as exterior fixtures with an id.
        /// The game does not actually recognize these as fixtures, they are part of the map.
        /// However, currently there is no way to know which transforms within the map sgbs belongs to
        /// which house size. So we have to work around it. Thanks SE!
        /// </summary>
        /// <param name="realm"></param>
        /// <param name="fixtures"></param>
        private static void AddDefaultFences(ARealmReversed realm, ref Dictionary <int, HousingExteriorFixture> fixtures)
        {
            List <TerritoryType> teris = GetHousingTerritoryTypes(realm);

            //Obtain all housing TerritoryTypes
            IXivSheet <PlaceName> placeNames = realm.GameData.GetSheet <PlaceName>();

            PlaceName[] pNames = placeNames.ToArray();

            string[] fncPaths =
            {
                "bg/ffxiv/{0}/hou/dyna/c_fnc/0000/asset/{1}_f_fnc0000a.sgb",
                "bg/ffxiv/{0}/hou/dyna/c_fnc/0000/asset/{1}_f_fnc0000b.sgb",
                "bg/ffxiv/{0}/hou/dyna/c_fnc/0000/asset/{1}_f_fnc0000c.sgb",
                "bg/ffxiv/{0}/hou/dyna/c_fnc/0000/asset/{1}_f_fnc0000d.sgb",
            };

            foreach (TerritoryType t in teris)
            {
                //Get usable strings
                string bgFolder   = t.Bg.ToString().Split('/')[1];
                string namePrefix = t.Name.ToString();
                namePrefix = namePrefix.Substring(0, namePrefix.Length - 1) + '0';

                //bgFolder is now 'sea_s1', 'est_e1', etc
                //namePrefix is now 's1h0', 'e1h0', etc
                int intUse = pNames.Where(_ => _.Name == t.RegionPlaceName.Name)
                             .Select(_ => _.Key)
                             .Min(_ => _);

                HousingExteriorFixture thisFence = new HousingExteriorFixture();
                thisFence.itemId             = 0;
                thisFence.fixtureId          = int.Parse("102" + intUse);
                thisFence.fixtureModelKey    = 0; //Not in the sheet, no key ¯\_(ツ)_/¯
                thisFence.fixtureType        = FixtureType.fnc;
                thisFence.fixtureIntendedUse = intUse;
                thisFence.size = Size.x;
                thisFence.name = $"Default {t.PlaceName.NameWithoutArticle} Fence";

                List <string> sgbPaths = new List <string>();

                foreach (string fnc in fncPaths)
                {
                    sgbPaths.Add(string.Format(fnc, bgFolder, namePrefix));
                }

                //I forgot this method existed. Thanks!
                thisFence.variants = ReadSgbForVariantInfo(realm, sgbPaths.ToArray());

                fixtures.Add(thisFence.fixtureId, thisFence);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Returns a HousingExteriorBlueprintSet read from the small, medium, and large sgb paths in
        /// HousingExteriorBlueprintSet.
        /// </summary>
        /// <param name="realm"></param>
        /// <returns></returns>
        private static HousingExteriorBlueprintSet ReadExteriorBlueprintSet(ARealmReversed realm)
        {
            HousingExteriorBlueprintSet thisSet = new HousingExteriorBlueprintSet();

            thisSet.set = new HousingExteriorBlueprint[HousingExteriorBlueprintSet.SgbPaths.Length];

            for (int i = 0; i < HousingExteriorBlueprintSet.SgbPaths.Length; i++)
            {
                string thisPath = HousingExteriorBlueprintSet.SgbPaths[i];
                HousingExteriorBlueprint thisBlueprint = new HousingExteriorBlueprint {
                    size = (Size)i
                };

                //These are hardcoded, double check they're there
                SaintCoinach.IO.File f;
                if (!realm.Packs.TryGetFile(thisPath, out f))
                {
                    throw new FileNotFoundException();
                }

                SgbFile sgb = new SgbFile(f);

                foreach (SgbGroup group in sgb.Data.OfType <SgbGroup>())
                {
                    foreach (SgbGimmickEntry gim in group.Entries.OfType <SgbGimmickEntry>())
                    {
                        string gimmickPath = gim.Gimmick.File.Path;

                        /*
                         * Group 1: s1h0 or opt
                         * Group 2: size, dor/wid variant, f for fence, or opt's 2chars
                         * Group 3: fixturetype or m for opt
                         * Group 4: a/b/c/d for fence, . for all others
                         */
                        Regex pattern = new Regex(@"asset\/(.*)?_(.{1,2})_(.{1,3})([0-9]{4})([a-z]|\.)");
                        Match m       = pattern.Match(gimmickPath);

                        if (!m.Success)
                        {
                            continue;
                        }

                        //Obtain fixture type
                        string fType = m.Groups[3].Value;
                        if (fType == "m")
                        {
                            fType = "o" + m.Groups[2].Value;
                        }
                        FixtureType fixtureType = (FixtureType)Enum.Parse(typeof(FixtureType), fType);

                        //Obtains the variant string, examples: s, m, l, co, ca, ci, a, b, c, d
                        string strVariant = m.Groups[5].Value == "." ? m.Groups[2].Value : m.Groups[5].Value;
                        int    variant    = 0;

                        //Attempt to parse group 2 into a Size to get variant
                        if (!Enum.TryParse(strVariant, out Size fixtureSize))
                        {
                            //If we can't parse variant to a size, we have to parse into a different fixture variant
                            if (fixtureType == FixtureType.dor)
                            {
                                variant = (int)Enum.Parse(typeof(DoorVariants), strVariant);
                            }
                            else if (fixtureType == FixtureType.wid)
                            {
                                variant = (int)Enum.Parse(typeof(WindowVariants), strVariant);
                            }
                            else if (fixtureType == FixtureType.fnc)
                            {
                                variant = (int)Enum.Parse(typeof(FenceVariants), strVariant);
                            }
                        }
                        else
                        {
                            //If rof/wal is not same size as blueprint, skip it
                            if (fixtureSize != thisBlueprint.size)
                            {
                                continue;
                            }
                        }

                        if (thisBlueprint.fixtureTransforms[fixtureType][variant] == null)
                        {
                            thisBlueprint.fixtureTransforms[fixtureType][variant] = new List <Transform>();
                        }

                        List <Transform> listForVariant = thisBlueprint.fixtureTransforms[fixtureType][variant];

                        Transform t = TransformFromVectors(gim.Header.Translation, gim.Header.Rotation,
                                                           gim.Header.Scale);

                        listForVariant.Add(t);

                        #region switch statement bad
//                        switch (m.Groups[3].Value)
//                        {
//                            case nameof(FixtureType.rof):
//                                if (m.Groups[2].Value == size.ToString())
//                                {
//                                    //exampe but cool
//                                }
//                                break;
//                            case nameof(FixtureType.wal):
//                                //Do stuff
//                                break;
//                            case nameof(FixtureType.wid):
//                                //Do stuff
//                                break;
//                            case nameof(FixtureType.dor):
//                                //Do stuff
//                                break;
//                            case "m":
//                                switch ("o" + m.Groups[2].Value)
//                                {
//                                    case nameof(FixtureType.orf):
//                                        //Do stuff
//                                        break;
//                                    case nameof(FixtureType.owl):
//                                        //Do stuff
//                                        break;
//                                    case nameof(FixtureType.osg):
//                                        //Do stuff
//                                        break;
//                                }
//                                break;
//                            case nameof(FixtureType.fnc):
//                                //Do stuff
//                                break;
//                        }
                        #endregion
                    }
                }

                /*
                 * The transforms relevant to the current blueprint come first,
                 * so figure out how many Transforms aren't for this size house
                 * by checking how many transforms are collectively in the blueprints
                 * below this size and variant, then remove that number of entries.
                 */

                if (i > 0)
                {
                    int[][] numTransformsInSmallerBlueprints = new int[Enum.GetValues(typeof(FixtureType)).Length][];
                    //For every smaller blueprint
                    for (int smallerBlueprintIndex = 0; smallerBlueprintIndex < i; smallerBlueprintIndex++)
                    {
                        //For every fixture type
                        for (int fixtureTypeIndex = 0; fixtureTypeIndex < numTransformsInSmallerBlueprints.Length; fixtureTypeIndex++)
                        {
                            FixtureType fixtureType      = (FixtureType)fixtureTypeIndex + 1;
                            int         numberOfVariants = HousingExteriorFixture.GetVariants(fixtureType);

                            if (numTransformsInSmallerBlueprints[fixtureTypeIndex] == null)
                            {
                                numTransformsInSmallerBlueprints[fixtureTypeIndex] = new int[numberOfVariants];
                            }

                            for (int variantIndex = 0; variantIndex < numberOfVariants; variantIndex++)
                            {
                                int?toAddn = thisSet.set[smallerBlueprintIndex].fixtureTransforms[fixtureType][variantIndex]?.Count;
                                int toAdd  = toAddn ?? 0;

                                numTransformsInSmallerBlueprints[fixtureTypeIndex][variantIndex] += toAdd;
                            }
                        }
                    }

                    //Whoops, don't do it for fences
                    for (int j = 0; j < numTransformsInSmallerBlueprints[(int)FixtureType.fnc - 1].Length; j++)
                    {
                        numTransformsInSmallerBlueprints[(int)FixtureType.fnc - 1][j] = 0;
                    }

                    //For every fixture type
                    for (int fixtureTypeIndex = 0; fixtureTypeIndex < numTransformsInSmallerBlueprints.Length; fixtureTypeIndex++)
                    {
                        FixtureType fixtureType      = (FixtureType)fixtureTypeIndex + 1;
                        int         numberOfVariants = HousingExteriorFixture.GetVariants(fixtureType);

                        for (int variantIndex = 0; variantIndex < numberOfVariants; variantIndex++)
                        {
                            List <Transform> variantTransformsList = thisBlueprint.fixtureTransforms[fixtureType][variantIndex];

                            if (thisBlueprint.fixtureTransforms[fixtureType][variantIndex] == null)
                            {
                                continue;
                            }
                            if (variantTransformsList == null)
                            {
                                continue;
                            }

                            int numTransforms = variantTransformsList.Count;
                            int difference    = numTransforms - numTransformsInSmallerBlueprints[fixtureTypeIndex][variantIndex];

                            if (difference > 0)
                            {
                                List <Transform> newTransforms = new List <Transform>();
                                for (int tCount = 0; tCount < difference; tCount++)
                                {
                                    newTransforms.Add(variantTransformsList[tCount]);
                                }
                                thisBlueprint.fixtureTransforms[fixtureType][variantIndex] = newTransforms;
                            }
                        }
                    }
                }
                thisSet.set[i] = thisBlueprint;
            }
            return(thisSet);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Reads from game data and serializes a dictionary containing exterior housing fixture information.<br />
        ///
        /// Reads from sheets HousingExterior and Item.
        /// </summary>
        private static Dictionary <int, HousingExteriorFixture> ReadHousingExteriorSheet(ARealmReversed realm)
        {
            Dictionary <int, HousingExteriorFixture> fixtures = new Dictionary <int, HousingExteriorFixture>();

            IXivSheet <XivRow> housingExteriorSheet = realm.GameData.GetSheet("HousingExterior");
            IXivSheet <XivRow> itemSheet            = realm.GameData.GetSheet("Item");

            foreach (XivRow row in housingExteriorSheet)
            {
                if (row.Key == 0)
                {
                    continue;
                }

                HousingExteriorFixture rowFixture = new HousingExteriorFixture();
                rowFixture.size = (Size)(byte)row[3];

                rowFixture.fixtureId          = row.Key;
                rowFixture.fixtureModelKey    = (byte)row[0];
                rowFixture.fixtureIntendedUse = (ushort)row[2];
                rowFixture.fixtureType        = (FixtureType)(byte)row[1];

                //Data from item sheet
                int[] stainResults = (from x in itemSheet
                                      where (uint)x.GetRaw("Stain") == row.Key
                                      select x.Key).ToArray();

                if (stainResults.Length == 1)
                {
                    rowFixture.itemId = stainResults[0];
                    rowFixture.name   = (from x in itemSheet
                                         where x.Key == rowFixture.itemId
                                         select x["Name"]).Single().ToString();
                }
                else
                {
                    rowFixture.itemId = -1;
                    rowFixture.name   = "";
                }

                //Get data for variants and modelEntries
                string   p        = row[4].ToString();
                string[] sgbPaths = { String.IsNullOrEmpty(p) ? null : p };

                //Fences too because row only has one .sgb for them - there are 4
                if (sgbPaths[0] == null)
                {
                    sgbPaths = rowFixture.GetPaths();
                }
                else if (rowFixture.fixtureType == FixtureType.fnc)
                {
                    sgbPaths = rowFixture.GetPaths(sgbPaths[0]);
                }

                /*
                 * For testing
                 *
                 * foreach (string path in sgbPaths)
                 * {
                 *  string name = rowFixture.name;
                 *  if (String.IsNullOrEmpty(name))
                 *      name = rowFixture.fixtureIntendedUse.ToString();
                 *  if (!realm.Packs.FileExists(path))
                 *      Console.WriteLine(name + "|" + path);
                 * }*/

                //Load model data and things
                rowFixture.variants = ReadSgbForVariantInfo(realm, sgbPaths);

                fixtures.Add(rowFixture.fixtureId, rowFixture);
            }
            return(fixtures);
        }