public static ContractTable ReadFromDat() { // Check the FileCache so we don't need to hit the FileSystem repeatedly if (DatManager.PortalDat.FileCache.ContainsKey(CONTRACT_TABLE_ID)) { return((ContractTable)DatManager.PortalDat.FileCache[CONTRACT_TABLE_ID]); } else { DatReader datReader = DatManager.PortalDat.GetReaderForFile(CONTRACT_TABLE_ID); ContractTable obj = new ContractTable(); obj.Id = datReader.ReadUInt32(); ushort num_contracts = datReader.ReadUInt16(); ushort table_size = datReader.ReadUInt16(); // We don't need this since C# handles it's own memory for (ushort i = 0; i < num_contracts; i++) { uint key = datReader.ReadUInt32(); Contract value = Contract.Read(datReader); obj.Contracts.Add(key, value); } DatManager.PortalDat.FileCache[CONTRACT_TABLE_ID] = obj; return(obj); } }
public static ReplaceObjectHook ReadHookType(DatReader datReader) { ReplaceObjectHook r = new ReplaceObjectHook(); AnimationPartChange ao = new AnimationPartChange(); ao.PartIndex = (byte)datReader.ReadUInt16(); ao.PartID = datReader.ReadUInt16(); r.APChange = ao; return(r); }
public static BSPPortal ReadPortal(DatReader datReader, BSPType treeType) { BSPPortal obj = new BSPPortal(); obj.Type = 0x504F5254; // PORT obj.SplittingPlane = Plane.Read(datReader); obj.PosNode = BSPNode.Read(datReader, treeType); obj.NegNode = BSPNode.Read(datReader, treeType); if (treeType == BSPType.Drawing) { obj.Sphere = CSphere.Read(datReader); uint numPolys = datReader.ReadUInt32(); uint numPortals = datReader.ReadUInt32(); for (uint i = 0; i < numPolys; i++) { obj.InPolys.Add(datReader.ReadUInt16()); } for (uint i = 0; i < numPortals; i++) { obj.InPortals.Add(PortalPoly.Read(datReader)); } } return(obj); }
} = new List <ushort>(); // List of PolygonIds public static BSPNode Read(DatReader datReader, BSPType treeType) { BSPNode obj = new BSPNode(); obj.Type = datReader.ReadUInt32(); switch (obj.Type) { case PORT: return(BSPPortal.ReadPortal(datReader, treeType)); case LEAF: return(BSPLeaf.ReadLeaf(datReader, treeType)); } obj.SplittingPlane = Plane.Read(datReader); switch (obj.Type) { case BPnn: case BPIn: obj.PosNode = BSPNode.Read(datReader, treeType); break; case BpIN: case BpnN: obj.NegNode = BSPNode.Read(datReader, treeType); break; case BPIN: case BPnN: obj.PosNode = BSPNode.Read(datReader, treeType); obj.NegNode = BSPNode.Read(datReader, treeType); break; } if (treeType == BSPType.Cell) { return(obj); } obj.Sphere = CSphere.Read(datReader); if (treeType == BSPType.Physics) { return(obj); } uint numPolys = datReader.ReadUInt32(); for (uint i = 0; i < numPolys; i++) { obj.InPolys.Add(datReader.ReadUInt16()); } return(obj); }
public static CellStruct Read(DatReader datReader) { CellStruct obj = new CellStruct(); uint numPolygons = datReader.ReadUInt32(); uint numPhysicsPolygons = datReader.ReadUInt32(); uint numPortals = datReader.ReadUInt32(); obj.VertexArray = CVertexArray.Read(datReader); for (uint i = 0; i < numPolygons; i++) { ushort poly_id = datReader.ReadUInt16(); obj.Polygons.Add(poly_id, Polygon.Read(datReader)); } for (uint i = 0; i < numPortals; i++) { obj.Portals.Add(datReader.ReadUInt16()); } datReader.AlignBoundary(); obj.CellBSP = BSPTree.Read(datReader, BSPType.Cell); for (uint i = 0; i < numPhysicsPolygons; i++) { ushort poly_id = datReader.ReadUInt16(); obj.PhysicsPolygons.Add(poly_id, Polygon.Read(datReader)); } obj.PhysicsBSP = BSPTree.Read(datReader, BSPType.Physics); uint hasDrawingBSP = datReader.ReadUInt32(); if (hasDrawingBSP != 0) { obj.DrawingBSP = BSPTree.Read(datReader, BSPType.Drawing); } datReader.AlignBoundary(); return(obj); }
/// <summary> /// Loads the structure of a CellLandblock from the client_cell.dat /// </summary> /// <param name="landblockId">Either a full int of the landblock or just the short of the cell itself</param> /// <returns></returns> public static CellLandblock ReadFromDat(uint landblockId) { CellLandblock c = new CellLandblock(); // Check if landblockId is a full dword. We just need the hiword for the landblockId if ((landblockId >> 16) != 0) { landblockId = landblockId >> 16; } // The file index is CELL + 0xFFFF. e.g. a cell of 1234, the file index would be 0x1234FFFF. uint landblockFileIndex = (landblockId << 16) + 0xFFFF; // Check the FileCache so we don't need to hit the FileSystem repeatedly if (DatManager.CellDat.FileCache.ContainsKey(landblockFileIndex)) { return((CellLandblock)DatManager.CellDat.FileCache[landblockFileIndex]); } else { if (DatManager.CellDat.AllFiles.ContainsKey(landblockFileIndex)) { DatReader datReader = DatManager.CellDat.GetReaderForFile(landblockFileIndex); uint cellId = datReader.ReadUInt32(); uint hasObjects = datReader.ReadUInt32(); if (hasObjects == 1) { c.HasObjects = true; } // Read in the terrain. 9x9 so 81 records. for (int i = 0; i < 81; i++) { uint terrain = datReader.ReadUInt16(); c.Terrain.Add(terrain); } // Read in the height. 9x9 so 81 records for (int i = 0; i < 81; i++) { ushort height = datReader.ReadByte(); c.Height.Add(height); } } // Store this object in the FileCache DatManager.CellDat.FileCache[landblockFileIndex] = c; return(c); } }
public static BSPLeaf ReadLeaf(DatReader datReader, BSPType treeType) { BSPLeaf obj = new BSPLeaf(); obj.Type = 0x4C454146; // LEAF obj.LeafIndex = datReader.ReadInt32(); if (treeType == BSPType.Physics) { obj.Solid = datReader.ReadInt32(); // Note that if Solid is equal to 0, these values will basically be null. Still read them, but they don't mean anything. obj.Sphere = CSphere.Read(datReader); uint numPolys = datReader.ReadUInt32(); for (uint i = 0; i < numPolys; i++) { obj.InPolys.Add(datReader.ReadUInt16()); } } return(obj); }
public static SpellComponentsTable ReadFromDat() { // Check the FileCache so we don't need to hit the FileSystem repeatedly if (DatManager.PortalDat.FileCache.ContainsKey(0x0E00000F)) { return((SpellComponentsTable)DatManager.PortalDat.FileCache[0x0E00000F]); } else { // Create the datReader for the proper file DatReader datReader = DatManager.PortalDat.GetReaderForFile(0x0E00000F); SpellComponentsTable comps = new SpellComponentsTable(); comps.FileId = datReader.ReadUInt32(); uint numComps = datReader.ReadUInt16(); // Should be 163 or 0xA3 datReader.AlignBoundary(); // loop through the entire file... for (uint i = 0; i < numComps; i++) { SpellComponentBase newComp = new SpellComponentBase(); uint compId = datReader.ReadUInt32(); newComp.Name = datReader.ReadObfuscatedString(); datReader.AlignBoundary(); newComp.Category = datReader.ReadUInt32(); newComp.Icon = datReader.ReadUInt32(); newComp.Type = datReader.ReadUInt32(); newComp.Gesture = datReader.ReadUInt32(); newComp.Time = datReader.ReadSingle(); newComp.Text = datReader.ReadObfuscatedString(); datReader.AlignBoundary(); newComp.CDM = datReader.ReadSingle(); comps.SpellComponents.Add(compId, newComp); } DatManager.PortalDat.FileCache[0x0E00000F] = comps; return(comps); } }
public static ObjDesc ReadFromDat(ref DatReader datReader) { ObjDesc od = new ObjDesc(); datReader.AlignBoundary(); // Align to the DWORD boundary before and after the ObjDesc datReader.ReadByte(); // ObjDesc always starts with 11. int numPalettes = datReader.ReadByte(); int numTextureMapChanges = datReader.ReadByte(); int numAnimPartChanges = datReader.ReadByte(); for (int k = 0; k < numPalettes; k++) { // TODO - This isn't actually used anywhere in the CharGen system, so let's find a test care to make sure this is accurate! SubPalette subpalette = new SubPalette(); subpalette.SubID = datReader.ReadUInt16(); subpalette.SubID = datReader.ReadUInt16(); subpalette.NumColors = Convert.ToUInt16(datReader.ReadByte()); od.SubPalettes.Add(subpalette); } for (int k = 0; k < numTextureMapChanges; k++) { TextureMapChange texturechange = new TextureMapChange(); texturechange.PartIndex = datReader.ReadByte(); texturechange.OldTexture = datReader.ReadUInt16(); texturechange.NewTexture = datReader.ReadUInt16(); od.TextureChanges.Add(texturechange); } for (int k = 0; k < numAnimPartChanges; k++) { AnimationPartChange apchange = new AnimationPartChange(); apchange.PartIndex = datReader.ReadByte(); apchange.PartID = datReader.ReadUInt16(); if (apchange.PartID == 0x8000) // To be honest, I'm not quite sure WHAT this is/means, but the math works out { apchange.PartID = datReader.ReadUInt16(); } apchange.PartID += 0x01000000u; // convert to full uint value od.AnimPartChanges.Add(apchange); } datReader.AlignBoundary(); // Align to the DWORD boundary before and after the ObjDesc return(od); }
} = new Dictionary <uint, CloSubPalEffect>(); // uint is a non-zero index public static ClothingTable ReadFromDat(uint fileId) { ClothingTable ct = new ClothingTable(); DatReader datReader = DatManager.PortalDat.GetReaderForFile(fileId); ct.Id = datReader.ReadUInt32(); uint numClothingEffects = datReader.ReadUInt16(); datReader.Offset += 2; for (uint i = 0; i < numClothingEffects; i++) { ClothingBaseEffect cb = new ClothingBaseEffect(); cb.SetupModel = datReader.ReadUInt32(); int numObjectEffects = datReader.ReadInt32(); for (int j = 0; j < numObjectEffects; j++) { CloObjectEffect cloObjEffect = new CloObjectEffect(); cloObjEffect.Index = datReader.ReadUInt32(); cloObjEffect.ModelId = datReader.ReadUInt32(); uint numTextureEffects = datReader.ReadUInt32(); for (uint k = 0; k < numTextureEffects; k++) { CloTextureEffect cloTexEffect = new CloTextureEffect(); cloTexEffect.OldTexture = datReader.ReadUInt32(); cloTexEffect.NewTexture = datReader.ReadUInt32(); cloObjEffect.CloTextureEffects.Add(cloTexEffect); } cb.CloObjectEffects.Add(cloObjEffect); } ct.ClothingBaseEffects.Add(cb.SetupModel, cb); } ushort numSubPalEffects = datReader.ReadUInt16(); for (uint i = 0; i < numSubPalEffects; i++) { datReader.AlignBoundary(); CloSubPalEffect cloSubPalEffect = new CloSubPalEffect(); uint subPalIdx = datReader.ReadUInt32(); cloSubPalEffect.Icon = datReader.ReadUInt32(); uint numPalettes = datReader.ReadUInt32(); for (uint j = 0; j < numPalettes; j++) { CloSubPalette cloSubPalette = new CloSubPalette(); uint length = datReader.ReadUInt32(); for (uint k = 0; k < length; k++) { CloSubPalleteRange range = new CloSubPalleteRange(); range.Offset = datReader.ReadUInt32(); range.NumColors = datReader.ReadUInt32(); cloSubPalette.Ranges.Add(range); } cloSubPalette.PaletteSet = datReader.ReadUInt32(); cloSubPalEffect.CloSubPalettes.Add(cloSubPalette); } ct.ClothingSubPalEffects.Add(subPalIdx, cloSubPalEffect); } return(ct); }
} = new List <Stab>(); // List of objects in the cell and their positions /// <summary> /// Load the EnvCell (Dungeon/Interior Block) from the client_cell.dat /// </summary> /// <param name="landblockId">The full int32/dword landblock value as reported by the @loc command (e.g. 0x12345678)</param> /// <returns></returns> public static EnvCell ReadFromDat(uint landblockId) { // Check the FileCache so we don't need to hit the FileSystem repeatedly if (DatManager.CellDat.FileCache.ContainsKey(landblockId)) { return((EnvCell)DatManager.CellDat.FileCache[landblockId]); } else { EnvCell c = new EnvCell(); if (DatManager.CellDat.AllFiles.ContainsKey(landblockId)) { DatReader datReader = DatManager.CellDat.GetReaderForFile(landblockId); c.CellId = datReader.ReadUInt32(); c.Bitfield = datReader.ReadUInt32(); datReader.Offset += 4; // Skip ahead 4 bytes, because this is the CellId. Again. Twice. byte numTextures = datReader.ReadByte(); // Note that "portal" in this context does not refer to the swirly pink/purple thing, its basically connecting cells byte numPortals = datReader.ReadByte(); // I believe this is what cells can be seen from this one. So the engine knows what else it needs to load/draw. ushort numVisibleBlocks = datReader.ReadUInt16(); // Read what textures are used in this cell for (uint i = 0; i < numTextures; i++) { c.Textures.Add(0x08000000u + datReader.ReadUInt16()); // these are stored in the dat as short vals, so we'll make them a full dword } c.EnvironmentId = (0x0D000000u + datReader.ReadUInt16()); c.CellStructure = datReader.ReadUInt16(); c.Position = new Position(); c.Position.LandblockId = new LandblockId(landblockId); c.Position.PositionX = datReader.ReadSingle(); c.Position.PositionY = datReader.ReadSingle(); c.Position.PositionZ = datReader.ReadSingle(); c.Position.RotationW = datReader.ReadSingle(); c.Position.RotationX = datReader.ReadSingle(); c.Position.RotationY = datReader.ReadSingle(); c.Position.RotationZ = datReader.ReadSingle(); for (uint i = 0; i < numPortals; i++) { CellPortal cp = new CellPortal(); cp.Flags = datReader.ReadUInt16(); cp.EnvironmentId = datReader.ReadUInt16(); cp.OtherCellId = datReader.ReadUInt16(); cp.OtherPortalId = datReader.ReadUInt16(); cp.ExactMatch = (byte)(cp.Flags & 1); cp.PortalSide = (byte)((cp.Flags >> 1) & 1); c.CellPortals.Add(cp); } for (uint i = 0; i < numVisibleBlocks; i++) { c.VisibleBlocks.Add(datReader.ReadUInt16()); } uint numObjects = datReader.ReadUInt32(); for (uint i = 0; i < numObjects; i++) { Stab s = new Stab(); s.Model = datReader.ReadUInt32(); s.Position.LandblockId = new LandblockId(landblockId); s.Position.PositionX = datReader.ReadSingle(); s.Position.PositionY = datReader.ReadSingle(); s.Position.PositionZ = datReader.ReadSingle(); s.Position.RotationW = datReader.ReadSingle(); s.Position.RotationX = datReader.ReadSingle(); s.Position.RotationY = datReader.ReadSingle(); s.Position.RotationZ = datReader.ReadSingle(); c.StabList.Add(s); } } // Store this object in the FileCache DatManager.CellDat.FileCache[landblockId] = c; return(c); } }
public static SpellTable ReadFromDat() { // Check the FileCache so we don't need to hit the FileSystem repeatedly if (DatManager.PortalDat.FileCache.ContainsKey(0x0E00000E)) { return((SpellTable)DatManager.PortalDat.FileCache[0x0E00000E]); } else { // Create the datReader for the proper file DatReader datReader = DatManager.PortalDat.GetReaderForFile(0x0E00000E); SpellTable spells = new SpellTable(); spells.FileId = datReader.ReadUInt32(); uint spellCount = datReader.ReadUInt16(); spells.SpellBaseHash = datReader.ReadUInt16(); for (uint i = 0; i < spellCount; i++) { SpellBase newSpell = new SpellBase(); uint spellId = datReader.ReadUInt32(); newSpell.Name = datReader.ReadObfuscatedString(); datReader.AlignBoundary(); newSpell.Desc = datReader.ReadObfuscatedString(); datReader.AlignBoundary(); newSpell.School = (MagicSchool)datReader.ReadUInt32(); newSpell.Icon = datReader.ReadUInt32(); newSpell.Category = datReader.ReadUInt32(); newSpell.Bitfield = datReader.ReadUInt32(); newSpell.BaseMana = datReader.ReadUInt32(); newSpell.BaseRangeConstant = datReader.ReadSingle(); newSpell.BaseRangeMod = datReader.ReadSingle(); newSpell.Power = datReader.ReadUInt32(); newSpell.SpellEconomyMod = datReader.ReadSingle(); newSpell.FormulaVersion = datReader.ReadUInt32(); newSpell.ComponentLoss = datReader.ReadUInt32(); newSpell.MetaSpellType = (SpellType)datReader.ReadUInt32(); newSpell.MetaSpellId = datReader.ReadUInt32(); switch (newSpell.MetaSpellType) { case SpellType.Enchantment: case SpellType.FellowEnchantment: { newSpell.Duration = datReader.ReadDouble(); newSpell.DegradeModifier = datReader.ReadSingle(); newSpell.DegradeLimit = datReader.ReadSingle(); break; } case SpellType.PortalSummon: { newSpell.PortalLifetime = datReader.ReadDouble(); break; } } // Components : Load them first, then decrypt them. More efficient to hash all at once. List <uint> rawComps = new List <uint>(); for (uint j = 0; j < 8; j++) { uint comp = datReader.ReadUInt32(); // We will only add the comp if it is valid if (comp > 0) { rawComps.Add(comp); } } // Get the decryped component values newSpell.Formula = DecryptFormula(rawComps, newSpell.Name, newSpell.Desc); newSpell.CasterEffect = datReader.ReadUInt32(); newSpell.TargetEffect = datReader.ReadUInt32(); newSpell.FizzleEffect = datReader.ReadUInt32(); newSpell.RecoveryInterval = datReader.ReadDouble(); newSpell.RecoveryAmount = datReader.ReadSingle(); newSpell.DisplayOrder = datReader.ReadUInt32(); newSpell.NonComponentTargetType = datReader.ReadUInt32(); newSpell.ManaMod = datReader.ReadUInt32(); spells.Spells.Add(spellId, newSpell); } DatManager.PortalDat.FileCache[0x0E00000E] = spells; return(spells); } }
public static GfxObj ReadFromDat(uint fileId) { // Check the FileCache so we don't need to hit the FileSystem repeatedly if (DatManager.PortalDat.FileCache.ContainsKey(fileId)) { return((GfxObj)DatManager.PortalDat.FileCache[fileId]); } else { DatReader datReader = DatManager.PortalDat.GetReaderForFile(fileId); GfxObj obj = new GfxObj(); obj.Id = datReader.ReadUInt32(); obj.Flags = datReader.ReadUInt32(); short num_surfaces = datReader.ReadPackedByte(); for (short i = 0; i < num_surfaces; i++) { obj.Surfaces.Add(datReader.ReadUInt32()); } obj.VertexArray = CVertexArray.Read(datReader); // Has Physics if ((obj.Flags & 1) > 0) { short num_physics_polygons = datReader.ReadPackedByte(); for (ushort i = 0; i < num_physics_polygons; i++) { ushort poly_id = datReader.ReadUInt16(); obj.PhysicsPolygons.Add(poly_id, Polygon.Read(datReader)); } obj.PhysicsBSP = BSPTree.Read(datReader, BSPType.Physics); } obj.SortCenter = PositionExtensions.ReadPositionFrame(datReader); // Has Drawing if ((obj.Flags & 2) > 0) { short num_polygons = datReader.ReadPackedByte(); for (ushort i = 0; i < num_polygons; i++) { ushort poly_id = datReader.ReadUInt16(); obj.Polygons.Add(poly_id, Polygon.Read(datReader)); } obj.DrawingBSP = BSPTree.Read(datReader, BSPType.Drawing); } if ((obj.Flags & 8) > 0) { obj.DIDDegrade = datReader.ReadUInt32(); } // Store this object in the FileCache DatManager.PortalDat.FileCache[fileId] = obj; return(obj); } }
} = new Dictionary <uint, CloSubPalEffect>(); // uint is a non-zero index public static ClothingTable ReadFromDat(uint fileId) { // Check the FileCache so we don't need to hit the FileSystem repeatedly if (DatManager.PortalDat.FileCache.ContainsKey(fileId)) { return((ClothingTable)DatManager.PortalDat.FileCache[fileId]); } else { ClothingTable ct = new ClothingTable(); DatReader datReader = DatManager.PortalDat.GetReaderForFile(fileId); ct.Id = datReader.ReadUInt32(); uint numClothingEffects = datReader.ReadUInt16(); datReader.Offset += 2; for (uint i = 0; i < numClothingEffects; i++) { ClothingBaseEffect cb = new ClothingBaseEffect(); cb.SetupModel = datReader.ReadUInt32(); int numObjectEffects = datReader.ReadInt32(); for (int j = 0; j < numObjectEffects; j++) { CloObjectEffect cloObjEffect = new CloObjectEffect(); cloObjEffect.Index = datReader.ReadUInt32(); cloObjEffect.ModelId = datReader.ReadUInt32(); uint numTextureEffects = datReader.ReadUInt32(); for (uint k = 0; k < numTextureEffects; k++) { CloTextureEffect cloTexEffect = new CloTextureEffect(); cloTexEffect.OldTexture = datReader.ReadUInt32(); cloTexEffect.NewTexture = datReader.ReadUInt32(); cloObjEffect.CloTextureEffects.Add(cloTexEffect); } cb.CloObjectEffects.Add(cloObjEffect); } ct.ClothingBaseEffects.Add(cb.SetupModel, cb); } ushort numSubPalEffects = datReader.ReadUInt16(); for (uint i = 0; i < numSubPalEffects; i++) { datReader.AlignBoundary(); CloSubPalEffect cloSubPalEffect = new CloSubPalEffect(); uint subPalIdx = datReader.ReadUInt32(); cloSubPalEffect.Icon = datReader.ReadUInt32(); uint numPalettes = datReader.ReadUInt32(); for (uint j = 0; j < numPalettes; j++) { CloSubPalette cloSubPalette = new CloSubPalette(); uint length = datReader.ReadUInt32(); for (uint k = 0; k < length; k++) { CloSubPalleteRange range = new CloSubPalleteRange(); range.Offset = datReader.ReadUInt32(); range.NumColors = datReader.ReadUInt32(); cloSubPalette.Ranges.Add(range); } cloSubPalette.PaletteSet = datReader.ReadUInt32(); cloSubPalEffect.CloSubPalettes.Add(cloSubPalette); } ct.ClothingSubPalEffects.Add(subPalIdx, cloSubPalEffect); } // Store this object in the FileCache DatManager.PortalDat.FileCache[fileId] = ct; return(ct); } }
public static CLandblockInfo ReadFromDat(uint landblockId) { // Check if landblockId is a full dword. We just need the hiword for the landblockId if ((landblockId >> 16) != 0) { landblockId = landblockId >> 16; } // The file index is CELL + 0xFFFF. e.g. a cell of 1234, the file index would be 0x1234FFFE. uint landblockFileIndex = (landblockId << 16) + 0xFFFE; // Check the FileCache so we don't need to hit the FileSystem repeatedly if (DatManager.CellDat.FileCache.ContainsKey(landblockFileIndex)) { return((CLandblockInfo)DatManager.CellDat.FileCache[landblockFileIndex]); } else { CLandblockInfo c = new CLandblockInfo(); if (DatManager.CellDat.AllFiles.ContainsKey(landblockFileIndex)) { DatReader datReader = DatManager.CellDat.GetReaderForFile(landblockFileIndex); uint file_id = datReader.ReadUInt32(); c.NumCells = datReader.ReadUInt32(); uint num_objects = datReader.ReadUInt32(); for (uint i = 0; i < num_objects; i++) { c.ObjectIds.Add(datReader.ReadUInt32()); Position objPosition = new Position(); objPosition.PositionX = datReader.ReadSingle(); objPosition.PositionY = datReader.ReadSingle(); objPosition.PositionZ = datReader.ReadSingle(); objPosition.RotationW = datReader.ReadSingle(); objPosition.RotationX = datReader.ReadSingle(); objPosition.RotationY = datReader.ReadSingle(); objPosition.RotationZ = datReader.ReadSingle(); c.ObjectFrames.Add(objPosition); } ushort num_buildings = datReader.ReadUInt16(); c.PackMask = datReader.ReadUInt16(); for (uint i = 0; i < num_buildings; i++) { BuildInfo b = new BuildInfo(); b.ModelId = datReader.ReadUInt32(); // position b.Frame.PositionX = datReader.ReadSingle(); b.Frame.PositionY = datReader.ReadSingle(); b.Frame.PositionZ = datReader.ReadSingle(); b.Frame.RotationW = datReader.ReadSingle(); b.Frame.RotationX = datReader.ReadSingle(); b.Frame.RotationY = datReader.ReadSingle(); b.Frame.RotationZ = datReader.ReadSingle(); b.NumLeaves = datReader.ReadUInt32(); uint num_portals = datReader.ReadUInt32(); for (uint j = 0; j < num_portals; j++) { CBldPortal cbp = new CBldPortal(); cbp.Flags = datReader.ReadUInt16(); cbp.ExactMatch = (ushort)(cbp.Flags & 1); cbp.PortalSide = (ushort)((cbp.Flags >> 1) & 1); cbp.OtherCellId = (landblockId << 16) + datReader.ReadUInt16(); cbp.OtherPortalId = (landblockId << 16) + datReader.ReadUInt16(); ushort num_stabs = datReader.ReadUInt16(); for (ushort k = 0; k < num_stabs; k++) { cbp.StabList.Add((landblockId << 16) + datReader.ReadUInt16()); } datReader.AlignBoundary(); b.Portals.Add(cbp); } c.Buildings.Add(b); } if ((c.PackMask & 1) == 1) { ushort num_restiction_table = datReader.ReadUInt16(); c.UnknownShort = datReader.ReadUInt16(); // seems to always be 0x0008 ... packed val? for (ushort i = 0; i < num_restiction_table; i++) { RestrictionTable r = new RestrictionTable(); r.Landblock = datReader.ReadUInt32(); r.Iid = datReader.ReadUInt32(); c.Restriction_table.Add(r); } } // Store this object in the FileCache DatManager.CellDat.FileCache[landblockFileIndex] = c; } return(c); } }