internal bool IsInsideHelper(Vector3D pt, List <int> selector) { // ReSharper disable once ImpureMethodCallOnReadonlyValueField if (Box.Contains(pt) == ContainmentType.Disjoint) { return(false); } var ray = new RayD(pt, QueryDir); double dist; var i = 0; if (selector != null) { foreach (var id in selector) { var k = _tris[id]; if (k.Intersects(ref ray, out dist)) { i++; } } } else { foreach (var k in _tris) { if (k.Intersects(ref ray, out dist)) { i++; } } } return((i & 1) == 1); }
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> /// Moller-Trumbore Intersection /// </summary> /// <param name="ray"></param> /// <param name="t"></param> /// <returns></returns> public bool Intersects(ref RayD ray, out double t) { t = double.NaN; const float epsilon = 0.0000001f; Vector3 h = ((Vector3)ray.Direction).Cross(Edge2); float a = h.Dot(Edge1); if (a > -epsilon && a < epsilon) { return(false); } var f = 1 / a; Vector3D s = ray.Position - Origin; var u = f * (s.Dot(h)); if (u < 0.0 || u > 1.0) { return(false); } Vector3D q = s.Cross(Edge1); var v = f * ray.Direction.Dot(q); if (v < 0.0 || u + v > 1.0) { return(false); } t = f * q.Dot(Edge2); return(t > epsilon); }
private Vector3D ComputeHandlerImpact() { WebDamage = false; HandlerImpact.Active = false; if (HandlerImpact.HitBlock == null) { return(DetectionCenter); } Vector3D originHit; HandlerImpact.HitBlock.ComputeWorldCenter(out originHit); var line = new LineD(HandlerImpact.Attacker.PositionComp.WorldAABB.Center, originHit); var testDir = Vector3D.Normalize(line.From - line.To); var ray = new RayD(line.From, -testDir); var matrix = DetectionMatrix; var invMatrix = MatrixD.Invert(matrix); var intersectDist = CustomCollision.IntersectEllipsoid(ref invMatrix, matrix, ref ray); var ellipsoid = intersectDist ?? line.Length; var shieldHitPos = line.From + (testDir * -ellipsoid); return(shieldHitPos); }
public bool HitFriendlyShield(Vector3D weaponPos, Vector3D targetPos, Vector3D dir) { var testRay = new RayD(weaponPos, dir); Comp.Ai.TestShields.Clear(); var checkDistanceSqr = Vector3.DistanceSquared(targetPos, weaponPos); for (int i = 0; i < Comp.Ai.NearByFriendlyShields.Count; i++) { var shield = Comp.Ai.NearByFriendlyShields[i]; var dist = testRay.Intersects(shield.PositionComp.WorldVolume); if (dist != null && dist.Value * dist.Value <= checkDistanceSqr) { Comp.Ai.TestShields.Add(shield); } } if (Comp.Ai.TestShields.Count == 0) { return(false); } var result = Comp.Ai.Session.SApi.IntersectEntToShieldFast(Comp.Ai.TestShields, testRay, true, false, Comp.Ai.AiOwner, checkDistanceSqr); return(result.Item1 && result.Item2 > 0); }
public void Execute() { if (Entity == null || Entity.MarkedForClose) { return; } var floater = (IMyFloatingObject)Entity; var entVel = Entity.Physics.LinearVelocity; var movingVel = entVel != Vector3.Zero ? entVel : -Shield.MyGrid.Physics.LinearVelocity; var rayDir = Vector3D.Normalize(movingVel); var ray = new RayD(Entity.PositionComp.WorldVolume.Center, rayDir); var intersect = CustomCollision.IntersectEllipsoid(Shield.DetectMatrixOutsideInv, Shield.DetectionMatrix, ray); var hitDist = intersect ?? 0; var hitPos = ray.Position + (ray.Direction * -hitDist); if (Session.Instance.MpActive) { Shield.AddShieldHit(Entity.EntityId, 1, Session.Instance.MPKinetic, null, false, hitPos); floater.DoDamage(9999999, Session.Instance.MpIgnoreDamage, true, null, Shield.MyCube.EntityId); } else { Shield.WorldImpactPosition = hitPos; Shield.ImpactSize = 10; floater.DoDamage(9999999, Session.Instance.MpIgnoreDamage, false, null, Shield.MyCube.EntityId); } Shield.WebDamage = true; Shield.Absorb += 1; }
public void TestPlaneRayCast() { Random.InitState(123); for (int i = 0; i < 1000; i++) { Vector3 direction = Random.onUnitSphere; float dist = Random.Range(-999, 999); Vector3D directionD = new Vector3D(direction); Plane3D planeD = new Plane3D(directionD, dist); Plane plane = new Plane(direction, dist); for (int j = 0; j < 10; j++) { Vector3 pos = Random.insideUnitSphere * 999; Vector3 rayDir = Random.onUnitSphere; Vector3D posD = new Vector3D(pos); Vector3D rayDirD = new Vector3D(rayDir); Ray r = new Ray(pos, rayDir); RayD rd = new RayD(posD, rayDirD); float enter; double enterD; bool res = plane.Raycast(r, out enter); bool resD = planeD.Raycast(rd, out enterD); Assert.AreEqual(res, resD, "Raycast Res " + plane + " ray " + r); if (enterD < 1e7) { Assert.AreEqual((double)enter, enterD, Mathf.Abs(enter) / 1000, "GetDistanceToPoint " + plane + " ray " + r); } } } }
private Vector3 GetBoneOnSphere(Vector3I center, Vector3I bonePos, MyCubeGrid grid) { Vector3D worldCenter = BoneToWorld(center, Vector3.Zero, grid); Vector3D worldBone = BoneToWorld(bonePos, Vector3.Zero, grid); BoundingSphereD sphere = new BoundingSphereD(worldCenter, grid.GridSize); Vector3D direction = worldCenter - worldBone; direction.Normalize(); RayD ray = new RayD(worldBone, direction); double tmin, tmax; if (sphere.IntersectRaySphere(ray, out tmin, out tmax)) { Vector3D onSphere = worldBone + direction * tmin; var worldOnSphere = Vector3D.Transform(onSphere, grid.PositionComp.WorldMatrixInvScaled); worldOnSphere += new Vector3D(grid.GridSize / grid.Skeleton.BoneDensity); return(worldOnSphere - (Vector3D)(bonePos / (float)grid.Skeleton.BoneDensity) * grid.GridSize); } else { return(Vector3.Zero); } }
private static Vector3D?TAPI_LineIntersectShield(IMyTerminalBlock block, LineD line) { var logic = block?.GameLogic?.GetAs <DefenseShields>()?.ShieldComp?.DefenseShields; if (logic == null) { return(null); } var ray = new RayD(line.From, line.Direction); float?intersectDist; lock (logic.MatrixLock) intersectDist = CustomCollision.IntersectEllipsoid(logic.DetectMatrixOutsideInv, logic.DetectMatrixOutside, ray); if (!intersectDist.HasValue) { return(null); } var ellipsoid = intersectDist ?? 0; if (ellipsoid > line.Length) { return(null); } return(ray.Position + (ray.Direction * ellipsoid)); }
private bool RayCheckTargets(Vector3D origin, Vector3D dir, out MyEntity closestEnt, out Vector3D hitPos, out bool foundOther, bool checkOthers = false) { var ai = _session.TrackingAi; var closestDist = double.MaxValue; closestEnt = null; foreach (var info in ai.Targets.Keys) { var hit = info as MyCubeGrid; if (hit == null) { continue; } var ray = new RayD(origin, dir); var dist = ray.Intersects(info.PositionComp.WorldVolume); if (dist.HasValue) { if (dist.Value < closestDist) { closestDist = dist.Value; closestEnt = hit; } } } foundOther = false; if (checkOthers) { for (int i = 0; i < ai.Obstructions.Count; i++) { var otherEnt = ai.Obstructions[i]; if (otherEnt is MyCubeGrid) { var ray = new RayD(origin, dir); var dist = ray.Intersects(otherEnt.PositionComp.WorldVolume); if (dist.HasValue) { if (dist.Value < closestDist) { closestDist = dist.Value; closestEnt = otherEnt; foundOther = true; } } } } } if (closestDist < double.MaxValue) { hitPos = origin + (dir * closestDist); } else { hitPos = Vector3D.Zero; } return(closestEnt != null); }
// ModApi only methods below private static Vector3D?TAPI_RayAttackShield(IMyTerminalBlock block, RayD ray, long attackerId, float damage, bool energy, bool drawParticle) { var logic = block?.GameLogic?.GetAs <DefenseShields>()?.ShieldComp?.DefenseShields; if (logic == null) { return(null); } float?intersectDist; lock (logic.MatrixLock) intersectDist = CustomCollision.IntersectEllipsoid(logic.DetectMatrixOutsideInv, logic.DetectMatrixOutside, ray); if (!intersectDist.HasValue) { return(null); } var ellipsoid = intersectDist ?? 0; var hitPos = ray.Position + (ray.Direction * ellipsoid); if (energy) { damage *= logic.DsState.State.ModulateKinetic; } else { damage *= logic.DsState.State.ModulateEnergy; } if (Session.Instance.MpActive) { var damageType = energy ? Session.Instance.MPEnergy : Session.Instance.MPKinetic; logic.AddShieldHit(attackerId, damage, damageType, null, true, hitPos); } else { if (!drawParticle) { logic.EnergyHit = DefenseShields.HitType.Other; } else if (energy) { logic.EnergyHit = DefenseShields.HitType.Energy; } else { logic.EnergyHit = DefenseShields.HitType.Kinetic; } logic.ImpactSize = damage; logic.WorldImpactPosition = hitPos; } logic.WebDamage = true; logic.Absorb += damage; return(hitPos); }
private void CheckInput() { MatrixD headMatrix = MyAPIGateway.Session.ControlledObject.GetHeadMatrix(true); RayD ray = new RayD(headMatrix.Translation, headMatrix.Forward); BoundingSphereD holoSphere = new BoundingSphereD(m_offset.ToWorld(m_block), m_radiusHolo); double tmin, tmax; if (!holoSphere.IntersectRaySphere(ray, out tmin, out tmax) || tmin > CrosshairRange) { return; } int scroll = MyAPIGateway.Input.DeltaMouseScrollWheelValue(); if (scroll != 0) { int scrollSteps = (int)Math.Round(scroll * InputScrollMulti); float rangeMulti = 1f; while (scrollSteps > 0) { rangeMulti *= ScrollRangeMulti; scrollSteps--; } while (scrollSteps < 0) { rangeMulti /= ScrollRangeMulti; scrollSteps++; } m_rangeDetection *= rangeMulti; } if (MyAPIGateway.Input.IsNewRightMousePressed()) { m_centreEntityId = 0L; } else if (MyAPIGateway.Input.IsNewLeftMousePressed()) { IMyEntity firstHit = null; double firstHitDistance = CrosshairRange; foreach (SeenHolo sh in m_holoEntities.Values) { if (sh.Holo.Render.Visible && sh.Holo.PositionComp.WorldAABB.Intersect(ref ray, out tmin, out tmax) && tmin < firstHitDistance) { firstHit = sh.Seen.Entity; firstHitDistance = tmin; } } if (firstHit != null) { m_centreEntityId = firstHit.EntityId; } } }
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)); }
public double GetSurfaceHeight(Vector3d planetLocalPosition, int detailDensity = 1) { double height = -1; //planetLocalPosition.Normalize(); var rayFromPlanet = new RayD(Vector3d.Zero, planetLocalPosition); var chunk = rootSegments.FirstOrDefault(c => rayFromPlanet.CastRay(c.NoElevationRange).DidHit); if (chunk != null) { //lock (chunk) { int safe = 100; while (chunk.Children.Count > 0 && chunk.Children.Any(c => c.IsGenerationDone) && safe-- > 0) { foreach (var child in chunk.Children) { if (child.IsGenerationDone && rayFromPlanet.CastRay(child.NoElevationRange).DidHit) { chunk = child; } } } } var chunkLocalPosition = (planetLocalPosition - chunk.NoElevationRange.CenterPos); height = chunk.GetHeight(chunkLocalPosition); } if (GetSurfaceHeightDebug) { if (height == -1) { height = RadiusMin; if (chunk == null) { Scene.DebugShere(GetPosition(planetLocalPosition, height), 1000, new Vector4(1, 0, 0, 1)); } else { Scene.DebugShere(GetPosition(planetLocalPosition, height), 1000, new Vector4(1, 1, 0, 1)); } } else { Scene.DebugShere(GetPosition(planetLocalPosition, height), 1000, new Vector4(0, 1, 0, 1)); } } return(height); }
//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); }
protected bool GetCubeAddAndRemovePositions(Vector3I intersectedCube, bool placingSmallGridOnLargeStatic, out Vector3I addPos, out Vector3I addDir, out Vector3I removePos) { bool result = false; addPos = new Vector3I(); addDir = new Vector3I(); removePos = new Vector3I(); MatrixD worldInv = MatrixD.Invert(CurrentGrid.WorldMatrix); Vector3D intersectionPos; addPos = intersectedCube; addDir = Vector3I.Forward; Vector3D rayStart = Vector3D.Transform(IntersectionStart, worldInv); Vector3D rayDir = Vector3D.Normalize(Vector3D.TransformNormal(IntersectionDirection, worldInv)); RayD r = new RayD(rayStart, rayDir); for (int i = 0; i < 100; ++i) // Limit iterations to 100 { var cubeBb = GetCubeBoundingBox(addPos); if (!placingSmallGridOnLargeStatic && cubeBb.Contains(rayStart) == ContainmentType.Contains) { break; } double?dist = cubeBb.Intersects(r); if (!dist.HasValue) { break; } removePos = addPos; intersectionPos = rayStart + rayDir * dist.Value; Vector3 center = removePos * CurrentGrid.GridSize; Vector3I dirInt = Vector3I.Sign(Vector3.DominantAxisProjection(intersectionPos - center)); addPos = removePos + dirInt; addDir = dirInt; result = true; if (!CurrentGrid.CubeExists(addPos)) { break; } } Debug.Assert(!result || addDir != Vector3I.Zero, "Direction vector cannot be zero"); return(result); }
public bool Raycast(RayD ray, out double enter) { double num = Vector3D.Dot (ray.direction, this.normal); double num2 = -Vector3D.Dot (ray.origin, this.normal) - this.distance; if (Mathf.Approximately ((float)num, 0f)) { enter = 0f; return false; } enter = num2 / num; return enter > 0f; }
private static MyTuple <float?, IMyTerminalBlock> TAPI_ClosestShieldInLine(LineD line, bool onlyIfOnline) { var segment = SegmentPool.Get(); MyGamePruningStructure.GetTopmostEntitiesOverlappingRay(ref line, segment, MyEntityQueryType.Dynamic); var ray = new RayD(line.From, line.Direction); var closest = float.MaxValue; IMyTerminalBlock closestShield = null; for (int i = 0; i < segment.Count; i++) { var ent = segment[i].Element; if (ent == null || ent.Physics != null && !ent.Physics.IsPhantom) { continue; } ShieldGridComponent c; if (Session.Instance.IdToBus.TryGetValue(ent.EntityId, out c) && c.DefenseShields != null) { if (onlyIfOnline && (!c.DefenseShields.DsState.State.Online || c.DefenseShields.DsState.State.Lowered)) { continue; } var s = c.DefenseShields; var intersectDist = CustomCollision.IntersectEllipsoid(s.DetectMatrixOutsideInv, s.DetectMatrixOutside, ray); if (!intersectDist.HasValue) { continue; } var ellipsoid = intersectDist ?? 0; if (ellipsoid > line.Length || ellipsoid > closest || CustomCollision.PointInShield(ray.Position, s.DetectMatrixOutsideInv)) { continue; } closest = ellipsoid; closestShield = s.Shield; } } segment.Clear(); SegmentPool.Return(segment); var response = new MyTuple <float?, IMyTerminalBlock>(); if (closestShield == null) { response.Item1 = null; response.Item2 = null; return(response); } response.Item1 = closest; response.Item2 = closestShield; return(response); }
public bool Raycast(RayD ray, out double enter) { double num = Vector3D.Dot(ray.direction, normal); double num2 = -Vector3D.Dot(ray.origin, normal) - distance; if (Mathf.Approximately((float)num, 0f)) { enter = 0f; return(false); } enter = num2 / num; return(enter > 0f); }
// return NaN if line is parallel with plane public Vector3D LineIntersection(Vector3D lineFrom, Vector3D lineTo) { var ray = new RayD(lineFrom, (lineTo - lineFrom).normalized); double enter; double num = Vector3D.Dot(ray.direction, normal); double num2 = -Vector3D.Dot(ray.origin, normal) - distance; if (num == 0) { return(Vector3D.one * double.NaN); } enter = num2 / num; return(ray.GetPointAt(enter)); }
Vector3D ProjectToTriangle(Vector3D point) { Plane3D plane = new Plane3D(Normal, points[0]); bool isPointInPlane = System.Math.Abs(plane.GetDistanceToPoint(point)) < 0.0001; if (!isPointInPlane) { double dist; point.y = 0; var ray = new RayD(point, Vector3D.up); plane.Raycast(ray, out dist); point.y = dist; } return(point); }
/** * Project a position to a face of the (-1, -1, -1)(1, 1, 1) cube. */ public static void ProjectToNearestFace(ref Vector3D localPos, out Vector3 faceCoords) { Vector3D gravity; Vector3D.Normalize(ref localPos, out gravity); gravity = -gravity; RayD r = new RayD(localPos, gravity); double?travel = s_unitsBox.Intersects(r); Debug.Assert(travel.HasValue, "Ray does not intersect with planet!"); faceCoords = localPos + (Vector3D)(gravity * travel); }
public bool IsBlockInTheWay(Vector3D origin, Vector3D targetPos, IMyCubeBlock constructBlock = null) { if (!Enabled) { return(false); } Vector3D targetDir = targetPos - origin; RayD line = new RayD(origin, targetDir); foreach (var grid in grids.Values) { if (constructBlock != null) { if (!constructBlock.CubeGrid.IsSameConstructAs(grid.grid)) { continue; } } double?result; if (grid.grid.WorldVolume.Contains(origin) != ContainmentType.Contains) { result = grid.grid.WorldVolume.Intersects(line); if (!result.HasValue) { continue; } targetDir.Normalize(); if (grid.IsBlockInTheWay(origin + targetDir * result.Value, targetPos)) { return(true); } } if (grid.IsBlockInTheWay(origin, targetPos)) { return(true); } } 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 bool IsVerticesLinear() { List <Vector3D> list = new List <Vector3D>(); double maxDist = 0; int maxIndexFrom = -1; int maxIndexTo = -1; var hes = Circulate(); for (int i = 0; i < hes.Count; i++) { var pos = hes[i].vert.positionD; if (list.Count > 2) { for (int j = 0; j < list.Count; j++) { double dist = Vector3D.Distance(pos, list[j]); if (dist > maxDist) { maxDist = dist; maxIndexFrom = i; maxIndexTo = j; } } } list.Add(pos); } if (maxIndexFrom == maxIndexTo) { // all same position return(true); } RayD r = new RayD(list[maxIndexFrom], list[maxIndexFrom] - list[maxIndexTo]); foreach (var p in list) { if (r.LinePointDistance(p) > hmesh.zeroMagnitudeTreshold) { // not linear return(false); } } return(true); }
internal void AddProjectileTargets() // This calls AI late for fragments need to fix { for (int i = 0; i < AddTargets.Count; i++) { var p = AddTargets[i]; for (int t = 0; t < p.Info.Ai.TargetAis.Count; t++) { var targetAi = p.Info.Ai.TargetAis[t]; var addProjectile = p.Info.AmmoDef.Trajectory.Guidance != GuidanceType.None && targetAi.PointDefense; if (!addProjectile && targetAi.PointDefense) { if (Vector3.Dot(p.Info.Direction, p.Info.Origin - targetAi.MyGrid.PositionComp.WorldMatrixRef.Translation) < 0) { var targetSphere = targetAi.MyGrid.PositionComp.WorldVolume; targetSphere.Radius *= 3; var testRay = new RayD(p.Info.Origin, p.Info.Direction); var quickCheck = Vector3D.IsZero(targetAi.GridVel, 0.025) && targetSphere.Intersects(testRay) != null; if (!quickCheck) { var deltaPos = targetSphere.Center - p.Info.Origin; var deltaVel = targetAi.GridVel - p.Info.Ai.GridVel; var timeToIntercept = MathFuncs.Intercept(deltaPos, deltaVel, p.Info.AmmoDef.Const.DesiredProjectileSpeed); var predictedPos = targetSphere.Center + (float)timeToIntercept * deltaVel; targetSphere.Center = predictedPos; } if (quickCheck || targetSphere.Intersects(testRay) != null) { addProjectile = true; } } } if (addProjectile) { targetAi.DeadProjectiles.Remove(p); targetAi.LiveProjectile.Add(p); targetAi.LiveProjectileTick = Session.Tick; targetAi.NewProjectileTick = Session.Tick; p.Watchers.Add(targetAi); } } } AddTargets.Clear(); }
void ReprojectY(List <Triangle> res, Plane3D plane) { double pos = 0; foreach (var t in res) { for (int i = 0; i < 3; i++) { var p = t.points[i]; p.y = 0; RayD r = new RayD(p, Vector3D.up); if (plane.Raycast(r, out pos)) { p.y = (float)pos; t.points[i] = p; } } } }
protected bool GetCubeAddAndRemovePositions(Vector3I intersectedCube, bool placingSmallGridOnLargeStatic, out Vector3I addPos, out Vector3I addDir, out Vector3I removePos) { bool flag = false; addPos = new Vector3I(); addDir = new Vector3I(); removePos = new Vector3I(); MatrixD worldMatrixInvScaled = this.CurrentGrid.PositionComp.WorldMatrixInvScaled; addPos = intersectedCube; addDir = Vector3I.Forward; Vector3D position = Vector3D.Transform(IntersectionStart, worldMatrixInvScaled); Vector3D direction = Vector3D.Normalize(Vector3D.TransformNormal(IntersectionDirection, worldMatrixInvScaled)); RayD ray = new RayD(position, direction); int num = 0; while (true) { if (num < 100) { BoundingBoxD cubeBoundingBox = this.GetCubeBoundingBox(addPos); if (placingSmallGridOnLargeStatic || (cubeBoundingBox.Contains(position) != ContainmentType.Contains)) { double?nullable = cubeBoundingBox.Intersects(ray); if (nullable != null) { removePos = addPos; Vector3I vectori = Vector3I.Sign(Vector3.DominantAxisProjection((Vector3)((position + (direction * nullable.Value)) - (removePos * this.CurrentGrid.GridSize)))); addPos = (Vector3I)(removePos + vectori); addDir = vectori; if (this.CurrentGrid.CubeExists(addPos)) { num++; continue; } flag = true; } } } return(flag); } }
public void Execute() { if (Entity == null || !Entity.InScene || Entity.MarkedForClose) { return; } var computedDamage = UtilsStatic.ComputeAmmoDamage(Entity); var damage = computedDamage * Shield.DsState.State.ModulateKinetic; if (computedDamage < 0) { damage = computedDamage; } var rayDir = Vector3D.Normalize(Entity.Physics.LinearVelocity); var ray = new RayD(Entity.PositionComp.WorldVolume.Center, rayDir); var intersect = CustomCollision.IntersectEllipsoid(ref Shield.DetectMatrixOutsideInv, Shield.DetectionMatrix, ref ray); var hitDist = intersect ?? 0; var hitPos = ray.Position + (ray.Direction * -hitDist); if (Session.Instance.MpActive) { Shield.AddShieldHit(Entity.EntityId, damage, Session.Instance.MPExplosion, null, true, hitPos); Entity.Close(); Entity.InScene = false; } else { Shield.EnergyHit = DefenseShields.HitType.Energy; Shield.WorldImpactPosition = hitPos; Shield.ImpactSize = damage; UtilsStatic.CreateFakeSmallExplosion(hitPos); Entity.Close(); Entity.InScene = false; } Shield.WebDamage = true; Shield.Absorb += damage; Shield.EnergyDamage += damage; Session.Instance.MissilePool.Return(this); }
public override IMyUseObject RaycastDetectors(Vector3D worldFrom, Vector3D worldTo, out float parameter) { MyPositionComponentBase base2 = base.Container.Get <MyPositionComponentBase>(); MatrixD worldMatrixNormalizedInv = base2.WorldMatrixNormalizedInv; RayD ray = new RayD(worldFrom, worldTo - worldFrom); IMyUseObject useObject = null; parameter = float.MaxValue; foreach (KeyValuePair <uint, DetectorData> pair in this.m_detectorInteractiveObjects) { MatrixD matrix = pair.Value.Matrix * base2.WorldMatrix; double? nullable = new MyOrientedBoundingBoxD(matrix).Intersects(ref ray); if ((nullable != null) && (nullable.Value < ((double)parameter))) { parameter = (float)nullable.Value; useObject = pair.Value.UseObject; } } return(useObject); }
public static bool IntersectPoints(this BoundingBoxD boundingBox, Vector3D position, Vector3D target, out Vector3D?hitIngoing, out Vector3D?hitOutgoing) { //if (!Sandbox.Game.Entities.MyEntities.IsRaycastBlocked(position, target)) //{ // hitIngoing = null; // hitOutgoing = null; // return false; //} // big enough for planets double outbound = 200000; var direction = Vector3D.Normalize(target - position); var ray = new RayD(position + direction * -outbound, Vector3D.Normalize(direction * outbound)); var interset = boundingBox.Intersects(ray); if (interset.HasValue) { hitIngoing = position + direction * -outbound + (direction * interset.Value); } else { hitIngoing = null; } direction = Vector3D.Normalize(position - target); ray = new RayD(target + direction * -outbound, Vector3D.Normalize(direction * outbound)); interset = boundingBox.Intersects(ray); if (interset.HasValue) { hitOutgoing = target + direction * -outbound + (direction * interset.Value); } else { hitOutgoing = null; } return(hitIngoing.HasValue && hitOutgoing.HasValue); }
public override bool Invoke(string messageText) { #region test if (messageText.Equals("/test", StringComparison.InvariantCultureIgnoreCase)) { // for testing things. //MyAPIGateway.Utilities.ShowMessage("path", MyAPIGateway.Session.CurrentPath); //MyAPIGateway.Utilities.ShowMessage("size1", MyAPIGateway.Utilities.ConfigDedicated.SessionSettings.WorldSizeKm.ToString()); //MyAPIGateway.Utilities.ShowMessage("size2", MyAPIGateway.Session.GetWorld().Checkpoint.Settings.WorldSizeKm.ToString()); IMyConfigDedicated config = null; //List<string> admins = null; try { config = MyAPIGateway.Utilities.ConfigDedicated; config.Load(); //config. } catch (Exception) { MyAPIGateway.Utilities.ShowMessage("Exception", "ConfigDedicated"); //ex.Message); } if (config != null) { try { var players = new List<IMyPlayer>(); MyAPIGateway.Players.GetPlayers(players, p => p != null); MyAPIGateway.Utilities.ShowMessage("Player Count", string.Format("{0}", players.Count)); var identities = new List<IMyIdentity>(); MyAPIGateway.Players.GetAllIdentites(identities); MyAPIGateway.Utilities.ShowMessage("Identities Count", string.Format("{0}", identities.Count)); MyAPIGateway.Utilities.ShowMessage("Admin Count", string.Format("{0}", config.Administrators.Count)); //MyAPIGateway.Utilities.ShowMessage("WorldName", string.Format("{0}", config.WorldName)); //MyAPIGateway.Utilities.ShowMessage("WorldSize", string.Format("{0}", config.SessionSettings.WorldSizeKm)); MyAPIGateway.Utilities.ShowMessage("Mods Count", string.Format("{0}", config.Mods.Count)); //MyAPIGateway.Utilities.ShowMessage("IP", string.Format("{0}", config.IP)); var clients = MyAPIGateway.Session.GetWorld().Checkpoint.Clients; MyAPIGateway.Utilities.ShowMessage("Client Count", clients == null ? "null" : string.Format("{0}", clients.Count)); if (clients != null) { var client = clients.FirstOrDefault(c => c.SteamId == MyAPIGateway.Multiplayer.MyId); if (client != null) { MyAPIGateway.Utilities.ShowMessage("IsAdmin", string.Format("{0}", client.IsAdmin)); } } } catch (Exception) { MyAPIGateway.Utilities.ShowMessage("Exception", "reading config"); //ex.Message); } } return true; } #endregion #region test2 if (messageText.Equals("/test2", StringComparison.InvariantCultureIgnoreCase)) { // for testing things. var count = MyAPIGateway.Utilities.ConfigDedicated.Administrators.Count.ToString(CultureInfo.InvariantCulture); MyAPIGateway.Utilities.ShowMessage("Admins", string.Format("Count {0}", count)); MyAPIGateway.Utilities.ShowMessage("Players", string.Format("Count {0}", MyAPIGateway.Players.Count)); MyAPIGateway.Utilities.ShowMessage("MultiPlayers", string.Format("Count {0}", MyAPIGateway.Multiplayer.Players.Count)); return true; } #endregion #region test3 if (messageText.Equals("/test3", StringComparison.InvariantCultureIgnoreCase)) { // for testing things. MyAPIGateway.Utilities.ShowMessage("MyId", "{0}", MyAPIGateway.Multiplayer.MyId); MyAPIGateway.Utilities.ShowMessage("SteamId", "{0}", MyAPIGateway.Session.Player.SteamUserId); MyAPIGateway.Utilities.ShowMessage("MyName", "{0}", MyAPIGateway.Multiplayer.MyName); MyAPIGateway.Utilities.ShowMessage("IsServer", "{0}", MyAPIGateway.Multiplayer.IsServer); MyAPIGateway.Utilities.ShowMessage("IsServerPlayer", "{0}", MyAPIGateway.Multiplayer.IsServerPlayer(MyAPIGateway.Session.Player.Client)); MyAPIGateway.Utilities.ShowMessage("MultiplayerActive", "{0}", MyAPIGateway.Multiplayer.MultiplayerActive); MyAPIGateway.Utilities.ShowMessage("OnlineMode", "{0}", MyAPIGateway.Session.OnlineMode); MyAPIGateway.Utilities.ShowMessage("IsDedicated", "{0}", MyAPIGateway.Utilities.IsDedicated); //MyAPIGateway.Utilities.ShowMessage("Culture", "{0}", MyTexts.Culture.IetfLanguageTag); MyAPIGateway.Utilities.ShowMessage("Culture", "{0} {1}", CultureInfo.CurrentUICulture, CultureInfo.CurrentUICulture.IetfLanguageTag); var ed = ((MyObjectBuilder_EnvironmentDefinition)MyDefinitionManager.Static.EnvironmentDefinition.GetObjectBuilder()); MyAPIGateway.Utilities.ShowMessage("LargeShipMaxSpeed", "{0}", ed.LargeShipMaxSpeed); MyAPIGateway.Utilities.ShowMessage("SunDirection", "{0} {1} {2}", ed.SunDirection.X, ed.SunDirection.Y, ed.SunDirection.Z); return true; } #endregion #region test4 if (messageText.Equals("/test4", StringComparison.InvariantCultureIgnoreCase)) { var player = MyAPIGateway.Session.Player; if (player != null) { var pos = player.GetPosition(); MyAPIGateway.Utilities.ShowMessage("Player", "pos={0:N},{1:N},{2:N}", pos.X, pos.Y, pos.Z); } var cockpit = MyAPIGateway.Session.ControlledObject as Sandbox.ModAPI.Ingame.IMyCockpit; var remoteControl = MyAPIGateway.Session.ControlledObject as Sandbox.ModAPI.Ingame.IMyRemoteControl; var character = MyAPIGateway.Session.ControlledObject as Sandbox.ModAPI.IMyCharacter; var character2 = MyAPIGateway.Session.ControlledObject as Sandbox.Game.Entities.Character.MyCharacter; var camera = MyAPIGateway.Session.ControlledObject as Sandbox.ModAPI.IMyCamera; var cameraBlock = MyAPIGateway.Session.ControlledObject as Sandbox.ModAPI.Ingame.IMyCameraBlock; var cameraController = MyAPIGateway.Session.ControlledObject as Sandbox.ModAPI.Interfaces.IMyCameraController; var spectator = MyAPIGateway.Session.ControlledObject as VRage.MySpectator; if (cockpit != null) { MyAPIGateway.Utilities.ShowMessage("Control", "in cockpit."); } if (remoteControl != null) { MyAPIGateway.Utilities.ShowMessage("Control", "remoting."); } if (character != null) { MyAPIGateway.Utilities.ShowMessage("Control", "character."); } if (character2 != null) { //var pos = character2.PositionComp.GetPosition(); // Uses MyEntity which is not whitelisted. MyAPIGateway.Utilities.ShowMessage("Control", "character2."); } if (camera != null) { MyAPIGateway.Utilities.ShowMessage("Control", "camera."); } if (cameraBlock != null) { MyAPIGateway.Utilities.ShowMessage("Control", "camera block."); } if (cameraController != null) { var pos = cameraController.GetViewMatrix().Translation; MyAPIGateway.Utilities.ShowMessage("Control", "camera controller 1. FPV={0} POS={1:N},{2:N},{3:N}", cameraController.IsInFirstPersonView, pos.X, pos.Y, pos.Z); } if (MyAPIGateway.Session.ControlledObject.Entity is Sandbox.ModAPI.Interfaces.IMyCameraController) { MyAPIGateway.Utilities.ShowMessage("Control", "camera controller 2."); } //MyAPIGateway.Utilities.ShowMessage("Player", "Spectator1. {0}", VRage.Common.MySpectator.Static.IsInFirstPersonView); //System.Windows.Forms.Clipboard.SetText("hello"); if (spectator != null) { MyAPIGateway.Utilities.ShowMessage("Player", "Spectator1."); } if (MyAPIGateway.Session.ControlledObject.Entity is MySpectator) { MyAPIGateway.Utilities.ShowMessage("Player", "Spectator2."); } //else //{ // MyAPIGateway.Utilities.ShowMessage("Player", "other."); //} return true; var playerMatrix = MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.WorldMatrix; var playerPosition = playerMatrix.Translation + playerMatrix.Forward * 0.5f + playerMatrix.Up * 1.0f; MyAPIGateway.Utilities.ShowMessage("Pos", string.Format("x={0:N},y={1:N},z={2:N} x={3:N},y={4:N},z={5:N}", playerPosition.X, playerPosition.Y, playerPosition.Z, playerMatrix.Forward.X, playerMatrix.Forward.Y, playerMatrix.Forward.Z)); //MyAPIGateway.Utilities.ShowMessage("Up", string.Format("x={0:N},y={1:N},z={2:N}", playerMatrix.Up.X, playerMatrix.Up.Y, playerMatrix.Up.Z)); // TODO: need to properly establish control state and how to tell which state we are in. // Player - First person. // Player - thrid person. // Cockpit - First person. ControlledObject.GetHeadMatrix(true, true, true); // Cockpit - thrid person. ControlledObject.GetHeadMatrix(true, true, true); // Spectator freeview. CameraController.GetViewMatrix() but corrupted pos and vector. // Camera. CameraController.GetViewMatrix() //MyAPIGateway.Session.Player.PlayerCharacter.GetHeadMatrix(true, true, true); //MyAPIGateway.Session.CameraController.GetViewMatrix(); //MyAPIGateway.Session.ControlledObject.GetHeadMatrix(true, true, true); //Sandbox.ModAPI.IMyControllerInfo //? //Sandbox.ModAPI.IMyEntityController //Sandbox.ModAPI.Interfaces.IMyCameraController //Sandbox.ModAPI.Interfaces.IMyControllableEntity // The CameraController.GetViewMatrix appears warped at the moment. //var position = ((IMyEntity)MyAPIGateway.Session.CameraController).GetPosition(); var camMatrix = MyAPIGateway.Session.CameraController.GetViewMatrix(); var camPosition = camMatrix.Translation; MyAPIGateway.Utilities.ShowMessage("Cam", string.Format("x={0:N},y={1:N},z={2:N} x={3:N},y={4:N},z={5:N}", camPosition.X, camPosition.Y, camPosition.Z, camMatrix.Forward.X, camMatrix.Forward.Y, camMatrix.Forward.Z)); //var worldMatrix = MyAPIGateway.Session.ControlledObject.Entity.WorldMatrix; var worldMatrix = MyAPIGateway.Session.ControlledObject.GetHeadMatrix(true, true, true); var position = worldMatrix.Translation; MyAPIGateway.Utilities.ShowMessage("Con", string.Format("x={0:N},y={1:N},z={2:N} x={3:N},y={4:N},z={5:N}", position.X, position.Y, position.Z, worldMatrix.Forward.X, worldMatrix.Forward.Y, worldMatrix.Forward.Z)); //MyAPIGateway.Session.Player.PlayerCharacter.MoveAndRotate(new Vector3(), new Vector2(0, 0), 90f); //MyAPIGateway.Session.Player.PlayerCharacter.MoveAndRotate(new Vector3(), new Vector2(3.14f, 0), 0f); //MyAPIGateway.Session.Player.PlayerCharacter.Up(); // thrust, walk player forward? //MyAPIGateway.Session.Player.PlayerCharacter.Entity.worldmatrix //var character = (MyObjectBuilder_Character)obj; return true; } #endregion #region test5 if (messageText.Equals("/test5", StringComparison.InvariantCultureIgnoreCase)) { var worldMatrix = MyAPIGateway.Session.Player.Controller.ControlledEntity.GetHeadMatrix(true, true, true); // most accurate for player view. var position = worldMatrix.Translation + worldMatrix.Forward * 0.5f; var entites = new HashSet<IMyEntity>(); MyAPIGateway.Entities.GetEntities(entites, e => e != null); var list = new Dictionary<IMyEntity, double>(); foreach (var entity in entites) { var cubeGrid = entity as Sandbox.ModAPI.IMyCubeGrid; // check if the ray comes anywhere near the Grid before continuing. var ray = new RayD(position, worldMatrix.Forward); if (cubeGrid != null && ray.Intersects(entity.WorldAABB).HasValue) { var hit = cubeGrid.RayCastBlocks(position, worldMatrix.Forward * 1000); if (hit.HasValue) { var blocks = new List<Sandbox.ModAPI.IMySlimBlock>(); cubeGrid.GetBlocks(blocks, f => f.FatBlock != null); MyAPIGateway.Utilities.ShowMessage("AABB", string.Format("{0}", entity.WorldAABB)); // var block = blocks[0]; // //block.wo // var hsv = block.FatBlock.GetDiffuseColor(); // MyAPIGateway.Utilities.ShowMessage("Hsv", string.Format("{0},{1},{2} {3}", hsv.X, hsv.Y, hsv.Z, 1.45f)); // var c = VRageMath.ColorExtensions.HSVtoColor(hsv); // MyAPIGateway.Utilities.ShowMessage("Rgb", string.Format("{0},{1},{2}", c.R, c.G, c.B)); } } } return true; } #endregion #region test6 if (messageText.Equals("/test6", StringComparison.InvariantCultureIgnoreCase)) { var entity = MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity; //MyAPIGateway.Utilities.ShowMessage("AABB", string.Format("{0}", entity.WorldAABB)); //MyAPIGateway.Utilities.ShowMessage("Size", string.Format("{0}", entity.WorldAABB.Size())); //if (entity is IMyPlayer) // MyAPIGateway.Utilities.ShowMessage("IMyPlayer", "true"); //if (entity is IMyCubeBlock) // MyAPIGateway.Utilities.ShowMessage("IMyCubeBlock", "true"); // Ship //if (entity is IMyCubeGrid) // MyAPIGateway.Utilities.ShowMessage("IMyCubeGrid", "true"); //if (entity is IMyIdentity) // MyAPIGateway.Utilities.ShowMessage("IMyIdentity", "true"); //if (entity is IMyNetworkClient) // MyAPIGateway.Utilities.ShowMessage("IMyNetworkClient", "true"); //if (entity is IMyEntityController) // MyAPIGateway.Utilities.ShowMessage("IMyEntityController", "true"); //if (entity is IMyControllableEntity) // MyAPIGateway.Utilities.ShowMessage("IMyControllableEntity", "true"); // Ship and player //if (entity is IMyCameraController) // MyAPIGateway.Utilities.ShowMessage("IMyCameraController", "true"); // Everything //if (entity is IMyMultiplayer) // MyAPIGateway.Utilities.ShowMessage("IMyMultiplayer", "true"); if (entity is Sandbox.ModAPI.IMyCubeGrid) entity = entity.Parent; if (entity.Physics != null) { var pos = entity.GetPosition(); //var pos = Vector3.Zero; var m = Matrix.CreateWorld(pos, Vector3.Forward, Vector3.Up); entity.SetWorldMatrix(m); //MyAPIGateway.Multiplayer.SendEntitiesCreated(); //entity.LocalMatrix //entity.SetPosition(pos); //if (entity.SyncObject.UpdatesOnlyOnServer) // entity.SyncObject.UpdatePosition(); //MyAPIGateway.Utilities.ShowMessage("Physics=null", string.Format("{0}", phys == null)); MyAPIGateway.Utilities.ShowMessage("LinearVelocity", string.Format("{0}", entity.Physics.LinearVelocity)); //MyAPIGateway.Utilities.ShowMessage("Speed", string.Format("{0}", phys.Speed)); //MyAPIGateway.Utilities.ShowMessage("Mass", string.Format("{0}", phys.Mass)); //phys.AddForce(Sandbox.Engine.Physics.MyPhysicsForceType.ADD_BODY_FORCE_AND_BODY_TORQUE, Vector3.Forward, Vector3.Zero, Vector3.Zero); //phys.LinearVelocity = Vector3.Forward; //phys } //var vm = MyAPIGateway.Session.Player.Controller.ControlledEntity.GetHeadMatrix(true, true, true); // most accurate for player view. return true; } #endregion #region test7 if (messageText.Equals("/test7", StringComparison.InvariantCultureIgnoreCase)) { var character = (MyObjectBuilder_Character)MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.GetObjectBuilder(); //var obj = MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.GetObjectBuilder(); var obj = MyAPIGateway.Session.Player.Client as IMyEntity; MyAPIGateway.Utilities.ShowMessage("isNull", string.Format("{0}", obj == null)); //MyAPIGateway.Utilities.ShowMessage("Name", string.Format("{0}", obj.GetType().Name)); return true; } #endregion #region test8 if (messageText.Equals("/test8A", StringComparison.InvariantCultureIgnoreCase)) { var gridBuilder = new MyObjectBuilder_CubeGrid() { PersistentFlags = MyPersistentEntityFlags2.CastShadows | MyPersistentEntityFlags2.InScene, GridSizeEnum = MyCubeSize.Large, IsStatic = true, LinearVelocity = new SerializableVector3(0, 0, 0), AngularVelocity = new SerializableVector3(0, 0, 0), PositionAndOrientation = new MyPositionAndOrientation(Vector3.Zero, Vector3.Forward, Vector3.Up), DisplayName = "test grid" }; Sandbox.Common.ObjectBuilders.MyObjectBuilder_CubeBlock cube = new Sandbox.Common.ObjectBuilders.MyObjectBuilder_CubeBlock(); cube.Min = new SerializableVector3I(0, 0, 0); cube.SubtypeName = "LargeBlockArmorBlock"; cube.ColorMaskHSV = new SerializableVector3(0, -1, 0); cube.ShareMode = MyOwnershipShareModeEnum.None; cube.EntityId = 0; cube.Owner = 0; cube.BlockOrientation = new SerializableBlockOrientation(Base6Directions.Direction.Forward, Base6Directions.Direction.Up); cube.ShareMode = Sandbox.Common.ObjectBuilders.MyOwnershipShareModeEnum.All; gridBuilder.CubeBlocks.Add(cube); // multiple grids... //var tempList = new List<MyObjectBuilder_EntityBase>(); //tempList.Add(gridBuilder); //MyAPIGateway.Entities.RemapObjectBuilderCollection(tempList); //tempList.ForEach(grid => MyAPIGateway.Entities.CreateFromObjectBuilderAndAdd(grid)); //MyAPIGateway.Multiplayer.SendEntitiesCreated(tempList); // Single grid. MyAPIGateway.Entities.RemapObjectBuilder(gridBuilder); MyAPIGateway.Entities.CreateFromObjectBuilderAndAdd(gridBuilder); MyAPIGateway.Multiplayer.SendEntitiesCreated(new List<MyObjectBuilder_EntityBase> { gridBuilder }); MyAPIGateway.Utilities.ShowMessage("OK", "fine"); return true; } if (messageText.Equals("/test8B", StringComparison.InvariantCultureIgnoreCase)) { var entity = Support.FindLookAtEntity(MyAPIGateway.Session.ControlledObject, true, false, false) as Sandbox.ModAPI.IMyCubeGrid; if (entity == null) return false; var gridBuilder = new MyObjectBuilder_CubeGrid() { PersistentFlags = MyPersistentEntityFlags2.CastShadows | MyPersistentEntityFlags2.InScene, GridSizeEnum = MyCubeSize.Large, IsStatic = true, LinearVelocity = new SerializableVector3(0, 0, 0), AngularVelocity = new SerializableVector3(0, 0, 0), PositionAndOrientation = new MyPositionAndOrientation(Vector3.Zero, Vector3.Forward, Vector3.Up), DisplayName = "test grid" }; Sandbox.Common.ObjectBuilders.MyObjectBuilder_CubeBlock cube = new Sandbox.Common.ObjectBuilders.MyObjectBuilder_CubeBlock(); cube.Min = new SerializableVector3I(0, 0, 0); cube.SubtypeName = "LargeBlockArmorBlock"; cube.ColorMaskHSV = new SerializableVector3(0, -1, 0); cube.ShareMode = MyOwnershipShareModeEnum.None; cube.Owner = 0; cube.BlockOrientation = new SerializableBlockOrientation(Base6Directions.Direction.Forward, Base6Directions.Direction.Up); cube.ShareMode = Sandbox.Common.ObjectBuilders.MyOwnershipShareModeEnum.All; gridBuilder.CubeBlocks.Add(cube); //var tempList = new List<MyObjectBuilder_EntityBase>(); //tempList.Add(gridBuilder); //MyAPIGateway.Entities.RemapObjectBuilderCollection(tempList); //no need for this on new object //var newEntity = (IMyCubeGrid)MyAPIGateway.Entities.CreateFromObjectBuilderAndAdd(tempList[0]); //MyAPIGateway.Multiplayer.SendEntitiesCreated(tempList); MyAPIGateway.Entities.RemapObjectBuilder(gridBuilder); var newEntity = (Sandbox.ModAPI.IMyCubeGrid)MyAPIGateway.Entities.CreateFromObjectBuilderAndAdd(gridBuilder); MyAPIGateway.Multiplayer.SendEntitiesCreated(new List<MyObjectBuilder_EntityBase> { gridBuilder }); entity.MergeGrid_MergeBlock(newEntity, new Vector3I(0, 1, 0)); MyAPIGateway.Utilities.ShowMessage("OK", "fine"); return true; } #endregion #region test9 if (messageText.Equals("/test9", StringComparison.InvariantCultureIgnoreCase)) { var allEntites = new HashSet<IMyEntity>(); MyAPIGateway.Entities.GetEntities(allEntites, e => e != null); var sphere = new BoundingSphereD(Vector3D.Zero, 1000000f); var allSphereEntities = MyAPIGateway.Entities.GetEntitiesInSphere(ref sphere); MyAPIGateway.Utilities.ShowMessage("All Entities", String.Format("{0} == {1} ??", allEntites.Count, allSphereEntities.Count)); return true; } #endregion #region test10 if (messageText.StartsWith("/test10 ", StringComparison.InvariantCultureIgnoreCase)) { var match = Regex.Match(messageText, @"/test10\s{1,}(?<Key>.+)", RegexOptions.IgnoreCase); if (match.Success) { var prefabName = match.Groups["Key"].Value; var entities = new HashSet<IMyEntity>(); MyAPIGateway.Entities.GetEntities(entities, e => e is Sandbox.ModAPI.IMyCubeGrid); var idx = Int32.Parse(prefabName); var cubeGrid = (Sandbox.ModAPI.IMyCubeGrid)entities.ToArray()[idx]; var grids = cubeGrid.GetAttachedGrids(); MyAPIGateway.Utilities.ShowMessage("Attached Count", string.Format("{0}", grids.Count)); //foreach (var grid in grids) // MyAPIGateway.Utilities.ShowMessage("Attached", string.Format("{0}", grid.EntityId)); return true; } //var vm = MyAPIGateway.Session.Player.Controller.ControlledEntity.GetHeadMatrix(true, true, true); // most accurate for player view. } #endregion #region test11 if (messageText.Equals("/test11", StringComparison.InvariantCultureIgnoreCase)) { //var identities = new List<IMyIdentity>(); //MyAPIGateway.Players.GetAllIdentites(identities); //var ident = identities.FirstOrDefault(); //var bIdent = ((IMyEntity)ident).GetObjectBuilder(); //MyAPIGateway.Utilities.ShowMessage("IMyIdentity", string.Format("{0}", bIdent.GetType())); var players = new List<IMyPlayer>(); MyAPIGateway.Players.GetPlayers(players, p => p != null); var player = players.FirstOrDefault(); var cpnt = MyAPIGateway.Session.GetCheckpoint("null"); MyAPIGateway.Utilities.ShowMessage("cpnt", cpnt.Clients == null ? "null" : string.Format("{0}", cpnt.Clients.Count)); var c = MyAPIGateway.Session.GetWorld().Checkpoint.Clients; MyAPIGateway.Utilities.ShowMessage("Count", c == null ? "null" : string.Format("{0}", c.Count)); var nc = player.Client; MyAPIGateway.Utilities.ShowMessage("IMyNetworkClient", string.Format("{0}", nc.GetType())); //MyAPIGateway.Utilities.ShowMessage("IMyNetworkClient", string.Format("{0}", nc.GetType().BaseType)); //var bPlayer = ((IMyEntity)nc).GetObjectBuilder(); //MyAPIGateway.Utilities.ShowMessage("IMyPlayer", string.Format("{0}", bPlayer.GetType())); //var vm = MyAPIGateway.Session.Player.Controller.ControlledEntity.GetHeadMatrix(true, true, true); // most accurate for player view. return true; } #endregion #region test12 if (messageText.Equals("/test12", StringComparison.InvariantCultureIgnoreCase)) { var entity = Support.FindLookAtEntity(MyAPIGateway.Session.ControlledObject); var resultList = new List<ITerminalAction>(); if (entity != null) { var displayName = entity.DisplayName; MyAPIGateway.Utilities.ShowMessage("ID", displayName); MyAPIGateway.Utilities.ShowMessage("Components", string.Format("{0}", entity.Components == null)); MyAPIGateway.Utilities.ShowMessage("Hierarchy", string.Format("{0}", entity.Hierarchy == null)); var cockpits = entity.FindWorkingCockpits(); var terminal = (IMyTerminalBlock)cockpits[0]; //cockpits[0] terminal.GetActions(resultList); MyAPIGateway.Utilities.ShowMessage("count", string.Format("{0}", resultList.Count)); } //Vector3D? FindFreePlace(Vector3D basePos, float radius, int maxTestCount = 20, int testsPerDistance = 5, float stepSize = 1f); //MyAPIGateway.Entities.FindFreePlace( //resultList.Clear(); //var myObject = Sandbox.Common.ObjectBuilders.Serializer.MyObjectBuilderSerializer.CreateNewObject(typeof(MyObjectBuilder_Reactor), "SmallBlockLargeGenerator"); //MyAPIGateway.TerminalActionsHelper.GetActions(typeof(MyObjectBuilder_Reactor), resultList); //MyAPIGateway.Utilities.ShowMessage("count", string.Format("{0}", resultList.Count)); //MyAPIGateway.TerminalActionsHelper.GetActions(typeof(IMyMotorStator), resultList); //MyAPIGateway.Utilities.ShowMessage("count", string.Format("{0}", resultList.Count)); //MyAPIGateway.TerminalActionsHelper.GetActions(typeof(IMyFunctionalBlock), resultList); //MyAPIGateway.Utilities.ShowMessage("count", string.Format("{0}", resultList.Count)); //MyAPIGateway.TerminalActionsHelper.GetActions(typeof(IMyTerminalBlock), resultList); //MyAPIGateway.Utilities.ShowMessage("count", string.Format("{0}", resultList.Count)); foreach (var a in resultList) { MyAPIGateway.Utilities.ShowMessage("item", string.Format("{0}={1}", a.Name, a.Id)); } return true; } #endregion #region test13 if (messageText.Equals("/test13", StringComparison.InvariantCultureIgnoreCase)) { var entites = new HashSet<IMyEntity>(); MyAPIGateway.Entities.GetEntities(entites, e => e != null); //var physicalItem = MyDefinitionManager.Static.GetCubeBlockDefinition(new MyDefinitionId(typeof(MyObjectBuilder_SpaceBall), "SpaceBallLarge")); //physicalItem.Public = true; //MyDefinitionManager.Static.EnvironmentDefinition.SmallShipMaxSpeed = 2000; //MyDefinitionManager.Static.EnvironmentDefinition.LargeShipMaxSpeed = 2000; MyAPIGateway.Session.GetCheckpoint("null").GameMode = MyGameModeEnum.Creative; //MyAPIGateway.Session.GetCheckpoint("null").CargoShipsEnabled //MyAPIGateway.Session.GetCheckpoint("null").EnableCopyPaste = true; //MyAPIGateway.Utilities.ShowMessage("Sun Distance", string.Format("{0}", MyDefinitionManager.Static.EnvironmentDefinition.DistanceToSun)); //MyDefinitionManager.Static.EnvironmentDefinition.DirectionToSun = new Vector3(0, 1, 0); foreach (var entity in entites) { var cubeGrid = entity as Sandbox.ModAPI.IMyCubeGrid; if (cubeGrid != null) { var terminalsys = MyAPIGateway.TerminalActionsHelper.GetTerminalSystemForGrid(cubeGrid); //MyAPIGateway.Utilities.ShowMessage("Grid count", string.Format("{0} {1} {2}", cubeGrid.DisplayName, terminalsys.Blocks.Count, terminalsys.BlockGroups.Count)); //var blocks = new List<Sandbox.ModAPI.IMySlimBlock>(); //cubeGrid.GetBlocks(blocks, f => f.FatBlock != null && f.FatBlock == MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity); //MyAPIGateway.Utilities.ShowMessage("Pilot count", string.Format("{0}", blocks.Count)); //cubeGrid.GetBlocks(blocks); //foreach (var block in blocks) //{ // cubeGrid.ColorBlocks(block.Position, block.Position, VRageMath.Color.Gold.ToHsvColor()); //} } } return true; } #endregion #region test14 // Tag every floating object in player GPS. if (messageText.Equals("/test14", StringComparison.InvariantCultureIgnoreCase)) { var entites = new HashSet<IMyEntity>(); MyAPIGateway.Entities.GetEntities(entites, e => (e is Sandbox.ModAPI.IMyFloatingObject)); foreach (var entity in entites) { var pos = entity.GetPosition(); var gps = MyAPIGateway.Session.GPS.Create("Floating " + entity.DisplayName, "Some drifting junk", pos, true, false); MyAPIGateway.Session.GPS.AddLocalGps(gps); } return true; } #endregion return false; }
/// <summary> /// Gets a destination and tries to fix it so that it does not collide with anything /// </summary> /// <param name="originalDestination">The final destination that the remote wants to get to.</param> /// <param name="checkRadius">The maximum radius until which this method should search.</param> /// <param name="shipRadius">The radius of our ship. Make sure that this is large enough to avoid collision.</param> Vector3D ModAPI.Ingame.IMyRemoteControl.GetFreeDestination(Vector3D originalDestination, float checkRadius, float shipRadius) { MyCestmirDebugInputComponent.ClearDebugSpheres(); MyCestmirDebugInputComponent.ClearDebugPoints(); MyCestmirDebugInputComponent.AddDebugPoint(this.WorldMatrix.Translation, Color.Green); Vector3D retval = originalDestination; BoundingSphereD sphere = new BoundingSphereD(this.WorldMatrix.Translation, shipRadius + checkRadius); Vector3D rayDirection = originalDestination - this.WorldMatrix.Translation; double originalDistance = rayDirection.Length(); rayDirection = rayDirection / originalDistance; RayD ray = new RayD(this.WorldMatrix.Translation, rayDirection); double closestIntersection = double.MaxValue; BoundingSphereD closestSphere = default(BoundingSphereD); var entities = MyEntities.GetEntitiesInSphere(ref sphere); for (int i = 0; i < entities.Count; ++i) { var entity = entities[i]; if (!(entity is MyCubeGrid) && !(entity is MyVoxelMap)) continue; if (entity.Parent != null) continue; if (entity == this.Parent) continue; BoundingSphereD entitySphere = entity.PositionComp.WorldVolume; entitySphere.Radius += shipRadius; MyCestmirDebugInputComponent.AddDebugSphere(entitySphere.Center, (float)entity.PositionComp.WorldVolume.Radius, Color.Plum); MyCestmirDebugInputComponent.AddDebugSphere(entitySphere.Center, (float)entity.PositionComp.WorldVolume.Radius + shipRadius, Color.Purple); double? intersection = ray.Intersects(entitySphere); if (intersection.HasValue && intersection.Value < closestIntersection) { closestIntersection = intersection.Value; closestSphere = entitySphere; } } if (closestIntersection != double.MaxValue) { Vector3D correctedDestination = ray.Position + closestIntersection * ray.Direction; MyCestmirDebugInputComponent.AddDebugSphere(correctedDestination, 1.0f, Color.Blue); Vector3D normal = correctedDestination - closestSphere.Center; if (Vector3D.IsZero(normal)) { normal = Vector3D.Up; } normal.Normalize(); MyCestmirDebugInputComponent.AddDebugSphere(correctedDestination + normal, 1.0f, Color.Red); Vector3D newDirection = Vector3D.Reject(ray.Direction, normal); newDirection.Normalize(); newDirection *= Math.Max(20.0, closestSphere.Radius * 0.5); MyCestmirDebugInputComponent.AddDebugSphere(correctedDestination + newDirection, 1.0f, Color.LightBlue); retval = correctedDestination + newDirection; } else { retval = ray.Position + ray.Direction * Math.Min(checkRadius, originalDistance); } entities.Clear(); return retval; }
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; }
void ReprojectY(List<Triangle> res, Plane3D plane) { double pos = 0; foreach (var t in res){ for (int i=0;i<3;i++){ var p = t.points[i]; p.y = 0; RayD r = new RayD(p, Vector3D.up); if (plane.Raycast(r,out pos)){ p.y = (float)pos; t.points[i] = p; } } } }
Vector3D ProjectToTriangle(Vector3D point) { Plane3D plane = new Plane3D(Normal, points[0]); bool isPointInPlane = System.Math.Abs(plane.GetDistanceToPoint(point))<0.0001; if (!isPointInPlane) { double dist; point.y = 0; var ray = new RayD(point, Vector3D.up); plane.Raycast(ray, out dist); point.y = dist; } return point; }
protected override void DoDetection(bool useHead) { ProfilerShort.Begin("DoDetection"); if (Character == MySession.Static.ControlledEntity) MyHud.SelectedObjectHighlight.RemoveHighlight(); var head = Character.GetHeadMatrix(false); var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head) Vector3D from; Vector3D dir; if (!useHead) { //Ondrej version var cameraMatrix = MySector.MainCamera.WorldMatrix; dir = cameraMatrix.Forward; from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir); } else { //Petr version dir = head.Forward; from = headPos; } Vector3D to = from + dir * MyConstants.DEFAULT_INTERACTIVE_DISTANCE; //EnableDetectorsInArea(from); GatherDetectorsInArea(from); float closestDetector = float.MaxValue; IMyEntity closestEntity = null; IMyUseObject closestInteractive = null; foreach(var entity in m_detectableEntities) { if (entity == Character) continue; var use = entity.Components.Get<MyUseObjectsComponentBase>() as MyUseObjectsComponent; if(use != null) { float detectorDistance; var interactive = use.RaycastDetectors(from, to, out detectorDistance); if(Math.Abs(detectorDistance) < Math.Abs(closestDetector)) { closestDetector = detectorDistance; closestEntity = entity; closestInteractive = interactive; } } //Floating object handling - give FO useobject component! var use2 = entity as IMyUseObject; if (use2 != null) { var m = use2.ActivationMatrix; var ray = new RayD(from, to - from); var obb = new MyOrientedBoundingBoxD(m); var dist = obb.Intersects(ref ray); if(dist.HasValue && Math.Abs(dist.Value) < Math.Abs(closestDetector)) { closestDetector = (float)dist.Value; closestEntity = entity; closestInteractive = use2; } } } m_detectableEntities.Clear(); //VRageRender.MyRenderProxy.DebugDrawLine3D(from, to, Color.Red, Color.Green, true); //VRageRender.MyRenderProxy.DebugDrawSphere(headPos, 0.05f, Color.Red.ToVector3(), 1.0f, false); StartPosition = from; MyPhysics.CastRay(from, to, m_hits, MyPhysics.CollisionLayers.FloatingObjectCollisionLayer); bool hasInteractive = false; int index = 0; while (index < m_hits.Count && (m_hits[index].HkHitInfo.Body == null || m_hits[index].HkHitInfo.GetHitEntity() == Character || m_hits[index].HkHitInfo.GetHitEntity() == null || m_hits[index].HkHitInfo.Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT) || m_hits[index].HkHitInfo.Body.Layer == MyPhysics.CollisionLayers.VoxelLod1CollisionLayer)) // Skip invalid hits and self character { index++; } if (index < m_hits.Count && m_hits[index].HkHitInfo.HitFraction > closestDetector - 0.05f)//compensation { // TODO: Uncomment to enforce that character must face object by front to activate it //if (TestInteractionDirection(head.Forward, h.Position - GetPosition())) //return; HitPosition = from + dir * closestDetector; MyUseObjectsComponentBase useObject; if(closestEntity.Components.TryGet<MyUseObjectsComponentBase>(out useObject)) { var detectorPhysics = useObject.DetectorPhysics; HitMaterial = detectorPhysics.GetMaterialAt(HitPosition); HitBody = ((MyPhysicsBody)detectorPhysics).RigidBody; } else { HitMaterial = closestEntity.Physics.GetMaterialAt(HitPosition); HitBody = ((MyPhysicsBody)closestEntity.Physics).RigidBody; } DetectedEntity = closestEntity; var interactive = closestInteractive; if (UseObject != null && interactive != null && UseObject != interactive) { UseObject.OnSelectionLost(); } //if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, (Vector3D)h.Position)) < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity) if (interactive != null && interactive.SupportedActions != UseActionEnum.None && closestDetector * MyConstants.DEFAULT_INTERACTIVE_DISTANCE < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity) { HandleInteractiveObject(interactive); UseObject = interactive; hasInteractive = true; } } if (!hasInteractive) { if (UseObject != null) { UseObject.OnSelectionLost(); } UseObject = null; } ProfilerShort.End(); }
public bool Intersect(LineD line, ref Vector3D p1, ref Vector3D p2, ref Vector3 n1, ref Vector3 n2) { RayD ray = new RayD(line.From, line.Direction); if (Intersect(ray, ref p1, ref p2, ref n1, ref n2)) { Vector3D p1Dir = p1 - line.From; Vector3D p2Dir = p2 - line.From; double p1Len = p1Dir.Normalize(); double p2Len = p2Dir.Normalize(); if (Vector3D.Dot(line.Direction, p1Dir) < 0.9) return false; if (Vector3D.Dot(line.Direction, p2Dir) < 0.9) return false; if (line.Length < p1Len) return false; return true; } return false; }
private void GetDeposit() { Vector3D pos = m_navDrill.WorldPosition; IMyVoxelBase foundMap; if (m_oreDetector.FindClosestOre(pos, OreTargets, out m_depositPos, out foundMap, out m_depostitOre)) { // from the centre of the voxel, passing through the deposit, find the edge of the AABB m_voxelCentre = foundMap.GetCentre(); Vector3D centreOut = m_depositPos - m_voxelCentre; centreOut.Normalize(); Vector3D bodEdgeFinderStart = m_voxelCentre + centreOut * foundMap.WorldAABB.GetLongestDim(); RayD boxEdgeFinder = new RayD(bodEdgeFinderStart, -centreOut); double? boxEdgeDist = foundMap.WorldAABB.Intersects(boxEdgeFinder); if (boxEdgeDist == null) throw new Exception("Math fail"); Vector3D boxEdge = bodEdgeFinderStart - centreOut * boxEdgeDist.Value; // was getting memory access violation, so not using MainLock.RayCastVoxel_Safe() MyAPIGateway.Utilities.TryInvokeOnGameThread(() => { Vector3 surfacePoint; if (foundMap is IMyVoxelMap) { MyAPIGateway.Entities.IsInsideVoxel(boxEdge, m_voxelCentre, out surfacePoint); m_miningPlanet = false; } else { MyPlanet planet = foundMap as MyPlanet; surfacePoint = planet.GetClosestSurfacePointGlobal(ref m_depositPos); m_logger.debugLog("Mining target is a planet, from nav drill position: " + m_navDrill.WorldPosition + ", surface is " + surfacePoint, "GetDeposit()"); m_miningPlanet = true; } m_approach = new Line(surfacePoint + centreOut * m_controlBlock.CubeGrid.GetLongestDim() * 2, surfacePoint); m_logger.debugLog("centre: " + m_voxelCentre.ToGpsTag("centre") + ", deposit: " + m_depositPos.ToGpsTag("deposit") + ", boxEdge: " + boxEdge.ToGpsTag("boxEdge") + ", m_approach: " + m_approach.From.ToGpsTag("m_approach From") + ", " + m_approach.To.ToGpsTag("m_approach To") + ", surfacePoint: " + surfacePoint , "GetDeposit()"); m_state = State.Approaching; }, m_logger); return; } m_logger.debugLog("No ore target found", "GetDeposit()", Logger.severity.INFO); m_navSet.OnTaskComplete_NavRot(); }
protected bool GetCubeAddAndRemovePositions(Vector3I intersectedCube, bool placingSmallGridOnLargeStatic, out Vector3I addPos, out Vector3I addDir, out Vector3I removePos) { bool result = false; addPos = new Vector3I(); addDir = new Vector3I(); removePos = new Vector3I(); MatrixD worldInv = MatrixD.Invert(CurrentGrid.WorldMatrix); Vector3D intersectionPos; addPos = intersectedCube; addDir = Vector3I.Forward; Vector3D rayStart = Vector3D.Transform(IntersectionStart, worldInv); Vector3D rayDir = Vector3D.Normalize(Vector3D.TransformNormal(IntersectionDirection, worldInv)); RayD r = new RayD(rayStart, rayDir); for (int i = 0; i < 100; ++i) // Limit iterations to 100 { var cubeBb = GetCubeBoundingBox(addPos); if (!placingSmallGridOnLargeStatic && cubeBb.Contains(rayStart) == ContainmentType.Contains) break; double? dist = cubeBb.Intersects(r); if (!dist.HasValue) break; removePos = addPos; intersectionPos = rayStart + rayDir * dist.Value; Vector3 center = removePos * CurrentGrid.GridSize; Vector3I dirInt = Vector3I.Sign(Vector3.DominantAxisProjection(intersectionPos - center)); addPos = removePos + dirInt; addDir = dirInt; result = true; if (!CurrentGrid.CubeExists(addPos)) break; } Debug.Assert(!result || addDir != Vector3I.Zero, "Direction vector cannot be zero"); return result; }
public static void FindLookAtEntity(IMyControllableEntity controlledEntity, out IMyEntity lookEntity, out double lookDistance, bool findShips = true, bool findPlayers = true, bool findAsteroids = true, bool findPlanets = true) { const float range = 5000000; Matrix worldMatrix; Vector3D startPosition; Vector3D endPosition; if (MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.Parent == null) { worldMatrix = MyAPIGateway.Session.Player.Controller.ControlledEntity.GetHeadMatrix(true, true, false); // dead center of player cross hairs. startPosition = worldMatrix.Translation + worldMatrix.Forward * 0.5f; endPosition = worldMatrix.Translation + worldMatrix.Forward * (range + 0.5f); } else { worldMatrix = MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.WorldMatrix; // TODO: need to adjust for position of cockpit within ship. startPosition = worldMatrix.Translation + worldMatrix.Forward * 1.5f; endPosition = worldMatrix.Translation + worldMatrix.Forward * (range + 1.5f); } //var worldMatrix = MyAPIGateway.Session.Player.PlayerCharacter.Entity.WorldMatrix; //var position = MyAPIGateway.Session.Player.PlayerCharacter.Entity.GetPosition(); //var position = worldMatrix.Translation + worldMatrix.Forward * 0.5f + worldMatrix.Up * 1.0f; //MyAPIGateway.Utilities.ShowMessage("Pos", string.Format("x={0:N},y={1:N},z={2:N} x={3:N},y={4:N},z={5:N}", playerPos.X, playerPos.Y, playerPos.Z, playerMatrix.Forward.X, playerMatrix.Forward.Y, playerMatrix.Forward.Z)); // The CameraController.GetViewMatrix appears warped at the moment. //var position = ((IMyEntity)MyAPIGateway.Session.CameraController).GetPosition(); //var worldMatrix = MyAPIGateway.Session.CameraController.GetViewMatrix(); //var position = worldMatrix.Translation; //MyAPIGateway.Utilities.ShowMessage("Cam", string.Format("x={0:N},y={1:N},z={2:N} x={3:N},y={4:N},z={5:N}", position.X, position.Y, position.Z, worldMatrix.Forward.X, worldMatrix.Forward.Y, worldMatrix.Forward.Z)); var entites = new HashSet<IMyEntity>(); MyAPIGateway.Entities.GetEntities(entites, e => e != null); var list = new Dictionary<IMyEntity, double>(); var ray = new RayD(startPosition, worldMatrix.Forward); foreach (var entity in entites) { if (findShips) { var cubeGrid = entity as Sandbox.ModAPI.IMyCubeGrid; // check if the ray comes anywhere near the Grid before continuing. if (cubeGrid != null && ray.Intersects(entity.WorldAABB).HasValue) { var hit = cubeGrid.RayCastBlocks(startPosition, endPosition); if (hit.HasValue) { var distance = (startPosition - cubeGrid.GridIntegerToWorld(hit.Value)).Length(); list.Add(entity, distance); } } } if (findPlayers) { var controller = entity as IMyControllableEntity; if (MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.EntityId != entity.EntityId && controller != null && ray.Intersects(entity.WorldAABB).HasValue) { var distance = (startPosition - entity.GetPosition()).Length(); list.Add(entity, distance); } } if (findAsteroids) { var voxelMap = entity as IMyVoxelMap; if (voxelMap != null) { var aabb = new BoundingBoxD(voxelMap.PositionLeftBottomCorner, voxelMap.PositionLeftBottomCorner + voxelMap.Storage.Size); var hit = ray.Intersects(aabb); if (hit.HasValue) { var center = voxelMap.PositionLeftBottomCorner + (voxelMap.Storage.Size / 2); var distance = (startPosition - center).Length(); // use distance to center of asteroid. list.Add(entity, distance); } } } if (findPlanets) { // Looks to be working against Git and public release. var planet = entity as Sandbox.Game.Entities.MyPlanet; if (planet != null) { var aabb = new BoundingBoxD(planet.PositionLeftBottomCorner, planet.PositionLeftBottomCorner + planet.Size); var hit = ray.Intersects(aabb); if (hit.HasValue) { var center = planet.PositionLeftBottomCorner + (planet.Size / 2); var distance = (startPosition - center).Length(); // use distance to center of planet. list.Add(entity, distance); } } } } if (list.Count == 0) { lookEntity = null; lookDistance = 0; return; } // find the closest Entity. var item = list.OrderBy(f => f.Value).First(); lookEntity = item.Key; lookDistance = item.Value; }
public bool TryNamingAnBlockOrFloatingObject() { var worldMatrix = MyAPIGateway.Session.Camera.WorldMatrix; // most accurate for player view. var position = worldMatrix.Translation + worldMatrix.Forward * 0.5f; var ray = new RayD(position, worldMatrix.Forward * 1000); var boundingSphere = new BoundingSphereD(worldMatrix.Translation, 30); var entites = MyEntities.GetEntitiesInSphere(ref boundingSphere); List<MyPhysics.HitInfo> hits = new List<MyPhysics.HitInfo>(); MyPhysics.CastRay(worldMatrix.Translation, worldMatrix.Translation + worldMatrix.Forward * 5, hits, 15); foreach (var hitInfo in hits) { var body = (MyPhysicsBody)hitInfo.HkHitInfo.Body.UserObject; if (body.Entity is MyFloatingObject) { var rayEntity = (MyEntity) body.Entity; NameDialog(rayEntity); return true; } } foreach (var entity in entites) { var cubeGrid = entity as MyCubeGrid; if (cubeGrid != null && ray.Intersects(entity.PositionComp.WorldAABB).HasValue) { var hit = cubeGrid.RayCastBlocks(worldMatrix.Translation, worldMatrix.Translation + worldMatrix.Forward * 100); if (hit.HasValue) { var block = cubeGrid.GetCubeBlock(hit.Value); if(block.FatBlock != null) { var dialog = new ValueGetScreenWithCaption("Name block dialog: " + block.FatBlock.DefinitionDisplayNameText, block.FatBlock.Name ?? block.FatBlock.DefinitionDisplayNameText + " has no name.", delegate(string text) { MyEntity foundEntity; if (MyEntities.TryGetEntityByName(text, out foundEntity)) { MyGuiSandbox.AddScreen(MyGuiSandbox.CreateMessageBox( buttonType: MyMessageBoxButtonsType.OK, messageText: new StringBuilder("Entity with same name already exits, please enter different name."), messageCaption: new StringBuilder("Naming error"))); } else { block.FatBlock.Name = text; MyEntities.SetEntityName(block.FatBlock, true); return true; } return false; }); MyGuiSandbox.AddScreen(dialog); entites.Clear(); return true; } } } } entites.Clear(); return false; }
public static void OnGlobalSpawnEvent(object senderEvent) { // Select a spawn group to spawn MySpawnGroupDefinition spawnGroup = PickRandomSpawnGroup(); if (spawnGroup == null) { return; } spawnGroup.ReloadPrefabs(); ProfilerShort.Begin("Generate position and direction"); double spawnDistance = NEUTRAL_SHIP_SPAWN_DISTANCE; Vector3D playerPosition = Vector3D.Zero; bool isWorldLimited = MyEntities.IsWorldLimited(); int numPlayers = 0; if (isWorldLimited) { spawnDistance = Math.Min(spawnDistance, MyEntities.WorldSafeHalfExtent() - spawnGroup.SpawnRadius); } else { // In infinite worlds players can be thousands of kilometers away, so spawn ship around random player // so cargo ships will be spawned around every player at some time var players = MySession.Static.Players.GetOnlinePlayers(); // In DS there can be no players connected numPlayers = Math.Max(0, players.Count - 1); int randomPlayerPosition = MyUtils.GetRandomInt(0, numPlayers); int i = 0; foreach (var player in players) { if (i == randomPlayerPosition) { if (player.Character != null) { playerPosition = player.GetPosition(); } break; } i++; } } if (spawnDistance < 0.0f) { MySandboxGame.Log.WriteLine("Not enough space in the world to spawn such a huge spawn group!"); return; } double forbiddenRadius = NEUTRAL_SHIP_FORBIDDEN_RADIUS; BoundingBoxD spawnBox; if (isWorldLimited) { spawnBox = new BoundingBoxD(new Vector3D(playerPosition - spawnDistance), new Vector3D(playerPosition + spawnDistance)); } else { // We need to extend bouding box so cargo ships aren't spawned near other players GetSafeBoundingBoxForPlayers(playerPosition, spawnDistance, out spawnBox); // Forbidden radius is sphere around all players in box. // Bounding box is generated from players positions so their distance to center shall be same for all players forbiddenRadius += spawnBox.HalfExtents.Max() - NEUTRAL_SHIP_FORBIDDEN_RADIUS; } // Get the direction to the center and deviate it randomly Vector3D? origin = MyUtils.GetRandomBorderPosition(ref spawnBox); origin = MyEntities.FindFreePlace(origin.Value, spawnGroup.SpawnRadius); if (!origin.HasValue) { MySandboxGame.Log.WriteLine("Could not spawn neutral ships - no free place found"); MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME); ProfilerShort.End(); return; } // Radius in arc units of the forbidden sphere in the center, when viewed from origin float centerArcRadius = (float)Math.Atan(forbiddenRadius / (origin.Value - spawnBox.Center).Length()); // Generate direction with elevation from centerArcRadius radians to (cAR + N_S_D_S) radians Vector3D direction = -Vector3D.Normalize(origin.Value); float theta = MyUtils.GetRandomFloat(centerArcRadius, centerArcRadius + NEUTRAL_SHIP_DIRECTION_SPREAD); float phi = MyUtils.GetRandomRadian(); Vector3D cosVec = Vector3D.CalculatePerpendicularVector(direction); Vector3D sinVec = Vector3D.Cross(direction, cosVec); cosVec *= (Math.Sin(theta) * Math.Cos(phi)); sinVec *= (Math.Sin(theta) * Math.Sin(phi)); direction = direction * Math.Cos(theta) + cosVec + sinVec; Vector3D destination = Vector3D.Zero; RayD ray = new RayD(origin.Value, direction); double? intersection = ray.Intersects(spawnBox); Vector3D directionMult; if (!intersection.HasValue || intersection.Value < NEUTRAL_SHIP_MINIMAL_ROUTE_LENGTH) { directionMult = direction * NEUTRAL_SHIP_MINIMAL_ROUTE_LENGTH; } else { directionMult = direction * intersection.Value; } destination = origin.Value + directionMult; Vector3D upVector = Vector3D.CalculatePerpendicularVector(direction); Vector3D rightVector = Vector3D.Cross(direction, upVector); MatrixD originMatrix = MatrixD.CreateWorld(origin.Value, direction, upVector); ProfilerShort.End(); ProfilerShort.Begin("Check free space"); // CH:TODO: Convex cast to detect collision // Check ships' path to avoid possible collisions. (TODO: But only if it is said in the definitions) m_raycastHits.Clear(); foreach (var shipPrefab in spawnGroup.Prefabs) { var prefabDef = MyDefinitionManager.Static.GetPrefabDefinition(shipPrefab.SubtypeId); Debug.Assert(prefabDef != null); Vector3D shipPosition = Vector3.Transform(shipPrefab.Position, originMatrix); Vector3D shipDestination = shipPosition + directionMult; float radius = prefabDef == null ? 10.0f : prefabDef.BoundingSphere.Radius; MyPhysics.CastRay(shipPosition, shipDestination, m_raycastHits, MyPhysics.CollisionLayers.ObjectDetectionCollisionLayer); if (m_raycastHits.Count > 0) { MySandboxGame.Log.WriteLine("Could not spawn neutral ships due to collision"); MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME); ProfilerShort.End(); return; } for (int i = 0; i < 4; ++i) { Vector3D shiftVector = upVector * m_upVecMultipliers[i] * radius + rightVector * m_rightVecMultipliers[i] * radius; MyPhysics.CastRay(shipPosition + shiftVector, shipDestination + shiftVector, m_raycastHits, MyPhysics.CollisionLayers.ObjectDetectionCollisionLayer); if (m_raycastHits.Count > 0) { MySandboxGame.Log.WriteLine("Could not spawn neutral ships due to collision"); MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME); ProfilerShort.End(); return; } } } ProfilerShort.End(); ProfilerShort.Begin("Spawn ships"); long spawnGroupId = MyPirateAntennas.GetPiratesId(); // The ships were collision-free. Now spawn them foreach (var shipPrefab in spawnGroup.Prefabs) { ProfilerShort.Begin(shipPrefab.BeaconText); // Yes, this could have been saved in the previous loop, but compared to (e.g.) raycasts, this does not take too much time to recalculate Vector3D shipPosition = Vector3D.Transform((Vector3D)shipPrefab.Position, originMatrix); Vector3D shipDestination = shipPosition + directionMult; Vector3D up = Vector3D.CalculatePerpendicularVector(-direction); m_tmpGridList.Clear(); // CH: We don't want a new identity for each ship anymore. We should handle that in a better way... /*if (shipPrefab.ResetOwnership) { if (spawnGroupId == 0) { //This is not an NPC so that it doesn't show up in assign ownership drop down menu MyIdentity spawnGroupIdentity = Sync.Players.CreateNewIdentity("Neutral NPC"); spawnGroupId = spawnGroupIdentity.IdentityId; } }*/ // Deploy ship ProfilerShort.Begin("Spawn cargo ship"); MyPrefabManager.Static.SpawnPrefab( resultList: m_tmpGridList, prefabName: shipPrefab.SubtypeId, position: shipPosition, forward: direction, up: up, initialLinearVelocity: shipPrefab.Speed * direction, beaconName: shipPrefab.BeaconText, spawningOptions: Sandbox.ModAPI.SpawningOptions.RotateFirstCockpitTowardsDirection | Sandbox.ModAPI.SpawningOptions.SpawnRandomCargo | Sandbox.ModAPI.SpawningOptions.DisableDampeners, ownerId: shipPrefab.ResetOwnership ? spawnGroupId : 0, updateSync: true); ProfilerShort.End(); foreach (var grid in m_tmpGridList) { var cockpit = grid.GetFirstBlockOfType<MyCockpit>(); if (cockpit != null) { MySimpleAutopilot ai = new MySimpleAutopilot(shipDestination, (Vector3)direction); cockpit.AttachAutopilot(ai); break; } } m_tmpGridList.Clear(); ProfilerShort.End(); } ProfilerShort.End(); }
private void CheckInput() { MatrixD headMatrix = MyAPIGateway.Session.ControlledObject.GetHeadMatrix(true); RayD ray = new RayD(headMatrix.Translation, headMatrix.Forward); BoundingSphereD holoSphere = new BoundingSphereD(m_offset.ToWorld(m_block), m_radiusHolo.Value); double tmin, tmax; if (!holoSphere.IntersectRaySphere(ray, out tmin, out tmax) || tmin > CrosshairRange) return; int scroll = MyAPIGateway.Input.DeltaMouseScrollWheelValue(); if (scroll != 0) { int scrollSteps = (int)Math.Round(scroll * InputScrollMulti); float rangeMulti = 1f; while (scrollSteps > 0) { rangeMulti *= ScrollRangeMulti; scrollSteps--; } while (scrollSteps < 0) { rangeMulti /= ScrollRangeMulti; scrollSteps++; } m_rangeDetection.Value *= rangeMulti; } if (MyAPIGateway.Input.IsNewRightMousePressed()) { m_centreEntityId.Value = 0L; } else if (MyAPIGateway.Input.IsNewLeftMousePressed()) { IMyEntity firstHit = null; double firstHitDistance = CrosshairRange; foreach (SeenHolo sh in m_holoEntities.Values) if (sh.Holo.Render.Visible && sh.Holo.PositionComp.WorldAABB.Intersect(ref ray, out tmin, out tmax) && tmin < firstHitDistance) { firstHit = sh.Seen.Entity; firstHitDistance = tmin; } if (firstHit != null) m_centreEntityId.Value = firstHit.EntityId; } }
public static void FindLookAtEntity(IMyControllableEntity controlledEntity, bool ignoreOccupiedGrid, bool ignoreProjection, out IMyEntity lookEntity, out double lookDistance, out Vector3D hitPoint, bool findShips, bool findCubes, bool findPlayers, bool findAsteroids, bool findPlanets, bool findReplicable) { const float range = 5000000; Matrix worldMatrix; Vector3D startPosition; Vector3D endPosition; IMyCubeGrid occupiedGrid = null; if (controlledEntity.Entity.Parent == null) { 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); } else { occupiedGrid = controlledEntity.Entity.GetTopMostParent() as IMyCubeGrid; worldMatrix = controlledEntity.Entity.WorldMatrix; // TODO: need to adjust for position of cockpit within ship. startPosition = worldMatrix.Translation + worldMatrix.Forward * 1.5f; endPosition = worldMatrix.Translation + worldMatrix.Forward * (range + 1.5f); } var entites = new HashSet<IMyEntity>(); MyAPIGateway.Entities.GetEntities(entites, e => e != null); var list = new Dictionary<IMyEntity, double>(); var ray = new RayD(startPosition, worldMatrix.Forward); foreach (var entity in entites) { if (findShips || findCubes) { var cubeGrid = entity as IMyCubeGrid; if (cubeGrid != null) { if (ignoreOccupiedGrid && occupiedGrid != null && occupiedGrid.EntityId == cubeGrid.EntityId) continue; // Will ignore Projected grids, new grid/cube placement, and grids in middle of copy/paste. if (ignoreProjection && cubeGrid.Physics == null) continue; // check if the ray comes anywhere near the Grid before continuing. if (ray.Intersects(entity.WorldAABB).HasValue) { var hit = cubeGrid.RayCastBlocks(startPosition, endPosition); if (hit.HasValue) { var distance = (startPosition - cubeGrid.GridIntegerToWorld(hit.Value)).Length(); var block = cubeGrid.GetCubeBlock(hit.Value); if (block.FatBlock != null && findCubes) list.Add(block.FatBlock, distance); else if (findShips) list.Add(entity, distance); } } } } if (findPlayers) { var controller = entity as IMyControllableEntity; if (controlledEntity.Entity.EntityId != entity.EntityId && controller != null && ray.Intersects(entity.WorldAABB).HasValue) { var distance = (startPosition - entity.GetPosition()).Length(); list.Add(entity, distance); } } if (findReplicable) { var replicable = entity as Sandbox.Game.Entities.MyInventoryBagEntity; if (replicable != null && ray.Intersects(entity.WorldAABB).HasValue) { var distance = (startPosition - entity.GetPosition()).Length(); list.Add(entity, distance); } } if (findAsteroids) { var voxelMap = entity as IMyVoxelMap; if (voxelMap != null) { var aabb = new BoundingBoxD(voxelMap.PositionLeftBottomCorner, voxelMap.PositionLeftBottomCorner + voxelMap.Storage.Size); var hit = ray.Intersects(aabb); if (hit.HasValue) { var center = voxelMap.PositionLeftBottomCorner + (voxelMap.Storage.Size / 2); var distance = (startPosition - center).Length(); // use distance to center of asteroid. list.Add(entity, distance); } } } if (findPlanets) { // Looks to be working against Git and public release. var planet = entity as Sandbox.Game.Entities.MyPlanet; if (planet != null) { var aabb = new BoundingBoxD(planet.PositionLeftBottomCorner, planet.PositionLeftBottomCorner + planet.Size); var hit = ray.Intersects(aabb); if (hit.HasValue) { var center = planet.WorldMatrix.Translation; var distance = (startPosition - center).Length(); // use distance to center of planet. list.Add(entity, distance); } } } } if (list.Count == 0) { lookEntity = null; lookDistance = 0; hitPoint = Vector3D.Zero; return; } // find the closest Entity. var item = list.OrderBy(f => f.Value).First(); lookEntity = item.Key; lookDistance = item.Value; hitPoint = startPosition + (Vector3D.Normalize(ray.Direction) * lookDistance); }
public static void FindLookAtEntity(IMyControllableEntity controlledEntity, bool ignoreOccupiedGrid, bool ignoreProjection, out IMyEntity lookEntity, out double lookDistance, out Vector3D hitPoint, bool findShips, bool findCubes, bool findPlayers, bool findAsteroids, bool findPlanets, bool findReplicable) { const float range = 5000000; Matrix worldMatrix; Vector3D startPosition; Vector3D endPosition; IMyCubeGrid occupiedGrid = null; if (controlledEntity.Entity.Parent == null) { 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); } else { occupiedGrid = controlledEntity.Entity.GetTopMostParent() as IMyCubeGrid; worldMatrix = controlledEntity.Entity.WorldMatrix; // TODO: need to adjust for position of cockpit within ship. startPosition = worldMatrix.Translation + worldMatrix.Forward * 1.5f; endPosition = worldMatrix.Translation + worldMatrix.Forward * (range + 1.5f); } //var worldMatrix = MyAPIGateway.Session.Player.PlayerCharacter.Entity.WorldMatrix; //var position = MyAPIGateway.Session.Player.PlayerCharacter.Entity.GetPosition(); //var position = worldMatrix.Translation + worldMatrix.Forward * 0.5f + worldMatrix.Up * 1.0f; //MyAPIGateway.Utilities.ShowMessage("Pos", string.Format("x={0:N},y={1:N},z={2:N} x={3:N},y={4:N},z={5:N}", playerPos.X, playerPos.Y, playerPos.Z, playerMatrix.Forward.X, playerMatrix.Forward.Y, playerMatrix.Forward.Z)); // The CameraController.GetViewMatrix appears warped at the moment. //var position = ((IMyEntity)MyAPIGateway.Session.CameraController).GetPosition(); //var worldMatrix = MyAPIGateway.Session.CameraController.GetViewMatrix(); //var position = worldMatrix.Translation; //MyAPIGateway.Utilities.ShowMessage("Cam", string.Format("x={0:N},y={1:N},z={2:N} x={3:N},y={4:N},z={5:N}", position.X, position.Y, position.Z, worldMatrix.Forward.X, worldMatrix.Forward.Y, worldMatrix.Forward.Z)); var entites = new HashSet<IMyEntity>(); MyAPIGateway.Entities.GetEntities(entites, e => e != null); var list = new Dictionary<IMyEntity, double>(); var ray = new RayD(startPosition, worldMatrix.Forward); foreach (var entity in entites) { if (findShips || findCubes) { var cubeGrid = entity as Sandbox.ModAPI.IMyCubeGrid; if (cubeGrid != null) { if (ignoreOccupiedGrid && occupiedGrid != null && occupiedGrid.EntityId == cubeGrid.EntityId) continue; // TODO: ignore construction. New cube, new ship, new station, new paste. //if (ignoreConstruction && (MyAPIGateway.CubeBuilder.BlockCreationIsActivated || MyAPIGateway.CubeBuilder.ShipCreationIsActivated || MyAPIGateway.CubeBuilder.CopyPasteIsActivated)) // continue; // Will ignore Projected grids, new grid/cube placement, and grids in middle of copy/paste. // TODO: need a better way of determining projection other than Physics, as constructions have no physics either.. if (ignoreProjection && cubeGrid.Physics == null) continue; // check if the ray comes anywhere near the Grid before continuing. if (ray.Intersects(entity.WorldAABB).HasValue) { var hit = cubeGrid.RayCastBlocks(startPosition, endPosition); if (hit.HasValue) { var distance = (startPosition - cubeGrid.GridIntegerToWorld(hit.Value)).Length(); var block = cubeGrid.GetCubeBlock(hit.Value); if (block.FatBlock != null && findCubes) list.Add(block.FatBlock, distance); else if (findShips) list.Add(entity, distance); } } } } if (findPlayers) { var controller = entity as IMyControllableEntity; if (controlledEntity.Entity.EntityId != entity.EntityId && controller != null && ray.Intersects(entity.WorldAABB).HasValue) { var distance = (startPosition - entity.GetPosition()).Length(); list.Add(entity, distance); } } if (findReplicable) { var replicable = entity as Sandbox.Game.Entities.MyInventoryBagEntity; if (replicable != null && ray.Intersects(entity.WorldAABB).HasValue) { var distance = (startPosition - entity.GetPosition()).Length(); list.Add(entity, distance); } } if (findAsteroids) { var voxelMap = entity as IMyVoxelMap; if (voxelMap != null) { var aabb = new BoundingBoxD(voxelMap.PositionLeftBottomCorner, voxelMap.PositionLeftBottomCorner + voxelMap.Storage.Size); var hit = ray.Intersects(aabb); if (hit.HasValue) { Vector3D? hitIngoing; Vector3D? hitOutgoing; // May not be asteroid that is blocking ray, so am doing additional checks. It's still not reliable. if (voxelMap.WorldAABB.IntersectPoints(startPosition, endPosition, out hitIngoing, out hitOutgoing) && Sandbox.Game.Entities.MyEntities.IsRaycastBlocked(hitIngoing.Value, hitOutgoing.Value)) { Vector3 lastOutsidePos; // TODO: IsInsideVoxel doesn't appear to be reliable. Need to find an improved method. //List<Sandbox.Engine.Physics.MyPhysics.HitInfo> m_hits = new List<Sandbox.Engine.Physics.MyPhysics.HitInfo>(); //Sandbox.Engine.Physics.MyPhysics.CastRay(startPosition, endPosition, m_hits, 0); // MyPhysics is not whitelisted. if (Sandbox.Game.Entities.MyEntities.IsInsideVoxel(startPosition, endPosition, out lastOutsidePos)) { list.Add(entity, Vector3D.Distance(startPosition, lastOutsidePos)); //MyAPIGateway.Utilities.ShowMessage("Range", "CheckA"); } else { var center = voxelMap.PositionLeftBottomCorner + (voxelMap.Storage.Size / 2); // use distance to center of asteroid as an approximation. //MyAPIGateway.Utilities.ShowMessage("Range", "CheckB"); list.Add(entity, Vector3D.Distance(startPosition, center)); } } } } } if (findPlanets) { // Looks to be working against Git and public release. var planet = entity as Sandbox.Game.Entities.MyPlanet; if (planet != null) { var aabb = new BoundingBoxD(planet.PositionLeftBottomCorner, planet.PositionLeftBottomCorner + planet.Size); var hit = ray.Intersects(aabb); if (hit.HasValue) { var center = planet.WorldMatrix.Translation; var distance = (startPosition - center).Length(); // use distance to center of planet. list.Add(entity, distance); } } } } if (list.Count == 0) { lookEntity = null; lookDistance = 0; hitPoint = Vector3D.Zero; return; } // find the closest Entity. var item = list.OrderBy(f => f.Value).First(); lookEntity = item.Key; lookDistance = item.Value; hitPoint = startPosition + (Vector3D.Normalize(ray.Direction) * lookDistance); }
private void PlayerUpdate() { var playerControlled = MyAPIGateway.Session.ControlledObject; if(playerControlled != null) { if(playerControlled.Entity is IMyCharacter) { SetCharacterReference(playerControlled.Entity); } else if(playerControlled.Entity is IMyCockpit) // in a seat, certainly not gonna climb ladders { SetCharacterReference(null); } // other cases depend on having the character controlled for a bit to get the reference else if(character != null && character.Closed) { SetCharacterReference(null); } } else { character = null; } if(character != null) { var cb = MyCubeBuilder.Static; // Dynamically enable/disable UseModelIntersection on ladder blocks that you hold to have the useful effect // of being able the block when another entity is blocking the grid space but not the blocks's physical shape. // This will still have the side effect issue if you aim at a ladder block with the same ladder block. if(cb.IsActivated && cb.CubeBuilderState != null && cb.CubeBuilderState.CurrentBlockDefinition != null && LadderLogic.ladderIds.Contains(cb.CubeBuilderState.CurrentBlockDefinition.Id.SubtypeName)) { if(prevCubeBuilderDefinition == null || prevCubeBuilderDefinition.Id != cb.CubeBuilderState.CurrentBlockDefinition.Id) { if(prevCubeBuilderDefinition != null) prevCubeBuilderDefinition.UseModelIntersection = false; prevCubeBuilderDefinition = cb.CubeBuilderState.CurrentBlockDefinition; cb.CubeBuilderState.CurrentBlockDefinition.UseModelIntersection = true; } } else if(prevCubeBuilderDefinition != null) { prevCubeBuilderDefinition.UseModelIntersection = false; prevCubeBuilderDefinition = null; } var charCtrl = character as IMyControllableEntity; bool controllingCharacter = (playerControlled != null && playerControlled.Entity is IMyCharacter); IMyTerminalBlock ladder = null; MyCubeBlock ladderInternal = null; MatrixD ladderMatrix = character.WorldMatrix; // temporarily using it for character matrix, then used for ladder matrix var charPos = ladderMatrix.Translation + ladderMatrix.Up * 0.05; var charPos2 = ladderMatrix.Translation + ladderMatrix.Up * RAY_HEIGHT; var charRay = new RayD(charPos, ladderMatrix.Up); if(dismounting <= 1) // relative top dismount sequence { if(usingLadder == null) { dismounting = 2; return; } ladder = usingLadder; ladderInternal = ladder as MyCubeBlock; dismounting *= ALIGN_MUL; if(settings.clientPrediction) { ladderMatrix = ladder.WorldMatrix; var charOnLadder = ladderMatrix.Translation + ladderMatrix.Forward * (ladderInternal.BlockDefinition.ModelOffset.Z + EXTRA_OFFSET_Z); if(ladder.CubeGrid.GridSizeEnum == MyCubeSize.Large) charOnLadder += ladderMatrix.Backward; var topDir = Vector3D.Dot(character.WorldMatrix.Up, ladderMatrix.Up); var matrix = character.WorldMatrix; var halfY = ((ladderInternal.BlockDefinition.Size.Y * ladder.CubeGrid.GridSize) / 2); matrix.Translation = charOnLadder + (topDir > 0 ? ladderMatrix.Up : ladderMatrix.Down) * (halfY + 0.1f) + ladderMatrix.Backward * 0.75; character.SetWorldMatrix(MatrixD.SlerpScale(character.WorldMatrix, matrix, MathHelper.Clamp(dismounting, 0.0f, 1.0f))); character.Physics.LinearVelocity = ladder.CubeGrid.Physics.GetVelocityAtPoint(character.WorldMatrix.Translation); // sync velocity with the ladder } SetLadderStatus("Dismounting ladder...", MyFontEnum.White); if(dismounting > 1f) ExitLadder(false); return; } // UNDONE DEBUG //{ // var c = Color.Blue.ToVector4(); // MySimpleObjectDraw.DrawLine(charPos, charPos2, "WeaponLaserIgnoreDepth", ref c, 0.5f); //} // find a ladder foreach(var l in ladders.Values) { if(l.Closed || l.MarkedForClose || !l.IsFunctional) continue; if(Vector3D.DistanceSquared(l.WorldMatrix.Translation, charPos) <= UPDATE_RADIUS) { ladderInternal = l as MyCubeBlock; ladderMatrix = l.WorldMatrix; // update ladder oriented box to find character in it accurately Quaternion.CreateFromRotationMatrix(ref ladderMatrix, out ladderBox.Orientation); if(l is MyAdvancedDoor && !(l as MyAdvancedDoor).FullyOpen) { ladderBox.HalfExtent = (ladderInternal.BlockDefinition.Size * l.CubeGrid.GridSize) / 2; var offset = ladderInternal.BlockDefinition.ModelOffset; ladderBox.Center = ladderMatrix.Translation + ladderMatrix.Up * 1.125f + ladderMatrix.Forward * (offset.Z + EXTRA_OFFSET_Z); ladderBox.HalfExtent.Y = 0.25 + 0.06; // 6mm offset to avoid some inaccuracies ladderBox.HalfExtent.Z = 0.5; if(l.CubeGrid.GridSizeEnum == MyCubeSize.Large) ladderBox.Center += ladderMatrix.Backward; } else { ladderBox.HalfExtent = (ladderInternal.BlockDefinition.Size * l.CubeGrid.GridSize) / 2; ladderBox.HalfExtent.Y += 0.06; // 6mm offset to avoid some inaccuracies ladderBox.HalfExtent.Z = 0.5; var offset = ladderInternal.BlockDefinition.ModelOffset; ladderBox.Center = ladderMatrix.Translation + ladderMatrix.Forward * (offset.Z + EXTRA_OFFSET_Z); if(l.CubeGrid.GridSizeEnum == MyCubeSize.Large) ladderBox.Center += ladderMatrix.Backward; } if(!ladderBox.Contains(ref charPos) && !ladderBox.Contains(ref charPos2)) { var intersect = ladderBox.Intersects(ref charRay); if(!intersect.HasValue || intersect.Value < 0 || intersect.Value > RAY_HEIGHT) continue; } // UNDONE DEBUG //{ // { // var c = Color.Red.ToVector4(); // MySimpleObjectDraw.DrawLine(ladderBox.Center + ladderMatrix.Down * ladderBox.HalfExtent.Y, ladderBox.Center + ladderMatrix.Up * ladderBox.HalfExtent.Y, "WeaponLaserIgnoreDepth", ref c, 0.01f); // } // // if(debugBox == null) // { // debugBox = new MyEntity(); // debugBox.Init(null, @"Models\Debug\Error.mwm", null, null, null); // debugBox.PositionComp.LocalMatrix = Matrix.Identity; // debugBox.Flags = EntityFlags.Visible | EntityFlags.NeedsDraw | EntityFlags.NeedsDrawFromParent | EntityFlags.InvalidateOnMove; // debugBox.OnAddedToScene(null); // debugBox.Render.Transparency = 0.5f; // debugBox.Render.RemoveRenderObjects(); // debugBox.Render.AddRenderObjects(); // } // var matrix = MatrixD.CreateWorld(ladderBox.Center, ladderMatrix.Forward, ladderMatrix.Up); // var scale = ladderBox.HalfExtent * 2; // MatrixD.Rescale(ref matrix, ref scale); // debugBox.PositionComp.SetWorldMatrix(matrix); //} ladder = l; ladderInternal = l as MyCubeBlock; break; } } if(ladder != null) { var offset = ladderInternal.BlockDefinition.ModelOffset; var charOnLadder = ladderMatrix.Translation + ladderMatrix.Forward * (offset.Z + EXTRA_OFFSET_Z); if(ladder.CubeGrid.GridSizeEnum == MyCubeSize.Large) charOnLadder += ladderMatrix.Backward; if(++skipRetryGravity >= GRAVITY_UPDATERATE) { skipRetryGravity = 0; alignedToGravity = true; var gravity = MyParticlesManager.CalculateGravityInPoint(character.WorldMatrix.Translation); var gravityLength = gravity.Normalize(); if(gravityLength > 0) { float gravDot = Vector3.Dot(gravity, ladderMatrix.Down); if(!(gravDot >= 0.9f || gravDot <= -0.9f)) { alignedToGravity = false; } } } //bool readInput = InputHandler.IsInputReadable(); // HACK use before GetPressedOr() once ActiveGameplayScreen's NRE is resolved if(!alignedToGravity) { bool pressed = InputHandler.GetPressedOr(settings.useLadder1, settings.useLadder2, false, false) && InputHandler.IsInputReadable(); // needs to support hold-press, so don't set JustPressed to true! if(pressed) SetLadderStatus("Gravity not parallel to ladder!", MyFontEnum.Red, 1000); if(usingLadder != null) ExitLadder(false); return; } if(usingLadder == null) // first ladder interaction { //var controlUse = MyAPIGateway.Input.GetGameControl(MyControlsSpace.USE); // //if(!controlUse.IsPressed()) //{ // string assigned = (controlUse.GetKeyboardControl() != MyKeys.None ? MyAPIGateway.Input.GetKeyName(controlUse.GetKeyboardControl()) : (controlUse.GetMouseControl() != MyMouseButtonsEnum.None ? MyAPIGateway.Input.GetName(controlUse.GetMouseControl()) : "(NONE)")) + (controlUse.GetSecondKeyboardControl() != MyKeys.None ? " or " + MyAPIGateway.Input.GetKeyName(controlUse.GetSecondKeyboardControl()) : null); // SetLadderStatus("Press "+assigned+" to use the ladder.", MyFontEnum.White); // return; //} if(grabOnLoad) { grabOnLoad = false; } else { aimingAtLadder = true; if(settings.useLadder1 == null && settings.useLadder2 == null) { SetLadderStatus("Ladder interaction is unassigned, edit the settings.cfg file!\nFor now you can use the USE key.", MyFontEnum.Red); if(!MyAPIGateway.Input.IsGameControlPressed(MyControlsSpace.USE)) return; } else { bool pressed = InputHandler.GetPressedOr(settings.useLadder1, settings.useLadder2, false, false) && InputHandler.IsInputReadable(); // needs to support hold-press, so don't set JustPressed to true! if(!pressed) { #if !STABLE // STABLE CONDITION if(!highlightedLadders.Contains(ladder.EntityId)) { if(highlightedLadders.Count > 0) { foreach(var id in highlightedLadders) { MyVisualScriptLogicProvider.SetHighlight(LADDER_NAME_PREFIX + id, false); } highlightedLadders.Clear(); } var envDef = MyDefinitionManager.Static.EnvironmentDefinition; var color = envDef.ContourHighlightColor; var thick = (int)envDef.ContourHighlightThickness; highlightedLadders.Add(ladder.EntityId); MyVisualScriptLogicProvider.SetHighlight(ladder.Name, true, thick, LADDER_HIGHLIGHT_PULSE, color); var ladderGrid = ladder.CubeGrid; for(int i = 1; i <= 10; i++) { var slim = ladderGrid.GetCubeBlock(ladderGrid.WorldToGridInteger(ladderMatrix.Translation + ladderMatrix.Up * i * ladderGrid.GridSize)); if(slim?.FatBlock?.GameLogic?.GetAs<LadderLogic>() == null) break; var id = slim.FatBlock.EntityId; highlightedLadders.Add(id); MyVisualScriptLogicProvider.SetHighlight(LADDER_NAME_PREFIX + id, true, thick, LADDER_HIGHLIGHT_PULSE, color); } for(int i = 1; i <= 10; i++) { var slim = ladderGrid.GetCubeBlock(ladderGrid.WorldToGridInteger(ladderMatrix.Translation + ladderMatrix.Down * i * ladderGrid.GridSize)); if(slim?.FatBlock?.GameLogic?.GetAs<LadderLogic>() == null) break; var id = slim.FatBlock.EntityId; highlightedLadders.Add(id); MyVisualScriptLogicProvider.SetHighlight(LADDER_NAME_PREFIX + id, true, thick, LADDER_HIGHLIGHT_PULSE, color); } } #endif SetLadderStatus("Press " + InputHandler.GetFriendlyStringOr(settings.useLadder1, settings.useLadder2) + " to use the ladder.", MyFontEnum.White); return; } } } skipRefreshAnim = 60; mounting = (controllingCharacter ? ALIGN_STEP : 2); usingLadder = ladder; SendLadderData(LadderAction.MOUNT, entId: ladder.EntityId); LadderAnim(character, LadderAnimation.MOUNTING); } if(usingLadder != ladder) { usingLadder = ladder; SendLadderData(LadderAction.CHANGE_LADDER, entId: ladder.EntityId); } if(charCtrl.Entity.Physics == null) { ExitLadder(false); return; } if(settings.clientPrediction) character.Physics.LinearVelocity = ladder.CubeGrid.Physics.GetVelocityAtPoint(character.WorldMatrix.Translation); // sync velocity with the ladder if(skipRefreshAnim > 0 && --skipRefreshAnim == 0) // force refresh animation after mounting due to an issue { var anim = lastLadderAnim; lastLadderAnim = LadderAnimation.NONE; LadderAnim(character, anim); } if(mounting <= 1) // mounting on ladder sequence { mounting *= ALIGN_MUL; if(settings.clientPrediction) { float align = Vector3.Dot(ladderMatrix.Up, character.WorldMatrix.Up); var matrix = MatrixD.CreateFromDir(ladderMatrix.Backward, (align > 0 ? ladderMatrix.Up : ladderMatrix.Down)); var halfY = ((ladderInternal.BlockDefinition.Size.Y * ladder.CubeGrid.GridSize) / 2); var diff = Vector3D.Dot(character.WorldMatrix.Translation, ladderMatrix.Up) - Vector3D.Dot(charOnLadder, ladderMatrix.Up); matrix.Translation = charOnLadder + ladderMatrix.Up * MathHelper.Clamp(diff, -halfY, halfY); character.SetWorldMatrix(MatrixD.SlerpScale(character.WorldMatrix, matrix, MathHelper.Clamp(mounting, 0.0f, 1.0f))); } if(mounting >= 0.75f && charCtrl.EnabledThrusts) // delayed turning off thrusts because gravity aligns you faster and can make you fail to attach to the ladder charCtrl.SwitchThrusts(); SetLadderStatus("Mounting ladder...", MyFontEnum.White); return; } // TODO jetpack assited climb/descend ? / gravity assisted descend ? if(charCtrl.EnabledThrusts) { if(!learned[4]) learned[4] = true; ExitLadder(false); // leave ladder if jetpack is turned on return; } // HACK use once input reading NRE is fixed //if(!controllingCharacter) // disable ladder control if not controlling character // readInput = false; bool movingSideways = false; var analogInput = MyAPIGateway.Input.GetPositionDelta(); // HACK use in-line once NRE is fixed if(!controllingCharacter) analogInput = Vector3.Zero; else if(analogInput.LengthSquared() > 0 && !InputHandler.IsInputReadable()) analogInput = Vector3.Zero; if(analogInput.Y < 0) // crouch { if(!learned[4]) learned[4] = true; ExitLadder(false); return; } float move = MathHelper.Clamp((float)Math.Round(-analogInput.Z, 1), -1, 1); // forward/backward float side = MathHelper.Clamp((float)Math.Round(analogInput.X, 1), -1, 1); // left/right //float move = readInput ? MathHelper.Clamp(MyAPIGateway.Input.GetGameControlAnalogState(MyControlsSpace.FORWARD) - MyAPIGateway.Input.GetGameControlAnalogState(MyControlsSpace.BACKWARD), -1, 1) : 0; //float side = readInput ? MathHelper.Clamp(MyAPIGateway.Input.GetGameControlAnalogState(MyControlsSpace.STRAFE_RIGHT) - MyAPIGateway.Input.GetGameControlAnalogState(MyControlsSpace.STRAFE_LEFT), -1, 1) : 0; var alignVertical = ladderMatrix.Up.Dot(character.WorldMatrix.Up); if(!loadedAllLearned) { bool allLearned = (learned[0] && learned[1] && learned[2] && learned[3] && learned[4]); for(int i = 0; i < learned.Length; i++) { if(learnNotify[i] == null) learnNotify[i] = MyAPIGateway.Utilities.CreateNotification(""); learnNotify[i].Text = (learned[i] ? LEARN_CHECK : LEARN_UNCHECK) + learnText[i]; learnNotify[i].Font = (learned[i] ? MyFontEnum.White : MyFontEnum.DarkBlue); learnNotify[i].AliveTime = (allLearned ? 1000 : 100); learnNotify[i].Show(); } if(allLearned) { SaveLearn(); loadedAllLearned = true; } } var view = MyAPIGateway.Session.ControlledObject.GetHeadMatrix(false, true); float lookVertical = Vector3.Dot(character.WorldMatrix.Up, view.Forward); if(settings.relativeControls) // climbing relative to camera { float verticalModifier = MathHelper.Clamp((lookVertical + 0.65f) / 0.5f, -0.5f, 1.0f); if(verticalModifier < 0) verticalModifier *= 2; move = (float)Math.Round(move * verticalModifier, 1); } if(analogInput.Y > 0) // jump { if(characterMovementState == MyCharacterMovementEnum.Jump) // this is still fine for avoiding jump as the character still is able to jump without needing feet on the ground { ExitLadder(false); // only release if on the floor as the character will jump regardless return; } if(settings.clientPrediction) character.Physics.LinearVelocity += view.Forward * (characterDefinition == null ? VEL_JUMP : 200 * characterDefinition.JumpForce) * TICKRATE; SendLadderData(LadderAction.JUMP_OFF, vec: view.Forward); LadderAnim(character, LadderAnimation.JUMP_OFF); if(!learned[3]) learned[3] = true; ExitLadder(false); return; } bool sprint = (characterDefinition != null && characterDefinition.Jetpack != null && MyAPIGateway.Input.IsGameControlPressed(MyControlsSpace.SPRINT)); if(Math.Abs(side) > 0.0001f) { if(settings.relativeControls) // side dismounting relative to camera { var alignForward = ladderMatrix.Backward.Dot(character.WorldMatrix.Forward); if(alignForward < 0) side = -side; } float speed = (characterDefinition == null ? (sprint ? VEL_SIDE : VEL_CLIMB) : CHAR_SPEED_MUL * (sprint ? characterDefinition.MaxSprintSpeed : characterDefinition.MaxRunStrafingSpeed)); if(settings.clientPrediction) character.Physics.LinearVelocity += side * (alignVertical > 0 ? ladderMatrix.Left : ladderMatrix.Right) * speed * TICKRATE; LadderAnim(character, (side > 0 ? LadderAnimation.DISMOUNT_LEFT : LadderAnimation.DISMOUNT_RIGHT)); movingSideways = true; if(!learned[2]) learned[2] = true; } else { // aligning player to ladder if(settings.clientPrediction) { Vector3 dir = charOnLadder - charPos; Vector3 vel = dir - (ladderMatrix.Up * Vector3D.Dot(dir, ladderMatrix.Up)); // projecting up/down direction to ignore it float len = vel.Normalize(); if(len >= ALIGN_ACCURACY) { float speed = (characterDefinition == null ? (sprint ? VEL_SIDE : VEL_CLIMB) : CHAR_SPEED_MUL * (sprint ? characterDefinition.MaxRunStrafingSpeed : characterDefinition.MaxWalkStrafingSpeed)); len = MathHelper.Clamp(len, 0.1f, 1); character.Physics.LinearVelocity += vel * len * speed * TICKRATE; } } } // TODO find a way to control view { //var ctrl2 = (Sandbox.Game.Entities.IMyControllableEntity)character; // //ctrl2.HeadLocalYAngle = 0; //ctrl2.HeadLocalXAngle = 0; // // or MoveAndRotate() ? // or... angularvelocity ? // or I dunno! } if(Math.Abs(move) > 0.0001f) { if(!learned[0]) learned[0] = true; var halfY = ((ladderInternal.BlockDefinition.Size.Y * ladder.CubeGrid.GridSize) / 2); var edge = charOnLadder + ((alignVertical > 0 ? ladderMatrix.Up : ladderMatrix.Down) * halfY); // climb over at the end when climbing up if(move > 0 && Vector3D.DistanceSquared(charPos, edge) <= 0.0625) // 0.25 squared { var nextBlockWorldPos = ladderMatrix.Translation + ladderMatrix.Forward * offset.Z + ((alignVertical > 0 ? ladderMatrix.Up : ladderMatrix.Down) * (halfY + 0.1f)); var nextBlockPos = ladder.CubeGrid.WorldToGridInteger(nextBlockWorldPos); var slim = ladder.CubeGrid.GetCubeBlock(nextBlockPos); // if the next block is not a ladder, dismount if(slim == null || !(slim.FatBlock is IMyTerminalBlock) || !LadderLogic.ladderIds.Contains(slim.FatBlock.BlockDefinition.SubtypeId)) { dismounting = ALIGN_STEP; SendLadderData(LadderAction.DISMOUNT); return; } } // on the floor and moving backwards makes you dismount if(move < 0) { var feetStart = character.WorldMatrix.Translation + character.WorldMatrix.Up * 0.2; // a bit higher because the floor might clip through the character var feetTarget = feetStart + character.WorldMatrix.Down * 0.3; IHitInfo hit; if(MyAPIGateway.Physics.CastRay(feetStart, feetTarget, out hit, COLLISSIONLAYER_NOCHARACTER)) { // need to check the block under the ladder if it's anything but a ladder because "standing" stance occurs when character rests on its chest-sphere collision mesh too var prevBlockWorldPos = ladderMatrix.Translation + ladderMatrix.Forward * offset.Z + (alignVertical > 0 ? ladderMatrix.Down : ladderMatrix.Up) * (halfY + 0.1f); var prevBlockPos = ladder.CubeGrid.WorldToGridInteger(prevBlockWorldPos); var slim = ladder.CubeGrid.GetCubeBlock(prevBlockPos); // if it's not a ladder, check the distance and confirm your feet are close to its edge if(slim == null || !(slim.FatBlock is IMyTerminalBlock) || !LadderLogic.ladderIds.Contains(slim.FatBlock.BlockDefinition.SubtypeId)) { // get the block's edge and the character feet position only along the ladder's up/down axis var blockPosProjectedUp = ladderMatrix.Up * Vector3D.Dot(prevBlockWorldPos, ladderMatrix.Up); var charPosProjectedUp = ladderMatrix.Up * Vector3D.Dot(character.WorldMatrix.Translation, ladderMatrix.Up); if(Vector3D.DistanceSquared(blockPosProjectedUp, charPosProjectedUp) <= 0.04) // 0.2 squared { ExitLadder(false); // to recap: if you're moving char-relative down and in "standing" stance and the block below is not a ladder and you're closer than 0.1m to its edge, then let go of the ladder. return; } } } } // climbing on the ladder if(!learned[1] && sprint) learned[1] = true; float speed = (characterDefinition == null ? (sprint ? VEL_SPRINT : VEL_CLIMB) : CHAR_SPEED_MUL * (sprint ? characterDefinition.MaxSprintSpeed : characterDefinition.MaxRunSpeed)); if(settings.clientPrediction) character.Physics.LinearVelocity += (alignVertical > 0 ? ladderMatrix.Up : ladderMatrix.Down) * move * speed * TICKRATE; if(!movingSideways) LadderAnim(character, (move > 0 ? LadderAnimation.UP : LadderAnimation.DOWN)); } else if(!movingSideways) { LadderAnim(character, LadderAnimation.IDLE); } SendLadderData(LadderAction.CLIMB, climb: (alignVertical > 0 ? move : -move), side: (alignVertical > 0 ? side : -side), sprint: sprint); return; } } ExitLadder(); }
public bool Intersect(RayD ray, ref Vector3D p1, ref Vector3D p2, ref Vector3 n1, ref Vector3 n2) { // Substituting equ. (1) - (6) to equ. (I) and solving for t' gives: // // t' = (t * dot(AB, d) + dot(AB, AO)) / dot(AB, AB); (7) or // t' = t * m + n where // m = dot(AB, d) / dot(AB, AB) and // n = dot(AB, AO) / dot(AB, AB) // Vector3D AB = P1 - P0; Vector3D AO = ray.Position - P0; double AB_dot_d = AB.Dot(ray.Direction); double AB_dot_AO = AB.Dot(AO); double AB_dot_AB = AB.Dot(AB); double m = AB_dot_AB > 0 ? AB_dot_d / AB_dot_AB : 0; double n = AB_dot_AB > 0 ? AB_dot_AO / AB_dot_AB : 0; // Substituting (7) into (II) and solving for t gives: // // dot(Q, Q)*t^2 + 2*dot(Q, R)*t + (dot(R, R) - r^2) = 0 // where // Q = d - AB * m // R = AO - AB * n Vector3D Q = ray.Direction - (AB * m); Vector3D R = AO - (AB * n); double a = Q.Dot(Q); double b = 2.0f * Q.Dot(R); double c = R.Dot(R) - (Radius * Radius); if (a == 0.0) { // Special case: AB and ray direction are parallel. If there is an intersection it will be on the end spheres... // NOTE: Why is that? // Q = d - AB * m => // Q = d - AB * (|AB|*|d|*cos(AB,d) / |AB|^2) => |d| == 1.0 // Q = d - AB * (|AB|*cos(AB,d)/|AB|^2) => // Q = d - AB * cos(AB, d) / |AB| => // Q = d - unit(AB) * cos(AB, d) // // |Q| == 0 means Q = (0, 0, 0) or d = unit(AB) * cos(AB,d) // both d and unit(AB) are unit vectors, so cos(AB, d) = 1 => AB and d are parallel. // BoundingSphereD sphereA, sphereB; sphereA.Center = P0; sphereA.Radius = Radius; sphereB.Center = P1; sphereB.Radius = Radius; double atmin, atmax, btmin, btmax; if (!sphereA.IntersectRaySphere(ray, out atmin, out atmax) || !sphereB.IntersectRaySphere(ray, out btmin, out btmax)) { // No intersection with one of the spheres means no intersection at all... return false; } if (atmin < btmin) { p1 = ray.Position + (ray.Direction * atmin); n1 = p1 - P0; n1.Normalize(); } else { p1 = ray.Position + (ray.Direction * btmin); n1 = p1 - P1; n1.Normalize(); } if (atmax > btmax) { p2 = ray.Position + (ray.Direction * atmax); n2 = p2 - P0; n2.Normalize(); } else { p2 = ray.Position + (ray.Direction * btmax); n2 = p2 - P1; n2.Normalize(); } return true; } double discriminant = b * b - 4.0 * a * c; if (discriminant < 0.0f) { // The ray doesn't hit the infinite cylinder defined by (A, B). // No intersection. return false; } double tmin = (-b - Math.Sqrt(discriminant)) / (2.0 * a); double tmax = (-b + Math.Sqrt(discriminant)) / (2.0 * a); if (tmin > tmax) { double temp = tmin; tmin = tmax; tmax = temp; } // Now check to see if K1 and K2 are inside the line segment defined by A,B double t_k1 = tmin * m + n; if (t_k1 < 0.0f) { // On sphere (A, r)... BoundingSphereD s; s.Center = P0; s.Radius = Radius; double stmin, stmax; if (s.IntersectRaySphere(ray, out stmin, out stmax)) { p1 = ray.Position + (ray.Direction * stmin); n1 = p1 - P0; n1.Normalize(); } else return false; } else if (t_k1 > 1.0f) { // On sphere (B, r)... BoundingSphereD s; s.Center = P1; s.Radius = Radius; double stmin, stmax; if (s.IntersectRaySphere(ray, out stmin, out stmax)) { p1 = ray.Position + (ray.Direction * stmin); n1 = p1 - P1; n1.Normalize(); } else return false; } else { // On the cylinder... p1 = ray.Position + (ray.Direction * tmin); Vector3 k1 = P0 + AB * t_k1; n1 = p1 - k1; n1.Normalize(); } double t_k2 = tmax * m + n; if (t_k2 < 0.0f) { // On sphere (A, r)... BoundingSphereD s; s.Center = P0; s.Radius = Radius; double stmin, stmax; if (s.IntersectRaySphere(ray, out stmin, out stmax)) { p2 = ray.Position + (ray.Direction * stmax); n2 = p2 - P0; n2.Normalize(); } else return false; } else if (t_k2 > 1.0f) { // On sphere (B, r)... BoundingSphereD s; s.Center = P1; s.Radius = Radius; double stmin, stmax; if (s.IntersectRaySphere(ray, out stmin, out stmax)) { p2 = ray.Position + (ray.Direction * stmax); n2 = p2 - P1; n2.Normalize(); } else return false; } else { p2 = ray.Position + (ray.Direction * tmax); Vector3D k2 = P0 + AB * t_k2; n2 = p2 - k2; n2.Normalize(); } return true; }
private Vector3 GetBoneOnSphere(Vector3I center, Vector3I bonePos, MyCubeGrid grid) { Vector3D worldCenter = BoneToWorld(center, Vector3.Zero, grid); Vector3D worldBone = BoneToWorld(bonePos, Vector3.Zero, grid); BoundingSphereD sphere = new BoundingSphereD(worldCenter, grid.GridSize); Vector3D direction = worldCenter - worldBone; direction.Normalize(); RayD ray = new RayD(worldBone, direction); double tmin, tmax; if (sphere.IntersectRaySphere(ray, out tmin, out tmax)) { Vector3D onSphere = worldBone + direction * tmin; var worldOnSphere = Vector3D.Transform(onSphere, grid.PositionComp.WorldMatrixInvScaled); worldOnSphere += new Vector3D(grid.GridSize / MyGridSkeleton.BoneDensity); return (worldOnSphere - (Vector3D)(bonePos / (float)MyGridSkeleton.BoneDensity) * grid.GridSize); } else { return Vector3.Zero; } }
/** * Project a position to a face of the (-1, -1, -1)(1, 1, 1) cube. */ public static void ProjectToNearestFace(ref Vector3D localPos, out Vector3 faceCoords) { Vector3D gravity; Vector3D.Normalize(ref localPos, out gravity); gravity = -gravity; RayD r = new RayD(localPos, gravity); double? travel = s_unitsBox.Intersects(r); Debug.Assert(travel.HasValue, "Ray does not intersect with planet!"); faceCoords = localPos + (Vector3D)(gravity * travel); }