private void ProcessDamage() { foreach (IMyEntity entity in _topEntityCache) { var grid = entity as IMyCubeGrid; if (grid?.Physics != null) { if (grid.Closed || grid.MarkedForClose) { continue; } float damage = grid.GridSizeEnum == MyCubeSize.Small ? Config.SMALL_SHIP_DAMAGE : Config.LARGE_SHIP_DAMAGE; if (Config.BLOCK_VOXEL_DAMAGE) { byte voxelId; List <IMySlimBlock> vBlocks = Utilities.GetBlocksContactingVoxel(grid, _planet, out voxelId); VoxelDamageItem item; if (!Config.VOXEL_IDS.TryGetValue(voxelId, out item)) { MyLog.Default.WriteLine($"{voxelId} NOT FOUND"); item = Config.VOXEL_IDS.First().Value; } foreach (IMySlimBlock b in vBlocks) { _damageEntities.AddOrUpdate(b, damage * item.DamageMultiplier); if (item.ParticleEffect.HasValue) { _blockParticles[b] = item.ParticleEffect.Value; } } } if (!Config.BLOCK_RADIATION_DAMAGE && !Config.BLOCK_ACID_RAIN && Utilities.IsEntityInsideGrid(grid)) { continue; } //if (BLOCK_ACID_RAIN && IsEntityCovered(grid, sphere.Center)) //{ // //MyAPIGateway.Utilities.ShowMessage("GRID COVERED", grid.DisplayName); // continue; //} var blocks = new List <IMySlimBlock>(); grid.GetBlocks(blocks); Vector3D offset = Vector3D.Zero; if (Config.BLOCK_ACID_RAIN) { Vector3D direction = grid.WorldVolume.Center - _sphere.Center; direction.Normalize(); offset = direction; } if (Config.BLOCK_ACID_RAIN || Config.BLOCK_RADIATION_DAMAGE) { for (var i = 0; i < Math.Max(1, blocks.Count * 0.3); i++) { IMySlimBlock block; if (Config.BLOCK_ACID_RAIN) { block = Utilities.GetRandomSkyFacingBlock(grid, blocks, offset, true); } else { block = Utilities.GetRandomExteriorBlock(grid, blocks); } if (block == null) { continue; } _damageEntities.AddOrUpdate(block, damage); //blocks.Remove(block); //QueueInvoke(() => // { // if (block != null && !block.Closed()) // block.DoDamage(damage, _damageHash, true); // }); } } continue; } var floating = entity as IMyFloatingObject; if (floating != null) { if (floating.Closed || floating.MarkedForClose) { continue; } if (Config.BLOCK_RADIATION_DAMAGE) { _damageEntities.AddOrUpdate(floating, Config.SMALL_SHIP_DAMAGE); } if (Config.BLOCK_ACID_RAIN && !(Utilities.IsEntityCovered(floating, _sphere.Center) || Utilities.IsFullyInsideVoxel(floating, _planet))) { _damageEntities.AddOrUpdate(floating, Config.SMALL_SHIP_DAMAGE); } Vector3D pos = floating.GetPosition(); Vector3D s = _planet.GetClosestSurfacePointGlobal(ref pos); if (Vector3D.DistanceSquared(pos, s) <= 4) { MyVoxelMaterialDefinition mat = _planet.GetMaterialAt_R(ref s); VoxelDamageItem vox; if (Config.VOXEL_IDS.TryGetValue(mat.Index, out vox)) { _damageEntities.AddOrUpdate(floating, Config.LARGE_SHIP_DAMAGE * vox.DamageMultiplier); } } } } if (Config.BLOCK_ACID_RAIN && Config.DRAW_RAIN) { SendDrawQueue(); } }
public static List <IMySlimBlock> GetBlocksContactingVoxel(IMyCubeGrid grid, MyPlanet planet, out byte voxelType) { Vector3D[] corners = grid.WorldAABB.GetCorners(); if (corners.All(c => Vector3D.DistanceSquared(c, planet.GetClosestSurfacePointGlobal(c)) > 2500)) { voxelType = 0; return(new List <IMySlimBlock>()); } Vector3D planetPos = planet.PositionComp.GetPosition(); var result = new MyConcurrentHashSet <IMySlimBlock>(); var blocks = new List <IMySlimBlock>(); grid.GetBlocks(blocks); byte id = 0; MyAPIGateway.Parallel.ForEach(blocks, block => { try { var b = block.GetPosition(); Vector3D closestSurfacePoint = planet.GetClosestSurfacePointGlobal(ref b); if (Vector3D.DistanceSquared(planetPos, closestSurfacePoint) > Vector3D.DistanceSquared(planetPos, b)) { var hits = new List <IHitInfo>(); MyAPIGateway.Physics.CastRay(b, closestSurfacePoint, hits); foreach (IHitInfo hit in hits) { if (hit.HitEntity is IMyVoxelBase) { closestSurfacePoint = hit.Position; } } } double cd = Vector3D.DistanceSquared(b, closestSurfacePoint); if (cd > 200) { return; } if (cd > 6.25) { BoundingBoxD box; block.GetWorldBoundingBox(out box, true); Vector3D[] bc = box.GetCorners(); if (bc.All(c => Vector3D.DistanceSquared(c, planet.GetClosestSurfacePointGlobal(c)) > 6.25)) { return; } } MyVoxelMaterialDefinition mat = planet.GetMaterialAt_R(ref closestSurfacePoint); if (Config.VOXEL_IDS.ContainsKey(mat.Index)) { result.Add(block); } id = mat.Index; } catch { //meh! } }); voxelType = id; return(result.ToList()); /* * var chunks = new HashSet<Vector3I[]>(); * * int chunkSize = grid.GridSizeEnum == MyCubeSize.Large ? 3 : 5; * for (int x = grid.Min.X; x < grid.Max.X + chunkSize; x += chunkSize) * { * for (int y = grid.Min.Y; y < grid.Max.Y + chunkSize; y += chunkSize) * { * for (int z = grid.Min.Z; z < grid.Max.Z + chunkSize; z += chunkSize) * { * chunks.Add(new[] * { * new Vector3I(x, y, z), * new Vector3I(x + chunkSize, y, z), * new Vector3I(x, y + chunkSize, z), * new Vector3I(x, y, z + chunkSize), * new Vector3I(x + chunkSize, y + chunkSize, z), * new Vector3I(x + chunkSize, y, z + chunkSize), * new Vector3I(x, y + chunkSize, z + chunkSize), * new Vector3I(x + chunkSize, y + chunkSize, z + chunkSize), * }); * } * } * } * * MyAPIGateway.Parallel.ForEach(chunks, chunk => * { * var success = false; * foreach (Vector3I pos in chunk) * { * Vector3D d = grid.GridIntegerToWorld(pos); * Vector3D s = planet.GetClosestSurfacePointGlobal(ref d); * if (Vector3D.DistanceSquared(d, s) > 6.25) * continue; * * if (!Config.VOXEL_IDS.ContainsKey(planet.GetMaterialAt_R(ref s).Index)) * continue; * success = true; * break; * } * * if (!success) * return; * * foreach (Vector3I pos in chunk) * { * IMySlimBlock block = grid.GetCubeBlock(pos); * if (block != null) * result.Add(block); * } * }); * * return result.ToList(); */ }