예제 #1
0
        /// <summary>
        /// Build dictionary of locations.
        /// </summary>
        private void EnumerateMaps()
        {
            //System.Diagnostics.Stopwatch s = System.Diagnostics.Stopwatch.StartNew();
            //long startTime = s.ElapsedMilliseconds;

            mapDict = new Dictionary <int, MapSummary>();
            locationIdToMapIdDict = new Dictionary <int, int>();
            for (int region = 0; region < mapFileReader.RegionCount; region++)
            {
                DFRegion dfRegion = mapFileReader.GetRegion(region);
                for (int location = 0; location < dfRegion.LocationCount; location++)
                {
                    // Get map summary
                    MapSummary summary = new MapSummary();
                    DFRegion.RegionMapTable mapTable = dfRegion.MapTable[location];
                    summary.ID           = mapTable.MapId & 0x000fffff;
                    summary.RegionIndex  = region;
                    summary.MapIndex     = location;
                    summary.LocationType = mapTable.LocationType;
                    summary.DungeonType  = mapTable.DungeonType;
                    mapDict.Add(summary.ID, summary);

                    // Link locationId with mapId - adds ~25ms overhead
                    int locationId = mapFileReader.ReadLocationIdFast(region, location);
                    locationIdToMapIdDict.Add(locationId, summary.ID);
                }
            }

            //long totalTime = s.ElapsedMilliseconds - startTime;
            //Debug.LogFormat("Total time to enum maps: {0}ms", totalTime);
        }
예제 #2
0
        /// <summary>
        /// Find a random dungeon site in player region.
        /// dungeonTypeIndex == -1 will select from all dungeons of type 0 through 16
        /// dungeonTypeIndex == 0 through 16 will select from all available dungeons of that specific type
        /// Note: Template only maps dungeon types 0-16 to p2 types dungeon0 through dungeon16.
        /// This is probably because types 17-18 don't seem to contain quest markers.
        /// Warning: Not all dungeon types are available in all regions. http://en.uesp.net/wiki/Daggerfall:Dungeons#Overview_of_Dungeon_Locations
        /// </summary>
        bool SelectRemoteDungeonSite(int dungeonTypeIndex)
        {
            // Get player region
            int      regionIndex = GameManager.Instance.PlayerGPS.CurrentRegionIndex;
            DFRegion regionData  = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetRegion(regionIndex);

            // Cannot use a region with no locations
            // This should not happen in normal play
            if (regionData.LocationCount == 0)
            {
                return(false);
            }

            //Debug.LogFormat("Selecting for random dungeon of type {0} in {1}", dungeonTypeIndex, regionData.Name);

            // Get indices for all dungeons of this type
            int[] foundIndices = CollectDungeonIndicesOfType(regionData, dungeonTypeIndex);
            if (foundIndices == null || foundIndices.Length == 0)
            {
                Debug.LogFormat("Could not find any random dungeons of type {0} in {1}", dungeonTypeIndex, regionData.Name);
                return(false);
            }

            //Debug.LogFormat("Found a total of {0} possible dungeons of type {1} in {2}", foundIndices.Length, dungeonTypeIndex, regionData.Name);

            // Select a random dungeon location index from available list
            int index = UnityEngine.Random.Range(0, foundIndices.Length);

            // Get location data for selected dungeon
            DFLocation location = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetLocation(regionIndex, foundIndices[index]);

            if (!location.Loaded)
            {
                return(false);
            }

            // Dungeon must be a valid quest site
            QuestMarker[] questSpawnMarkers, questItemMarkers;
            EnumerateDungeonQuestMarkers(location, out questSpawnMarkers, out questItemMarkers);
            if (!ValidateQuestMarkers(questSpawnMarkers, questItemMarkers))
            {
                Debug.LogFormat("Could not find any quest markers in random dungeon {0}", location.Name);
                return(false);
            }

            // Configure new site details
            siteDetails                          = new SiteDetails();
            siteDetails.questUID                 = ParentQuest.UID;
            siteDetails.siteType                 = SiteTypes.Dungeon;
            siteDetails.mapId                    = location.MapTableData.MapId;
            siteDetails.locationId               = location.Exterior.ExteriorData.LocationId;
            siteDetails.regionName               = location.RegionName;
            siteDetails.locationName             = location.Name;
            siteDetails.questSpawnMarkers        = questSpawnMarkers;
            siteDetails.questItemMarkers         = questItemMarkers;
            siteDetails.selectedQuestSpawnMarker = UnityEngine.Random.Range(0, questSpawnMarkers.Length);
            siteDetails.selectedQuestItemMarker  = UnityEngine.Random.Range(0, questItemMarkers.Length);

            return(true);
        }
