Example #1
0
 /// <summary>
 /// Draws and consume building from pool.
 /// Checking if buildings are ordered by special type.
 /// </summary>
 static bool GetNextBuildingFromPool(List <BuildingPoolItem> namedBuildingPool, DFLocation.BuildingTypes buildingType, out BuildingPoolItem itemOut)
 {
     itemOut = new BuildingPoolItem();
     for (int i = 0; i < namedBuildingPool.Count; i++)
     {
         if (!namedBuildingPool[i].used && namedBuildingPool[i].buildingData.BuildingType == buildingType)
         {
             itemOut      = namedBuildingPool[i];
             itemOut.used = true;
             return(true);
         }
     }
     return(false);
 }
Example #2
0
        /// <summary>
        /// Gets all RMB blocks from a location populated with building data from MAPS.BSA.
        /// This method is using "best effort" process at this point in time.
        /// However, it does yield very accurate results most of the time.
        /// Please use exception handling when calling this method for now.
        /// It will be progressed over time.
        /// </summary>
        /// <param name="location">Location to use.</param>
        /// <param name="blocksOut">Array of blocks populated with data from MAPS.BSA.</param>
        public static void GetLocationBuildingData(DFLocation location, out DFBlock[] blocksOut)
        {
            List <BuildingPoolItem> namedBuildingPool = new List <BuildingPoolItem>();
            List <DFBlock>          blocks            = new List <DFBlock>();

            // Get content reader
            ContentReader contentReader = DaggerfallUnity.Instance.ContentReader;

            if (contentReader == null)
            {
                throw new Exception("GetCompleteBuildingData() could not find ContentReader.");
            }

            // Store named buildings in pool for distribution
            for (int i = 0; i < location.Exterior.BuildingCount; i++)
            {
                DFLocation.BuildingData building = location.Exterior.Buildings[i];
                if (IsNamedBuilding(building.BuildingType))
                {
                    BuildingPoolItem bpi = new BuildingPoolItem();
                    bpi.buildingData = building;
                    bpi.used         = false;
                    namedBuildingPool.Add(bpi);
                }
            }

            // Get building summary of all blocks in this location
            int width  = location.Exterior.ExteriorData.Width;
            int height = location.Exterior.ExteriorData.Height;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    // Get block name
                    string blockName = contentReader.BlockFileReader.CheckName(contentReader.MapFileReader.GetRmbBlockName(ref location, x, y));

                    // Get block data
                    DFBlock block;
                    if (!contentReader.GetBlock(blockName, out block))
                    {
                        throw new Exception("GetCompleteBuildingData() could not read block " + blockName);
                    }

                    // Make a copy of the building data array for our block copy since we're modifying it
                    DFLocation.BuildingData[] buildingArray = new DFLocation.BuildingData[block.RmbBlock.FldHeader.BuildingDataList.Length];
                    Array.Copy(block.RmbBlock.FldHeader.BuildingDataList, buildingArray, block.RmbBlock.FldHeader.BuildingDataList.Length);
                    block.RmbBlock.FldHeader.BuildingDataList = buildingArray;

                    // Assign building data for this block
                    BuildingReplacementData buildingReplacementData;
                    for (int i = 0; i < block.RmbBlock.SubRecords.Length; i++)
                    {
                        DFLocation.BuildingData building = block.RmbBlock.FldHeader.BuildingDataList[i];
                        if (IsNamedBuilding(building.BuildingType))
                        {
                            // Try to find next building and merge data
                            BuildingPoolItem item;
                            if (!GetNextBuildingFromPool(namedBuildingPool, building.BuildingType, out item))
                            {
                                Debug.LogFormat("End of city building list reached without finding building type {0} in location {1}.{2}", building.BuildingType, location.RegionName, location.Name);
                            }

                            // Copy found city building data to block level
                            building.NameSeed   = item.buildingData.NameSeed;
                            building.FactionId  = item.buildingData.FactionId;
                            building.Sector     = item.buildingData.Sector;
                            building.LocationId = item.buildingData.LocationId;
                            building.Quality    = item.buildingData.Quality;

                            // Check for replacement building data and use it if found
                            if (WorldDataReplacement.GetBuildingReplacementData(blockName, block.Index, i, out buildingReplacementData))
                            {
                                // Use custom building values from replacement data, but only use up pool item if factionId is zero
                                if (buildingReplacementData.FactionId != 0)
                                {
                                    // Don't use up pool item and set factionId, NameSeed, Quality from replacement data
                                    item.used          = false;
                                    building.FactionId = buildingReplacementData.FactionId;
                                    building.Quality   = buildingReplacementData.Quality;
                                    building.NameSeed  = (ushort)(buildingReplacementData.NameSeed + location.LocationIndex);   // Vary name seed by location
                                }
                                // Always override type
                                building.BuildingType = (DFLocation.BuildingTypes)buildingReplacementData.BuildingType;
                            }

                            // Matched to classic: special handling for some Order of the Raven buildings
                            if (block.RmbBlock.FldHeader.OtherNames != null &&
                                block.RmbBlock.FldHeader.OtherNames[i] == "KRAVE01.HS2")
                            {
                                building.BuildingType = DFLocation.BuildingTypes.GuildHall;
                                building.FactionId    = 414;
                            }

                            // Set whatever building data we could find
                            block.RmbBlock.FldHeader.BuildingDataList[i] = building;
                        }
                    }

                    // Save block data
                    blocks.Add(block);
                }
            }

            // Send blocks array back to caller
            blocksOut = blocks.ToArray();
        }
