internal void ProjectileHit(Projectile attacker, Projectile target, bool lineCheck, ref LineD beam) { var hitEntity = HitEntityPool.Get(); hitEntity.Info = attacker.Info; hitEntity.EventType = HitEntity.Type.Projectile; hitEntity.Hit = true; hitEntity.Projectile = target; hitEntity.SphereCheck = !lineCheck; hitEntity.PruneSphere = attacker.PruneSphere; double dist; Vector3D.Distance(ref beam.From, ref target.Position, out dist); hitEntity.HitDist = dist; hitEntity.Intersection = new LineD(attacker.LastPosition, attacker.LastPosition + (attacker.Info.Direction * dist)); hitEntity.HitPos = hitEntity.Intersection.To; attacker.Info.HitList.Add(hitEntity); attacker.FinalizeIntersection = true; }
internal void InitialHitCheck() { var vhCount = ValidateHits.Count; var minCount = Session.Settings.Enforcement.ServerOptimizations ? 96 : 99999; var stride = vhCount < minCount ? 100000 : 48; MyAPIGateway.Parallel.For(0, ValidateHits.Count, x => { var p = ValidateHits[x]; var shieldByPass = p.Info.ConsumableDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Bypass; var shieldFullBypass = shieldByPass && p.Info.ConsumableDef.Const.ShieldBypassMod >= 1; var genericFields = p.Info.EwarActive && (p.Info.ConsumableDef.Const.AreaEffect == DotField || p.Info.ConsumableDef.Const.AreaEffect == PushField || p.Info.ConsumableDef.Const.AreaEffect == PullField); p.FinalizeIntersection = false; var lineCheck = p.Info.ConsumableDef.Const.CollisionIsLine && !p.Info.EwarAreaPulse; var ewarProjectile = (p.Info.EwarActive || p.Info.ConsumableDef.Const.EwarEffect); bool projetileInShield = false; var tick = p.Info.System.Session.Tick; var useEntityCollection = p.CheckType != Projectile.CheckTypes.Ray; var entityCollection = p.UseEntityCache ? p.Info.Ai.NearByEntityCache : p.MyEntityList; var collectionCount = !useEntityCollection ? p.MySegmentList.Count : entityCollection.Count; var ray = new RayD(ref p.Beam.From, ref p.Beam.Direction); var myGrid = p.Info.Target.FiringCube.CubeGrid; Water water = null; if (Session.WaterApiLoaded && p.Info.MyPlanet != null) { Session.WaterMap.TryGetValue(p.Info.MyPlanet, out water); } for (int i = 0; i < collectionCount; i++) { var ent = !useEntityCollection ? p.MySegmentList[i].Element : entityCollection[i]; var grid = ent as MyCubeGrid; var entIsSelf = grid != null && (grid == myGrid || myGrid.IsSameConstructAs(grid)); if (entIsSelf && p.SmartsOn || ent.MarkedForClose || !ent.InScene || ent == p.Info.MyShield) { continue; } var character = ent as IMyCharacter; if (p.Info.EwarActive && character != null && !genericFields) { continue; } var entSphere = ent.PositionComp.WorldVolume; if (useEntityCollection) { if (p.CheckType == Projectile.CheckTypes.CachedRay) { var dist = ray.Intersects(entSphere); if (!dist.HasValue || dist > p.Beam.Length) { continue; } } else if (p.CheckType == Projectile.CheckTypes.CachedSphere && p.PruneSphere.Contains(entSphere) == ContainmentType.Disjoint) { continue; } } if (grid != null || character != null) { var extBeam = new LineD(p.Beam.From - p.Beam.Direction * (entSphere.Radius * 2), p.Beam.To); var transform = ent.PositionComp.WorldMatrixRef; var box = ent.PositionComp.LocalAABB; var obb = new MyOrientedBoundingBoxD(box, transform); if (lineCheck && obb.Intersects(ref extBeam) == null || !lineCheck && !obb.Intersects(ref p.PruneSphere)) { continue; } } var safeZone = ent as MySafeZone; if (safeZone != null && safeZone.Enabled) { var action = (Session.SafeZoneAction)safeZone.AllowedActions; if ((action & Session.SafeZoneAction.Damage) == 0) { bool intersects; if (safeZone.Shape == MySafeZoneShape.Sphere) { var sphere = new BoundingSphereD(safeZone.PositionComp.WorldVolume.Center, safeZone.Radius); var dist = ray.Intersects(sphere); intersects = dist != null && dist <= p.Beam.Length; } else { intersects = new MyOrientedBoundingBoxD(safeZone.PositionComp.LocalAABB, safeZone.PositionComp.WorldMatrixRef).Intersects(ref p.Beam) != null; } if (intersects) { p.State = Projectile.ProjectileState.Depleted; p.EarlyEnd = true; if (p.EnableAv) { p.Info.AvShot.ForceHitParticle = true; } break; } } } HitEntity hitEntity = null; var checkShield = Session.ShieldApiLoaded && Session.ShieldHash == ent.DefinitionId?.SubtypeId && ent.Render.Visible; MyTuple <IMyTerminalBlock, MyTuple <bool, bool, float, float, float, int>, MyTuple <MatrixD, MatrixD> >?shieldInfo = null; if (checkShield && (!shieldFullBypass && !p.ShieldBypassed || p.Info.EwarActive && (p.Info.ConsumableDef.Const.AreaEffect == DotField || p.Info.ConsumableDef.Const.AreaEffect == EmpField))) { shieldInfo = p.Info.System.Session.SApi.MatchEntToShieldFastExt(ent, true); if (shieldInfo != null && !myGrid.IsSameConstructAs(shieldInfo.Value.Item1.CubeGrid)) { if (p.Info.IsShrapnel || Vector3D.Transform(p.Info.Origin, shieldInfo.Value.Item3.Item1).LengthSquared() > 1) { p.EntitiesNear = true; var dist = MathFuncs.IntersectEllipsoid(shieldInfo.Value.Item3.Item1, shieldInfo.Value.Item3.Item2, new RayD(p.Beam.From, p.Beam.Direction)); if (p.Info.Target.IsProjectile && Vector3D.Transform(p.Info.Target.Projectile.Position, shieldInfo.Value.Item3.Item1).LengthSquared() <= 1) { projetileInShield = true; } if (dist != null && (dist.Value < p.Beam.Length || p.Info.EwarActive)) { if (shieldByPass) { p.ShieldBypassed = true; } hitEntity = HitEntityPool.Get(); hitEntity.EventType = Shield; hitEntity.HitPos = p.Beam.From + (p.Beam.Direction * dist.Value); hitEntity.HitDist = dist; } else { continue; } } } } var destroyable = ent as IMyDestroyableObject; var voxel = ent as MyVoxelBase; if (voxel != null && voxel == voxel?.RootVoxel) { if (ent == p.Info.MyPlanet && !(p.LinePlanetCheck || p.DynamicGuidance || p.CachedPlanetHit)) { continue; } VoxelIntersectBranch voxelState = VoxelIntersectBranch.None; Vector3D?voxelHit = null; if (tick - p.Info.VoxelCache.HitRefreshed < 60) { var cacheDist = ray.Intersects(p.Info.VoxelCache.HitSphere); if (cacheDist.HasValue && cacheDist.Value <= p.Beam.Length) { voxelHit = p.Beam.From + (p.Beam.Direction * cacheDist.Value); voxelState = VoxelIntersectBranch.PseudoHit1; } else if (cacheDist.HasValue) { p.Info.VoxelCache.MissSphere.Center = p.Beam.To; } } if (voxelState != VoxelIntersectBranch.PseudoHit1) { if (voxel == p.Info.MyPlanet && p.Info.VoxelCache.MissSphere.Contains(p.Beam.To) == ContainmentType.Disjoint) { if (p.LinePlanetCheck) { if (water != null && !p.Info.ConsumableDef.IgnoreWater) { var waterSphere = new BoundingSphereD(p.Info.MyPlanet.PositionComp.WorldAABB.Center, water.radius); var estiamtedSurfaceDistance = ray.Intersects(waterSphere); if (estiamtedSurfaceDistance.HasValue && estiamtedSurfaceDistance.Value <= p.Beam.Length) { var estimatedHit = ray.Position + (ray.Direction * estiamtedSurfaceDistance.Value); voxelHit = estimatedHit; voxelState = VoxelIntersectBranch.PseudoHit2; } } if (voxelState != VoxelIntersectBranch.PseudoHit2) { var surfacePos = p.Info.MyPlanet.GetClosestSurfacePointGlobal(ref p.Position); var planetCenter = p.Info.MyPlanet.PositionComp.WorldAABB.Center; double surfaceToCenter; Vector3D.DistanceSquared(ref surfacePos, ref planetCenter, out surfaceToCenter); double endPointToCenter; Vector3D.DistanceSquared(ref p.Position, ref planetCenter, out endPointToCenter); double startPointToCenter; Vector3D.DistanceSquared(ref p.Info.Origin, ref planetCenter, out startPointToCenter); var prevEndPointToCenter = p.PrevEndPointToCenterSqr; Vector3D.DistanceSquared(ref surfacePos, ref p.Position, out p.PrevEndPointToCenterSqr); if (surfaceToCenter > endPointToCenter || p.PrevEndPointToCenterSqr <= (p.Beam.Length * p.Beam.Length) || endPointToCenter > startPointToCenter && prevEndPointToCenter > p.DistanceToTravelSqr || surfaceToCenter > Vector3D.DistanceSquared(planetCenter, p.LastPosition)) { var estiamtedSurfaceDistance = ray.Intersects(p.Info.VoxelCache.PlanetSphere); var fullCheck = p.Info.VoxelCache.PlanetSphere.Contains(p.Info.Origin) != ContainmentType.Disjoint || !estiamtedSurfaceDistance.HasValue; if (!fullCheck && estiamtedSurfaceDistance.HasValue && (estiamtedSurfaceDistance.Value <= p.Beam.Length || p.Info.VoxelCache.PlanetSphere.Radius < 1)) { double distSqr; var estimatedHit = ray.Position + (ray.Direction * estiamtedSurfaceDistance.Value); Vector3D.DistanceSquared(ref p.Info.VoxelCache.FirstPlanetHit, ref estimatedHit, out distSqr); if (distSqr > 625) { fullCheck = true; } else { voxelHit = estimatedHit; voxelState = VoxelIntersectBranch.PseudoHit2; } } if (fullCheck) { voxelState = VoxelIntersectBranch.DeferFullCheck; } if (voxelHit.HasValue && Vector3D.DistanceSquared(voxelHit.Value, p.Info.VoxelCache.PlanetSphere.Center) > p.Info.VoxelCache.PlanetSphere.Radius * p.Info.VoxelCache.PlanetSphere.Radius) { p.Info.VoxelCache.GrowPlanetCache(voxelHit.Value); } } } } } else if (voxelHit == null && p.Info.VoxelCache.MissSphere.Contains(p.Beam.To) == ContainmentType.Disjoint) { voxelState = VoxelIntersectBranch.DeferedMissUpdate; } } if (voxelState == VoxelIntersectBranch.PseudoHit1 || voxelState == VoxelIntersectBranch.PseudoHit2) { if (!voxelHit.HasValue) { if (p.Info.VoxelCache.MissSphere.Contains(p.Beam.To) == ContainmentType.Disjoint) { p.Info.VoxelCache.MissSphere.Center = p.Beam.To; } continue; } hitEntity = HitEntityPool.Get(); var hitPos = voxelHit.Value; hitEntity.HitPos = hitPos; double dist; Vector3D.Distance(ref p.Beam.From, ref hitPos, out dist); hitEntity.HitDist = dist; hitEntity.EventType = Voxel; } else if (voxelState == VoxelIntersectBranch.DeferedMissUpdate || voxelState == VoxelIntersectBranch.DeferFullCheck) { DeferedVoxels.Add(new DeferedVoxels { Projectile = p, Branch = voxelState, Voxel = voxel }); } } else if (ent.Physics != null && !ent.Physics.IsPhantom && !ent.IsPreview && grid != null) { if (grid != null) { hitEntity = HitEntityPool.Get(); if (entIsSelf) { if (!p.Info.ConsumableDef.Const.IsBeamWeapon && p.Beam.Length <= grid.GridSize * 2) { MyCube cube; if (!(grid.TryGetCube(grid.WorldToGridInteger(p.Position), out cube) && cube.CubeBlock != p.Info.Target.FiringCube.SlimBlock || grid.TryGetCube(grid.WorldToGridInteger(p.LastPosition), out cube) && cube.CubeBlock != p.Info.Target.FiringCube.SlimBlock)) { HitEntityPool.Return(hitEntity); continue; } } if (!p.Info.EwarAreaPulse) { var forwardPos = p.Info.Age != 1 ? p.Beam.From : p.Beam.From + (p.Beam.Direction * Math.Min(grid.GridSizeHalf, p.Info.DistanceTraveled - p.Info.PrevDistanceTraveled)); grid.RayCastCells(forwardPos, p.Beam.To, hitEntity.Vector3ICache, null, true, true); if (hitEntity.Vector3ICache.Count > 0) { IHitInfo hitInfo; p.Info.System.Session.Physics.CastRay(forwardPos, p.Beam.To, out hitInfo, CollisionLayers.DefaultCollisionLayer); var hitGrid = hitInfo?.HitEntity?.GetTopMostParent() as MyCubeGrid; if (hitGrid == null || !myGrid.IsSameConstructAs(hitGrid)) { HitEntityPool.Return(hitEntity); continue; } hitEntity.HitPos = hitInfo.Position; hitEntity.Blocks.Add(grid.GetCubeBlock(hitEntity.Vector3ICache[0])); } } } else { grid.RayCastCells(p.Beam.From, p.Beam.To, hitEntity.Vector3ICache, null, true, true); } if (!ewarProjectile) { hitEntity.EventType = Grid; } else if (!p.Info.EwarAreaPulse) { hitEntity.EventType = Effect; } else { hitEntity.EventType = Field; } p.EntitiesNear = true; } } else if (destroyable != null) { hitEntity = HitEntityPool.Get(); hitEntity.EventType = Destroyable; } if (hitEntity != null) { p.FinalizeIntersection = true; hitEntity.Info = p.Info; hitEntity.Entity = hitEntity.EventType != Shield ? ent : (MyEntity)shieldInfo.Value.Item1; hitEntity.Intersection = p.Beam; hitEntity.SphereCheck = !lineCheck; hitEntity.PruneSphere = p.PruneSphere; hitEntity.SelfHit = entIsSelf; hitEntity.DamageOverTime = p.Info.ConsumableDef.Const.AreaEffect == DotField; p.Info.HitList.Add(hitEntity); } } if (p.Info.Target.IsProjectile && !p.Info.ConsumableDef.Const.EwarEffect && !projetileInShield) { var detonate = p.State == Projectile.ProjectileState.Detonate; var hitTolerance = detonate ? p.Info.ConsumableDef.Const.DetonationRadius : p.Info.ConsumableDef.Const.AreaEffectSize > p.Info.ConsumableDef.Const.CollisionSize ? p.Info.ConsumableDef.Const.AreaEffectSize : p.Info.ConsumableDef.Const.CollisionSize; var useLine = p.Info.ConsumableDef.Const.CollisionIsLine && !detonate && p.Info.ConsumableDef.Const.AreaEffectSize <= 0; var sphere = new BoundingSphereD(p.Info.Target.Projectile.Position, p.Info.Target.Projectile.Info.ConsumableDef.Const.CollisionSize); sphere.Include(new BoundingSphereD(p.Info.Target.Projectile.LastPosition, 1)); bool rayCheck = false; if (useLine) { var dist = sphere.Intersects(new RayD(p.LastPosition, p.Info.Direction)); if (dist <= hitTolerance || p.Info.ConsumableDef.Const.IsBeamWeapon && dist <= p.Beam.Length) { rayCheck = true; } } var testSphere = p.PruneSphere; testSphere.Radius = hitTolerance; if (rayCheck || sphere.Intersects(testSphere)) { ProjectileHit(p, p.Info.Target.Projectile, lineCheck, ref p.Beam); } } if (!useEntityCollection) { p.MySegmentList.Clear(); } else if (p.CheckType == Projectile.CheckTypes.Sphere) { entityCollection.Clear(); } if (p.FinalizeIntersection) { FinalHitCheck.Add(p); } }, stride); ValidateHits.ClearImmediate(); }
internal void DeferedVoxelCheck() { DeferedVoxels.ApplyAdditions(); for (int i = 0; i < DeferedVoxels.Count; i++) { var p = DeferedVoxels[i].Projectile; var branch = DeferedVoxels[i].Branch; var voxel = DeferedVoxels[i].Voxel; Vector3D?voxelHit = null; if (branch == VoxelIntersectBranch.DeferFullCheck) { if (p.Beam.Length > 85) { IHitInfo hit; p.Info.System.Session.Physics.CastLongRay(p.Beam.From, p.Beam.To, out hit, false); if (hit?.HitEntity is MyVoxelBase) { voxelHit = hit.Position; } } else { using (voxel.Pin()) { if (!voxel.GetIntersectionWithLine(ref p.Beam, out voxelHit, true, IntersectionFlags.DIRECT_TRIANGLES) && VoxelIntersect.PointInsideVoxel(voxel, p.Info.System.Session.TmpStorage, p.Beam.From)) { voxelHit = p.Beam.From; } } } if (voxelHit.HasValue && p.Info.IsShrapnel && p.Info.Age == 0) { if (!VoxelIntersect.PointInsideVoxel(voxel, p.Info.System.Session.TmpStorage, voxelHit.Value + (p.Beam.Direction * 1.25f))) { voxelHit = null; } } } else if (branch == VoxelIntersectBranch.DeferedMissUpdate) { using (voxel.Pin()) { if (!voxel.GetIntersectionWithLine(ref p.Beam, out voxelHit, true, IntersectionFlags.DIRECT_TRIANGLES) && VoxelIntersect.PointInsideVoxel(voxel, p.Info.System.Session.TmpStorage, p.Beam.From)) { voxelHit = p.Beam.From; } } } if (!voxelHit.HasValue) { if (p.Info.VoxelCache.MissSphere.Contains(p.Beam.To) == ContainmentType.Disjoint) { p.Info.VoxelCache.MissSphere.Center = p.Beam.To; } continue; } p.Info.VoxelCache.Update(voxel, ref voxelHit, p.Info.System.Session.Tick); if (voxelHit == null) { continue; } if (!p.FinalizeIntersection) { p.FinalizeIntersection = true; FinalHitCheck.Add(p); } var hitEntity = HitEntityPool.Get(); var lineCheck = p.Info.ConsumableDef.Const.CollisionIsLine && !p.Info.EwarAreaPulse; hitEntity.Info = p.Info; hitEntity.Entity = voxel; hitEntity.Intersection = p.Beam; hitEntity.SphereCheck = !lineCheck; hitEntity.PruneSphere = p.PruneSphere; hitEntity.DamageOverTime = p.Info.ConsumableDef.Const.AreaEffect == DotField; var hitPos = voxelHit.Value; hitEntity.HitPos = hitPos; double dist; Vector3D.Distance(ref p.Beam.From, ref hitPos, out dist); hitEntity.HitDist = dist; hitEntity.EventType = Voxel; p.Info.HitList.Add(hitEntity); } DeferedVoxels.ClearImmediate(); }
internal bool GetAllEntitiesInLine(Projectile p, LineD beam) { var shieldByPass = p.Info.AmmoDef.DamageScales.Shields.Type == ShieldDef.ShieldType.Bypass; var shieldFullBypass = shieldByPass && p.Info.AmmoDef.Const.ShieldBypassMod >= 1; var genericFields = p.Info.EwarActive && (p.Info.AmmoDef.Const.AreaEffect == DotField || p.Info.AmmoDef.Const.AreaEffect == PushField || p.Info.AmmoDef.Const.AreaEffect == PullField); var ai = p.Info.Ai; var found = false; var lineCheck = p.Info.AmmoDef.Const.CollisionIsLine && !p.Info.EwarActive && !p.Info.TriggeredPulse; var planetBeam = beam; planetBeam.To = p.Info.AmmoDef.Const.IsBeamWeapon && p.MaxTrajectory > 1500 ? beam.From + (beam.Direction * 1500) : beam.To; bool projetileInShield = false; for (int i = 0; i < p.SegmentList.Count; i++) { var ent = p.SegmentList[i].Element; var grid = ent as MyCubeGrid; var destroyable = ent as IMyDestroyableObject; var voxel = ent as MyVoxelBase; if (ent is IMyCharacter && p.Info.EwarActive && !genericFields) { continue; } if (grid != null && p.SmartsOn && p.Info.Ai.MyGrid.IsSameConstructAs(grid) || ent.MarkedForClose || !ent.InScene || ent == p.Info.Ai.MyShield) { continue; } if (!shieldFullBypass && !p.ShieldBypassed || p.Info.EwarActive && (p.Info.AmmoDef.Const.AreaEffect == DotField && p.Info.AmmoDef.Const.AreaEffect == EmpField)) { var shieldInfo = p.Info.Ai.Session.SApi?.MatchEntToShieldFastExt(ent, true); if (shieldInfo != null) { double?dist = null; if (ent.Physics != null && ent.Physics.IsPhantom) { dist = MathFuncs.IntersectEllipsoid(shieldInfo.Value.Item3.Item1, shieldInfo.Value.Item3.Item2, new RayD(beam.From, beam.Direction)); if (p.Info.Target.IsProjectile && Vector3D.Transform(p.Info.Target.Projectile.Position, shieldInfo.Value.Item3.Item1).LengthSquared() <= 1) { projetileInShield = true; } } if (dist != null && (dist.Value < beam.Length || p.Info.EwarActive) && !p.Info.Ai.MyGrid.IsSameConstructAs(shieldInfo.Value.Item1.CubeGrid)) { var hitEntity = HitEntityPool.Get(); hitEntity.Clean(); hitEntity.Info = p.Info; found = true; if (shieldByPass) { p.ShieldBypassed = true; } hitEntity.Entity = (MyEntity)shieldInfo.Value.Item1; hitEntity.Intersection = beam; hitEntity.EventType = Shield; hitEntity.SphereCheck = !lineCheck; hitEntity.PruneSphere = p.PruneSphere; hitEntity.HitPos = beam.From + (beam.Direction * dist.Value); hitEntity.HitDist = dist; p.Info.HitList.Add(hitEntity); } else { continue; } } } if ((ent == ai.MyPlanet && (p.LinePlanetCheck || p.DynamicGuidance || p.CachedPlanetHit)) || ent.Physics != null && !ent.Physics.IsPhantom && !ent.IsPreview && (grid != null || voxel != null || destroyable != null)) { var extFrom = beam.From - (beam.Direction * (ent.PositionComp.WorldVolume.Radius * 2)); var extBeam = new LineD(extFrom, beam.To); var rotMatrix = Quaternion.CreateFromRotationMatrix(ent.WorldMatrix); var obb = new MyOrientedBoundingBoxD(ent.PositionComp.WorldAABB.Center, ent.PositionComp.LocalAABB.HalfExtents, rotMatrix); if (lineCheck && obb.Intersects(ref extBeam) == null || !lineCheck && !obb.Intersects(ref p.PruneSphere)) { continue; } Vector3D?voxelHit = null; if (voxel != null) { if (voxel.RootVoxel != voxel) { continue; } if (voxel == ai.MyPlanet) { if (p.CachedPlanetHit) { IHitInfo cachedPlanetResult; if (p.Info.WeaponCache.VoxelHits[p.CachedId].NewResult(out cachedPlanetResult)) { voxelHit = cachedPlanetResult.Position; } else { continue; } } if (p.LinePlanetCheck) { var check = false; var surfacePos = ai.MyPlanet.GetClosestSurfacePointGlobal(ref p.Position); var planetCenter = ai.MyPlanet.PositionComp.WorldAABB.Center; double surfaceToCenter; Vector3D.DistanceSquared(ref surfacePos, ref planetCenter, out surfaceToCenter); double endPointToCenter; Vector3D.DistanceSquared(ref p.Position, ref planetCenter, out endPointToCenter); double startPointToCenter; Vector3D.DistanceSquared(ref p.Info.Origin, ref planetCenter, out startPointToCenter); var prevEndPointToCenter = p.PrevEndPointToCenterSqr; Vector3D.DistanceSquared(ref surfacePos, ref p.Position, out p.PrevEndPointToCenterSqr); if (surfaceToCenter > endPointToCenter || p.PrevEndPointToCenterSqr <= (planetBeam.Length * planetBeam.Length) || endPointToCenter > startPointToCenter && prevEndPointToCenter > p.DistanceToTravelSqr || surfaceToCenter > Vector3D.DistanceSquared(planetCenter, p.LastPosition)) { check = true; } if (check) { using (voxel.Pin()) voxel.GetIntersectionWithLine(ref planetBeam, out voxelHit); } } } else { using (voxel.Pin()) voxel.GetIntersectionWithLine(ref beam, out voxelHit); } if (!voxelHit.HasValue) { continue; } } var hitEntity = HitEntityPool.Get(); hitEntity.Clean(); hitEntity.Info = p.Info; hitEntity.Entity = ent; hitEntity.Intersection = beam; hitEntity.SphereCheck = !lineCheck; hitEntity.PruneSphere = p.PruneSphere; if (voxelHit != null) { var hitPos = voxelHit.Value; hitEntity.HitPos = hitPos; double dist; Vector3D.Distance(ref beam.From, ref hitPos, out dist); hitEntity.HitDist = dist; } if (grid != null) { if (!p.Info.AmmoDef.Const.IsBeamWeapon && beam.Length <= grid.GridSize * 2 && grid.IsSameConstructAs(p.Info.Target.FiringCube.CubeGrid)) { MyCube cube; if (!(grid.TryGetCube(grid.WorldToGridInteger(p.Position), out cube) && cube.CubeBlock != p.Info.Target.FiringCube.SlimBlock || grid.TryGetCube(grid.WorldToGridInteger(p.LastPosition), out cube) && cube.CubeBlock != p.Info.Target.FiringCube.SlimBlock)) { continue; } } if (!(p.Info.EwarActive && p.Info.AmmoDef.Const.EwarEffect)) { hitEntity.EventType = Grid; } else if (!p.Info.AmmoDef.Const.Pulse) { hitEntity.EventType = Effect; } else { hitEntity.EventType = Field; } if (p.Info.AmmoDef.Const.AreaEffect == DotField) { hitEntity.DamageOverTime = true; } } else if (destroyable != null) { hitEntity.EventType = Destroyable; } else if (voxel != null) { hitEntity.EventType = Voxel; } found = true; p.Info.HitList.Add(hitEntity); } } if (p.Info.Target.IsProjectile && !p.Info.AmmoDef.Const.EwarEffect && !projetileInShield) { var detonate = p.State == Projectile.ProjectileState.Detonate; var hitTolerance = detonate ? p.Info.AmmoDef.AreaEffect.Detonation.DetonationRadius : p.Info.AmmoDef.Const.AreaEffectSize > p.Info.AmmoDef.Const.CollisionSize ? p.Info.AmmoDef.Const.AreaEffectSize : p.Info.AmmoDef.Const.CollisionSize; var useLine = p.Info.AmmoDef.Const.CollisionIsLine && !detonate && p.Info.AmmoDef.Const.AreaEffectSize <= 0; var sphere = new BoundingSphereD(p.Info.Target.Projectile.Position, p.Info.Target.Projectile.Info.AmmoDef.Const.CollisionSize); sphere.Include(new BoundingSphereD(p.Info.Target.Projectile.LastPosition, 1)); var rayCheck = useLine && sphere.Intersects(new RayD(p.LastPosition, p.Info.Direction)) != null; var testSphere = p.PruneSphere; testSphere.Radius = hitTolerance; if (rayCheck || sphere.Intersects(testSphere)) { found = ProjectileHit(p, p.Info.Target.Projectile, lineCheck, ref beam); } } p.SegmentList.Clear(); return(found && GenerateHitInfo(p)); }