public TmpFile GetTmpFile(MapTile t, bool damaged = false) { if (TmpFiles.Count == 0) return null; var randomChosen = TmpFiles[Rand.Next(TmpFiles.Count)]; // if this is not a randomizing tileset, but instead one with damaged data, // then return the "undamaged" version randomChosen.Initialize(); if (randomChosen.Images[Math.Min(t.SubTile, randomChosen.Images.Count - 1)].HasDamagedData) return TmpFiles[Math.Min(damaged ? 1 : 0, TmpFiles.Count - 1)]; else return randomChosen; }
private void ProcessTile(MapTile tile) { // "lock" this tile at least until we've examined its neighbourhood AddDependency(tile, null); ExamineNeighbourhood(tile); foreach (var obj in tile.AllObjects) { // every object depends on its bottom-most host tile at least AddDependency(obj, null); ExamineNeighbourhood(obj); } _graph[tile].Remove(tile); if (_graph[tile].Count == 0) // mark this tile and remove it as dependency from all other objects MarkDependencies(tile); // Debug.WriteLine("----------------------- processed " + tile); }
public static Rectangle GetBounds(MapTile tile, TmpFile tmp) { tmp.Initialize(); if (tile.SubTile >= tmp.Images.Count) return Rectangle.Empty; var img = tmp.Images[tile.SubTile]; int left = tile.Dx * tmp.BlockWidth / 2; int top = (tile.Dy - tile.Z) * tmp.BlockHeight / 2; int width = tmp.BlockWidth; int height = tmp.BlockHeight; if (img.HasExtraData) { if (img.ExtraX < 0) { left += img.ExtraX; width -= img.ExtraX; } if (img.ExtraY < 0) { top += img.ExtraY; height -= img.ExtraY; } width = Math.Max(width, img.ExtraWidth); height = Math.Max(height, img.ExtraHeight); } return new Rectangle(left, top, width, height); }
/// <summary>Recalculates tile system. </summary> public static void FixTiles(TileLayer tiles, TileCollection collection) { Logger.Info("Recalculating tile LAT system"); // change all CLAT tiles to their corresponding LAT tiles foreach (MapTile t in tiles) { // If this tile comes from a CLAT (connecting lat) set, // then replace it's set and tilenr by corresponding LAT sets' t.SetNum = collection.GetSetNum(t.TileNum); if (collection.IsCLAT(t.SetNum)) { t.SetNum = collection.GetLAT(t.SetNum); t.TileNum = collection.GetTileNumFromSet(t.SetNum); } } // apply autolat foreach (MapTile t in tiles) { // If this tile is a LAT tile, we might have to connect it if (collection.IsLAT(t.SetNum)) { // Which tile to use from CLAT tileset byte transitionTile = 0; MapTile tileTopRight = tiles.GetNeighbourTile(t, TileLayer.TileDirection.TopRight); MapTile tileBottomRight = tiles.GetNeighbourTile(t, TileLayer.TileDirection.BottomRight); MapTile tileBottomLeft = tiles.GetNeighbourTile(t, TileLayer.TileDirection.BottomLeft); MapTile tileTopLeft = tiles.GetNeighbourTile(t, TileLayer.TileDirection.TopLeft); // Find out setnums of adjacent cells if (tileTopRight != null && collection.ConnectTiles(t.SetNum, tileTopRight.SetNum)) { transitionTile += 1; } if (tileBottomRight != null && collection.ConnectTiles(t.SetNum, tileBottomRight.SetNum)) { transitionTile += 2; } if (tileBottomLeft != null && collection.ConnectTiles(t.SetNum, tileBottomLeft.SetNum)) { transitionTile += 4; } if (tileTopLeft != null && collection.ConnectTiles(t.SetNum, tileTopLeft.SetNum)) { transitionTile += 8; } if (transitionTile > 0) { // Find Tileset that contains the connecting pieces short clatSet = collection.GetCLATSet(t.SetNum); // Do not change this setnum, as then we could recognize it as // a different tileset for later tiles around this one. // (T->SetNum = clatSet;) t.TileNum = collection.GetTileNumFromSet(clatSet, transitionTile); t.Drawable = collection.GetDrawable(t); } } // apply ramp fixup else if (t.SetNum == collection.RampBase) { var ti = t.GetTileImage(); if (ti.RampType < 1 || 4 < ti.TerrainType) { continue; } int fixup = -1; MapTile tileTopRight = tiles.GetNeighbourTile(t, TileLayer.TileDirection.TopRight); MapTile tileBottomRight = tiles.GetNeighbourTile(t, TileLayer.TileDirection.BottomRight); MapTile tileBottomLeft = tiles.GetNeighbourTile(t, TileLayer.TileDirection.BottomLeft); MapTile tileTopLeft = tiles.GetNeighbourTile(t, TileLayer.TileDirection.TopLeft); switch (ti.RampType) { case 1: // northwest facing if (tileTopLeft != null && tileTopLeft.GetTileImage().RampType == 0) { fixup++; } if (tileBottomRight != null && tileBottomRight.GetTileImage().RampType == 0) { fixup += 2; } break; case 2: // northeast facing if (tileTopRight != null && tileTopRight.GetTileImage().RampType == 0) { fixup++; } if (tileBottomLeft != null && tileBottomLeft.GetTileImage().RampType == 0) { fixup += 2; } break; case 3: // southeast facing if (tileBottomRight != null && tileBottomRight.GetTileImage().RampType == 0) { fixup++; } if (tileTopLeft != null && tileTopLeft.GetTileImage().RampType == 0) { fixup += 2; } break; case 4: // southwest facing if (tileBottomLeft != null && tileBottomLeft.GetTileImage().RampType == 0) { fixup++; } if (tileTopRight != null && tileTopRight.GetTileImage().RampType == 0) { fixup += 2; } break; } if (fixup != -1) { t.TileNum = collection.GetTileNumFromSet(collection.RampSmooth, (byte)((ti.RampType - 1) * 3 + fixup)); // update drawable too t.Drawable = collection.GetDrawable(t); } } } }
private static int CountNeighbouringVeins(MapTile ne, MapTile se, MapTile sw, MapTile nw, Func <OverlayObject, bool> test) { bool neV = ne != null && ne.AllObjects.OfType <OverlayObject>().Any(test); bool seV = se != null && se.AllObjects.OfType <OverlayObject>().Any(test); bool swV = sw != null && sw.AllObjects.OfType <OverlayObject>().Any(test); bool nwV = nw != null && nw.AllObjects.OfType <OverlayObject>().Any(test); int numNeighbours = (neV ? 1 : 0) + (seV ? 1 : 0) + (swV ? 1 : 0) + (nwV ? 1 : 0); return(numNeighbours); }
unsafe public static void Draw(MapTile tile, TmpFile tmp, DrawingSurface ds) { tmp.Initialize(); if (tile.SubTile >= tmp.Images.Count) return; TmpFile.TmpImage img = tmp.Images[tile.SubTile]; var zBuffer = ds.GetZBuffer(); var heightBuffer = ds.GetHeightBuffer(); Palette p = tile.Palette; // calculate tile index -> pixel index Point offset = new Point(tile.Dx * tmp.BlockWidth / 2, (tile.Dy - tile.Z) * tmp.BlockHeight / 2); // make touched tiles (used for determining image cutoff) Point center = offset + new Size(tmp.BlockWidth / 2, tmp.BlockHeight / 2); var centerGridTile = tile.Layer.GetTileScreen(center, true, true); if (centerGridTile != null) { tile.Layer.GridTouched[centerGridTile.Dx, centerGridTile.Dy / 2] |= TileLayer.TouchType.ByNormalData; tile.Layer.GridTouchedBy[centerGridTile.Dx, centerGridTile.Dy / 2] = tile; } Logger.Trace("Drawing TMP file {0} (subtile {1}) at ({2},{3})", tmp.FileName, tile.SubTile, offset.X, offset.Y); int stride = ds.BitmapData.Stride; int halfCx = tmp.BlockWidth / 2, halfCy = tmp.BlockHeight / 2; // writing bounds var w_low = (byte*)ds.BitmapData.Scan0; byte* w_high = (byte*)ds.BitmapData.Scan0 + stride * ds.BitmapData.Height; byte* w = (byte*)ds.BitmapData.Scan0 + stride * offset.Y + (offset.X + halfCx - 2) * 3; int rIdx = 0, x, y = 0; int zIdx = offset.Y * ds.Width + offset.X + halfCx - 2; int cx = 0; // Amount of pixel to copy for (; y < halfCy; y++) { cx += 4; for (ushort c = 0; c < cx; c++) { byte paletteValue = img.TileData[rIdx]; short zBufVal = (short)((tile.Rx + tile.Ry) * tmp.BlockHeight / 2 - (img.ZData != null ? img.ZData[rIdx] : 0)); if (paletteValue != 0 && w_low <= w && w < w_high && zBufVal >= zBuffer[zIdx]) { *(w + 0) = p.Colors[paletteValue].B; *(w + 1) = p.Colors[paletteValue].G; *(w + 2) = p.Colors[paletteValue].R; zBuffer[zIdx] = zBufVal; heightBuffer[zIdx] = (short)(tile.Z * Drawable.TileHeight / 2); } w += 3; zIdx++; rIdx++; } w += stride - 3 * (cx + 2); zIdx += ds.Width - (cx + 2); } w += 12; zIdx += 4; for (; y < tmp.BlockHeight; y++) { cx -= 4; for (ushort c = 0; c < cx; c++) { byte paletteValue = img.TileData[rIdx]; short zBufVal = (short)((tile.Rx + tile.Ry) * tmp.BlockHeight / 2 - (img.ZData != null ? img.ZData[rIdx] : 0)); if (paletteValue != 0 && w_low <= w && w < w_high && zBufVal >= zBuffer[zIdx]) { *(w + 0) = p.Colors[paletteValue].B; *(w + 1) = p.Colors[paletteValue].G; *(w + 2) = p.Colors[paletteValue].R; zBuffer[zIdx] = zBufVal; heightBuffer[zIdx] = (short)(tile.Z * Drawable.TileHeight / 2); } w += 3; zIdx++; rIdx++; } w += stride - 3 * (cx - 2); zIdx += ds.Width - (cx - 2); } if (!img.HasExtraData) return; // we're done now offset.X += img.ExtraX - img.X; offset.Y += img.ExtraY - img.Y; w = w_low + stride * offset.Y + 3 * offset.X; zIdx = offset.X + offset.Y * ds.Width; rIdx = 0; // identify extra-data affected tiles for cutoff var extraScreenBounds = Rectangle.FromLTRB( Math.Max(0, offset.X), Math.Max(0, offset.Y), Math.Min(offset.X + img.ExtraWidth, ds.Width), Math.Min(offset.Y + img.ExtraHeight, ds.Height)); for (int by = extraScreenBounds.Top; by < extraScreenBounds.Bottom; by += tmp.BlockHeight / 2) { for (int bx = extraScreenBounds.Left; bx < extraScreenBounds.Right; bx += tmp.BlockWidth / 2) { var gridTileNoZ = tile.Layer.GetTileScreen(new Point(bx, by), true, true); if (gridTileNoZ != null) { Logger.Trace("Tile at ({0},{1}) has extradata affecting ({2},{3})", tile.Dx, tile.Dy, gridTileNoZ.Dx, gridTileNoZ.Dy); tile.Layer.GridTouched[gridTileNoZ.Dx, gridTileNoZ.Dy / 2] |= TileLayer.TouchType.ByExtraData; tile.Layer.GridTouchedBy[gridTileNoZ.Dx, gridTileNoZ.Dy / 2] = tile; } } } // Extra graphics are just a square for (y = 0; y < img.ExtraHeight; y++) { for (x = 0; x < img.ExtraWidth; x++) { // Checking per line is required because v needs to be checked every time byte paletteValue = img.ExtraData[rIdx]; short zBufVal = (short)((tile.Rx + tile.Ry) * tmp.BlockHeight / 2 + (img.ExtraZData != null ? img.ExtraZData[rIdx] : 0)); if (paletteValue != 0 && w_low <= w && w < w_high && zBufVal >= zBuffer[zIdx]) { *w++ = p.Colors[paletteValue].B; *w++ = p.Colors[paletteValue].G; *w++ = p.Colors[paletteValue].R; zBuffer[zIdx] = zBufVal; heightBuffer[zIdx] = (short)(img.ExtraHeight - y + tile.Z * Drawable.TileHeight / 2); } else w += 3; zIdx++; rIdx++; } w += stride - img.ExtraWidth * 3; zIdx += ds.Width - img.ExtraWidth; } }
public TmpFile.TmpImage GetTileImage(MapTile t) { var tmp = TsEntry.GetTmpFile(t); if (tmp.Images.Count > t.SubTile) return tmp.Images[t.SubTile]; return tmp.Images.Count > 0 ? tmp.Images[0] : null; }
public TmpFile GetTileFile(MapTile t) { return TsEntry.GetTmpFile(t); }
private static int CountNeighbouringVeins(MapTile ne, MapTile se, MapTile sw, MapTile nw, Func<OverlayObject, bool> test) { bool neV = ne != null && ne.AllObjects.OfType<OverlayObject>().Any(test); bool seV = se != null && se.AllObjects.OfType<OverlayObject>().Any(test); bool swV = sw != null && sw.AllObjects.OfType<OverlayObject>().Any(test); bool nwV = nw != null && nw.AllObjects.OfType<OverlayObject>().Any(test); int numNeighbours = (neV ? 1 : 0) + (seV ? 1 : 0) + (swV ? 1 : 0) + (nwV ? 1 : 0); return numNeighbours; }
public static int CountNeighbouringVeins(MapTile t, Func<OverlayObject, bool> test) { var ne = t.Layer.GetNeighbourTile(t, TileLayer.TileDirection.TopRight); var se = t.Layer.GetNeighbourTile(t, TileLayer.TileDirection.BottomRight); var sw = t.Layer.GetNeighbourTile(t, TileLayer.TileDirection.BottomLeft); var nw = t.Layer.GetNeighbourTile(t, TileLayer.TileDirection.TopLeft); return CountNeighbouringVeins(ne, se, sw, nw, test); }
public void DebugDrawTile(MapTile tile) { _theater.Draw(tile, _drawingSurface); foreach (GameObject o in GetObjectsAt(tile.Dx, tile.Dy / 2)) _theater.Draw(o, _drawingSurface); Operations.CountNeighbouringVeins(tile, Operations.IsVeins); }
private void ChangeTileToClear(TileCollection coll, MapTile tile) { tile.TileNum = 0; tile.SubTile = 0; tile.Drawable = coll.GetDrawable(0); var t = _mapFile.Tiles.GetTileR(tile.Rx, tile.Ry); t.TileNum = 0; t.SubTile = 0; }