예제 #3
0
        void AssignHomeTown()
        {
            // If this is a Questor or individual NPC then use current location name
            // Person is being instantiated where player currently is
            if (isQuestor || (IsIndividualNPC && isIndividualAtHome))
            {
                if (GameManager.Instance.PlayerGPS.HasCurrentLocation)
                {
                    homeTownName = GameManager.Instance.PlayerGPS.CurrentLocation.Name;
                    return;
                }
            }

            // Find a random location name from town types
            // This might take a few attempts but will very quickly find a random town name
            int      index;
            bool     found       = false;
            int      regionIndex = GameManager.Instance.PlayerGPS.CurrentRegionIndex;
            DFRegion regionData  = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetRegion(regionIndex);

            while (!found)
            {
                index = UnityEngine.Random.Range(0, regionData.MapTable.Length);
                DFRegion.LocationTypes locationType = regionData.MapTable[index].LocationType;
                if (locationType == DFRegion.LocationTypes.TownCity ||
                    locationType == DFRegion.LocationTypes.TownHamlet ||
                    locationType == DFRegion.LocationTypes.TownVillage)
                {
                    homeTownName = regionData.MapNames[index];
                    found        = true;
                }
            }
        }
예제 #4
0
        DFLocation GetRandomCemetery()
        {
            // Get player region data
            int      regionIndex = GameManager.Instance.PlayerGPS.CurrentRegionIndex;
            DFRegion regionData  = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetRegion(regionIndex);

            // Collect all cemetery locations
            List <int> foundLocationIndices = new List <int>();

            for (int i = 0; i < regionData.LocationCount; i++)
            {
                if (((int)regionData.MapTable[i].DungeonType) == (int)DFRegion.DungeonTypes.Cemetery)
                {
                    foundLocationIndices.Add(i);
                }
            }

            // Select one at random
            int        index    = UnityEngine.Random.Range(0, foundLocationIndices.Count);
            DFLocation location = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetLocation(regionIndex, foundLocationIndices[index]);

            if (!location.Loaded)
            {
                throw new System.Exception("VampirismInfection.GetRandomCemetery() could not find a cemetery in this region.");
            }

            return(location);
        }
예제 #5
0
        private void UpdateWorldInfo(int x, int y)
        {
            // Requires MAPS.BSA connection
            if (dfUnity.ContentReader.MapFileReader == null)
            {
                return;
            }

            // Get climate and politic data
            currentClimateIndex = dfUnity.ContentReader.MapFileReader.GetClimateIndex(x, y);
            currentPoliticIndex = dfUnity.ContentReader.MapFileReader.GetPoliticIndex(x, y);
            climateSettings     = MapsFile.GetWorldClimateSettings(currentClimateIndex);
            if (currentPoliticIndex > 128)
            {
                regionName = dfUnity.ContentReader.MapFileReader.GetRegionName(currentPoliticIndex - 128);
            }
            else if (currentPoliticIndex == 64)
            {
                regionName = "Ocean";
            }
            else
            {
                regionName = "Unknown";
            }

            // Get region data
            currentRegion = dfUnity.ContentReader.MapFileReader.GetRegion(CurrentRegionIndex);

            // Get location data
            ContentReader.MapSummary mapSummary;
            if (dfUnity.ContentReader.HasLocation(x, y, out mapSummary))
            {
                currentLocation    = dfUnity.ContentReader.MapFileReader.GetLocation(mapSummary.RegionIndex, mapSummary.MapIndex);
                hasCurrentLocation = true;
                CalculateWorldLocationRect();
            }
            else
            {
                currentLocation    = new DFLocation();
                hasCurrentLocation = false;
                ClearWorldLocationRect();
            }

            // Get location type
            if (hasCurrentLocation)
            {
                if (currentRegion.MapTable == null)
                {
                    DaggerfallUnity.LogMessage(string.Format("PlayerGPS: Location {0} in region{1} has a null MapTable.", currentLocation.Name, currentLocation.RegionName));
                }
                else
                {
                    currentLocationType = currentRegion.MapTable[mapSummary.MapIndex].LocationType;
                }
            }
        }
