using System; using System.Collections.Generic; using System.IO; using System.Numerics; namespace ACE.DatLoader.FileTypes { /// /// A landblock is divided into 8 x 8 tiles, which means 9 x 9 vertices reporesenting those tiles. /// (Draw a grid of 9x9 dots; connect those dots to form squares; you'll have 8x8 squares) /// It is also divided in 192x192 units (this is the x and the y) /// /// 0,0 is the bottom left corner of the landblock. /// /// Height 0-9 is Western most edge. 10-18 is S-to-N strip just to the East. And so on. /// /// The fileId is CELL + 0xFFFF. e.g. a cell of 1234, the file index would be 0x1234FFFF. /// /// /// Very special thanks to David Simpson for his early work on reading the cell.dat. Even bigger thanks for his documentation of it! /// [DatFileType(DatFileType.LandBlock)] public class CellLandblock : FileType { /// /// Places in the inland sea, for example, are false. Should denote presence of xxxxFFFE (where xxxx is the cell). /// public bool HasObjects { get; set; } public List Terrain { get; } = new List(); public static ushort TerrainMask_Road = 0x3; public static ushort TerrainMask_Type = 0x7C; public static ushort TerrainMask_Scenery = 0XF800; public static byte TerrainShift_Road = 0; public static byte TerrainShift_Type = 2; public static byte TerrainShift_Scenery = 11; /// /// Z value in-game is double this height. /// public List Height { get; } = new List(); public override void Unpack(BinaryReader reader) { Id = reader.ReadUInt32(); uint hasObjects = reader.ReadUInt32(); if (hasObjects == 1) HasObjects = true; // Read in the terrain. 9x9 so 81 records. for (int i = 0; i < 81; i++) { var terrain = reader.ReadUInt16(); Terrain.Add(terrain); } // Read in the height. 9x9 so 81 records for (int i = 0; i < 81; i++) { var height = reader.ReadByte(); Height.Add(height); } reader.AlignBoundary(); } public static ushort GetRoad(ushort terrain) { return GetTerrain(terrain, TerrainMask_Road, TerrainShift_Road); } public static ushort GetType(ushort terrain) { return GetTerrain(terrain, TerrainMask_Type, TerrainShift_Type); } public static ushort GetScenery(ushort terrain) { return GetTerrain(terrain, TerrainMask_Scenery, TerrainShift_Scenery); } public static ushort GetTerrain(ushort terrain, ushort mask, byte shift) { return (ushort)((terrain & mask) >> shift); } } }