public Vector3 GetOffset(Position pos) { var blockOffset = LandDefs.GetBlockOffset(ObjCellID, pos.ObjCellID); var globalOffset = blockOffset + pos.Frame.Origin - Frame.Origin; return(globalOffset); }
public void init_buildings() { if (Info == null || SideCellCount != 8) { return; } uint maxSize = 0, stabNum = 0; foreach (var info in Info.Buildings) { var building = BuildingObj.makeBuilding(info.ModelId, info.Portals, info.NumLeaves); var position = new Position(ID, new AFrame(info.Frame)); var outside = LandDefs.AdjustToOutside(position); var cell = get_landcell(position.ObjCellID); if (cell == null) { continue; } building.set_initial_frame(position.Frame); // hack building.PartArray.Parts[0].Pos = position; building.Position = position; cell.Building = building; building.add_to_cell(cell); // SortCell? Buildings.Add(building); building.add_to_stablist(ref StabList, ref maxSize, ref stabNum); } }
public Vector3 LocalToGlobal(Position pos, Vector3 point) { var cellOffset = pos.Frame.LocalToGlobal(point); var blockOffset = LandDefs.GetBlockOffset(ObjCellID, pos.ObjCellID); return(blockOffset + cellOffset); }
public void init_static_objs() { if (SideCellCount != 8) { return; } if (StaticObjects.Count > 0) { adjust_scene_obj_height(); foreach (var obj in StaticObjects) { if (!obj.is_completely_visible()) { obj.calc_cross_cells_static(); } } } else if (Info != null) { foreach (var info in Info.Objects) { var obj = PhysicsObj.makeObject(info.Id, 0, false); obj.DatObject = true; var position = new Position(ID, new AFrame(info.Frame)); var outside = LandDefs.AdjustToOutside(position); var cell = get_landcell(position.ObjCellID); if (cell == null) { //Console.WriteLine($"Landblock {ID:X8} - failed to spawn static object {info.Id:X8}"); obj.DestroyObject(); continue; } obj.add_obj_to_cell(cell, position.Frame); add_static_object(obj); } if (Info.RestrictionTables != null) { foreach (var kvp in Info.RestrictionTables) { var lcoord = LandDefs.gid_to_lcoord(kvp.Key); if (lcoord == null) { continue; } var idx = ((int)lcoord.Value.Y & 7) + ((int)lcoord.Value.X & 7) * SideCellCount; LandCells[idx].RestrictionObj = kvp.Value; } } } if (UseSceneFiles) { get_land_scenes(); } }
/// <summary>s /// Gets the landcell from a landblock. If the cell is an indoor cell and hasn't been loaded, it will be loaded.<para /> /// This function is thread safe /// </summary> public static ObjCell get_landcell(ulong iBlockCellID) { /*if ((iBlockCellID | 0xFFFF) == 0x1D9FFFF) * { * Console.WriteLine(System.Environment.StackTrace); * var debug = true; * }*/ //Console.WriteLine($"get_landcell({blockCellID:X8}"); var landblock = get_landblock(iBlockCellID); if (landblock == null) { return(null); } var cellID = iBlockCellID & 0xFFFF; ObjCell cell = null; // outdoor cells if (cellID < 0x100) { var lcoord = LandDefs.gid_to_lcoord((uint)iBlockCellID, false); if (lcoord == null) { return(null); } var landCellIdx = ((int)lcoord.Value.Y % 8) + ((int)lcoord.Value.X % 8) * landblock.SideCellCount; landblock.LandCells.TryGetValue(landCellIdx, out cell); } // indoor cells else { if (landblock.LandCells.TryGetValue((int)cellID, out cell)) { return(cell); } lock (landblock.LandCellMutex) { if (landblock.LandCells.TryGetValue((int)cellID, out cell)) { return(cell); } cell = DBObj.GetEnvCell((uint)iBlockCellID); cell.CurLandblock = landblock; landblock.LandCells.TryAdd((int)cellID, cell); var envCell = (EnvCell)cell; envCell.PostInit(); } } return(cell); }
public float calc_water_depth(uint blockCellID, Vector3 point) { var cellID = blockCellID & 0xFFFF; var cellOffset = cellID - 1; uint cellX = 0, cellY = cellID; if (LandDefs.inbound_valid_cellid(cellID) && cellID < 0x100) { cellX = cellOffset / 8; cellY = cellOffset & 7; } uint terrainIdx; uint surfOffset = 0; // missing fpu instructions if (point.X <= point.Y) { terrainIdx = (cellY + 8 * cellX + cellX + 1); if (point.X == point.Y) { terrainIdx--; } } else if (point.X >= point.Y) { terrainIdx = cellY + 8 * (cellX + 1) + cellX + 1; } else // ? { terrainIdx = 8 * cellX + 10; surfOffset = (cellX + cellY) * 2; } var column = Terrain[(int)terrainIdx & 0xFF]; var hasWater = SurfChar[column + (int)surfOffset & 0x7F]; if (hasWater != 0) { if (hasWater == 1) { return(0.44999999f); } else { return(0); } } else { return(0.1f); } }
public LandCell get_landcell(uint cellID) { var landblock = get_landblock(cellID); if (landblock == null) { return(null); } var lcoord = LandDefs.gid_to_lcoord(cellID); var landCellIdx = ((int)lcoord.Value.Y % 8) + ((int)lcoord.Value.X % 8) * landblock.SideCellCount; return(landblock.LandCells[landCellIdx]); }
public Landblock(CellLandblock landblock) : base(landblock) { Init(); ID = landblock.Id; BlockInfoExists = landblock.HasObjects; if (BlockInfoExists) { Info = (LandblockInfo)DBObj.Get(new QualifiedDataID(2, ID - 1)); } BlockCoord = LandDefs.blockid_to_lcoord(landblock.Id).Value; _landblock = landblock; get_land_limits(); }
public LandCell get_landcell(uint cellID) { var lcoord = LandDefs.gid_to_lcoord(cellID).Value; var idx = ((int)lcoord.Y & 7) + ((int)lcoord.X & 7) * SideCellCount; if (LandCells[idx].ID == cellID) { return((LandCell)LandCells[idx]); } else { return(null); } }
public void GetCellRotation(uint landblockID, uint x, uint y, ref bool singleTextureCell, ref uint surfNum, ref LandDefs.Rotation rotation) { var lcoord = LandDefs.blockid_to_lcoord(landblockID); var globalCellX = (int)(lcoord.Value.X + x); var globalCellY = (int)(lcoord.Value.Y + y); // no palette shift // SW / SE / NE / NW var i = (int)(LandDefs.VertexDim * x + y); var terrain = Terrain[i]; var t1 = (terrain & 0x7F) >> 2; var r1 = terrain & 3; var j = (int)(LandDefs.VertexDim * (x + 1) + y); var terrain2 = Terrain[j]; var t2 = (terrain2 & 0x7F) >> 2; var r2 = terrain2 & 3; var terrain3 = Terrain[j + 1]; var t3 = (terrain3 & 0x7F) >> 2; var r3 = terrain3 & 3; var terrain4 = Terrain[i + 1]; var t4 = (terrain4 & 0x7F) >> 2; var r4 = terrain4 & 3; /*Console.WriteLine($"LandblockStruct.GetCellRotation({landblockID:X8}, x:{x}, y:{y})"); * Console.WriteLine($"I1: {i}, I2: {j}, I3: {j+1}, I4: {i+1}"); * if (r1 != 0 || r2 != 0 || r3 != 0 || r4 != 0) * Console.WriteLine($"R1: {r1}, R2: {r2}, R3: {r3}, R4: {r4}"); * Console.WriteLine($"T1: {(LandDefs.TerrainType)t1}, T2: {(LandDefs.TerrainType)t2}, T3: {(LandDefs.TerrainType)t3}, T4: {(LandDefs.TerrainType)t4}");*/ var palCodes = new List <uint>(); palCodes.Add(GetPalCode(r1, r2, r3, r4, t1, t2, t3, t4)); // 0 //palCodes.Add(GetPalCode(r2, r3, r4, r1, t2, t3, t4, t1)); // 270 //palCodes.Add(GetPalCode(r3, r4, r1, r2, t3, t4, t1, t2)); // 180 //palCodes.Add(GetPalCode(r4, r1, r2, r3, t4, t1, t2, t3)); // 90 var singleRoadCell = r1 == r2 && r1 == r3 && r1 == r4; var singleTypeCell = t1 == t2 && t1 == t3 && t1 == t4; singleTextureCell = r1 != 0 ? singleRoadCell : singleRoadCell && singleTypeCell; var regionDesc = DatManager.PortalDat.RegionDesc; var minimizePal = true; LandSurf.Instance.SelectTerrain(globalCellX, globalCellY, ref surfNum, ref rotation, palCodes, 1, minimizePal); }
/// <summary> /// Gets the landcell from a landblock. If the cell is an indoor cell and hasn't been loaded, it will be loaded.<para /> /// This function is thread safe /// </summary> public static ObjCell get_landcell(uint blockCellID) { //Console.WriteLine($"get_landcell({blockCellID:X8}"); var landblock = get_landblock(blockCellID); if (landblock == null) { return(null); } var cellID = blockCellID & 0xFFFF; ObjCell cell = null; // outdoor cells if (cellID < 0x100) { var lcoord = LandDefs.gid_to_lcoord(blockCellID, false); if (lcoord == null) { return(null); } var landCellIdx = ((int)lcoord.Value.Y % 8) + ((int)lcoord.Value.X % 8) * landblock.SideCellCount; landblock.LandCells.TryGetValue(landCellIdx, out cell); } // indoor cells else { if (landblock.LandCells.TryGetValue((int)cellID, out cell)) { return(cell); } lock (landblock.LandCellMutex) { if (landblock.LandCells.TryGetValue((int)cellID, out cell)) { return(cell); } cell = DBObj.GetEnvCell(blockCellID); landblock.LandCells.TryAdd((int)cellID, cell); var envCell = (EnvCell)cell; envCell.PostInit(); } } return(cell); }
public Landblock(CellLandblock landblock) : base(landblock) { Init(); ID = landblock.Id; //Console.WriteLine("Loading landblock " + ID.ToString("X8")); BlockInfoExists = landblock.HasObjects; if (BlockInfoExists) { Info = DBObj.GetLandblockInfo(ID - 1); } BlockCoord = LandDefs.blockid_to_lcoord(landblock.Id).Value; _landblock = landblock; get_land_limits(); }
public static void add_all_outside_cells(Position position, int numSphere, List <Sphere> spheres, CellArray cellArray) { if (cellArray.AddedOutside) { return; } if (numSphere != 0) { foreach (var sphere in spheres) { var cellPoint = position.ObjCellID; var center = sphere.Center; if (!LandDefs.AdjustToOutside(ref cellPoint, ref center)) { break; } var point = new Vector2(); point.X = center.X - (float)Math.Floor(center.X / 24.0f) * 24.0f; point.Y = center.Y - (float)Math.Floor(center.Y / 24.0f) * 24.0f; var minRad = sphere.Radius; var maxRad = 24.0f - minRad; var lcoord = LandDefs.gid_to_lcoord(cellPoint); if (lcoord != null) { add_outside_cell(cellArray, lcoord.Value); check_add_cell_boundary(cellArray, point, lcoord.Value, minRad, maxRad); } } } else { if (!LandDefs.AdjustToOutside(position)) { return; } var lcoord = LandDefs.gid_to_lcoord(position.ObjCellID); if (lcoord != null) { add_outside_cell(cellArray, lcoord.Value); } } }
public override TransitionState FindEnvCollisions(Transition transition) { var transitState = check_entry_restrictions(transition); if (transitState != TransitionState.OK) { return(transitState); } var path = transition.SpherePath; var blockOffset = LandDefs.GetBlockOffset(path.CheckPos.ObjCellID, ID); var localPoint = transition.SpherePath.GlobalLowPoint - blockOffset; Polygon walkable = null; if (!find_terrain_poly(localPoint, ref walkable)) { return(transitState); } var objInfo = transition.ObjectInfo; if (get_block_water_type() == LandDefs.WaterType.EntirelyWater && !objInfo.State.HasFlag(ObjectInfoState.IsViewer) && !objInfo.Object.State.HasFlag(PhysicsState.Missile)) { return(TransitionState.Collided); } var waterDepth = get_water_depth(localPoint); var checkPos = new Sphere(path.GlobalSphere[0]); checkPos.Center -= LandDefs.GetBlockOffset(path.CheckPos.ObjCellID, ID); var result = objInfo.ValidateWalkable(checkPos, walkable.Plane, WaterType != LandDefs.WaterType.NotWater, waterDepth, transition, ID); if (result != TransitionState.OK && PhysicsObj.IsPicking) { Picker.PickResult.Type = PickType.LandCell; Picker.PickResult.ObjCell = this; Picker.PickResult.HitPoly = walkable; } return(result); }
public void init_static_objs() { if (SideCellCount != 8) { return; } if (StaticObjects.Count > 0) { adjust_scene_obj_height(); foreach (var obj in StaticObjects) { if (!obj.is_completely_visible()) { obj.calc_cross_cells_static(); } } } else if (Info != null) { foreach (var info in Info.Objects) { var obj = PhysicsObj.makeObject(info.Id, 0, false); obj.DatObject = true; var position = new Position(ID, new AFrame(info.Frame)); var outside = LandDefs.AdjustToOutside(position); var cell = get_landcell(position.ObjCellID); if (cell == null) { continue; } obj.add_obj_to_cell(cell, position.Frame); add_static_object(obj); } } if (UseSceneFiles) { get_land_scenes(); } }
/// <summary> /// Returns a list of outdoor cells within visible range of player /// </summary> public List <ObjCell> GetOutdoorCells(ObjCell cell) { // get cell x/y global offset var lcoord = LandDefs.get_outside_lcoord(cell.ID, PhysicsObj.Position.Frame.Origin.X, PhysicsObj.Position.Frame.Origin.Y).Value; // includes the origin cell var blockLength = (int)CellRadiusOutside * 2 + 1; var cells = new List <ObjCell>(/*blockLength * blockLength*/); var start = new Vector2(lcoord.X - CellRadiusOutside, lcoord.Y - CellRadiusOutside); var end = new Vector2(lcoord.X + CellRadiusOutside, lcoord.Y + CellRadiusOutside); for (var cellX = start.X; cellX <= end.X; cellX++) { for (var cellY = start.Y; cellY <= end.Y; cellY++) { var blockCellID = LandDefs.lcoord_to_gid(cellX, cellY); var _cell = LScape.get_landcell((uint)blockCellID); if (_cell == null) { continue; } cells.Add(_cell); // does this outdoor cell contain a building? // if so, add all of its cells var landCell = _cell as LandCell; if (landCell.has_building()) { //Console.WriteLine($"Found building in cell {landCell.ID:X8}"); var buildingCells = landCell.Building.get_building_cells(); //Console.WriteLine("# cells: " + buildingCells.Count); cells.AddRange(buildingCells); } } } return(cells); }
public static ObjCell get_landcell(uint blockCellID) { var landblock = get_landblock(blockCellID); if (landblock == null) { return(null); } var cellID = blockCellID & 0xFFFF; ObjCell cell = null; // outdoor cells if (cellID < 0x100) { var lcoord = LandDefs.gid_to_lcoord(blockCellID, false); if (lcoord == null) { return(null); } var landCellIdx = ((int)lcoord.Value.Y % 8) + ((int)lcoord.Value.X % 8) * landblock.SideCellCount; landblock.LandCells.TryGetValue(landCellIdx, out cell); } // indoor cells else { landblock.LandCells.TryGetValue((int)cellID, out cell); if (cell != null) { return(cell); } cell = (EnvCell)DBObj.Get(new QualifiedDataID(3, blockCellID)); landblock.LandCells.Add((int)cellID, cell); ((EnvCell)cell).build_visible_cells(); } return(cell); }
public static void add_all_outside_cells(int numParts, List <PhysicsPart> parts, CellArray cellArray, uint id) { if (cellArray.AddedOutside) { return; } cellArray.AddedOutside = true; if (numParts == 0) { return; } var min_x = 0; var min_y = 0; var max_x = 0; var max_y = 0; for (var i = 0; i < numParts; i++) { var curPart = parts[i]; var loc = new Position(curPart.Pos); if (!LandDefs.AdjustToOutside(loc)) { continue; } var _lcoord = LandDefs.gid_to_lcoord(loc.ObjCellID); if (_lcoord == null) { continue; } var lcoord = _lcoord.Value; var lx = (int)(((loc.ObjCellID & 0xFFFF) - 1) / 8); var ly = (int)(((loc.ObjCellID & 0xFFFF) - 1) % 8); for (var j = 0; j < numParts; j++) { var otherPart = parts[j]; if (otherPart == null) { continue; } // add if missing: otherPart.Always2D, checks degrades.degradeMode != 1 var bbox = new BBox(); bbox.LocalToGlobal(otherPart.GetBoundingBox(), otherPart.Pos, loc); var min_cx = (int)Math.Floor(bbox.Min.X / 24.0f); var min_cy = (int)Math.Floor(bbox.Min.Y / 24.0f); var max_cx = (int)Math.Floor(bbox.Max.X / 24.0f); var max_cy = (int)Math.Floor(bbox.Max.Y / 24.0f); min_x = Math.Min(min_cx - lx, min_x); min_y = Math.Min(min_cy - ly, min_y); max_x = Math.Max(max_cx - lx, max_x); max_y = Math.Max(max_cy - ly, max_y); } add_cell_block(min_x + (int)lcoord.X, min_y + (int)lcoord.Y, max_x + (int)lcoord.X, max_y + (int)lcoord.Y, cellArray, id); } }
public Vector3 GetOffset(Position pos, Vector3 rotation) { var blockOffset = LandDefs.GetBlockOffset(ObjCellID, pos.ObjCellID); return(blockOffset + pos.LocalToGlobal(rotation) - Frame.Origin); }
public static void find_cell_list(Position position, int numSphere, List <Sphere> sphere, CellArray cellArray, ref ObjCell currCell, SpherePath path) { cellArray.NumCells = 0; cellArray.AddedOutside = false; var visibleCell = GetVisible(position.ObjCellID); if ((position.ObjCellID & 0xFFFF) >= 0x100) { if (path != null) { path.HitsInteriorCell = true; } cellArray.add_cell(position.ObjCellID, visibleCell); } else { LandCell.add_all_outside_cells(position, numSphere, sphere, cellArray); } if (visibleCell != null && numSphere != 0) { for (var i = 0; i < cellArray.Cells.Count; i++) { var cell = cellArray.Cells.Values.ElementAt(i); if (cell == null) { continue; } cell.find_transit_cells(position, numSphere, sphere, cellArray, path); } //var checkCells = cellArray.Cells.Values.ToList(); //foreach (var cell in checkCells) //cell.find_transit_cells(position, numSphere, sphere, cellArray, path); if (currCell != null) { currCell = null; foreach (var cell in cellArray.Cells.Values) { if (cell == null) { continue; } var blockOffset = LandDefs.GetBlockOffset(position.ObjCellID, cell.ID); var localPoint = sphere[0].Center - blockOffset; if (cell.point_in_cell(localPoint)) { currCell = cell; if ((cell.ID & 0xFFFF) >= 0x100) { if (path != null) { path.HitsInteriorCell = true; } return; // break? } } } } } if (!cellArray.LoadCells && (position.ObjCellID & 0xFFFF) >= 0x100) { var cells = cellArray.Cells.Values.ToList(); foreach (var cell in cells) { if (cell == null) { continue; } if (visibleCell.ID == cell.ID) { continue; } var found = false; foreach (var stab in ((EnvCell)visibleCell).VisibleCells.Values) { if (stab == null) { continue; } if (cell.ID == stab.ID) { found = true; break; } } if (!found) { cellArray.remove_cell(cell); } } } }
public void adjust_to_outside() { LandDefs.AdjustToOutside(this); }
public void ConstructPolygons(uint landblockID) { var lcoord = LandDefs.blockid_to_lcoord(landblockID).Value; var polyNum = 1; var seedA = (uint)((int)lcoord.X * LandDefs.VertexPerCell * 214614067); var seedB = (uint)((int)lcoord.X * LandDefs.VertexPerCell * 1109124029); var vertexCnt = 0; for (var x = 0; x < SideCellCount; x++) { var lcoordX = lcoord.X + x; var originY = 1; var colVertexCnt = 0; var originX = polyNum; for (var y = 0; y < SideCellCount; y++) { var lcoordY = (int)lcoord.Y + y; var magicB = seedB; var magicA = seedA + 1813693831; for (var i = 0; i < LandDefs.VertexPerCell; i++) { var idxI = vertexCnt + i; var idxJ = colVertexCnt; for (var j = 0; j < LandDefs.VertexPerCell; j++) { var splitDir = (uint)(((int)lcoord.Y * LandDefs.VertexPerCell + idxJ) * magicA - magicB - 1369149221); var polyIdx = (LandDefs.VertexPerCell * i + j) * 2; var cellIdx = x * SideCellCount + y; var vertIdx = idxI * SideVertexCount + idxJ; var firstVertex = (idxI * SidePolyCount + idxJ) * 2; var nextVertIdx = (idxI + 1) * SideVertexCount + idxJ; var lcell = (LandCell)LandCells[cellIdx]; if (splitDir * 2.3283064e-10 < 0.5f) { // 2 1---0 // | \ \ | // | \ \ | // 0---1 2 SWtoNEcut[cellIdx] = false; lcell.Polygons[polyIdx] = AddPolygon(firstVertex, vertIdx, nextVertIdx, vertIdx + 1); lcell.Polygons[polyIdx + 1] = AddPolygon(firstVertex + 1, nextVertIdx + 1, vertIdx + 1, nextVertIdx); } else { // 2 2---1 // / | | / // / | | / // 0---1 0 SWtoNEcut[cellIdx] = true; lcell.Polygons[polyIdx] = AddPolygon(firstVertex, vertIdx, nextVertIdx, nextVertIdx + 1); lcell.Polygons[polyIdx + 1] = AddPolygon(firstVertex + 1, vertIdx, nextVertIdx + 1, vertIdx + 1); } idxJ++; } magicA += 214614067; magicB += 1109124029; } var cellID = (uint)LandDefs.lcoord_to_gid(lcoordX, lcoordY); var landCell = LandCells[x * SideCellCount + y]; landCell.ID = cellID; landCell.Pos.ObjCellID = cellID; landCell.Pos.Frame.Origin.X = originX * LandDefs.HalfSquareLength; landCell.Pos.Frame.Origin.Y = originY * LandDefs.HalfSquareLength; originY += 2; colVertexCnt += LandDefs.VertexPerCell; } vertexCnt += LandDefs.VertexPerCell; seedB += 1109124029 * (uint)LandDefs.VertexPerCell; seedA += 214614067 * (uint)LandDefs.VertexPerCell; polyNum += 2; } }
public void get_land_scenes() { //Console.WriteLine("Loading scenery for " + ID.ToString("X8")); // ported from Scenery Scenery = new List <PhysicsObj>(); // get the landblock cell offsets var blockX = (ID >> 24) * 8; var blockY = (ID >> 16 & 0xFF) * 8; for (uint i = 0; i < Terrain.Count; i++) { var terrain = Terrain[(int)i]; var terrainType = terrain >> 2 & 0x1F; // TerrainTypes table size = 32 (grass, desert, volcano, etc.) var sceneType = terrain >> 11; // SceneTypes table size = 89 total, 32 which can be indexed for each terrain type var sceneInfo = (int)DatManager.PortalDat.RegionDesc.TerrainInfo.TerrainTypes[terrainType].SceneTypes[sceneType]; var scenes = DatManager.PortalDat.RegionDesc.SceneInfo.SceneTypes[sceneInfo].Scenes; if (scenes.Count == 0) { continue; } var cellX = i / LandDefs.VertexDim; var cellY = i % LandDefs.VertexDim; var globalCellX = (uint)(cellX + blockX); var globalCellY = (uint)(cellY + blockY); var cellMat = globalCellY * (712977289 * globalCellX + 1813693831) - 1109124029 * globalCellX + 2139937281; var offset = cellMat * 2.3283064e-10; var scene_idx = (int)(scenes.Count * offset); if (scene_idx >= scenes.Count) { scene_idx = 0; } var sceneId = scenes[scene_idx]; var scene = DatManager.PortalDat.ReadFromDat <Scene>(sceneId); var cellXMat = -1109124029 * globalCellX; var cellYMat = 1813693831 * globalCellY; cellMat = 1360117743 * globalCellX * globalCellY + 1888038839; for (uint j = 0; j < scene.Objects.Count; j++) { var obj = scene.Objects[(int)j]; var noise = (uint)(cellXMat + cellYMat - cellMat * (23399 + j)) * 2.3283064e-10; if (noise < obj.Freq && obj.WeenieObj == 0) { // pseudo-randomized placement var position = ObjectDesc.Displace(obj, globalCellX, globalCellY, j); var lx = cellX * LandDefs.CellLength + position.X; var ly = cellY * LandDefs.CellLength + position.Y; var loc = new Vector3(lx, ly, position.Z); // ensure within landblock range, and not near road if (lx < 0 || ly < 0 || lx >= LandDefs.BlockLength || ly >= LandDefs.BlockLength || OnRoad(loc)) { continue; } // load scenery var pos = new Position(ID); pos.Frame.Origin = loc; var outside = LandDefs.AdjustToOutside(pos); var cell = get_landcell(pos.ObjCellID); if (cell == null) { continue; } // check for buildings var sortCell = (SortCell)cell; if (sortCell != null && sortCell.has_building()) { continue; } Polygon walkable = null; var terrainPoly = cell.find_terrain_poly(pos.Frame.Origin, ref walkable); if (walkable == null) { continue; } // ensure walkable slope if (!ObjectDesc.CheckSlope(obj, walkable.Plane.Normal.Z)) { continue; } walkable.Plane.set_height(ref pos.Frame.Origin); // rotation if (obj.Align != 0) { pos.Frame = ObjectDesc.ObjAlign(obj, walkable.Plane, pos.Frame.Origin); } else { pos.Frame = ObjectDesc.RotateObj(obj, globalCellX, globalCellY, j, pos.Frame.Origin); } // build object var physicsObj = PhysicsObj.makeObject(obj.ObjId, 0, false); physicsObj.DatObject = true; physicsObj.set_initial_frame(pos.Frame); if (!physicsObj.obj_within_block()) { //Console.WriteLine($"Landblock {ID:X8} scenery: failed to spawn {obj.ObjId:X8}"); physicsObj.DestroyObject(); continue; } physicsObj.add_obj_to_cell(cell, pos.Frame); var scale = ObjectDesc.ScaleObj(obj, globalCellX, globalCellY, j); physicsObj.SetScaleStatic(scale); Scenery.Add(physicsObj); } } } //Console.WriteLine("Landblock " + ID.ToString("X8") + " scenery count: " + Scenery.Count); }
public uint get_terrain(uint cellID, Vector3 point) { var lcoord = LandDefs.gid_to_lcoord(cellID).Value; return(Terrain[(int)lcoord.X * 255 * 9 + (int)lcoord.Y]); }
public static ObjCell find_cell_list(Position position, int numSphere, List <Sphere> sphere, CellArray cellArray, ObjCell currCell, SpherePath path) { cellArray.NumCells = 0; cellArray.AddedOutside = false; var cell = GetVisible(position.ObjCellID); if ((position.ObjCellID & 0xFFFF) >= 0x100) { if (path != null) { path.HitsInteriorCell = true; } cellArray.add_cell(position.ObjCellID, cell); } else { LandCell.add_all_outside_cells(position, numSphere, sphere, cellArray); } if (cell != null && numSphere != 0) { foreach (var otherCell in cellArray.Cells) { if (otherCell != null) { otherCell.find_transit_cells(position, numSphere, sphere, cellArray, path); } } if (currCell != null) { foreach (var otherCell in cellArray.Cells) { var blockOffset = LandDefs.GetBlockOffset(position.ObjCellID, otherCell.ID); var localPoint = sphere[0].Center - blockOffset; if (otherCell.point_in_cell(localPoint) && (otherCell.ID & 0xFFFF) >= 0x100) { if (path != null) { path.HitsInteriorCell = true; } return(otherCell); } } } } if (!cellArray.LoadCells && (position.ObjCellID & 0xFFFF) >= 0x100) { foreach (var otherCell in cellArray.Cells) { if (cell.ID != otherCell.ID) { continue; } var found = false; foreach (var stab in cell.StabList) { if (otherCell.ID == stab) { found = true; break; } } if (!found) { cellArray.remove_cell(otherCell); } } } return(null); }
public void get_land_scenes() { // ported from Scenery Scenery = new List <PhysicsObj>(); // get the landblock cell offsets var blockX = (ID >> 24) * 8; var blockY = (ID >> 16 & 0xFF) * 8; for (var i = 0; i < Terrain.Count; i++) { var terrain = Terrain[(int)i]; var terrainType = terrain >> 2 & 0x1F; // TerrainTypes table size = 32 (grass, desert, volcano, etc.) var sceneType = terrain >> 11; // SceneTypes table size = 89 total, 32 which can be indexed for each terrain type var sceneInfo = (int)DatManager.PortalDat.RegionDesc.TerrainInfo.TerrainTypes[terrainType].SceneTypes[sceneType]; var scenes = DatManager.PortalDat.RegionDesc.SceneInfo.SceneTypes[sceneInfo].Scenes; if (scenes.Count == 0) { continue; } var cellX = i / LandDefs.VertexDim; var cellY = i % LandDefs.VertexDim; var globalCellX = (uint)(cellX + blockX); var globalCellY = (uint)(cellY + blockY); var cellMat = globalCellY * (712977289 * globalCellX + 1813693831) - 1109124029 * globalCellX + 2139937281; var offset = cellMat * 2.3283064e-10; var scene_idx = (int)(scenes.Count * offset); if (scene_idx >= scenes.Count) { scene_idx = 0; } var sceneId = scenes[scene_idx]; var scene = DatManager.PortalDat.ReadFromDat <Scene>(sceneId); var cellXMat = -1109124029 * globalCellX; var cellYMat = 1813693831 * globalCellY; cellMat = 1360117743 * globalCellX * globalCellY + 1888038839; for (uint j = 0; j < scene.Objects.Count; j++) { var obj = scene.Objects[(int)j]; var noise = (uint)(cellXMat + cellYMat - cellMat * (23399 + j)) * 2.3283064e-10; if (noise < obj.Freq && obj.WeenieObj == 0) { var position = Displace(obj, globalCellX, globalCellY, j); // ensure within landblock range, and not near road var lx = cellX * LandDefs.CellLength + position.X; var ly = cellY * LandDefs.CellLength + position.Y; // TODO: ensure walkable slope if (lx < 0 || ly < 0 || lx >= LandDefs.BlockLength || ly >= LandDefs.BlockLength || OnRoad(obj, lx, ly)) { continue; } // load scenery var pos = new Position(ID); pos.Frame.Origin = new Vector3(lx, ly, 0); pos.Frame.Orientation = Quaternion.CreateFromYawPitchRoll(0, 0, RotateObj(obj, globalCellX, globalCellY, j)); var outside = LandDefs.AdjustToOutside(pos); var cell = get_landcell(pos.ObjCellID); //if (cell == null) continue; Polygon walkable = null; var terrainPoly = cell.find_terrain_poly(pos.Frame.Origin, ref walkable); walkable.Plane.set_height(ref pos.Frame.Origin); // todo: collision detection var physicsObj = PhysicsObj.makeObject(obj.ObjId, 0, false); //physicsObj.set_initial_frame(pos.Frame); physicsObj.add_obj_to_cell(cell, pos.Frame); Scenery.Add(physicsObj); } } } //Console.WriteLine("Landblock " + ID.ToString("X8") + " scenery count: " + Scenery.Count); }