public static List <IMySlimBlock> GetBlocksOnRay(this IMyCubeGrid Grid, Vector3D From, Vector3D To) { List <IMySlimBlock> Blocks = new List <IMySlimBlock>(); List <Vector3I> BlockPositions = new List <Vector3I>(); Grid.RayCastCells(From, To, BlockPositions); foreach (Vector3I Position in BlockPositions) { IMySlimBlock Block = Grid.GetCubeBlock(Position); if (Block != null) { Blocks.Add(Block); } } return(Blocks); }
public static void ApplyRegularDamage(IMyCubeGrid cubeGrid, Vector3D startCoords, Vector3D endCoords, float damageAmount, long damageOwner) { var newStartCoords = Vector3D.Normalize(startCoords - endCoords) * 50 + endCoords; var newEndCoords = Vector3D.Normalize(endCoords - startCoords) * 50 + endCoords; var cellList = new List <Vector3I>(); cubeGrid.RayCastCells(newStartCoords, newEndCoords, cellList); IMySlimBlock closestBlock = null; double closestBlockDist = 0; foreach (var cell in cellList) { var block = cubeGrid.GetCubeBlock(cell); if (block == null) { continue; } var blockPosition = Vector3D.Zero; block.ComputeWorldCenter(out blockPosition); var thisBlockDist = Vector3D.Distance(blockPosition, endCoords); if (closestBlock == null) { closestBlock = block; closestBlockDist = thisBlockDist; } if (thisBlockDist < closestBlockDist) { closestBlock = block; closestBlockDist = thisBlockDist; } } if (closestBlock == null) { return; } closestBlock.DoDamage(damageAmount, MyStringHash.GetOrCompute("Laser"), true, null, damageOwner); }
private bool IsObstructing(IMyCubeGrid grid, Vector3D target) { List <Vector3I> cells = new List <Vector3I>(); grid.RayCastCells(turretPosition, target, cells, null, true); if (cells.Count == 0) { return(false); } if (grid != myCubeBlock.CubeGrid) { return(true); } //myLogger.debugLog("testing " + cells.Count + " of " + grid.getBestName() + " cells for obstruction", "IsObstructing()"); foreach (Vector3I pos in cells) { //if (pos == myCubeBlock.Position) //{ // //myLogger.debugLog("my cell: " + pos + ", world:" + grid.GridIntegerToWorld(pos), "IsObstructing()"); // continue; //} IMySlimBlock block = grid.GetCubeBlock(pos); if (block != null) { if (block.FatBlock == null) { //myLogger.debugLog("obstructing slim pos = " + pos + ", world = " + grid.GridIntegerToWorld(pos), "IsObstructing()"); } else { if (block.FatBlock == myCubeBlock) { continue; } //myLogger.debugLog("obstructing cube: " + block.FatBlock.DisplayNameText + ", pos = " + pos + ", world = " + grid.GridIntegerToWorld(pos), "IsObstructing()"); } return(true); } //myLogger.debugLog("empty cell: " + pos + ", world:" + grid.GridIntegerToWorld(pos), "IsObstructing()"); } return(false); }
public static void GetBlocksOnRay(this IMyCubeGrid Grid, ICollection <LineD> Rays, ICollection <IMySlimBlock> Blocks, Func <IMySlimBlock, bool> collect = null) { foreach (LineD Ray in Rays) { List <Vector3I> BlockPositions = new List <Vector3I>(); Grid.RayCastCells(Ray.From, Ray.To, BlockPositions); foreach (Vector3I Position in BlockPositions) { IMySlimBlock Block = Grid.GetCubeBlock(Position); if (Block == null) { continue; } if (collect == null || collect(Block)) { Blocks.Add(Block); } } } }
public static void ApplyPenetrativeDamage(IMyCubeGrid cubeGrid, Vector3D startCoords, Vector3D endCoords, float damageAmount, long damageOwner, double penetrateDistance) { var newStartCoords = Vector3D.Normalize(startCoords - endCoords) * 50 + endCoords; var newEndCoords = Vector3D.Normalize(endCoords - startCoords) * penetrateDistance + endCoords; var cellList = new List <Vector3I>(); cubeGrid.RayCastCells(newStartCoords, newEndCoords, cellList); var blockList = new List <IMySlimBlock>(); foreach (var cell in cellList) { var block = cubeGrid.GetCubeBlock(cell); if (block == null) { continue; } var blockPosition = Vector3D.Zero; block.ComputeWorldCenter(out blockPosition); var thisBlockDist = Vector3D.Distance(blockPosition, endCoords); if (thisBlockDist < penetrateDistance) { blockList.Add(block); } } foreach (var targetBlock in blockList) { if (targetBlock == null) { continue; } targetBlock.DoDamage(damageAmount, MyStringHash.GetOrCompute("Laser"), true, null, damageOwner); } }
public static IMySlimBlock GetClosestBlock(Vector3D fromCoords, Vector3D coords, IMyCubeGrid cubeGrid) { IMySlimBlock closestBlock = null; double closestDistance = 0; Vector3D closestPosition = Vector3D.Zero; var directionToGridCenter = Vector3D.Normalize(cubeGrid.GetPosition() - coords); var toCoords = directionToGridCenter * 1500 + coords; var cellHits = new List <Vector3I>(); cubeGrid.RayCastCells(coords, toCoords, cellHits); foreach (var cell in cellHits) { var thisBlock = cubeGrid.GetCubeBlock(cell); if (thisBlock == null) { continue; } var thisBlockPos = Vector3D.Zero; thisBlock.ComputeWorldCenter(out thisBlockPos); var distance = Vector3D.Distance(coords, thisBlockPos); if (closestBlock == null) { closestBlock = thisBlock; closestDistance = distance; closestPosition = thisBlockPos; continue; } if (distance < closestDistance) { closestBlock = thisBlock; closestDistance = distance; closestPosition = thisBlockPos; } } if (closestBlock != null) { return(closestBlock); } var blockList = new List <IMySlimBlock>(); cubeGrid.GetBlocks(blockList); foreach (var block in blockList) { var thisBlockPos = Vector3D.Zero; block.ComputeWorldCenter(out thisBlockPos); var distance = Vector3D.Distance(coords, thisBlockPos); if (closestBlock == null) { closestBlock = block; closestDistance = distance; closestPosition = thisBlockPos; continue; } if (distance < closestDistance) { closestBlock = block; closestDistance = distance; closestPosition = thisBlockPos; } } return(closestBlock); }
/// <summary> /// <para>Test for entities intersecting a line segment.</para> /// </summary> /// <param name="world">Line to test for entities</param> /// <param name="pointOfIntersection">the point of contact between Line and intersecting entity</param> /// <param name="collect">Ignore entity if function returns false. Not tested against IMyCubeBlock</param> /// <param name="collect_CubeBlock">If null, do not ignore any IMyCubeBlock. Ignore IMyCubeBlock if function returns false</param> /// <param name="sort">entities will be sorted according to results of this function</param> /// <returns>An entity intersecting the Line</returns> /// <remarks> /// <para>For IMyCubeGrid, if a cell the line passes through is occupied, the cell is considered to be the point of intersection</para> /// <para>For entities that are not IMyCubeGrid, Line will be tested against IMyEntity.WorldVolume</para> /// </remarks> public static IMyEntity EntityOnLine(LineD world, out Vector3D?pointOfIntersection, Func <IMyEntity, bool> collect, Func <IMyCubeBlock, bool> collect_CubeBlock = null, Func <IMyEntity, double> sort = null) { if (collect == null) { throw new ArgumentNullException("collect"); } // Get entities in AABB Vector3D[] points = { world.From, world.To }; BoundingBoxD AABB = BoundingBoxD.CreateFromPoints(points); ICollection <IMyEntity> entitiesInAABB = MyAPIGateway.Entities.GetEntitiesInAABB_Safe(ref AABB); RayD worldRay = new RayD(world.From, world.Direction); if (sort != null) { SortedDictionary <double, IMyEntity> sortedEntities = new SortedDictionary <double, IMyEntity>(); foreach (IMyEntity entity in entitiesInAABB) { // filter entities if (entity is IMyCubeBlock || !collect(entity)) { continue; } sortedEntities.Add(sort(entity), entity); } entitiesInAABB = sortedEntities.Values; } foreach (IMyEntity entity in entitiesInAABB) { if (sort == null) { // filter entities if (entity is IMyCubeBlock || !collect(entity)) { continue; } } // ray cast IMyCubeGrid entityAsGrid = entity as IMyCubeGrid; if (entityAsGrid != null) { // TODO: test GetLineIntersectionExact... List <Vector3I> rayCastCells = new List <Vector3I>(); entityAsGrid.RayCastCells(world.From, world.To, rayCastCells); // I do not know if rayCastCells will be sorted foreach (Vector3I cell in rayCastCells) { IMySlimBlock block = entityAsGrid.GetCubeBlock(cell); if (block == null) { continue; } IMyCubeBlock FatBlock = block.FatBlock; if (FatBlock == null) { pointOfIntersection = entityAsGrid.GridIntegerToWorld(cell); return(entityAsGrid); } else if (collect_CubeBlock == null || collect_CubeBlock(FatBlock)) { pointOfIntersection = entityAsGrid.GridIntegerToWorld(cell); return(entityAsGrid); } } } else { double tMin, tMax; if (entity.WorldVolume.IntersectRaySphere(worldRay, out tMin, out tMax)) { pointOfIntersection = tMin * worldRay.Direction + worldRay.Position; return(entity); } } } pointOfIntersection = null; return(null); }
/// <summary> /// <para>Test line segment between startPosition and targetPosition for obstructing entities.</para> /// <para>Tests for obstructing voxel map, character, or grid.</para> ///// <param name="shortTest">When checking voxels, shortens the line by 1 m, needed to interact with an entity that may be on the surface of the voxel.</param> /// </summary> public static bool Obstructed <Tobstruct, Tignore>(LineD line, IEnumerable <Tobstruct> potentialObstructions, IEnumerable <Tignore> ignoreList, bool checkVoxel = true, bool checkPlanet = DefaultCheckPlanet) //, bool shortTest = true) where Tobstruct : IMyEntity where Tignore : IMyEntity { Profiler.StartProfileBlock(); // Test each entity foreach (IMyEntity entity in potentialObstructions) { if (entity.Closed) { continue; } if (ignoreList != null && ignoreList.Contains((Tignore)entity)) { continue; } IMyCharacter asChar = entity as IMyCharacter; if (asChar != null) { double distance; if (entity.WorldAABB.Intersects(ref line, out distance)) { Logger.DebugLog("obstructed by character: " + entity.getBestName()); Profiler.EndProfileBlock(); return(true); } continue; } IMyCubeGrid asGrid = entity as IMyCubeGrid; if (asGrid != null) { if (!asGrid.Save) { continue; } ICollection <Vector3I> allHitCells; List <Vector3I> hitCells = new List <Vector3I>(); asGrid.RayCastCells(line.From, line.To, hitCells); allHitCells = hitCells; foreach (Vector3I pos in allHitCells) { IMySlimBlock slim = asGrid.GetCubeBlock(pos); if (slim == null) { continue; } MyCubeBlock fatblock = (MyCubeBlock)slim.FatBlock; if (fatblock != null) { if (ignoreList != null && ignoreList.Contains((Tignore)slim.FatBlock)) { continue; } Dictionary <string, MyEntitySubpart> subparts = fatblock.Subparts; if (subparts != null && subparts.Count != 0) { Vector3 gsPosition = pos * asGrid.GridSize; BoundingBox gsAABB; fatblock.CombinedAABB(out gsAABB); if (gsAABB.Contains(gsPosition) == ContainmentType.Disjoint) { continue; } } } Logger.DebugLog("obstructed by block: " + slim.getBestName() + " on " + slim.CubeGrid.DisplayName + ", id: " + slim.CubeGrid.EntityId); Profiler.EndProfileBlock(); return(true); } } } if (checkVoxel) { // Voxel Test MyVoxelBase hitVoxel; Vector3D hitPosition; if (RayCastVoxels(line, out hitVoxel, out hitPosition, checkPlanet)) { Logger.DebugLog("obstructed by voxel: " + hitVoxel + " at " + hitPosition); Profiler.EndProfileBlock(); return(true); } } // no obstruction found Profiler.EndProfileBlock(); return(false); }