예제 #6
0
            public override string LocationDirection()
            {
                Vector2 positionPlayer;
                Vector2 positionLocation = Vector2.zero;

                DFPosition position  = new DFPosition();
                PlayerGPS  playerGPS = GameManager.Instance.PlayerGPS;

                if (playerGPS)
                {
                    position = playerGPS.CurrentMapPixel;
                }

                positionPlayer = new Vector2(position.X, position.Y);

                int region = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetPoliticIndex(position.X, position.Y) - 128;

                if (region < 0 || region >= DaggerfallUnity.Instance.ContentReader.MapFileReader.RegionCount)
                {
                    region = -1;
                }

                DFRegion.RegionMapTable locationInfo = new DFRegion.RegionMapTable();

                DFRegion currentDFRegion = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetRegion(region);

                string name = this.parent.LastPlaceReferenced.SiteDetails.locationName.ToLower();

                string[] locations = currentDFRegion.MapNames;
                for (int i = 0; i < locations.Length; i++)
                {
                    if (locations[i].ToLower() == name) // Valid location found with exact name
                    {
                        if (currentDFRegion.MapNameLookup.ContainsKey(locations[i]))
                        {
                            int index = currentDFRegion.MapNameLookup[locations[i]];
                            locationInfo     = currentDFRegion.MapTable[index];
                            position         = MapsFile.LongitudeLatitudeToMapPixel((int)locationInfo.Longitude, (int)locationInfo.Latitude);
                            positionLocation = new Vector2(position.X, position.Y);
                        }
                    }
                }

                if (positionLocation != Vector2.zero)
                {
                    Vector2 vecDirectionToTarget = positionLocation - positionPlayer;
                    vecDirectionToTarget.y = -vecDirectionToTarget.y; // invert y axis
                    return(GameManager.Instance.TalkManager.DirectionVector2DirectionHintString(vecDirectionToTarget));
                }
                else
                {
                    return("... never mind ...");
                }
            }
예제 #7
0
        static void Main(string[] args)
        {
            // Specify Arena2 path of local Daggerfall installation
            string MyArena2Path = "C:\\dosgames\\DAGGER\\ARENA2";

            // Path to BSA file
            string FilePath = Path.Combine(MyArena2Path, "MAPS.BSA");

            // Open file
            MapsFile mapsFile = new MapsFile(
                FilePath,
                FileUsage.UseDisk,
                true);

            // Loop through regions
            for (int r = 0; r < mapsFile.RegionCount; r++)
            {
                // Get the region object
                DFRegion region = mapsFile.GetRegion(r);

                // Loop through locations to look for largest dungeon
                int        maxDungeonBlocks   = -1;
                DFLocation maxDungeonLocation = new DFLocation();
                for (int l = 0; l < region.LocationCount; l++)
                {
                    // Get the location object
                    DFLocation location = mapsFile.GetLocation(r, l);

                    // Continue if location does not have a dungeon
                    if (!location.HasDungeon)
                    {
                        continue;
                    }

                    // Find dungeon with most number of blocks
                    if (location.Dungeon.Blocks.Length > maxDungeonBlocks)
                    {
                        maxDungeonBlocks   = location.Dungeon.Blocks.Length;
                        maxDungeonLocation = location;
                    }
                }

                // Output information if dungeon found
                if (maxDungeonBlocks != -1)
                {
                    Console.WriteLine("{0}, {1}, {2}",
                                      region.Name,
                                      maxDungeonLocation.Name,
                                      maxDungeonLocation.Dungeon.Blocks.Length);
                }
            }
        }
