/// <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); }
/// <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); }
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; } } }
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); }
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; } } }
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 ..."); } }
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); } } }
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); }
/// <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); } } }
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; } }
/// <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)); }
/// <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()); }
/// <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); }
/// <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); }
/// <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); }