private bool CheckIfEntityRelevant(HaE_Entity entity, Vector3D currentHeading) { if (entity.entityInfo.EntityId == rc.CubeGrid.EntityId) { return(false); } if (entity.BoundingSphere.Radius <= 0) { return(false); } Vector3D movementDir = rc.GetShipVelocities().LinearVelocity; movementDir.Normalize(); RayD movementRay = new RayD(rc.CubeGrid.WorldVolume.Center, movementDir); RayD headingRay = new RayD(rc.CubeGrid.WorldVolume.Center, currentHeading); BoundingSphereD sphere = entity.BoundingSphere; sphere.Radius += rc.CubeGrid.WorldVolume.Radius; double?intersectVel = sphere.Intersects(movementRay); double?intersectHeading = sphere.Intersects(headingRay); return(intersectVel.HasValue || intersectHeading.HasValue); }
/// <summary> /// <para>Uses IMyEntities.GetEntities to get entities in Sphere</para> /// <para>Always use over GetEntitiesInSphere_Safe() when blocks are not needed, much faster.</para> /// </summary> /// <param name="preCollect">applied before intersection test</param> public static void GetEntitiesInSphere_Safe_NoBlock(this IMyEntities entitiesObject, BoundingSphereD boundingSphere, HashSet <IMyEntity> entities, Func <IMyEntity, bool> preCollect = null) { Func <IMyEntity, bool> collector; if (preCollect == null) { collector = (entity) => boundingSphere.Intersects(entity.WorldAABB); } else { collector = (entity) => { return(preCollect(entity) && boundingSphere.Intersects(entity.WorldAABB)); } }; entitiesObject.GetEntities_Safe(entities, collector); }
/// <summary> /// Check intersection between line and bounding sphere /// We don't use BoundingSphere.Contains(Ray ...) because ray doesn't have an end, but line does, so we need /// to check if line really intersects the sphere. /// </summary> public static bool IsLineIntersectingBoundingSphere(ref LineD line, ref BoundingSphereD boundingSphere) { // Create temporary ray and do intersection. But we can't rely only on it, because ray doesn't have end, yet our line does, so we // need to check if ray-bounding_sphere intersection lies in the range of our line VRageMath.RayD ray = new VRageMath.RayD(line.From, line.Direction); double? intersectionDistance = boundingSphere.Intersects(ray); if (intersectionDistance.HasValue == false) { // No intersection between ray/line and bounding sphere return(false); } else { if (intersectionDistance.Value <= line.Length) { // Intersection between ray/line and bounding sphere IS withing the range of the line return(true); } else { // Intersection between ray/line and bounding sphere IS NOT withing the range of the line return(false); } } }
public void NextPosition(ref Vector3D nextDirection, Vector3D headingDir, double safetyMargin = 1.25) { CreateSphereFromEntities(headingDir); Vector3D position = rc.CubeGrid.WorldVolume.Center; Vector3D movementDir = rc.GetShipVelocities().LinearVelocity; movementDir.Normalize(); RayD movementRay = new RayD(position, movementDir); RayD headingRay = new RayD(rc.CubeGrid.WorldVolume.Center, headingDir); BoundingSphereD sphere = boundingSphere; sphere.Radius += rc.CubeGrid.WorldVolume.Radius; if (sphere.Contains(position) != ContainmentType.Disjoint) { Vector3D dodgeDirection = Vector3D.Normalize(position - sphere.Center); nextDirection = sphere.Center + dodgeDirection * sphere.Radius * safetyMargin; return; } double?movementDist = sphere.Intersects(movementRay); double?headingDist = sphere.Intersects(headingRay); if (movementDist.HasValue || headingDist.HasValue) { Vector3D pointOnSphere; Vector3D dodgeDirection; if (movementDist.HasValue) { pointOnSphere = position + movementDir * movementDist.Value; dodgeDirection = GetAvoidanceVector(pointOnSphere, sphere, movementDir); } else { pointOnSphere = position + headingDir * headingDist.Value; dodgeDirection = GetAvoidanceVector(pointOnSphere, sphere, headingDir); } nextDirection = dodgeDirection; } }
private double?CollisionDistance(ref MyDetectedEntityInfo e, ref BoundingSphereD volume, ref Vector3D myVel) { BoundingSphereD sphere = new BoundingSphereD(e.Position, e.BoundingBox.Size.Length() / 2 + volume.Radius + Clearance); Vector3D vel = myVel + e.Velocity; vel.Normalize(); RayD ray = new RayD(ref volume.Center, ref vel); return(sphere.Intersects(ray)); }
//Method From DarkStar for Detecting Sphere Intersections in Defense Shield public static Vector3D?DsRayCast(IMyEntity shield, LineD line, long attackerId, float damage, MyStringId effect) { var worldSphere = new BoundingSphereD(shield.PositionComp.WorldVolume.Center, shield.PositionComp.LocalAABB.HalfExtents.AbsMax()); var myObb = MyOrientedBoundingBoxD.Create(shield.PositionComp.LocalAABB, shield.PositionComp.WorldMatrix.GetOrientation()); myObb.Center = shield.PositionComp.WorldVolume.Center; var obbCheck = myObb.Intersects(ref line); var testDir = line.From - line.To; testDir.Normalize(); var ray = new RayD(line.From, -testDir); var sphereCheck = worldSphere.Intersects(ray); var obb = obbCheck ?? 0; var sphere = sphereCheck ?? 0; double furthestHit; if (obb <= 0 && sphere <= 0) { furthestHit = 0; } else if (obb > sphere) { furthestHit = obb; } else { furthestHit = sphere; } var hitPos = line.From + testDir * -furthestHit; /* * var parent = MyAPIGateway.Entities.GetEntityById(long.Parse(shield.Name)); * var cubeBlock = (MyCubeBlock)parent; * var block = (IMySlimBlock)cubeBlock.SlimBlock; * * if(block == null){ * * return null; * * } * * block.DoDamage(damage, MyStringHash.GetOrCompute(effect.ToString()), true, null, attackerId); * shield.Render.ColorMaskHsv = hitPos; * * if(effect.ToString() == "bypass"){ * * return null; * * } */ return(hitPos); }
public static void AddKnownPlayerLocation(Vector3D coords, string faction, double radius, int duration = -1, int maxEncounters = -1, int minThreatToAvoidAbandonment = -1) { bool foundExistingLocation = false; var sphere = new BoundingSphereD(coords, radius); List <KnownPlayerLocation> intersectingLocations = new List <KnownPlayerLocation>(); foreach (var location in Locations) { if (location.NpcFaction != faction) { continue; } if (!sphere.Intersects(location.Sphere) && location.Sphere.Contains(coords) == ContainmentType.Disjoint) { continue; } intersectingLocations.Add(location); foundExistingLocation = true; } if (foundExistingLocation == false) { Logger.AddMsg("Creating KnownPlayerLocation at " + coords.ToString() + " / Radius: " + radius.ToString(), true); Locations.Add(new KnownPlayerLocation(faction, coords, radius, duration, maxEncounters, minThreatToAvoidAbandonment)); AlertPlayersOfNewKPL(coords, radius, faction); } else { var currentLocation = new KnownPlayerLocation(faction, coords, radius, duration, maxEncounters, minThreatToAvoidAbandonment); foreach (var location in intersectingLocations) { var dirFromCurrentToIntersection = Vector3D.Normalize(location.Coords - currentLocation.Coords); var coordsBetweenCenters = dirFromCurrentToIntersection * (Vector3D.Distance(location.Coords, currentLocation.Coords) / 2) + currentLocation.Coords; var radiusToUse = location.Radius == currentLocation.Radius ? currentLocation.Radius : currentLocation.Radius > location.Radius ? currentLocation.Radius : location.Radius; var outerRimCoords = -dirFromCurrentToIntersection * radiusToUse + currentLocation.Coords; var finalRadius = Vector3D.Distance(outerRimCoords, coordsBetweenCenters); currentLocation = new KnownPlayerLocation(faction, coordsBetweenCenters, finalRadius, duration, maxEncounters, minThreatToAvoidAbandonment); Locations.Remove(location); } Locations.Add(currentLocation); AlertPlayersOfNewKPL(coords, radius, faction); Logger.AddMsg("Known Player Location(s) Already Exist, Merging Locations.", true); } SaveLocations(); }
public bool Contains(IMyEntity entity) { switch (Shape) { case ProtectionAreaShape.Cube: var boundingBox = new BoundingBoxD(new Vector3D(Center.X - Size, Center.Y - Size, Center.Z - Size), new Vector3D(Center.X + Size, Center.Y + Size, Center.Z + Size)); return boundingBox.Intersects(entity.WorldAABB); case ProtectionAreaShape.Sphere: var boundingSphere = new BoundingSphereD(Center, Size); return boundingSphere.Intersects(entity.WorldAABB); } return false; }
public bool Contains(BoundingBoxD boundingbox) { switch (Shape) { case ProtectionAreaShape.Cube: var boundingBox = new BoundingBoxD(Center - Size, Center + Size); return(boundingBox.Intersects(boundingbox)); case ProtectionAreaShape.Sphere: var boundingSphere = new BoundingSphereD(Center, Size); return(boundingSphere.Intersects(boundingbox)); } return(false); }
public bool Contains(IMyEntity entity) { switch (Shape) { case ProtectionAreaShape.Cube: var boundingBox = new BoundingBoxD(new Vector3D(Center.X - Size, Center.Y - Size, Center.Z - Size), new Vector3D(Center.X + Size, Center.Y + Size, Center.Z + Size)); return(boundingBox.Intersects(entity.WorldAABB)); case ProtectionAreaShape.Sphere: var boundingSphere = new BoundingSphereD(Center, Size); return(boundingSphere.Intersects(entity.WorldAABB)); } return(false); }
private void BroadcastDamageMessage(IMyTerminalBlock _b) { if (_b == null) { return; } List <IMyPlayer> players = new List <IMyPlayer>(); MyAPIGateway.Players.GetPlayers(players); if (players != null) { var sphere = new BoundingSphereD(_b.PositionComp.WorldAABB.Center, 250); var sendMessage = false; foreach (var player in players) { if (player != null && player.IdentityId != MyAPIGateway.Session.Player.IdentityId) { continue; } if (player != null && !sphere.Intersects(player.Character.WorldVolume)) { continue; } sendMessage = true; break; } if (sendMessage) { if (!MessageSent) { MyAPIGateway.Utilities.ShowNotification("Beacon Tampering Detected: Power System Damaged.", 9600, "Red"); MessageSent = true; } } else { //MyAPIGateway.Utilities.ShowNotification("Player NO.", 9600, "Red"); } } }
private void BroadcastSpamMessage(IMyTerminalBlock _b) { if (_b == null) { return; } List <IMyPlayer> players = new List <IMyPlayer>(); MyAPIGateway.Players.GetPlayers(players); if (players != null) { var sphere = new BoundingSphereD(_b.PositionComp.WorldAABB.Center, 500); var sendMessage = false; foreach (var player in players) { if (player != null && player.IdentityId != MyAPIGateway.Session.Player.IdentityId) { continue; } if (player != null && !sphere.Intersects(player.Character.WorldVolume)) { continue; } sendMessage = true; break; } if (sendMessage) { if (!SpamMessageSent) { MyAPIGateway.Utilities.ShowNotification("Coolant System Overloaded: Too many Heat Sinks on " + _b.CubeGrid.DisplayName.ToString(), 9600, "Red"); SpamMessageSent = true; } } else { //MyAPIGateway.Utilities.ShowNotification("Player NO.", 9600, "Red"); } } }
private void BroadCastLosMessage(int blocked, int needed, DefenseShields controller) { var sphere = new BoundingSphereD(Emitter.PositionComp.WorldAABB.Center, 1500); var sendMessage = false; foreach (var player in Session.Instance.Players.Values) { if (player.IdentityId != MyAPIGateway.Session.Player.IdentityId) { continue; } if (!sphere.Intersects(player.Character.WorldVolume)) { continue; } sendMessage = true; break; } if (sendMessage) { var sighted = _vertsSighted.Count; if (needed > 0) { needed = 0; } MyAPIGateway.Utilities.ShowNotification("The shield emitter DOES NOT have a CLEAR ENOUGH LINE OF SIGHT to the shield, SHUTTING DOWN.", 960, "Red"); MyAPIGateway.Utilities.ShowNotification($"Green means clear line of sight, Flashing Orange means blocked | Blocked: {blocked} | Clear: {sighted} | Needed (Approximate): {needed}", 960, "Red"); if (needed == 0 && controller.LosCheckTick != uint.MaxValue) { MyAPIGateway.Utilities.ShowNotification($"Needed is only an approximation, if shield does not start in 30 seconds or is unstable, then it is not clear.", 960, "White"); } else if (needed == 0 && _lCount % 2 == 1) { MyAPIGateway.Utilities.ShowNotification($"Shield is still not clear!", 960, "White"); } } }
public static float?IntersectEllipsoid(MatrixD ellipsoidMatrixInv, MatrixD ellipsoidMatrix, RayD ray) { var _normSphere = new BoundingSphereD(Vector3.Zero, 1f); var _kRay = new RayD(Vector3D.Zero, Vector3D.Forward); var krayPos = Vector3D.Transform(ray.Position, ellipsoidMatrixInv); var krayDir = Vector3D.Normalize(Vector3D.TransformNormal(ray.Direction, ellipsoidMatrixInv)); _kRay.Direction = krayDir; _kRay.Position = krayPos; var nullDist = _normSphere.Intersects(_kRay); if (!nullDist.HasValue) { return(null); } var hitPos = krayPos + (krayDir * -nullDist.Value); var worldHitPos = Vector3D.Transform(hitPos, ellipsoidMatrix); return(Vector3.Distance(worldHitPos, ray.Position)); }
bool GetTargetCharacter(Vector3D rayFrom, Vector3D rayDir, double rayLength, IMyCharacter character, ref IMyPlayer targetPlayer) { List <IMyPlayer> players = Main.Caches.Players.Get(); MyAPIGateway.Players.GetPlayers(players); RayD ray = new RayD(rayFrom, rayDir); foreach (IMyPlayer p in players) { IMyCharacter c = p.Character; if (c == null || c == character) { continue; } BoundingSphereD sphere = Utils.GetCharacterSelectionSphere(c); if (Vector3D.DistanceSquared(rayFrom, sphere.Center) > (rayLength * rayLength)) { continue; } double?dist = sphere.Intersects(ray); if (!dist.HasValue || dist.Value > rayLength) { continue; } targetPlayer = p; break; } Main.Caches.Players.Return(players); return(targetPlayer != null); }
internal static double?IntersectEllipsoid(MatrixD ellipsoidMatrixInv, MatrixD ellipsoidMatrix, RayD ray) { var normSphere = new BoundingSphereD(Vector3.Zero, 1f); var kRay = new RayD(Vector3D.Zero, Vector3D.Forward); Vector3D krayPos; Vector3D.Transform(ref ray.Position, ref ellipsoidMatrixInv, out krayPos); Vector3D nDir; Vector3D.TransformNormal(ref ray.Direction, ref ellipsoidMatrixInv, out nDir); Vector3D krayDir; Vector3D.Normalize(ref nDir, out krayDir); kRay.Direction = krayDir; kRay.Position = krayPos; var nullDist = normSphere.Intersects(kRay); if (!nullDist.HasValue) { return(null); } var hitPos = krayPos + (krayDir * -nullDist.Value); Vector3D worldHitPos; Vector3D.Transform(ref hitPos, ref ellipsoidMatrix, out worldHitPos); double dist; Vector3D.Distance(ref worldHitPos, ref ray.Position, out dist); return(double.IsNaN(dist) ? (double?)null : dist); }
public override IEnumerable <ProceduralObject> Generate(BoundingSphereD include, BoundingSphereD?exclude) { var aabb = new BoundingBoxD(include.Center - include.Radius, include.Center + include.Radius); foreach (var cell in StationNoise.TryGetSpawnIn(aabb, (x) => include.Intersects(x) && (!exclude.HasValue || exclude.Value.Contains(x) != ContainmentType.Contains))) { LoadingConstruction instance; if (!m_instances.TryGetValue(cell.Item1, out instance)) { var numSeed = cell.Item1.GetHashCode(); Ob_ProceduralConstructionSeed dbSeed; Ob_ProceduralConstruction dbBlueprint; Ob_ProceduralFaction dbFaction; ProceduralConstructionSeed seed; if (m_database.TryGetBuildingBlueprint(numSeed, out dbSeed, out dbBlueprint) && dbSeed != null && m_database.TryGetFaction(dbSeed.FactionSeed, out dbFaction) && dbFaction != null) { seed = new ProceduralConstructionSeed(new ProceduralFactionSeed(dbFaction), cell.Item2.XYZ(), dbSeed); } else { seed = new ProceduralConstructionSeed(Factions.SeedAt(cell.Item2.XYZ()), cell.Item2, null, numSeed); } instance = m_instances[cell.Item1] = new LoadingConstruction(this, cell.Item1, seed); } else if (!instance.IsMarkedForRemoval) { continue; // Already loaded + not marked for removal -- already in the tree. } instance.EnsureGenerationStarted(); yield return(instance); } }
public bool Drill(bool collectOre = true, bool performCutout = true) { ProfilerShort.Begin("MyDrillBase::Drill()"); bool drillingSuccess = false; MySoundPair sound = null; if ((m_drillEntity.Parent != null) && (m_drillEntity.Parent.Physics != null) && !m_drillEntity.Parent.Physics.Enabled) { return(false); } if (performCutout) { var entitiesInRange = m_sensor.EntitiesInRange; foreach (var entry in entitiesInRange) { drillingSuccess = false; var entity = entry.Value.Entity; if (entity.MarkedForClose) { continue; } if (entity is MyCubeGrid) { var grid = entity as MyCubeGrid; if (grid.Physics != null && grid.Physics.Enabled) { drillingSuccess = TryDrillBlocks(grid, entry.Value.DetectionPoint, !Sync.IsServer); } if (drillingSuccess) { m_initialHeatup = false; sound = m_sounds.MetalLoop; CreateParticles(entry.Value.DetectionPoint, false, true, false); } } else if (entity is MyVoxelBase) { ProfilerShort.Begin("Drill voxel map"); var voxels = entity as MyVoxelBase; drillingSuccess = TryDrillVoxels(voxels, entry.Value.DetectionPoint, collectOre, !Sync.IsServer); ProfilerShort.BeginNextBlock("Create particles"); if (drillingSuccess) { sound = m_sounds.RockLoop; CreateParticles(entry.Value.DetectionPoint, true, false, true); } ProfilerShort.End(); } else if (entity is MyFloatingObject) { var sphere = (BoundingSphereD)m_cutOut.Sphere; sphere.Radius *= 1.33f; if (entity.GetIntersectionWithSphere(ref sphere)) { MyFloatingObject flObj = entity as MyFloatingObject; if (Sync.IsServer) { if (flObj.Item.Content.TypeId == typeof(MyObjectBuilder_Ore)) { IMyInventoryOwner invOwn = m_drillEntity as IMyInventoryOwner; if (invOwn == null) { invOwn = (m_drillEntity as MyHandDrill).Owner as IMyInventoryOwner; } invOwn.GetInventory(0).TakeFloatingObject(flObj); } else { (entity as MyFloatingObject).DoDamage(70, MyDamageType.Drill, true, attackerId: m_drillEntity != null ? m_drillEntity.EntityId : 0); } } drillingSuccess = true; } } else if (entity is MyCharacter) { var sphere = (BoundingSphereD)m_cutOut.Sphere; sphere.Radius *= (4 / 5f); var character = entity as MyCharacter; if (entity.GetIntersectionWithSphere(ref sphere)) { //MyRenderProxy.DebugDrawSphere(sphere.Center, sphere.Radius, Color.Green.ToVector3(), 1, true); if (Sync.IsServer) { character.DoDamage(20, MyDamageType.Drill, true, attackerId: m_drillEntity != null ? m_drillEntity.EntityId : 0); } drillingSuccess = true; } else { BoundingSphereD headSphere = new BoundingSphereD(character.PositionComp.WorldMatrix.Translation + character.WorldMatrix.Up * 1.25f, 0.6f); //MyRenderProxy.DebugDrawSphere(headSphere.Center, headSphere.Radius, Color.Red.ToVector3(), 1, false); if (headSphere.Intersects(sphere)) { //MyRenderProxy.DebugDrawSphere(sphere.Center, sphere.Radius, Color.Green.ToVector3(), 1, true); if (Sync.IsServer) { character.DoDamage(20, MyDamageType.Drill, true, attackerId: m_drillEntity != null ? m_drillEntity.EntityId : 0); } drillingSuccess = true; } } } if (drillingSuccess) { m_lastContactTime = MySandboxGame.TotalGamePlayTimeInMilliseconds; } } } if (sound != null) { StartLoopSound(sound); } else { StartIdleSound(m_sounds.IdleLoop); } IsDrilling = true; m_animationLastUpdateTime = MySandboxGame.TotalGamePlayTimeInMilliseconds; ProfilerShort.End(); return(drillingSuccess); }
private void PlayerMessages(PlayerNotice notice) { double radius; if (notice == PlayerNotice.EmpOverLoad || notice == PlayerNotice.OverLoad) { radius = 500; } else { radius = ShieldSphere.Radius * 2; } var center = GridIsMobile ? MyGrid.PositionComp.WorldVolume.Center : OffsetEmitterWMatrix.Translation; var sphere = new BoundingSphereD(center, radius); var sendMessage = false; IMyPlayer targetPlayer = null; foreach (var player in Session.Instance.Players.Values) { if (player.IdentityId != MyAPIGateway.Session.Player.IdentityId) { continue; } if (!sphere.Intersects(player.Character.WorldVolume)) { continue; } var relation = MyAPIGateway.Session.Player.GetRelationTo(MyCube.OwnerId); if (relation == MyRelationsBetweenPlayerAndBlock.Neutral || relation == MyRelationsBetweenPlayerAndBlock.Enemies) { continue; } sendMessage = true; targetPlayer = player; break; } if (sendMessage && !DsSet.Settings.NoWarningSounds) { BroadcastSound(targetPlayer.Character, notice); } switch (notice) { case PlayerNotice.EmitterInit: if (sendMessage) { MyAPIGateway.Utilities.ShowNotification("[ " + MyGrid.DisplayName + " ]" + " -- shield is reinitializing and checking LOS, attempting startup in 30 seconds!", 4816); } break; case PlayerNotice.FieldBlocked: if (sendMessage) { MyAPIGateway.Utilities.ShowNotification("[ " + MyGrid.DisplayName + " ]" + "-- the shield's field cannot form when in contact with a solid body", 6720, "Blue"); } break; case PlayerNotice.OverLoad: if (sendMessage) { MyAPIGateway.Utilities.ShowNotification("[ " + MyGrid.DisplayName + " ]" + " -- shield has overloaded, restarting in 20 seconds!!", 8000, "Red"); } break; case PlayerNotice.EmpOverLoad: if (sendMessage) { MyAPIGateway.Utilities.ShowNotification("[ " + MyGrid.DisplayName + " ]" + " -- shield was EMPed, restarting in 60 seconds!!", 8000, "Red"); } break; case PlayerNotice.Remodulate: if (sendMessage) { MyAPIGateway.Utilities.ShowNotification("[ " + MyGrid.DisplayName + " ]" + " -- shield remodulating, restarting in 5 seconds.", 4800); } break; case PlayerNotice.NoLos: if (sendMessage) { MyAPIGateway.Utilities.ShowNotification("[ " + MyGrid.DisplayName + " ]" + " -- Emitter does not have line of sight, shield offline", 8000, "Red"); } break; case PlayerNotice.NoPower: if (sendMessage) { MyAPIGateway.Utilities.ShowNotification("[ " + MyGrid.DisplayName + " ]" + " -- Insufficient Power, shield is failing!", 5000, "Red"); } break; } if (Session.Enforced.Debug == 3) { Log.Line($"[PlayerMessages] Sending:{sendMessage} - rangeToClinetPlayer:{Vector3D.Distance(sphere.Center, MyAPIGateway.Session.Player.Character.WorldVolume.Center)}"); } }
/// <summary> /// Override this function to set custom update behaviour. /// Call base at first because it queries objects if DoQuery is set. /// </summary> protected virtual void UpdateInternal() { if (DoQuery) { m_queryResult.Clear(); switch (m_triggerType) { case TriggerType.AABB: MyGamePruningStructure.GetTopMostEntitiesInBox(ref m_AABB, m_queryResult); break; case TriggerType.Sphere: MyGamePruningStructure.GetAllTopMostEntitiesInSphere(ref m_boundingSphere, m_queryResult); break; default: throw new ArgumentOutOfRangeException(); } for (int index = 0; index < m_queryResult.Count;) { var result = m_queryResult[index]; if (!QueryEvaluator(result)) { m_queryResult.RemoveAtFast(index); } else { switch (m_triggerType) { case TriggerType.AABB: if (!m_AABB.Intersects(m_queryResult[index].PositionComp.WorldAABB)) { m_queryResult.RemoveAtFast(index); } else { index++; } break; case TriggerType.Sphere: if (!m_boundingSphere.Intersects(m_queryResult[index].PositionComp.WorldAABB)) { m_queryResult.RemoveAtFast(index); } else { index++; } break; default: index++; break; } } } } }
public bool Drill(bool collectOre = true, bool performCutout = true) { ProfilerShort.Begin("MyDrillBase::Drill()"); bool drillingSuccess = false; MySoundPair sound = null; if ((m_drillEntity.Parent != null) && (m_drillEntity.Parent.Physics != null) && !m_drillEntity.Parent.Physics.Enabled) return false; if (performCutout) { var entitiesInRange = m_sensor.EntitiesInRange; foreach (var entry in entitiesInRange) { drillingSuccess = false; var entity = entry.Value.Entity; if (entity.MarkedForClose) continue; if (entity is MyCubeGrid) { var grid = entity as MyCubeGrid; if (grid.Physics != null && grid.Physics.Enabled) { drillingSuccess = TryDrillBlocks(grid, entry.Value.DetectionPoint, !Sync.IsServer); } if (drillingSuccess) { m_initialHeatup = false; sound = m_sounds.MetalLoop; CreateParticles(entry.Value.DetectionPoint, false, true, false); } } else if (entity is MyVoxelBase) { ProfilerShort.Begin("Drill voxel map"); var voxels = entity as MyVoxelBase; drillingSuccess = TryDrillVoxels(voxels, entry.Value.DetectionPoint, collectOre, !Sync.IsServer); ProfilerShort.BeginNextBlock("Create particles"); if (drillingSuccess) { sound = m_sounds.RockLoop; CreateParticles(entry.Value.DetectionPoint, true, false, true); } ProfilerShort.End(); } else if (entity is MyFloatingObject) { var sphere = (BoundingSphereD)m_cutOut.Sphere; sphere.Radius *= 1.33f; if (entity.GetIntersectionWithSphere(ref sphere)) { MyFloatingObject flObj = entity as MyFloatingObject; if (Sync.IsServer) { if (flObj.Item.Content.TypeId == typeof(MyObjectBuilder_Ore)) { IMyInventoryOwner invOwn = m_drillEntity as IMyInventoryOwner; if (invOwn == null) invOwn = (m_drillEntity as MyHandDrill).Owner as IMyInventoryOwner; invOwn.GetInventory(0).TakeFloatingObject(flObj); } else (entity as MyFloatingObject).DoDamage(70, MyDamageType.Drill, true); } drillingSuccess = true; } } else if (entity is MyCharacter) { var sphere = (BoundingSphereD)m_cutOut.Sphere; sphere.Radius *= (4 / 5f); var character = entity as MyCharacter; if (entity.GetIntersectionWithSphere(ref sphere)) { //MyRenderProxy.DebugDrawSphere(sphere.Center, sphere.Radius, Color.Green.ToVector3(), 1, true); if (Sync.IsServer) character.DoDamage(20, MyDamageType.Drill, true); drillingSuccess = true; } else { BoundingSphereD headSphere = new BoundingSphereD(character.PositionComp.WorldMatrix.Translation + character.WorldMatrix.Up * 1.25f, 0.6f); //MyRenderProxy.DebugDrawSphere(headSphere.Center, headSphere.Radius, Color.Red.ToVector3(), 1, false); if (headSphere.Intersects(sphere)) { //MyRenderProxy.DebugDrawSphere(sphere.Center, sphere.Radius, Color.Green.ToVector3(), 1, true); if (Sync.IsServer) character.DoDamage(20, MyDamageType.Drill, true); drillingSuccess = true; } } } if (drillingSuccess) { m_lastContactTime = MySandboxGame.TotalGamePlayTimeInMilliseconds; } } } if (sound != null) StartLoopSound(sound); else StartIdleSound(m_sounds.IdleLoop); IsDrilling = true; m_animationLastUpdateTime = MySandboxGame.TotalGamePlayTimeInMilliseconds; ProfilerShort.End(); return drillingSuccess; }
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)); }
public static bool SpawnWeather(MyWeatherEffectDefinition weather, Vector3D position, float radius) { MyPlanet closestPlanet = MyGamePruningStructure.GetClosestPlanet(position); if (closestPlanet == null) { return(false); } var sessionWeather = MySession.Static.GetComponent <MySectorWeatherComponent>(); var sessionWeatherPlanetData = _planetWeatherGet(sessionWeather); if (Math.Abs((double)radius) < 1) { radius = 0.1122755f * closestPlanet.AtmosphereRadius; } var weatherPosition = new Vector3D?(closestPlanet.GetClosestSurfacePointGlobal(ref position)); MyObjectBuilder_WeatherEffect builderWeatherEffect1 = new MyObjectBuilder_WeatherEffect() { Weather = weather.Id.SubtypeName, Position = weatherPosition.Value, Radius = radius }; List <MyObjectBuilder_WeatherEffect> builderWeatherEffectList = new List <MyObjectBuilder_WeatherEffect>(); BoundingSphereD boundingSphereD = new BoundingSphereD(weatherPosition.Value, (double)radius); for (int index1 = 0; index1 < sessionWeatherPlanetData.Count; ++index1) { if (sessionWeatherPlanetData[index1].PlanetId == closestPlanet.EntityId) { builderWeatherEffectList.Clear(); for (int index2 = 0; index2 < sessionWeatherPlanetData[index1].Weathers.Count; ++index2) { BoundingSphereD sphere = new BoundingSphereD(sessionWeatherPlanetData[index1].Weathers[index2].Position, (double)sessionWeatherPlanetData[index1].Weathers[index2].Radius); if (boundingSphereD.Intersects(sphere)) { builderWeatherEffectList.Add(sessionWeatherPlanetData[index1].Weathers[index2]); } } foreach (MyObjectBuilder_WeatherEffect builderWeatherEffect in builderWeatherEffectList) { sessionWeatherPlanetData[index1].Weathers.Remove(builderWeatherEffect); } } } bool flag = false; for (int index = 0; index < sessionWeatherPlanetData.Count; ++index) { if (sessionWeatherPlanetData[index].PlanetId == closestPlanet.EntityId) { sessionWeatherPlanetData[index].Weathers.Add(builderWeatherEffect1); flag = true; break; } } if (!flag) { var weatherPlanetData = new MyObjectBuilder_WeatherPlanetData() { PlanetId = closestPlanet.EntityId }; weatherPlanetData.Weathers.Add(builderWeatherEffect1); sessionWeatherPlanetData.Add(weatherPlanetData); } SyncWeather(); return(true); }
public bool Drill(bool collectOre = true, bool performCutout = true, bool assignDamagedMaterial = false) { ProfilerShort.Begin("MyDrillBase::Drill()"); bool drillingSuccess = false; MySoundPair sound = null; if ((m_drillEntity.Parent != null) && (m_drillEntity.Parent.Physics != null) && !m_drillEntity.Parent.Physics.Enabled) { return(false); } if (performCutout) { StopSparkParticles(); StopDustParticles(); var entitiesInRange = m_sensor.EntitiesInRange; MyStringHash targetMaterial = MyStringHash.NullOrEmpty; bool targetIsBlock = false; foreach (var entry in entitiesInRange) { drillingSuccess = false; var entity = entry.Value.Entity; if (entity.MarkedForClose) { continue; } if (entity is MyCubeGrid) { var grid = entity as MyCubeGrid; if (grid.Physics != null && grid.Physics.Enabled) { drillingSuccess = TryDrillBlocks(grid, entry.Value.DetectionPoint, !Sync.IsServer, out targetMaterial); targetIsBlock = true; } if (drillingSuccess) { m_initialHeatup = false; CreateParticles(entry.Value.DetectionPoint, false, true, false); } } else if (entity is MyVoxelBase) { ProfilerShort.Begin("Drill voxel map"); var voxels = entity as MyVoxelBase; drillingSuccess = TryDrillVoxels(voxels, entry.Value.DetectionPoint, collectOre, !Sync.IsServer, assignDamagedMaterial); ProfilerShort.BeginNextBlock("Create particles"); if (drillingSuccess) { Vector3D drillHitPoint = entry.Value.DetectionPoint; if (targetMaterial == MyStringHash.NullOrEmpty) { var voxelMaterial = voxels.GetMaterialAt(ref drillHitPoint); if (voxelMaterial != null) { targetMaterial = MyStringHash.GetOrCompute(voxelMaterial.MaterialTypeName); } } CreateParticles(entry.Value.DetectionPoint, true, false, true); } ProfilerShort.End(); } else if (entity is MyFloatingObject) { var sphere = (BoundingSphereD)m_cutOut.Sphere; sphere.Radius *= 1.33f; if (entity.GetIntersectionWithSphere(ref sphere)) { MyFloatingObject flObj = entity as MyFloatingObject; if (Sync.IsServer) { if (flObj.Item.Content.TypeId == typeof(MyObjectBuilder_Ore)) { var invOwn = (m_drillEntity != null && m_drillEntity.HasInventory) ? m_drillEntity : null; if (invOwn == null) { invOwn = (m_drillEntity as MyHandDrill).Owner; } System.Diagnostics.Debug.Assert((invOwn.GetInventory(0) as MyInventory) != null, "Null or unexpected inventory type!"); (invOwn.GetInventory(0) as MyInventory).TakeFloatingObject(flObj); } else { (entity as MyFloatingObject).DoDamage(70, MyDamageType.Drill, true, attackerId: m_drillEntity != null ? m_drillEntity.EntityId : 0); } } drillingSuccess = true; } } else if (entity is MyCharacter) { var sphere = (BoundingSphereD)m_cutOut.Sphere; sphere.Radius *= 0.8f; var character = entity as MyCharacter; if (targetMaterial == MyStringHash.NullOrEmpty) { targetMaterial = MyStringHash.GetOrCompute((entity as MyCharacter).Definition.PhysicalMaterial); } if (entity.GetIntersectionWithSphere(ref sphere)) { //MyRenderProxy.DebugDrawSphere(sphere.Center, sphere.Radius, Color.Green.ToVector3(), 1, true); //damage tracking if ((m_drillEntity is MyHandDrill) && (m_drillEntity as MyHandDrill).Owner == MySession.Static.LocalCharacter && character != MySession.Static.LocalCharacter && character.IsDead == false) { MySession.Static.TotalDamageDealt += 20; } if (Sync.IsServer) { character.DoDamage(20, MyDamageType.Drill, true, attackerId: m_drillEntity != null ? m_drillEntity.EntityId : 0); } drillingSuccess = true; } else { BoundingSphereD headSphere = new BoundingSphereD(character.PositionComp.WorldMatrix.Translation + character.WorldMatrix.Up * 1.25f, 0.6f); //MyRenderProxy.DebugDrawSphere(headSphere.Center, headSphere.Radius, Color.Red.ToVector3(), 1, false); if (headSphere.Intersects(sphere)) { //MyRenderProxy.DebugDrawSphere(sphere.Center, sphere.Radius, Color.Green.ToVector3(), 1, true); //damage tracking if ((m_drillEntity is MyHandDrill) && (m_drillEntity as MyHandDrill).Owner == MySession.Static.LocalCharacter && character != MySession.Static.LocalCharacter && character.IsDead == false) { MySession.Static.TotalDamageDealt += 20; } if (Sync.IsServer) { character.DoDamage(20, MyDamageType.Drill, true, attackerId: m_drillEntity != null ? m_drillEntity.EntityId : 0); } drillingSuccess = true; } } } if (drillingSuccess) { m_lastContactTime = MySandboxGame.TotalGamePlayTimeInMilliseconds; } } if (targetMaterial != null && targetMaterial != MyStringHash.NullOrEmpty) { sound = MyMaterialPropertiesHelper.Static.GetCollisionCue(MyMaterialPropertiesHelper.CollisionType.Start, m_drillMaterial, targetMaterial); if (sound == null || sound == MySoundPair.Empty)//target material was not set in definition - using metal/rock sound { if (targetIsBlock) { targetMaterial = m_metalMaterial; } else { targetMaterial = m_rockMaterial; } } sound = MyMaterialPropertiesHelper.Static.GetCollisionCue(MyMaterialPropertiesHelper.CollisionType.Start, m_drillMaterial, targetMaterial); } } if (sound != null && sound != MySoundPair.Empty) { StartLoopSound(sound); } else { StartIdleSound(m_idleSoundLoop); } if (!IsDrilling) { IsDrilling = true; m_animationLastUpdateTime = MySandboxGame.TotalGamePlayTimeInMilliseconds; } ProfilerShort.End(); return(drillingSuccess); }
internal void EwarEffects() { switch (Info.AmmoDef.Const.AreaEffect) { case AreaEffectType.AntiSmart: var eWarSphere = new BoundingSphereD(Position, Info.AmmoDef.Const.AreaEffectSize); DynTrees.GetAllProjectilesInSphere(Info.System.Session, ref eWarSphere, EwaredProjectiles, false); for (int j = 0; j < EwaredProjectiles.Count; j++) { var netted = EwaredProjectiles[j]; if (eWarSphere.Intersects(new BoundingSphereD(netted.Position, netted.Info.AmmoDef.Const.CollisionSize))) { if (netted.Info.Target.FiringCube.CubeGrid.IsSameConstructAs(Info.Target.FiringCube.CubeGrid) || netted.Info.Target.IsProjectile) { continue; } if (Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f < Info.AmmoDef.Const.PulseChance || !Info.AmmoDef.Const.Pulse) { Info.BaseEwarPool -= (float)netted.Info.AmmoDef.Const.HealthHitModifier; if (Info.BaseEwarPool <= 0 && Info.BaseHealthPool-- > 0) { Info.EwarActive = true; netted.Info.Target.Projectile = this; netted.Info.Target.IsProjectile = true; Seekers.Add(netted); } } Info.WeaponRng.ClientProjectileCurrentCounter++; } } EwaredProjectiles.Clear(); return; case AreaEffectType.PushField: if (Info.EwarAreaPulse && Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f <= Info.AmmoDef.Const.PulseChance || !Info.AmmoDef.Const.Pulse) { Info.EwarActive = true; } break; case AreaEffectType.PullField: if (Info.EwarAreaPulse && Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f <= Info.AmmoDef.Const.PulseChance || !Info.AmmoDef.Const.Pulse) { Info.EwarActive = true; } break; case AreaEffectType.JumpNullField: if (Info.EwarAreaPulse && Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f <= Info.AmmoDef.Const.PulseChance || !Info.AmmoDef.Const.Pulse) { Info.EwarActive = true; } break; case AreaEffectType.AnchorField: if (Info.EwarAreaPulse && Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f <= Info.AmmoDef.Const.PulseChance || !Info.AmmoDef.Const.Pulse) { Info.EwarActive = true; } break; case AreaEffectType.EnergySinkField: if (Info.EwarAreaPulse && Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f <= Info.AmmoDef.Const.PulseChance || !Info.AmmoDef.Const.Pulse) { Info.EwarActive = true; } break; case AreaEffectType.EmpField: if (Info.EwarAreaPulse && Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f <= Info.AmmoDef.Const.PulseChance || !Info.AmmoDef.Const.Pulse) { Info.EwarActive = true; } break; case AreaEffectType.OffenseField: if (Info.EwarAreaPulse && Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f <= Info.AmmoDef.Const.PulseChance || !Info.AmmoDef.Const.Pulse) { Info.EwarActive = true; } break; case AreaEffectType.NavField: if (!Info.AmmoDef.Const.Pulse || Info.EwarAreaPulse && Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f <= Info.AmmoDef.Const.PulseChance) { Info.EwarActive = true; } break; case AreaEffectType.DotField: if (Info.EwarAreaPulse && Info.WeaponRng.ClientProjectileRandom.NextDouble() * 100f <= Info.AmmoDef.Const.PulseChance || !Info.AmmoDef.Const.Pulse) { Info.EwarActive = true; } break; } Info.WeaponRng.ClientProjectileCurrentCounter++; }
private void ActivateCommon() { BoundingSphereD globalSphere = new BoundingSphereD(Vector3D.Transform(m_detectorSphere.Center, CubeGrid.WorldMatrix), m_detectorSphere.Radius); if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW) { MyRenderProxy.DebugDrawSphere(globalSphere.Center, (float)globalSphere.Radius, Color.Red.ToVector3(), 1.0f, false); } m_isActivatedOnSomething = false; ProfilerShort.Begin("Query"); var res = MyEntities.GetTopMostEntitiesInSphere(ref globalSphere); m_entitiesInContact.Clear(); foreach (MyEntity entity in res) { var rootEntity = entity.GetTopMostParent(); if (CanInteractWith(rootEntity)) { m_entitiesInContact.Add(rootEntity); } } res.Clear(); ProfilerShort.End(); //TODO:cache blocks on this grid foreach (var entry in m_entitiesInContact) { MyCubeGrid grid = entry as MyCubeGrid; MyCharacter character = entry as MyCharacter; if (grid != null) { m_tempBlocksBuffer.Clear(); grid.GetBlocksInsideSphere(ref globalSphere, m_tempBlocksBuffer); m_blocksToActivateOn.UnionWith(m_tempBlocksBuffer); } if (character != null && Sync.IsServer) { MyStringHash damageType = MyDamageType.Drill; if (this is IMyShipGrinder) { damageType = MyDamageType.Grind; } else if (this is IMyShipWelder) { damageType = MyDamageType.Weld; } if (globalSphere.Intersects(character.PositionComp.WorldAABB)) { character.DoDamage(20, damageType, true, attackerId: EntityId); } } } m_isActivatedOnSomething |= Activate(m_blocksToActivateOn); m_activateCounter++; m_lastTimeActivate = MySandboxGame.TotalGamePlayTimeInMilliseconds; PlayLoopSound(m_isActivatedOnSomething); m_blocksToActivateOn.Clear(); }
public MyDetectedEntityInfo Raycast(double distance, Vector3D direction) { if (Vector3D.IsZero(direction)) { throw new ArgumentOutOfRangeException("direction", "Direction cannot be 0,0,0"); } //mods can disable raycast on a block by setting the distance limit to 0 (-1 means infinite) if (distance <= 0 || (BlockDefinition.RaycastDistanceLimit > -1 && distance > BlockDefinition.RaycastDistanceLimit)) { return(new MyDetectedEntityInfo()); } if (AvailableScanRange < distance || !this.CheckIsWorking()) { return(new MyDetectedEntityInfo()); } AvailableScanRange -= distance; var startPos = this.WorldMatrix.Translation; var targetPos = startPos + direction * distance; //try a physics raycast first //very accurate, but very slow List <MyPhysics.HitInfo> hits = new List <MyPhysics.HitInfo>(); MyPhysics.CastRay(startPos, targetPos, hits); foreach (var hit in hits) { var entity = (MyEntity)hit.HkHitInfo.GetHitEntity(); if (entity == this) { continue; } m_lastRay = new RaycastInfo() { Distance = distance, Start = startPos, End = targetPos, Hit = hit.Position }; return(MyDetectedEntityInfoHelper.Create(entity, this.OwnerId, hit.Position)); } //long-distance planet scanning //fastest way is to intersect planet bounding boxes then treat the planet as a sphere LineD line = new LineD(startPos, targetPos); var voxels = new List <MyLineSegmentOverlapResult <MyVoxelBase> >(); MyGamePruningStructure.GetVoxelMapsOverlappingRay(ref line, voxels); foreach (var result in voxels) { var planet = result.Element as MyPlanet; if (planet == null) { continue; } double distCenter = Vector3D.DistanceSquared(this.PositionComp.GetPosition(), planet.PositionComp.GetPosition()); var gravComp = planet.Components.Get <MyGravityProviderComponent>(); if (gravComp == null) { continue; } if (!gravComp.IsPositionInRange(startPos) && distCenter > planet.MaximumRadius * planet.MaximumRadius) { var boundingSphere = new BoundingSphereD(planet.PositionComp.GetPosition(), planet.MaximumRadius); var rayd = new RayD(startPos, direction); var intersection = boundingSphere.Intersects(rayd); if (!intersection.HasValue) { continue; } if (distance < intersection.Value) { continue; } var hitPos = startPos + direction * intersection.Value; m_lastRay = new RaycastInfo() { Distance = distance, Start = startPos, End = targetPos, Hit = hitPos }; return(MyDetectedEntityInfoHelper.Create(result.Element, this.OwnerId, hitPos)); } //if the camera is inside gravity, query voxel storage if (planet.RootVoxel.Storage == null) { continue; } var start = Vector3D.Transform(line.From, planet.PositionComp.WorldMatrixInvScaled); start += planet.SizeInMetresHalf; var end = Vector3D.Transform(line.To, planet.PositionComp.WorldMatrixInvScaled); end += planet.SizeInMetresHalf; var voxRay = new LineD(start, end); double startOffset; double endOffset; if (!planet.RootVoxel.Storage.DataProvider.Intersect(ref voxRay, out startOffset, out endOffset)) { continue; } var from = voxRay.From; voxRay.From = from + voxRay.Direction * voxRay.Length * startOffset; voxRay.To = from + voxRay.Direction * voxRay.Length * endOffset; start = voxRay.From - planet.SizeInMetresHalf; start = Vector3D.Transform(start, planet.PositionComp.WorldMatrix); m_lastRay = new RaycastInfo() { Distance = distance, Start = startPos, End = targetPos, Hit = start }; return(MyDetectedEntityInfoHelper.Create(result.Element, this.OwnerId, start)); } m_lastRay = new RaycastInfo() { Distance = distance, Start = startPos, End = targetPos, Hit = null }; return(new MyDetectedEntityInfo()); }
private bool IsInStoppingDistance() { int currentIndex = m_waypoints.IndexOf(CurrentWaypoint); double currentDstSqr = (WorldMatrix.Translation - CurrentWaypoint.Coords).LengthSquared(); double dstError = CubeGrid.GridSize * 3; if (m_automaticBehaviour != null && m_automaticBehaviour.IsActive) { dstError = m_automaticBehaviour.WaypointThresholdDistance; } else if (m_waypointThresholdDistance > 0) { dstError = m_waypointThresholdDistance; } else if (m_dockingModeEnabled || (m_currentFlightMode == FlightMode.OneWay && currentIndex == m_waypoints.Count - 1)) { if (CubeGrid.GridSize >= 0.5f) dstError = CubeGrid.GridSize * 0.25; else dstError = CubeGrid.GridSize; } if (MyFakes.ENABLE_VR_REMOTE_CONTROL_WAYPOINTS_FAST_MOVEMENT) { // Check if movement from previous position to current position intersects waypoint sphere. if (currentDstSqr < dstError * dstError) return true; double prevDstSqr = (m_previousWorldPosition - CurrentWaypoint.Coords).LengthSquared(); if (prevDstSqr < dstError * dstError) return true; var dir = WorldMatrix.Translation - m_previousWorldPosition; double rayLength = dir.Normalize(); if (rayLength > 0.01) { RayD ray = new RayD(m_previousWorldPosition, dir); BoundingSphereD sphere = new BoundingSphereD(CurrentWaypoint.Coords, dstError); double? intersection = sphere.Intersects(ray); return (intersection != null) ? intersection.Value <= rayLength : false; } } return currentDstSqr < dstError * dstError; }
public bool Drill(bool collectOre = true, bool performCutout = true, bool assignDamagedMaterial = false) { ProfilerShort.Begin("MyDrillBase::Drill()"); bool drillingSuccess = false; MySoundPair sound = null; if ((m_drillEntity.Parent != null) && (m_drillEntity.Parent.Physics != null) && !m_drillEntity.Parent.Physics.Enabled) return false; if (performCutout) { StopSparkParticles(); StopDustParticles(); var entitiesInRange = m_sensor.EntitiesInRange; MyStringHash targetMaterial = MyStringHash.NullOrEmpty; MyStringHash bestMaterial = MyStringHash.NullOrEmpty; float distanceBest = float.MaxValue; bool targetIsBlock = false; foreach (var entry in entitiesInRange) { drillingSuccess = false; var entity = entry.Value.Entity; if (entity.MarkedForClose) continue; if (entity is MyCubeGrid) { var grid = entity as MyCubeGrid; if (grid.Physics != null && grid.Physics.Enabled) { drillingSuccess = TryDrillBlocks(grid, entry.Value.DetectionPoint, !Sync.IsServer, out targetMaterial); targetIsBlock = true; } if (drillingSuccess) { m_initialHeatup = false; CreateParticles(entry.Value.DetectionPoint, false, true, false); } } else if (entity is MyVoxelBase) { ProfilerShort.Begin("Drill voxel map"); var voxels = entity as MyVoxelBase; drillingSuccess = TryDrillVoxels(voxels, entry.Value.DetectionPoint, collectOre, !Sync.IsServer, assignDamagedMaterial); ProfilerShort.BeginNextBlock("Create particles"); if (drillingSuccess) { Vector3D drillHitPoint = entry.Value.DetectionPoint; if(targetMaterial == MyStringHash.NullOrEmpty) { var voxelMaterial = voxels.GetMaterialAt(ref drillHitPoint); if (voxelMaterial != null) targetMaterial = MyStringHash.GetOrCompute(voxelMaterial.MaterialTypeName); } CreateParticles(entry.Value.DetectionPoint, true, false, true); } ProfilerShort.End(); } else if (entity is MyFloatingObject) { var sphere = (BoundingSphereD)m_cutOut.Sphere; sphere.Radius *= 1.33f; if (entity.GetIntersectionWithSphere(ref sphere)) { MyFloatingObject flObj = entity as MyFloatingObject; if (Sync.IsServer) { if (flObj.Item.Content.TypeId == typeof(MyObjectBuilder_Ore)) { var invOwn = (m_drillEntity != null && m_drillEntity.HasInventory) ? m_drillEntity : null; if (invOwn == null) invOwn = (m_drillEntity as MyHandDrill).Owner; System.Diagnostics.Debug.Assert((invOwn.GetInventory(0) as MyInventory) != null, "Null or unexpected inventory type!"); (invOwn.GetInventory(0) as MyInventory).TakeFloatingObject(flObj); } else (entity as MyFloatingObject).DoDamage(70, MyDamageType.Drill, true, attackerId: m_drillEntity != null ? m_drillEntity.EntityId : 0); } drillingSuccess = true; } } else if (entity is MyCharacter) { var sphere = (BoundingSphereD)m_cutOut.Sphere; sphere.Radius *= 0.8f; var character = entity as MyCharacter; if (targetMaterial == MyStringHash.NullOrEmpty) targetMaterial = MyStringHash.GetOrCompute((entity as MyCharacter).Definition.PhysicalMaterial); if (entity.GetIntersectionWithSphere(ref sphere)) { //MyRenderProxy.DebugDrawSphere(sphere.Center, sphere.Radius, Color.Green.ToVector3(), 1, true); //damage tracking if ((m_drillEntity is MyHandDrill) && (m_drillEntity as MyHandDrill).Owner == MySession.Static.LocalCharacter && character != MySession.Static.LocalCharacter && character.IsDead == false) MySession.Static.TotalDamageDealt += 20; if (Sync.IsServer) character.DoDamage(20, MyDamageType.Drill, true, attackerId: m_drillEntity != null ? m_drillEntity.EntityId : 0); drillingSuccess = true; } else { BoundingSphereD headSphere = new BoundingSphereD(character.PositionComp.WorldMatrix.Translation + character.WorldMatrix.Up * 1.25f, 0.6f); //MyRenderProxy.DebugDrawSphere(headSphere.Center, headSphere.Radius, Color.Red.ToVector3(), 1, false); if (headSphere.Intersects(sphere)) { //MyRenderProxy.DebugDrawSphere(sphere.Center, sphere.Radius, Color.Green.ToVector3(), 1, true); //damage tracking if ((m_drillEntity is MyHandDrill) && (m_drillEntity as MyHandDrill).Owner == MySession.Static.LocalCharacter && character != MySession.Static.LocalCharacter && character.IsDead == false) MySession.Static.TotalDamageDealt += 20; if (Sync.IsServer) character.DoDamage(20, MyDamageType.Drill, true, attackerId: m_drillEntity != null ? m_drillEntity.EntityId : 0); drillingSuccess = true; } } } if (drillingSuccess) { m_lastContactTime = MySandboxGame.TotalGamePlayTimeInMilliseconds; float dist = Vector3.DistanceSquared(entry.Value.DetectionPoint, Sensor.Center); if (targetMaterial != null && targetMaterial != MyStringHash.NullOrEmpty && dist < distanceBest) { bestMaterial = targetMaterial; distanceBest = dist; } } } if (bestMaterial != null && bestMaterial != MyStringHash.NullOrEmpty) { sound = MyMaterialPropertiesHelper.Static.GetCollisionCue(MyMaterialPropertiesHelper.CollisionType.Start, m_drillMaterial, bestMaterial); if (sound == null || sound == MySoundPair.Empty)//target material was not set in definition - using metal/rock sound { if (targetIsBlock) { bestMaterial = m_metalMaterial; } else { bestMaterial = m_rockMaterial; } } sound = MyMaterialPropertiesHelper.Static.GetCollisionCue(MyMaterialPropertiesHelper.CollisionType.Start, m_drillMaterial, bestMaterial); } } if (sound != null && sound != MySoundPair.Empty) StartLoopSound(sound); else StartIdleSound(m_idleSoundLoop); if (!IsDrilling) { IsDrilling = true; m_animationLastUpdateTime = MySandboxGame.TotalGamePlayTimeInMilliseconds; } ProfilerShort.End(); return drillingSuccess; }
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(); }
private static MyTuple <bool, float> TAPI_IntersectEntToShieldFast(List <MyEntity> entities, RayD ray, bool onlyIfOnline, bool enenmyOnly = false, long requesterId = 0, float maxLengthSqr = float.MaxValue) { if (enenmyOnly) { if (requesterId == 0) { return(new MyTuple <bool, float>(false, 0)); } } float closestOtherDist = float.MaxValue; float closestFriendDist = float.MaxValue; bool closestOther = false; bool closestFriend = false; for (int i = 0; i < entities.Count; i++) { var entity = entities[i]; ShieldGridComponent c; if (entity != null && Session.Instance.IdToBus.TryGetValue(entity.EntityId, out c) && c?.DefenseShields?.DsState?.State != null && c.DefenseShields.MyCube != null) { var s = c.DefenseShields; if (onlyIfOnline && (!s.DsState.State.Online || s.DsState.State.Lowered) || s.ReInforcedShield) { continue; } lock (s.MatrixLock) { var normSphere = new BoundingSphereD(Vector3.Zero, 1f); var kRay = new RayD(Vector3D.Zero, Vector3D.Forward); var ellipsoidMatrixInv = s.DetectMatrixOutsideInv; Vector3D krayPos; Vector3D.Transform(ref ray.Position, ref ellipsoidMatrixInv, out krayPos); Vector3D nDir; Vector3D.TransformNormal(ref ray.Direction, ref ellipsoidMatrixInv, out nDir); Vector3D krayDir; Vector3D.Normalize(ref nDir, out krayDir); kRay.Direction = krayDir; kRay.Position = krayPos; var nullDist = normSphere.Intersects(kRay); if (!nullDist.HasValue) { continue; } var hitPos = krayPos + (krayDir * -nullDist.Value); var ellipsoidMatrix = s.DetectMatrixOutside; Vector3D worldHitPos; Vector3D.Transform(ref hitPos, ref ellipsoidMatrix, out worldHitPos); var intersectDist = Vector3.DistanceSquared(worldHitPos, ray.Position); if (intersectDist <= 0 || intersectDist > maxLengthSqr) { continue; } var firstOrLast = enenmyOnly && (!closestFriend || intersectDist < closestFriendDist); var notEnemyCheck = false; if (firstOrLast) { var relationship = MyIDModule.GetRelationPlayerBlock(requesterId, s.MyCube.OwnerId); var enemy = relationship != MyRelationsBetweenPlayerAndBlock.Owner && relationship != MyRelationsBetweenPlayerAndBlock.FactionShare; notEnemyCheck = !enemy; } if (notEnemyCheck) { closestFriendDist = intersectDist; closestFriend = true; } else { closestOtherDist = intersectDist; closestOther = true; } } } } if (!enenmyOnly && closestOther || closestOther && !closestFriend) { return(new MyTuple <bool, float>(true, closestOtherDist)); } if (closestFriend && !closestOther || closestFriendDist < closestOtherDist) { return(new MyTuple <bool, float>(false, closestFriendDist)); } if (!closestOther) { return(new MyTuple <bool, float>(false, 0)); } return(new MyTuple <bool, float>(true, closestOtherDist)); }