예제 #8
0
        void AssignHomeTown()
        {
            const string blank = "BLANK";

            // If this is a Questor or individual NPC then use current location name
            // Person is being instantiated where player currently is
            if (isQuestor || (IsIndividualNPC && isIndividualAtHome))
            {
                if (GameManager.Instance.PlayerGPS.HasCurrentLocation)
                {
                    homeTownName     = GameManager.Instance.PlayerGPS.CurrentLocation.Name;
                    homeRegionName   = GameManager.Instance.PlayerGPS.CurrentLocation.RegionName;
                    homeBuildingName = blank;
                    return;
                }
            }

            // Handle specific home Place assigned at create time
            if (homePlaceSymbol != null)
            {
                Place home = ParentQuest.GetPlace(homePlaceSymbol);
                if (home != null)
                {
                    homeTownName     = home.SiteDetails.locationName;
                    homeRegionName   = home.SiteDetails.regionName;
                    homeBuildingName = home.SiteDetails.buildingName;
                }
            }
            else
            {
                // Find a random location name from town types for flavour text
                // This might take a few attempts but will very quickly find a random town name
                int      index;
                bool     found       = false;
                int      regionIndex = GameManager.Instance.PlayerGPS.CurrentRegionIndex;
                DFRegion regionData  = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetRegion(regionIndex);
                while (!found)
                {
                    index = UnityEngine.Random.Range(0, regionData.MapTable.Length);
                    DFRegion.LocationTypes locationType = regionData.MapTable[index].LocationType;
                    if (locationType == DFRegion.LocationTypes.TownCity ||
                        locationType == DFRegion.LocationTypes.TownHamlet ||
                        locationType == DFRegion.LocationTypes.TownVillage)
                    {
                        homeTownName     = regionData.MapNames[index];
                        homeRegionName   = regionData.Name;
                        homeBuildingName = blank;
                        found            = true;
                    }
                }
            }
        }
        // Teleports player to a random location in a random region
        IEnumerator TeleportRandomLocation()
        {
            if (!CanTeleport())
            {
                yield break;
            }

            // Find a random location
            UnityEngine.Random.seed = UnityEngine.Time.renderedFrameCount;
            DFPosition mapPos = new DFPosition();
            bool       found  = false;

            while (!found)
            {
                // Get random region
                int      regionIndex = UnityEngine.Random.Range(0, dfUnity.ContentReader.MapFileReader.RegionCount);
                DFRegion region      = dfUnity.ContentReader.MapFileReader.GetRegion(regionIndex);
                if (region.LocationCount == 0)
                {
                    continue;
                }

                // Get random location
                int        locationIndex = UnityEngine.Random.Range(0, region.MapTable.Length);
                DFLocation location      = dfUnity.ContentReader.MapFileReader.GetLocation(regionIndex, locationIndex);
                if (!location.Loaded)
                {
                    continue;
                }

                // Check inside range
                mapPos = MapsFile.LongitudeLatitudeToMapPixel((int)location.MapTableData.Longitude, (int)location.MapTableData.Latitude);
                if ((mapPos.X >= TerrainHelper.minMapPixelX + 2 && mapPos.X < TerrainHelper.maxMapPixelX - 2) &&
                    (mapPos.Y >= TerrainHelper.minMapPixelY + 2 && mapPos.Y < TerrainHelper.maxMapPixelY - 2))
                {
                    found = true;
                }
            }

            // Teleport
            if (titleScreen)
            {
                titleScreen.ShowTitle = true;
            }
            yield return(new WaitForEndOfFrame());

            streamingWorld.TeleportToCoordinates(mapPos.X, mapPos.Y);
        }
예제 #10
0
 /// <summary>
 /// Build dictionary of locations.
 /// </summary>
 private void EnumerateMaps()
 {
     mapDict = new Dictionary <int, MapSummary>();
     for (int region = 0; region < mapFileReader.RegionCount; region++)
     {
         DFRegion dfRegion = mapFileReader.GetRegion(region);
         for (int location = 0; location < dfRegion.LocationCount; location++)
         {
             MapSummary summary = new MapSummary();
             DFRegion.RegionMapTable mapTable = dfRegion.MapTable[location];
             summary.ID          = mapTable.MapId & 0x000fffff;
             summary.RegionIndex = region;
             summary.MapIndex    = location;
             mapDict.Add(summary.ID, summary);
         }
     }
 }
예제 #11
0
        private void UpdateWorldInfo(int x, int y)
        {
            // Get climate and politic data
            currentClimateIndex = dfUnity.ContentReader.MapFileReader.GetClimateIndex(x, y);
            currentPoliticIndex = dfUnity.ContentReader.MapFileReader.GetPoliticIndex(x, y);
            climateSettings     = MapsFile.GetWorldClimateSettings(currentClimateIndex);
            if (currentPoliticIndex > 128)
            {
                regionName = dfUnity.ContentReader.MapFileReader.GetRegionName(currentPoliticIndex - 128);
            }
            else if (currentPoliticIndex == 64)
            {
                regionName = "Ocean";
            }
            else
            {
                regionName = "Unknown";
            }

            // Get region data
            currentRegion = dfUnity.ContentReader.MapFileReader.GetRegion(CurrentRegionIndex);

            // Get location data
            ContentReader.MapSummary mapSummary;
            if (dfUnity.ContentReader.HasLocation(x, y, out mapSummary))
            {
                currentLocation    = dfUnity.ContentReader.MapFileReader.GetLocation(mapSummary.RegionIndex, mapSummary.MapIndex);
                hasCurrentLocation = true;
                CalculateWorldLocationRect();
            }
            else
            {
                currentLocation    = new DFLocation();
                hasCurrentLocation = false;
                ClearWorldLocationRect();
            }

            // Get location type
            if (hasCurrentLocation)
            {
                currentLocationType = currentRegion.MapTable[mapSummary.MapIndex].Type;
            }
        }
