Vector3D GetSpraySoundPosition() { IMyCharacter owner = Rifle.Owner as IMyCharacter; if (owner != null) { MatrixD headMatrix = owner.GetHeadMatrix(true, true); Vector3D soundPos = headMatrix.Translation + headMatrix.Down * 0.1 + headMatrix.Forward * 0.6; // HACK: sound somehow plays ahead of position, adjusted by trial and error if (owner.Physics != null) { soundPos -= owner.Physics.LinearVelocity / Constants.TICKS_PER_SECOND; // remove 1 tick worth of velocity } return(soundPos); } else { MatrixD muzzleMatrix = Rifle.GunBase.GetMuzzleWorldMatrix(); return(muzzleMatrix.Translation + muzzleMatrix.Forward * 0.2); } }
public static ConcurrentBag <MyGroups <MyCubeGrid, MyGridPhysicalGroupData> .Group> FindLookAtGridGroup(IMyCharacter controlledEntity) { const float range = 5000; Matrix worldMatrix; Vector3D startPosition; Vector3D endPosition; worldMatrix = controlledEntity.GetHeadMatrix(true, true, false); // dead center of player cross hairs, or the direction the player is looking with ALT. startPosition = worldMatrix.Translation + worldMatrix.Forward * 0.5f; endPosition = worldMatrix.Translation + worldMatrix.Forward * (range + 0.5f); var list = new Dictionary <MyGroups <MyCubeGrid, MyGridPhysicalGroupData> .Group, double>(); var ray = new RayD(startPosition, worldMatrix.Forward); foreach (var group in MyCubeGridGroups.Static.Physical.Groups) { foreach (MyGroups <MyCubeGrid, MyGridPhysicalGroupData> .Node groupNodes in group.Nodes) { IMyCubeGrid cubeGrid = groupNodes.NodeData; if (cubeGrid == null) { continue; } if (cubeGrid.Physics == null) { continue; } // check if the ray comes anywhere near the Grid before continuing. if (!ray.Intersects(cubeGrid.WorldAABB).HasValue) { continue; } Vector3I?hit = cubeGrid.RayCastBlocks(startPosition, endPosition); if (!hit.HasValue) { continue; } double distance = (startPosition - cubeGrid.GridIntegerToWorld(hit.Value)).Length(); if (list.TryGetValue(group, out double oldDistance)) { if (distance < oldDistance) { list.Remove(group); list.Add(group, distance); } } else { list.Add(group, distance); } } } var bag = new ConcurrentBag <MyGroups <MyCubeGrid, MyGridPhysicalGroupData> .Group>(); if (list.Count == 0) { return(bag); } // find the closest Entity. var item = list.OrderBy(f => f.Value).First(); bag.Add(item.Key); return(bag); }
public static List <MyCubeGrid> FindLookAtGridGroup(IMyCharacter controlledEntity, long playerId, out CheckResult result) { const float range = 5000; Matrix worldMatrix; Vector3D startPosition; Vector3D endPosition; var GridsGroup = new List <MyCubeGrid>(); var charlocation = controlledEntity.PositionComp.GetPosition(); var sphere = new BoundingSphereD(charlocation, range); var entList = MyAPIGateway.Entities.GetTopMostEntitiesInSphere(ref sphere); if (entList == null || entList.Count == 0) { result = CheckResult.GRID_NOT_FOUND; return(GridsGroup); } worldMatrix = controlledEntity.GetHeadMatrix(true, true, false); // dead center of player cross hairs, or the direction the player is looking with ALT. startPosition = worldMatrix.Translation + worldMatrix.Forward * 0.5f; endPosition = worldMatrix.Translation + worldMatrix.Forward * (range + 0.5f); var list = new Dictionary <MyCubeGrid, double>(); var ray = new RayD(startPosition, worldMatrix.Forward); var FoundWrongOwner = false; foreach (var ent in entList) { if (ent is MyCubeGrid cubeGrid) { if (cubeGrid.Physics != null) { // check if the ray comes anywhere near the Grid before continuing. if (ray.Intersects(cubeGrid.PositionComp.WorldAABB).HasValue) { Vector3I?hit = cubeGrid.RayCastBlocks(startPosition, endPosition); if (hit.HasValue) { /* We are not the server and playerId is not owner */ if (playerId != 0 && !OwnershipCorrect(cubeGrid, playerId)) { FoundWrongOwner = true; continue; } double distance = (startPosition - cubeGrid.GridIntegerToWorld(hit.Value)).Length(); if (list.TryGetValue(cubeGrid, out double oldDistance)) { if (distance < oldDistance) { list.Remove(cubeGrid); list.Add(cubeGrid, distance); } } else { list.Add(cubeGrid, distance); } } } } } } // find the closest Entity. if (list != null && list.Any()) { var grid = list.OrderBy(f => f.Value).First().Key; // only here we can see attached by landing gear grids to main grid! var IMygrids = new List <IMyCubeGrid>(); MyAPIGateway.GridGroups.GetGroup(grid, GridLinkTypeEnum.Physical, IMygrids); // convert back to MyCubeGrid foreach (var Mygrid in IMygrids) { GridsGroup.Add((MyCubeGrid)Mygrid); } // sort the list. largest to smallest GridsGroup.SortNoAlloc((x, y) => x.BlocksCount.CompareTo(y.BlocksCount)); GridsGroup.Reverse(); GridsGroup.SortNoAlloc((x, y) => x.GridSizeEnum.CompareTo(y.GridSizeEnum)); result = CheckResult.OK; return(GridsGroup); } if (FoundWrongOwner) { result = CheckResult.OWNED_BY_DIFFERENT_PLAYER; } else { result = CheckResult.GRID_NOT_FOUND; } return(GridsGroup); }
void GetTarget(IMyCharacter character, out IMyCubeGrid targetGrid, out IMySlimBlock targetBlock, out IMyPlayer targetPlayer, out Vector3D aimPoint) { targetGrid = null; targetBlock = null; targetPlayer = null; bool aiming = Utils.IsAimingDownSights(character); MatrixD head = character.GetHeadMatrix(false, true); Vector3D rayDir = head.Forward; Vector3D rayFrom = head.Translation; if (aiming) { rayFrom += rayDir * PAINT_AIM_START_OFFSET; } Vector3D rayTo = head.Translation + rayDir * PAINT_DISTANCE; aimPoint = rayTo; targetGrid = MyAPIGateway.CubeBuilder.FindClosestGrid(); if (targetGrid == null || targetGrid.Physics == null || !targetGrid.Physics.Enabled) { targetGrid = null; return; } // older selection behavior when aiming down sights if (aiming) { Vector3I?blockPos = targetGrid.RayCastBlocks(rayFrom, rayTo); if (blockPos.HasValue) { targetBlock = targetGrid.GetCubeBlock(blockPos.Value); } return; } // HACK copied and converted from MyDrillSensorRayCast.ReadEntitiesInRange() + MyCasterComponent.OnWorldPosChanged() // last cloned in SE v201 #region Welder-like block selection hits.Clear(); detections.Clear(); rayOverlapResults.Clear(); MyAPIGateway.Physics.CastRay(rayFrom, rayTo, hits, 24); foreach (IHitInfo hit in hits) { IMyEntity parent = hit.HitEntity?.GetTopMostParent(); if (parent == null || parent.Physics == null || !parent.Physics.Enabled) { continue; } Vector3D hitPos = hit.Position; IMyCubeGrid grid = parent as IMyCubeGrid; if (grid != null) { // just how it's set in game code /shrug hitPos += hit.Normal * -0.005f; } DetectionInfo detected; if (detections.TryGetValue(parent.EntityId, out detected)) { double dist1 = Vector3D.DistanceSquared(rayFrom, detected.DetectionPoint); double dist2 = Vector3D.DistanceSquared(rayFrom, hitPos); if (dist1 > dist2) { detections[parent.EntityId] = new DetectionInfo(parent, hitPos); } } else { detections[parent.EntityId] = new DetectionInfo(parent, hitPos); } } hits.Clear(); LineD line = new LineD(rayFrom, rayTo); MyGamePruningStructure.GetAllEntitiesInRay(ref line, rayOverlapResults); foreach (MyLineSegmentOverlapResult <MyEntity> result in rayOverlapResults) { if (result.Element == null) { continue; } IMyCubeBlock block = result.Element as IMyCubeBlock; if (block == null) { continue; } MyCubeBlockDefinition def = (MyCubeBlockDefinition)block.SlimBlock.BlockDefinition; if (def.HasPhysics) { continue; // this section is only for things that are not caught by the raycast } MyEntity parent = result.Element.GetTopMostParent(); if (parent.Physics == null || !parent.Physics.Enabled) { continue; } MatrixD invMatrix = block.PositionComp.WorldMatrixNormalizedInv; Vector3 localFrom = Vector3D.Transform(rayFrom, ref invMatrix); Vector3 localTo = Vector3D.Transform(rayTo, ref invMatrix); float?intersectDistance = new Ray(localFrom, Vector3.Normalize(localTo - localFrom)).Intersects(block.PositionComp.LocalAABB) + 0.01f; if (intersectDistance.HasValue && intersectDistance <= PAINT_DISTANCE) { Vector3D hitPos = rayFrom + rayDir * intersectDistance.Value; DetectionInfo detected; if (detections.TryGetValue(parent.EntityId, out detected)) { double dist1 = Vector3D.DistanceSquared(rayFrom, detected.DetectionPoint); double dist2 = Vector3D.DistanceSquared(rayFrom, hitPos); if (dist1 > dist2) { detections[parent.EntityId] = new DetectionInfo(parent, hitPos); } } else { detections[parent.EntityId] = new DetectionInfo(parent, hitPos); } } } rayOverlapResults.Clear(); if (detections.Count == 0) { return; } double closetDist = double.MaxValue; DetectionInfo closestObj = new DetectionInfo(null, Vector3D.Zero); foreach (DetectionInfo detected in detections.Values) { double dist = Vector3D.DistanceSquared(detected.DetectionPoint, rayFrom); if (dist < closetDist) { closestObj = detected; closetDist = dist; } } detections.Clear(); targetGrid = closestObj.Entity as IMyCubeGrid; if (targetGrid == null) { return; } Vector3D localPos = Vector3D.Transform(closestObj.DetectionPoint, targetGrid.WorldMatrixNormalizedInv); Vector3I cube; targetGrid.FixTargetCube(out cube, localPos / targetGrid.GridSize); targetBlock = targetGrid.GetCubeBlock(cube); #endregion Welder-like block selection }