public unsafe void DrawMapCell(int xCell, int yCell, int xPixel, int yPixel, MPQDS1 mapData, int main_index, int sub_index, Palette palette, int orientation) { var tiles = mapData.LookupTable.Where(x => x.MainIndex == main_index && x.SubIndex == sub_index && (orientation == -1 || x.Orientation == orientation)).Select(x => x.TileRef); if (!tiles.Any()) { return; } //throw new ApplicationException("Invalid tile id found!"); // TODO: This isn't good.. should be remembered in the map engine layer MPQDT1Tile tile = null; if (tiles.Count() > 0) { var totalRarity = tiles.Sum(q => q.RarityOrFrameIndex); var random = new Random(gameState.Seed + xCell + (mapData.Width * yCell)); var x = random.Next(totalRarity); var z = 0; foreach (var t in tiles) { z += t.RarityOrFrameIndex; if (x <= z) { tile = t; break; } } } else { tile = tiles.First(); } // This WILL happen to you if (tile.Width == 0 || tile.Height == 0) { return; } if (mapDataLookup.ContainsKey(mapData.Id)) { var lookupDetails = mapDataLookup[mapData.Id].FirstOrDefault(x => x.TileId == tile.Id); if (lookupDetails != null) { var dx = new SDL.SDL_Rect { x = xPixel - lookupDetails.OffX, y = yPixel - lookupDetails.OffY, w = lookupDetails.FrameWidth, h = lookupDetails.FrameHeight }; SDL.SDL_RenderCopy(renderer, lookupDetails.Texture, ref lookupDetails.SrcRect, ref dx); return; } } var minX = tile.Blocks.Min(x => x.PositionX); var minY = tile.Blocks.Min(x => x.PositionY); var maxX = tile.Blocks.Max(x => x.PositionX + 32); var maxY = tile.Blocks.Max(x => x.PositionY + 32); var diffX = maxX - minX; var diffY = maxY - minY; var offX = -minX; var offy = -minY; var frameSize = new Size(diffX, Math.Abs(diffY)); var srcRect = new SDL.SDL_Rect { x = 0, y = 0, w = frameSize.Width, h = Math.Abs(frameSize.Height) }; var frameSizeMax = diffX * Math.Abs(diffY); var texId = SDL.SDL_CreateTexture(renderer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, frameSize.Width, frameSize.Height); SDL.SDL_SetTextureBlendMode(texId, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); if (SDL.SDL_LockTexture(texId, IntPtr.Zero, out IntPtr pixels, out int pitch) != 0) { log.Error("Could not lock texture for map rendering"); return; } try { UInt32 *data = (UInt32 *)pixels; var pitchChange = (pitch / 4); for (var i = 0; i < frameSize.Height * pitchChange; i++) { data[i] = 0x0; } foreach (var block in tile.Blocks) { var index = block.PositionX + offX + ((block.PositionY + offy) * pitchChange); var xx = 0; var yy = 0; foreach (var colorIndex in block.PixelData) { try { if (colorIndex == 0) { continue; } var color = palette.Colors[colorIndex]; if (color > 0) { data[index] = color; } } finally { index++; xx++; if (xx == 32) { index -= 32; index += pitchChange; xx = 0; yy++; } } } } } finally { SDL.SDL_UnlockTexture(texId); } if (!mapDataLookup.ContainsKey(mapData.Id)) { mapDataLookup[mapData.Id] = new List <_MapDataLookup>(); } var lookup = new _MapDataLookup { FrameHeight = frameSize.Height, FrameWidth = frameSize.Width, OffX = offX, OffY = offy, SrcRect = srcRect, TileId = tile.Id, Texture = texId }; mapDataLookup[mapData.Id].Add(lookup); var dr = new SDL.SDL_Rect { x = xPixel - lookup.OffX, y = yPixel - lookup.OffY, w = lookup.FrameWidth, h = lookup.FrameHeight }; SDL.SDL_RenderCopy(renderer, lookup.Texture, ref lookup.SrcRect, ref dr); }
private MapCellInfo GetMapCellInfo(IMapInfo map, int cellX, int cellY, MPQDS1TileProps props, eRenderCellType cellType, byte orientation) { if (props.Prop1 == 0) { return(null); } if (!map.CellInfo.ContainsKey(cellType)) { map.CellInfo[cellType] = new MapCellInfo[map.FileData.Width * map.FileData.Height]; } var cellInfo = map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)]; if (cellInfo != null && (cellInfo.Ignore || !cellInfo.Tile.Animated)) { return(cellInfo.Ignore ? null : cellInfo); } var mainIndex = (props.Prop3 >> 4) + ((props.Prop4 & 0x03) << 4); var subIndex = props.Prop2; if (orientation == 0) { // Floor or Shadow if (cellType != eRenderCellType.Floor && cellType != eRenderCellType.Shadow) { map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; return(null); } } else if (orientation == 10 || orientation == 11) { if (cellType != eRenderCellType.WallNormal) { // Special tile map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; return(null); } } else if (orientation == 14) { // Walls (objects?) with precedent shadows if (cellType != eRenderCellType.WallNormal) { map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; return(null); } } else if (orientation < 15) { // Upper walls if (cellType != eRenderCellType.WallNormal) { map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; return(null); } } else if (orientation == 15) { // Roof if (cellType != eRenderCellType.Roof) { map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; return(null); } } else { // Lower Walls if (cellType != eRenderCellType.WallLower) { map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; return(null); } } IEnumerable <MPQDT1Tile> tiles = Enumerable.Empty <MPQDT1Tile>(); tiles = map.FileData.LookupTable .Where(x => x.MainIndex == mainIndex && x.SubIndex == subIndex && x.Orientation == orientation) .Select(x => x.TileRef); if (tiles == null || !tiles.Any()) { log.Error($"Could not find tile [{mainIndex}:{subIndex}:{orientation}]!"); map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; return(null); } MPQDT1Tile tile = null; if (tiles.First().Animated) { #if DEBUG if (!tiles.All(x => x.Animated)) { throw new OpenDiablo2Exception("Some tiles are animated and some aren't..."); } #endif var frameIndex = (int)Math.Floor(tiles.Count() * animationTime); tile = tiles.ElementAt(frameIndex); } else { if (tiles.Any()) { var totalRarity = tiles.Sum(q => q.RarityOrFrameIndex); var random = new Random(Seed + cellX + (map.FileData.Width * cellY)); var x = random.Next(totalRarity); var z = 0; foreach (var t in tiles) { z += t.RarityOrFrameIndex; if (x <= z) { tile = t; break; } } if (tile.Animated) { throw new OpenDiablo2Exception("Why are we randomly finding an animated tile? Something's wrong here."); } } else { tile = tiles.First(); } } // This WILL happen to you if (tile.Width == 0 || tile.Height == 0) { map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; return(null); } if (tile.BlockDataLength == 0) { map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = new MapCellInfo { Ignore = true }; return(null); // Why is this a thing? } var mapCellInfo = mapDataLookup.FirstOrDefault(x => x.Tile.Id == tile.Id); if (mapCellInfo == null) { mapCellInfo = renderWindow.CacheMapCell(tile, cellType); mapDataLookup.Add(mapCellInfo); } map.CellInfo[cellType][cellX + (cellY * map.FileData.Width)] = mapCellInfo; return(mapCellInfo); }