예제 #12
0
        /// <summary>
        /// Build dictionary of locations.
        /// </summary>
        private void EnumerateMaps()
        {
            //System.Diagnostics.Stopwatch s = System.Diagnostics.Stopwatch.StartNew();
            //long startTime = s.ElapsedMilliseconds;

            mapDict = new Dictionary <int, MapSummary>();
            locationIdToMapIdDict = new Dictionary <int, int>();
            for (int region = 0; region < mapFileReader.RegionCount; region++)
            {
                DFRegion dfRegion = mapFileReader.GetRegion(region);
                for (int location = 0; location < dfRegion.LocationCount; location++)
                {
                    MapSummary summary = new MapSummary();
                    try
                    {
                        // Get map summary
                        DFRegion.RegionMapTable mapTable = dfRegion.MapTable[location];
                        summary.ID           = mapTable.MapId & 0x000fffff;
                        summary.RegionIndex  = region;
                        summary.MapIndex     = location;
                        summary.LocationType = mapTable.LocationType;
                        summary.DungeonType  = mapTable.DungeonType;

                        // TODO: This by itself doesn't account for DFRegion.LocationTypes.GraveyardForgotten locations that start the game discovered in classic
                        summary.Discovered = mapTable.Discovered;

                        mapDict.Add(summary.ID, summary);

                        // Link locationId with mapId - adds ~25ms overhead
                        int locationId = mapFileReader.ReadLocationIdFast(region, location);
                        locationIdToMapIdDict.Add(locationId, summary.ID);
                    }
                    catch (ArgumentException)
                    {
                        Debug.LogErrorFormat("Colliding location for MapId:{0} found when enumerating maps! Unable to initialise content reader. ", summary.ID);
                    }
                }
            }

            //long totalTime = s.ElapsedMilliseconds - startTime;
            //Debug.LogFormat("Total time to enum maps: {0}ms", totalTime);
        }
        private static bool AddLocationToRegion(int regionIndex, ref DFRegion dfRegion, ref List <string> mapNames, ref List <DFRegion.RegionMapTable> mapTable, ref DFLocation dfLocation)
        {
            // Copy the location id for ReadLocationIdFast() to use instead of peeking the classic data files
            dfLocation.MapTableData.LocationId = dfLocation.Exterior.RecordElement.Header.LocationId;

            // Add location to region using next index value
            int locationIndex = (int)dfRegion.LocationCount++;

            mapNames.Add(dfLocation.Name);
            dfLocation.LocationIndex = locationIndex;
            dfLocation.Exterior.RecordElement.Header.Unknown2 = (uint)locationIndex;
            mapTable.Add(dfLocation.MapTableData);
            dfRegion.MapIdLookup.Add(dfLocation.MapTableData.MapId, locationIndex);
            dfRegion.MapNameLookup.Add(dfLocation.Name, locationIndex);

            // Store location replacement/addition
            locations[MakeLocationKey(regionIndex, locationIndex).ToString()] = dfLocation;

            // Assign any new blocks in this location a block index if they haven't already been assigned
            return(AssignBlockIndices(ref dfLocation));
        }
