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); }