/// <summary> /// Get a new list of spawn points. /// </summary> private void RefreshSpawnPointList() { bool ctf = GameMode == VTankObject.GameMode.CAPTURETHEFLAG; bool ctb = GameMode == VTankObject.GameMode.CAPTURETHEBASE; int halfTile = Tile.TILE_SIZE_IN_PIXELS / 2; spawnPointList.Clear(); AIFramework.Bot.Game.Map map = CurrentMap; for (int y = 0; y < map.Height; ++y) { for (int x = 0; x < map.Width; ++x) { AIFramework.Bot.Game.Tile tile = map.GetTile(x, y); if (GameMode == VTankObject.GameMode.DEATHMATCH) { if (tile.EventID == 1) // '1' represents a spawn point. { spawnPointList.Add(new TileNode( x * Tile.TILE_SIZE_IN_PIXELS - halfTile, y * Tile.TILE_SIZE_IN_PIXELS - halfTile)); } } else if (ctf) { if (tile.EventID == 4 || tile.EventID == 5) { spawnPointList.Add(new TileNode( x * Tile.TILE_SIZE_IN_PIXELS, y * Tile.TILE_SIZE_IN_PIXELS)); } } else if (ctb) { if (tile.EventID >= 8 && tile.EventID < 14) { spawnPointList.Add(new TileNode( x * Tile.TILE_SIZE_IN_PIXELS, y * Tile.TILE_SIZE_IN_PIXELS)); } } else /*if (GameMode == VTankObject.GameMode.TEAMDEATHMATCH)*/ { if (tile.EventID == 3 || tile.EventID == 2) { spawnPointList.Add(new TileNode( x * Tile.TILE_SIZE_IN_PIXELS - halfTile, y * Tile.TILE_SIZE_IN_PIXELS - halfTile)); } } } } foreach (TileNode node in spawnPointList) { int tileX = (int)Math.Round((double)node.X / Tile.TILE_SIZE_IN_PIXELS); int tileY = (int)Math.Round((double)node.Y / Tile.TILE_SIZE_IN_PIXELS); Tile tile = map.GetTile(tileX, tileY); if (!tile.IsPassable) { Console.Error.WriteLine("[WARNING] ({0}, {1}) => ({2}, {3}) is unpassable.", node.X, node.Y, tileX, tileY); } } refreshSpawnPointList = false; spawnPointIndex = 0; Shuffle <TileNode>(spawnPointList); }
/// <summary> /// Set new data for a tile at a specific location on a 2D map plane. /// </summary> /// <param name="x">X-coordinate (in tiles) of the tile.</param> /// <param name="y">Y-coordinate (in tiles) of the tile.</param> /// <param name="tile">Tile to set to the given (x, y) location.</param> public void SetTile(uint x, uint y, Tile tile) { tile_data[y * Width + x] = tile; }
/// <summary> /// Create a new map from scratch. Initializes all tiles to ID '0'. /// It will attempt to write the map to disk with the given filename. If an error occurs, /// a System.IO.IOException will be thrown. /// </summary> /// <param name="mapTitle">Title of the map.</param> /// <param name="mapFileName">The filename of the map.</param> /// <param name="mapWidth">Width (in tiles) of the map.</param> /// <param name="mapHeight">Height (in tiles) of the map.</param> /// <see>System.IO.IOException</see> public void CreateMap(string mapTitle, string mapFileName, uint mapWidth, uint mapHeight) { Title = mapTitle; FileName = mapFileName; Width = mapWidth; Height = mapHeight; tile_data = new Tile[Width * Height]; version = FORMAT_VERSION; uint mapSize = Width * Height; for (uint i = 0; i < mapSize; i++) { tile_data[i] = new Tile(0, 0, 0, true, 0, 0, 0); } SaveMap(); }
/// <summary> /// Load a map that exists from disk using the stored filename. /// If the map can't be found, this method throws a FileNotFoundException. If otherwise /// an IO error occurs, a more general-purpose IOException is thrown. /// </summary> /// <see>System.IO.IOException</see> public void LoadMap() { using (BinaryReader reader = new BinaryReader(new StreamReader(FileName).BaseStream)) { byte version_byte = (byte)reader.Read(); if (version_byte != FORMAT_VERSION) { throw new IOException("Version mismatch: The map " + FileName + " uses an invalid format version."); } char c; StringBuilder stringBuffer = new StringBuilder(); while ((c = reader.ReadChar()) != '\n') { stringBuffer.Append(c); } title = stringBuffer.ToString(); byte[] buf = reader.ReadBytes(4); int width = ToInt32(buf[0], buf[1], buf[2], buf[3]); buf = reader.ReadBytes(4); int height = ToInt32(buf[0], buf[1], buf[2], buf[3]); string gameModes = ""; byte b; while ((b = reader.ReadByte()) != '\n') { gameModes += b; } if (width <= 0 || height <= 0) { throw new IOException("Map size cannot have a width or height less than or equal to 0"); } tile_data = new Tile[width * height]; version = version_byte; Title = title; Width = (uint)width; Height = (uint)height; for (int i = 0; i < gameModes.Length; i++) { supportedGameModes.Add(gameModes[i]); } // Now read file contents into the tile data. // The cast is justified if the map is smaller than 2 GiB (on 32 bit systems) int byte_count = Tile.BYTES_PER_TILE * width * height; byte[] buffer = new byte[byte_count]; reader.Read(buffer, 0, byte_count); for (int i = 0, j = 0; i < byte_count; i += Tile.BYTES_PER_TILE, j++) { int tileId = (buffer[i]) | ((buffer[i + 1] << 8)) | ((buffer[i + 2] << 16)) | ((buffer[i + 3] << 24)); int objectId = (buffer[i + 4]) + ((buffer[i + 5] << 8)); int eventId = (buffer[i + 6]) + ((buffer[i + 7] << 8)); bool passable = (buffer[i + 8] == 0) ? false : true; int tile_height = (buffer[i + 9]); int type = (buffer[i + 10]); int effect = (buffer[i + 11]); tile_data[j] = new Tile( (uint)tileId, (ushort)objectId, (ushort)eventId, passable, (ushort)tile_height, (ushort)type, (ushort)effect); } } sha1sum = Hash.CalculateSHA1OfFile(FileName); }
/// <summary> /// Performs the actual map download operation. /// </summary> /// <param name="localPath">Local path in the operating system.</param> /// <param name="mapFileName"></param> /// <returns></returns> private static Map DownloadMap(string mapFileName, MasterCommunicator main) { Debugger.Write("Downloading map {0}...", mapFileName); VTankObject.Map map = main.GetProxy().DownloadMap(mapFileName); string title = map.title; int width = map.width; int height = map.height; VTankObject.Tile[] tiles = map.tileData; Tile[] realTiles = new Tile[tiles.Length]; Map newMap = new Map(title, mapFileName, (uint)width, (uint)height); int size = width * height; for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { VTankObject.Tile relevantTile = tiles[y * width + x]; newMap.SetTile((uint)x, (uint)y, new Tile( (uint)relevantTile.id, (ushort)relevantTile.objectId, (ushort)relevantTile.eventId, relevantTile.passable, (ushort)relevantTile.height, (ushort)relevantTile.type, (ushort)relevantTile.effect)); } } List<int> buf = new List<int>(); for (int i = 0; i < map.supportedGameModes.Length; i++) { buf.Add(map.supportedGameModes[i]); } newMap.SetGameModes(buf); return newMap; }