// Calculate location rect in world units private void CalculateWorldLocationRect() { if (!hasCurrentLocation) { return; } // Convert world coords to map pixel coords then back again // This finds the absolute SW origin of this map pixel in world coords DFPosition mapPixel = CurrentMapPixel; DFPosition worldOrigin = MapsFile.MapPixelToWorldCoord(mapPixel.X, mapPixel.Y); // Find tile offset point using same logic as terrain helper DFPosition tileOrigin = TerrainHelper.GetLocationTerrainTileOrigin(CurrentLocation); // Adjust world origin by tileorigin*2 in world units worldOrigin.X += (tileOrigin.X * 2) * MapsFile.WorldMapTileDim; worldOrigin.Y += (tileOrigin.Y * 2) * MapsFile.WorldMapTileDim; // Get width and height of location in world units int width = currentLocation.Exterior.ExteriorData.Width * MapsFile.WorldMapRMBDim; int height = currentLocation.Exterior.ExteriorData.Height * MapsFile.WorldMapRMBDim; // Set location rect in world coordinates locationWorldRectMinX = worldOrigin.X; locationWorldRectMaxX = worldOrigin.X + width; locationWorldRectMinZ = worldOrigin.Y; locationWorldRectMaxZ = worldOrigin.Y + height; }
/// <summary> /// Helper to get location rect in world coordinates. /// </summary> /// <param name="location">Target location.</param> /// <returns>Location rect in world space. xMin,yMin is SW corner. xMax,yMax is NE corner.</returns> public static Rect GetLocationRect(DFLocation location) { // This finds the absolute SW origin of map pixel in world coords DFPosition mapPixel = MapsFile.LongitudeLatitudeToMapPixel(location.MapTableData.Longitude, location.MapTableData.Latitude); DFPosition worldOrigin = MapsFile.MapPixelToWorldCoord(mapPixel.X, mapPixel.Y); // Find tile offset point using same logic as terrain helper DFPosition tileOrigin = TerrainHelper.GetLocationTerrainTileOrigin(location); // Adjust world origin by tileorigin*2 in world units worldOrigin.X += (tileOrigin.X * 2) * MapsFile.WorldMapTileDim; worldOrigin.Y += (tileOrigin.Y * 2) * MapsFile.WorldMapTileDim; // Get width and height of location in world units int width = location.Exterior.ExteriorData.Width * MapsFile.WorldMapRMBDim; int height = location.Exterior.ExteriorData.Height * MapsFile.WorldMapRMBDim; // Create location rect in world coordinates Rect locationRect = new Rect() { xMin = worldOrigin.X, xMax = worldOrigin.X + width, yMin = worldOrigin.Y, yMax = worldOrigin.Y + height, }; return(locationRect); }
// Set location tilemap data public static void SetLocationTiles(ref MapPixelData mapPixel) { // Get location DaggerfallUnity dfUnity = DaggerfallUnity.Instance; DFLocation location = dfUnity.ContentReader.MapFileReader.GetLocation(mapPixel.mapRegionIndex, mapPixel.mapLocationIndex); // Position tiles inside terrain area DFPosition tilePos = TerrainHelper.GetLocationTerrainTileOrigin(location); // Full 8x8 locations have "terrain blend space" around walls to smooth down random terrain towards flat area. // This is indicated by texture index > 55 (ground texture range is 0-55), larger values indicate blend space. // We need to know rect of actual city area so we can use blend space outside walls. int xmin = int.MaxValue, ymin = int.MaxValue; int xmax = 0, ymax = 0; // Iterate blocks of this location for (int blockY = 0; blockY < location.Exterior.ExteriorData.Height; blockY++) { for (int blockX = 0; blockX < location.Exterior.ExteriorData.Width; blockX++) { // Get block data DFBlock block; string blockName = dfUnity.ContentReader.MapFileReader.GetRmbBlockName(ref location, blockX, blockY); if (!dfUnity.ContentReader.GetBlock(blockName, out block)) { continue; } // Copy ground tile info for (int tileY = 0; tileY < RMBLayout.RMBTilesPerBlock; tileY++) { for (int tileX = 0; tileX < RMBLayout.RMBTilesPerBlock; tileX++) { DFBlock.RmbGroundTiles tile = block.RmbBlock.FldHeader.GroundData.GroundTiles[tileX, (RMBLayout.RMBTilesPerBlock - 1) - tileY]; int xpos = tilePos.X + blockX * RMBLayout.RMBTilesPerBlock + tileX; int ypos = tilePos.Y + blockY * RMBLayout.RMBTilesPerBlock + tileY; if (tile.TextureRecord < 56) { // Track interior bounds of location tiled area if (xpos < xmin) { xmin = xpos; } if (xpos > xmax) { xmax = xpos; } if (ypos < ymin) { ymin = ypos; } if (ypos > ymax) { ymax = ypos; } // Store texture data from block mapPixel.tilemapData[JobA.Idx(xpos, ypos, MapsFile.WorldMapTileDim)] = tile.TileBitfield == 0 ? byte.MaxValue : tile.TileBitfield; } } } } } // Update location rect with extra clearance int extraClearance = location.MapTableData.LocationType == DFRegion.LocationTypes.TownCity ? 3 : 2; Rect locationRect = new Rect(); locationRect.xMin = xmin - extraClearance; locationRect.xMax = xmax + extraClearance; locationRect.yMin = ymin - extraClearance; locationRect.yMax = ymax + extraClearance; mapPixel.locationRect = locationRect; }
// Set location tilemap data public static void SetLocationTiles(ref MapPixelData mapPixel) { //const int tileDim = 16; //const int chunkDim = 8; DaggerfallUnity dfUnity = DaggerfallUnity.Instance; // Get location DFLocation location = dfUnity.ContentReader.MapFileReader.GetLocation(mapPixel.mapRegionIndex, mapPixel.mapLocationIndex); // Centre location tiles inside terrain area //int startX = ((chunkDim * tileDim) - location.Exterior.ExteriorData.Width * tileDim) / 2; //int startY = ((chunkDim * tileDim) - location.Exterior.ExteriorData.Height * tileDim) / 2; // Position tiles inside terrain area int width = location.Exterior.ExteriorData.Width; int height = location.Exterior.ExteriorData.Height; DFPosition tilePos = TerrainHelper.GetLocationTerrainTileOrigin(width, height); // Full 8x8 locations have "terrain blend space" around walls to smooth down random terrain towards flat area. // This is indicated by texture index > 55 (ground texture range is 0-55), larger values indicate blend space. // We need to know rect of actual city area so we can use blend space outside walls. int xmin = int.MaxValue, ymin = int.MaxValue; int xmax = 0, ymax = 0; // Iterate blocks of this location for (int blockY = 0; blockY < location.Exterior.ExteriorData.Height; blockY++) { for (int blockX = 0; blockX < location.Exterior.ExteriorData.Width; blockX++) { // Get block data DFBlock block; string blockName = dfUnity.ContentReader.MapFileReader.GetRmbBlockName(ref location, blockX, blockY); if (!dfUnity.ContentReader.GetBlock(blockName, out block)) { continue; } // Copy ground tile info for (int tileY = 0; tileY < RMBLayout.RMBTilesPerBlock; tileY++) { for (int tileX = 0; tileX < RMBLayout.RMBTilesPerBlock; tileX++) { DFBlock.RmbGroundTiles tile = block.RmbBlock.FldHeader.GroundData.GroundTiles[tileX, (RMBLayout.RMBTilesPerBlock - 1) - tileY]; int xpos = tilePos.X + blockX * RMBLayout.RMBTilesPerBlock + tileX; int ypos = tilePos.Y + blockY * RMBLayout.RMBTilesPerBlock + tileY; int record = tile.TextureRecord; if (tile.TextureRecord < 56) { // Track interior bounds of location tiled area if (xpos < xmin) { xmin = xpos; } if (xpos > xmax) { xmax = xpos; } if (ypos < ymin) { ymin = ypos; } if (ypos > ymax) { ymax = ypos; } // Store texture data from block mapPixel.tilemapSamples[xpos, ypos].record = record; mapPixel.tilemapSamples[xpos, ypos].flip = tile.IsFlipped; mapPixel.tilemapSamples[xpos, ypos].rotate = tile.IsRotated; mapPixel.tilemapSamples[xpos, ypos].location = true; } } } } } // Update location rect with extra clearance const int extraClearance = 2; Rect locationRect = new Rect(); locationRect.xMin = xmin - extraClearance; locationRect.xMax = xmax + extraClearance; locationRect.yMin = ymin - extraClearance; locationRect.yMax = ymax + extraClearance; mapPixel.locationRect = locationRect; }