예제 #14
0
        /// <summary>
        /// Gets location indices for all dungeons of type.
        /// dungeonTypeIndex == -1 will select all available dungeon
        /// </summary>
        int[] CollectDungeonIndicesOfType(DFRegion regionData, int dungeonTypeIndex)
        {
            // Collect all dungeon types
            List <int> foundLocationIndices = new List <int>();

            for (int i = 0; i < regionData.LocationCount; i++)
            {
                // Discard all non-dungeon location types
                if (!IsDungeonType(regionData.MapTable[i].LocationType))
                {
                    continue;
                }

                //Debug.LogFormat("Checking dungeon type {0} at location {1}", (int)regionData.MapTable[i].DungeonType, regionData.MapNames[i]);

                // Collect dungeons
                if (dungeonTypeIndex == -1)
                {
                    // Limit range to indices 0-16
                    int testIndex = ((int)regionData.MapTable[i].DungeonType >> 8);
                    if (testIndex >= 0 && testIndex <= 16)
                    {
                        foundLocationIndices.Add(i);
                    }
                }
                else
                {
                    // Otherwise dungeon must be of specifed type
                    if (((int)regionData.MapTable[i].DungeonType >> 8) == dungeonTypeIndex)
                    {
                        foundLocationIndices.Add(i);
                    }
                }
            }

            return(foundLocationIndices.ToArray());
        }
예제 #15
0
        /// <summary>
        /// Opens the save game index specified.
        /// </summary>
        /// <param name="save">Save index</param>
        /// <param name="loadingInGame">True if the save game is being loaded for regular play, false if loading for Save Explorer.</param>
        /// <returns>True if successful.</returns>
        public bool OpenSave(int save, bool loadingInGame = true)
        {
            if (!HasSave(save))
            {
                return(false);
            }

            if (!LoadSaveImage(save))
            {
                throw new Exception("Could not open SaveImage for index " + save);
            }

            if (!LoadSaveName(save))
            {
                throw new Exception("Could not open SaveName for index " + save);
            }

            saveTree = new SaveTree();
            if (!saveTree.Open(Path.Combine(saveGameDict[save], SaveTree.Filename)))
            {
                throw new Exception("Could not open SaveTree for index " + save);
            }

            saveVars = new SaveVars();
            if (!saveVars.Open(Path.Combine(saveGameDict[save], SaveVars.Filename)))
            {
                throw new Exception("Could not open SaveVars for index " + save);
            }

            mapSave = new BsaFile();
            if (!mapSave.Load(Path.Combine(saveGameDict[save], "MAPSAVE.SAV"), FileUsage.UseMemory, true))
            {
                throw new Exception("Could not open MapSave for index " + save);
            }

            if (loadingInGame) // Only check MAPSAVE if loading in-game, not if viewing in Save Explorer. There is a noticeable delay for
                               // Save Explorer as the classic saves are loaded, and a null exception if the Save Explorer is opened
                               // without the game running in the editor, due to PlayerGPS.dfUnity not being instantiated.
                               // Save Explorer currently has no use for MAPSAVE data. This code should be revisited (speed up MAPSAVE processing,
                               // fix null exception, remove this bool check) if MAPSAVE-related functionality is added to Save Explorer.
            {
                PlayerGPS gps = GameManager.Instance.PlayerGPS;
                gps.ClearDiscoveryData();
                for (int regionIndex = 0; regionIndex < 62; regionIndex++)
                {
                    // Generate name from region index
                    string name = string.Format("MAPSAVE.{0:000}", regionIndex);

                    // Get record index
                    int index = mapSave.GetRecordIndex(name);
                    if (index == -1)
                    {
                        return(false);
                    }

                    // Read MAPSAVE data
                    byte[] data = mapSave.GetRecordBytes(index);

                    // Parse MAPSAVE data for discovered locations
                    DFRegion regionData    = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetRegion(regionIndex);
                    int      locationCount = Math.Min(data.Length, (int)regionData.LocationCount);
                    for (int i = 0; i < locationCount; i++)
                    {
                        // If a location is marked as discovered in classic but not DF Unity, discover it for DF Unity
                        if ((data[i] & 0x40) != 0 && !regionData.MapTable[i].Discovered)
                        {
                            DFLocation location = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetLocation(regionIndex, i);
                            gps.DiscoverLocation(regionData.Name, location.Name);
                        }
                    }
                }
            }

            rumorFile = new RumorFile();
            if (!rumorFile.Load(Path.Combine(saveGameDict[save], "RUMOR.DAT"), FileUsage.UseMemory, true))
            {
                UnityEngine.Debug.Log("Could not open RUMOR.DAT for index " + save);
            }

            for (int i = 0; i < rumorFile.rumors.Count; i++)
            {
                GameManager.Instance.TalkManager.ImportClassicRumor(rumorFile.rumors[i]);
            }

            bioFile = new BioFile();
            if (!bioFile.Load(Path.Combine(saveGameDict[save], "BIO.DAT")))
            {
                UnityEngine.Debug.Log("Could not open BIO.DAT for index " + save);
            }

            return(true);
        }