Example #3
0
        /// <summary>
        /// Gets all RMB blocks from a location populated with building data from MAPS.BSA.
        /// This method is using "best effort" process at this point in time.
        /// However, it does yield very accurate results most of the time.
        /// Please use exception handling when calling this method for now.
        /// It will be progressed over time.
        /// </summary>
        /// <param name="location">Location to use.</param>
        /// <param name="blocksOut">Array of blocks populated with data from MAPS.BSA.</param>
        public static void GetLocationBuildingData(DFLocation location, out DFBlock[] blocksOut)
        {
            List <BuildingPoolItem> namedBuildingPool = new List <BuildingPoolItem>();
            List <DFBlock>          blocks            = new List <DFBlock>();

            // Get content reader
            ContentReader contentReader = DaggerfallUnity.Instance.ContentReader;

            if (contentReader == null)
            {
                throw new Exception("GetCompleteBuildingData() could not find ContentReader.");
            }

            // Store named buildings in pool for distribution
            for (int i = 0; i < location.Exterior.BuildingCount; i++)
            {
                DFLocation.BuildingData building = location.Exterior.Buildings[i];
                if (IsNamedBuilding(building.BuildingType))
                {
                    BuildingPoolItem bpi = new BuildingPoolItem();
                    bpi.buildingData = building;
                    bpi.used         = false;
                    namedBuildingPool.Add(bpi);
                }
            }

            // Get building summary of all blocks in this location
            int width  = location.Exterior.ExteriorData.Width;
            int height = location.Exterior.ExteriorData.Height;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    // Get block name
                    string blockName = contentReader.BlockFileReader.CheckName(contentReader.MapFileReader.GetRmbBlockName(ref location, x, y));

                    // Get block data
                    DFBlock block;
                    if (!contentReader.GetBlock(blockName, out block))
                    {
                        throw new Exception("GetCompleteBuildingData() could not read block " + blockName);
                    }

                    // Assign building data for this block
                    BuildingReplacementData buildingReplacementData;
                    for (int i = 0; i < block.RmbBlock.SubRecords.Length; i++)
                    {
                        DFLocation.BuildingData building = block.RmbBlock.FldHeader.BuildingDataList[i];
                        if (IsNamedBuilding(building.BuildingType))
                        {
                            // Check for replacement building data and use it if found
                            if (WorldDataReplacement.GetBuildingReplacementData(blockName, block.Index, i, out buildingReplacementData))
                            {
                                // Use custom building values from replacement data, don't use pool or maps file
                                building.NameSeed     = location.Exterior.Buildings[0].NameSeed;
                                building.FactionId    = buildingReplacementData.FactionId;
                                building.BuildingType = (DFLocation.BuildingTypes)buildingReplacementData.BuildingType;
                                building.LocationId   = location.Exterior.Buildings[0].LocationId;
                                building.Quality      = buildingReplacementData.Quality;
                            }
                            else
                            {
                                // Try to find next building and merge data
                                BuildingPoolItem item;
                                if (!GetNextBuildingFromPool(namedBuildingPool, building.BuildingType, out item))
                                {
                                    Debug.LogFormat("End of city building list reached without finding building type {0} in location {1}.{2}", building.BuildingType, location.RegionName, location.Name);
                                }
                                else
                                {
                                    // Copy found city building data to block level
                                    building.NameSeed   = item.buildingData.NameSeed;
                                    building.FactionId  = item.buildingData.FactionId;
                                    building.Sector     = item.buildingData.Sector;
                                    building.LocationId = item.buildingData.LocationId;
                                    building.Quality    = item.buildingData.Quality;
                                }
                            }
                            // Set whatever building data we could find
                            block.RmbBlock.FldHeader.BuildingDataList[i] = building;
                        }
                    }

                    // Save block data
                    blocks.Add(block);
                }
            }

            // Send blocks array back to caller
            blocksOut = blocks.ToArray();
        }