예제 #16
0
        /// <summary>
        /// Find a town for remote site containing building type.
        /// Daggerfall's locations are so generic that we usually find a match within a few random attempts
        /// compared to indexing several hundred locations and only selecting from known-good candidates.
        /// In short, there are so many possible candidates it's not worth narrowing them down. Throw darts instead.
        /// Basic checks are still done to reject unsuitable locations very quickly.
        /// </summary>
        bool SelectRemoteTownSite(DFLocation.BuildingTypes requiredBuildingType)
        {
            // Get player region
            int      regionIndex = GameManager.Instance.PlayerGPS.CurrentRegionIndex;
            DFRegion regionData  = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetRegion(regionIndex);

            // Cannot use a region with no locations
            // This should not happen in normal play
            if (regionData.LocationCount == 0)
            {
                return(false);
            }

            // Find random town containing building
            int  attempts = 0;
            bool found    = false;

            while (!found)
            {
                // Increment attempts
                attempts++;

                // Get a random location index
                int locationIndex = UnityEngine.Random.Range(0, (int)regionData.LocationCount);

                // Discard all dungeon location types
                if (IsDungeonType(regionData.MapTable[locationIndex].LocationType))
                {
                    continue;
                }

                // Get location data for town
                DFLocation location = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetLocation(regionIndex, locationIndex);
                if (!location.Loaded)
                {
                    continue;
                }

                // Get list of valid sites
                SiteDetails[] foundSites = null;
                if (p2 == -1)
                {
                    // Collect random building sites
                    foundSites = CollectQuestSitesOfBuildingType(location, DFLocation.BuildingTypes.AllValid);
                }
                else
                {
                    // Check if town contains specified building type in MAPS.BSA directory
                    if (!HasBuildingType(location, requiredBuildingType))
                    {
                        continue;
                    }

                    // Get an array of potential quest sites with specified building type
                    // This ensures building site actually exists inside town, as MAPS.BSA directory can be incorrect
                    foundSites = CollectQuestSitesOfBuildingType(location, (DFLocation.BuildingTypes)p2);
                }

                // Must have found at least one site
                if (foundSites == null || foundSites.Length == 0)
                {
                    continue;
                }

                // Select a random site from available list
                int selectedIndex = UnityEngine.Random.Range(0, foundSites.Length);
                siteDetails = foundSites[selectedIndex];

                // All conditions have been satisfied
                found = true;
            }

            //Debug.LogFormat("Found remote candidate site in {0} attempts", attempts);

            return(true);
        }
 void ReloadCurrentRegion()
 {
     regionData         = dfUnity.ContentReader.MapFileReader.GetRegion(regionNames[selectedRegion]);
     lastSelectedRegion = selectedRegion;
 }
        /// <summary>
        /// Checks a region for added location data. (i.e. new locations)
        /// </summary>
        /// <param name="regionIndex">Region index</param>
        /// <param name="locationIndex">Location index</param>
        /// <param name="dfRegion">DFRegion data output updated with any added locations found</param>
        /// <returns>True if added blocks had indices assigned, false otherwise</returns>
        public static bool GetDFRegionAdditionalLocationData(int regionIndex, ref DFRegion dfRegion)
        {
            if (DaggerfallUnity.Settings.AssetInjection && ModManager.Instance != null)
            {
                // If found, return a previously cached DFRegion
                if (regions.ContainsKey(regionIndex))
                {
                    if (regions[regionIndex].LocationCount != noReplacementRegion.LocationCount)
                    {
                        dfRegion = regions[regionIndex];
                        return(true);
                    }
                    return(false);
                }
                // Setup local lists for the region arrays and record the location count from data
                uint          dataLocationCount         = dfRegion.LocationCount;
                List <string> mapNames                  = new List <string>(dfRegion.MapNames);
                List <DFRegion.RegionMapTable> mapTable = new List <DFRegion.RegionMapTable>(dfRegion.MapTable);
                bool newBlocksAssigned                  = false;

                // Seek from loose files
                string   locationPattern = string.Format("locationnew-*-{0}.json", regionIndex);
                string[] fileNames       = Directory.GetFiles(worldDataPath, locationPattern);
                foreach (string fileName in fileNames)
                {
                    string     locationReplacementJson = File.ReadAllText(Path.Combine(worldDataPath, fileName));
                    DFLocation dfLocation = (DFLocation)SaveLoadManager.Deserialize(typeof(DFLocation), locationReplacementJson);
                    newBlocksAssigned = AddLocationToRegion(regionIndex, ref dfRegion, ref mapNames, ref mapTable, ref dfLocation);
                }
                // Seek from mods
                string           locationExtension = string.Format("-{0}.json", regionIndex);
                List <TextAsset> assets            = ModManager.Instance.FindAssets <TextAsset>(worldData, locationExtension);
                if (assets != null)
                {
                    foreach (TextAsset locationReplacementJsonAsset in assets)
                    {
                        if (locationReplacementJsonAsset.name.StartsWith("locationnew-"))
                        {
                            DFLocation dfLocation = (DFLocation)SaveLoadManager.Deserialize(typeof(DFLocation), locationReplacementJsonAsset.text);
                            newBlocksAssigned &= AddLocationToRegion(regionIndex, ref dfRegion, ref mapNames, ref mapTable, ref dfLocation);
                        }
                    }
                }
                // If found any new locations for this region,
                if (dfRegion.LocationCount > dataLocationCount)
                {
                    // Update the region arrays from local lists
                    dfRegion.MapNames = mapNames.ToArray();
                    dfRegion.MapTable = mapTable.ToArray();

#if !UNITY_EDITOR  // Cache region data for added locations if new blocks have been assigned indices (unless running in editor)
                    if (newBlocksAssigned)
                    {
                        regions.Add(regionIndex, dfRegion);
                    }
#endif
                    Debug.LogFormat("Added {0} new DFLocation's to region {1}, indexes: {2} - {3}",
                                    dfRegion.LocationCount - dataLocationCount, regionIndex, dataLocationCount, dfRegion.LocationCount - 1);
                    return(true);
                }

#if !UNITY_EDITOR // Cache that there's no replacement region data, so only look for added locations once per region (unless running in editor)
                regions.Add(regionIndex, noReplacementRegion);
#endif
            }
            return(false);
        }
예제 #19
0
        /// <summary>
        /// Opens the save game index specified.
        /// </summary>
        /// <param name="save">Save index</param>
        /// <returns>True if successful.</returns>
        public bool OpenSave(int save)
        {
            if (!HasSave(save))
            {
                return(false);
            }

            if (!LoadSaveImage(save))
            {
                throw new Exception("Could not open SaveImage for index " + save);
            }

            if (!LoadSaveName(save))
            {
                throw new Exception("Could not open SaveName for index " + save);
            }

            saveTree = new SaveTree();
            if (!saveTree.Open(Path.Combine(saveGameDict[save], SaveTree.Filename)))
            {
                throw new Exception("Could not open SaveTree for index " + save);
            }

            saveVars = new SaveVars();
            if (!saveVars.Open(Path.Combine(saveGameDict[save], SaveVars.Filename)))
            {
                throw new Exception("Could not open SaveVars for index " + save);
            }

            mapSave = new BsaFile();
            if (!mapSave.Load(Path.Combine(saveGameDict[save], "MAPSAVE.SAV"), FileUsage.UseMemory, true))
            {
                throw new Exception("Could not open MapSave for index " + save);
            }

            PlayerGPS gps = GameManager.Instance.PlayerGPS;

            gps.ClearDiscoveryData();
            for (int regionIndex = 0; regionIndex < 62; regionIndex++)
            {
                // Generate name from region index
                string name = string.Format("MAPSAVE.{0:000}", regionIndex);

                // Get record index
                int index = mapSave.GetRecordIndex(name);
                if (index == -1)
                {
                    return(false);
                }

                // Read MAPSAVE data
                byte[] data = mapSave.GetRecordBytes(index);

                // Parse MAPSAVE data for discovered locations
                DFRegion regionData = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetRegion(regionIndex);
                for (int i = 0; i < regionData.LocationCount; i++)
                {
                    if ((data[i] & 0x40) != 0)
                    {
                        // Discover the location in DF Unity's data
                        if (regionData.MapTable[i].Discovered == false)
                        {
                            DFLocation location = DaggerfallUnity.Instance.ContentReader.MapFileReader.GetLocation(regionIndex, i);
                            gps.DiscoverLocation(regionData.Name, location.Name);
                        }
                    }
                }
            }

            return(true);
        }