public Grinder(Pathfinder pathfinder, float maxRange) : base(pathfinder) { this.m_startPostion = m_controlBlock.CubeBlock.GetPosition(); this.m_longestDimension = m_controlBlock.CubeGrid.GetLongestDim(); PseudoBlock navBlock = m_navSet.Settings_Current.NavigationBlock; m_navGrind = navBlock.Block is IMyShipGrinder ? new MultiBlock <MyObjectBuilder_ShipGrinder>(navBlock.Block) : new MultiBlock <MyObjectBuilder_ShipGrinder>(() => m_mover.Block.CubeGrid); if (m_navGrind.FunctionalBlocks == 0) { Log.DebugLog("no working grinders", Logger.severity.INFO); return; } m_grinderOffset = m_navGrind.Block.GetLengthInDirection(m_navGrind.Block.FirstFaceDirection()) * 0.5f + 2.5f; if (m_navSet.Settings_Current.DestinationRadius > m_longestDimension) { Log.DebugLog("Reducing DestinationRadius from " + m_navSet.Settings_Current.DestinationRadius + " to " + m_longestDimension, Logger.severity.DEBUG); m_navSet.Settings_Task_NavRot.DestinationRadius = m_longestDimension; } this.m_finder = new GridFinder(m_navSet, m_controlBlock, maxRange); this.m_finder.OrderValue = OrderValue; m_navSet.Settings_Task_NavRot.NavigatorMover = this; m_navSet.Settings_Task_NavRot.NavigatorRotator = this; m_navSet.Settings_Task_NavRot.IgnoreEntity = IgnoreEntity; }
public void TestRotate(Vector3 displacement) { if (Globals.UpdateCount < m_nextRunRotate) { return; } m_nextRunRotate = Globals.UpdateCount + 10ul; m_navBlock = m_navSet.Settings_Current.NavigationBlock; m_pathHigh.Enqueue(() => { Vector3 axis; Vector3.Normalize(ref displacement, out axis); IMyEntity obstruction; if (m_rotateChecker.TestRotate(axis, m_ignoreAsteroid, out obstruction)) { m_rotateState = PathState.No_Obstruction; } else { m_rotateState = PathState.Path_Blocked; } RotateObstruction = obstruction; RunItem(); }); RunItem(); }
public WeldGrid(Pathfinder pathfinder, string gridName, bool shopAfter) : base(pathfinder) { this.m_finder = new GridFinder(pathfinder.NavSet, m_controlBlock, gridName); this.m_shopAfter = shopAfter; PseudoBlock navBlock = m_navSet.Settings_Current.NavigationBlock; if (navBlock.Block is IMyShipWelder) { m_navWeld = new MultiBlock <MyObjectBuilder_ShipWelder>(navBlock.Block); } else { CubeGridCache cache = CubeGridCache.GetFor(m_controlBlock.CubeGrid); if (cache == null) { Log.DebugLog("failed to get cache", Logger.severity.WARNING); return; } if (cache.CountByType(typeof(MyObjectBuilder_ShipWelder)) < 1) { Log.DebugLog("no welders on ship", Logger.severity.WARNING); return; } m_navWeld = new MultiBlock <MyObjectBuilder_ShipWelder>(() => m_mover.Block.CubeGrid); } UpdateTimeout(); m_navSet.Settings_Task_NavMove.NavigatorMover = this; }
protected override void ActionMethod(Pathfinding.Pathfinder pathfinder) { PseudoBlock pseudo = new PseudoBlock(m_block, m_forward, m_upward); pathfinder.NavSet.Settings_Task_NavRot.LandingBlock = pseudo; pathfinder.NavSet.LastLandingBlock = pseudo; }
public Orbiter(Mover mover, AllNavigationSettings navSet, string entity) : base(mover, navSet) { this.m_logger = new Logger(GetType().Name, m_controlBlock.CubeBlock); this.m_navBlock = m_navSet.Settings_Current.NavigationBlock; switch (entity.LowerRemoveWhitespace()) { case "asteroid": SetOrbitClosestVoxel(true); CalcFakeOrbitSpeedForce(); m_logger.debugLog("Orbiting asteroid: " + OrbitEntity.getBestName(), Logger.severity.INFO); break; case "planet": SetOrbitClosestVoxel(false); OrbitSpeed = (float)Math.Sqrt((OrbitEntity as MyPlanet).GetGravityMultiplier(m_navBlock.WorldPosition) * 9.81f * Altitude); if (OrbitSpeed < 1f) CalcFakeOrbitSpeedForce(); m_logger.debugLog("Orbiting planet: " + OrbitEntity.getBestName(), Logger.severity.INFO); break; default: m_gridFinder = new GridFinder(navSet, mover.Block, entity, mustBeRecent: true); m_logger.debugLog("Searching for a grid: " + entity, Logger.severity.INFO); break; } m_navSet.Settings_Task_NavMove.NavigatorMover = this; }
/// <summary> /// Checks for enough acceleration to move the ship forward and backward with the specified acceleration. /// </summary> protected bool SufficientAcceleration(float acceleration) { PseudoBlock navBlock = m_navSet.Settings_Current.NavigationBlock; return(m_mover.Thrust.CanMoveDirection(Base6Directions.GetClosestDirection(navBlock.LocalMatrix.Forward), acceleration) && m_mover.Thrust.CanMoveDirection(Base6Directions.GetClosestDirection(navBlock.LocalMatrix.Backward), acceleration)); }
public ShipControllerBlock(IMyCubeBlock block) { m_logger = new Logger(GetType().Name, block); Controller = block as MyShipController; CubeBlock = block; Terminal = block as IMyTerminalBlock; Pseudo = new PseudoBlock(block); }
public ShipControllerBlock(IMyCubeBlock block, Action <Message> messageHandler) { CubeBlock = block; Pseudo = new PseudoBlock(block); NetworkNode = new RelayNode(block) { MessageHandler = messageHandler }; AutopilotTerminal = new AutopilotTerminal(block); }
public EnemyFinder(Pathfinder pathfinder, AllNavigationSettings navSet, long entityId) : base(navSet, pathfinder.Mover.Block) { this.m_pathfinder = pathfinder; this.m_navSet = navSet; this.m_targetEntityId = entityId; this.m_landingGear = m_navSet.Settings_Current.LandingBlock; Log.DebugLog("Initialized"); }
public EnemyFinder(Mover mover, AllNavigationSettings navSet, long entityId) : base(navSet, mover.Block) { this.m_logger = new Logger(GetType().Name, mover.Block.CubeBlock, () => CurrentResponse.Response.ToString()); this.m_mover = mover; this.m_navSet = navSet; this.m_targetEntityId = entityId; this.m_landingGear = m_navSet.Settings_Current.LandingBlock; m_logger.debugLog("Initialized"); }
public FlightControlAssist(MyCockpit cockpit) { this.m_cockpit = cockpit; this.m_aileron = m_elevator = m_rudder = new FlightControlStator[0]; CubeGridCache cache = CubeGridCache.GetFor(m_grid); Pseudo = new PseudoBlock(cockpit); Update.UpdateManager.Register(10, Update10, m_grid); }
//private void CheckInterrupt() //{ // if (Interrupt) // throw new InterruptException(); //} /// <summary> /// Performs a fast test to see if the path is clear. /// </summary> /// <returns>True if path is clear. False if slow test needs to be run.</returns> public bool TestFast(PseudoBlock NavigationBlock, Vector3D worldDestination, bool ignoreAsteroid, MyEntity ignoreEntity, bool landing) { m_logger.debugLog("NavigationBlock.CubeGrid != m_grid", Logger.severity.FATAL, condition: NavigationBlock.Grid != m_grid); //CheckInterrupt(); this.m_ignoreEntity = ignoreEntity; this.m_ignoreAsteroid = ignoreAsteroid; this.m_profiler.Init(m_grid, RelativePosition3F.FromWorld(m_grid, worldDestination), NavigationBlock.LocalPosition, landing); Vector3D Displacement = worldDestination - NavigationBlock.WorldPosition; //m_logger.debugLog("Displacement = " + Displacement, "TestPath()"); // entities in large AABB BoundingBoxD AtDest = m_grid.WorldAABB.Translate(Displacement); ICollection <MyEntity> offenders = EntitiesInLargeAABB(m_grid.WorldAABB, AtDest); if (offenders.Count == 0) { m_logger.debugLog("AABB is empty", Logger.severity.TRACE); return(true); } m_logger.debugLog("collected entities to test: " + offenders.Count); // perform capsule vs AABB test List <MyEntity> remove = new List <MyEntity>(); foreach (MyEntity offending in offenders) { if (!m_path.IntersectsAABB(offending)) { //m_logger.debugLog("no AABB intersection: " + offending.getBestName(), "TestPath()"); remove.Add(offending); } } foreach (MyEntity entity in remove) { offenders.Remove(entity); } if (offenders.Count == 0) { m_logger.debugLog("no entities intersect path", Logger.severity.TRACE); return(true); } m_logger.debugLog("entities intersecting path: " + offenders.Count); //foreach (var ent in offenders) // m_logger.debugLog("entity: " + ent.getBestName(), "TestPath()"); m_offendingEntities = offenders.OrderBy(entity => m_grid.WorldAABB.Distance(entity.PositionComp.WorldAABB)); return(false); }
/// <summary> /// Creates a GOLIS /// </summary> /// <param name="mover">The mover to use</param> /// <param name="navSet">The settings to use</param> /// <param name="location">The location to fly to</param> public GOLIS(Mover mover, AllNavigationSettings navSet, Vector3D location, AllNavigationSettings.SettingsLevelName level = AllNavigationSettings.SettingsLevelName.NavMove) : base(mover, navSet) { this.myLogger = new Logger("GOLIS", m_controlBlock.CubeBlock); this.NavigationBlock = m_navSet.Settings_Current.NavigationBlock; this.location = location; this.m_level = level; var atLevel = m_navSet.GetSettingsLevel(level); atLevel.NavigatorMover = this; //atLevel.DestinationEntity = mover.Block.CubeBlock; // in case waypoint is blocked by moving target }
/// <summary> /// Creates a GOLIS /// </summary> /// <param name="pathfinder">The mover to use</param> /// <param name="navSet">The settings to use</param> /// <param name="location">The location to fly to</param> public GOLIS(Pathfinder pathfinder, Vector3D location, AllNavigationSettings.SettingsLevelName level = AllNavigationSettings.SettingsLevelName.NavMove) : base(pathfinder) { this.NavigationBlock = m_navSet.Settings_Current.NavigationBlock; this.location = location; this.m_level = level; var atLevel = m_navSet.GetSettingsLevel(level); atLevel.NavigatorMover = this; //atLevel.DestinationEntity = mover.Block.CubeBlock; // in case waypoint is blocked by moving target }
/// <summary> /// Creates a GOLIS /// </summary> /// <param name="mover">The mover to use</param> /// <param name="navSet">The settings to use</param> /// <param name="location">The location to fly to</param> public GOLIS(Mover mover, AllNavigationSettings navSet, Vector3 location, bool waypoint = false) : base(mover, navSet) { this.myLogger = new Logger("GOLIS", m_controlBlock.CubeBlock); this.NavigationBlock = m_navSet.Settings_Current.NavigationBlock; this.location = location; this.Waypoint = waypoint; var atLevel = waypoint ? m_navSet.Settings_Task_NavWay : m_navSet.Settings_Task_NavMove; atLevel.NavigatorMover = this; atLevel.DestinationEntity = mover.Block.CubeGrid; // in case waypoint is blocked by moving target }
protected override void ActionMethod(Rynchodon.Autopilot.Pathfinding.Pathfinder pathfinder) { PseudoBlock pseudo = new PseudoBlock(m_block, m_forward, m_upward); if (m_block is IMyLaserAntenna || m_block is SpaceEngineers.Game.ModAPI.Ingame.IMySolarPanel || m_block is SpaceEngineers.Game.ModAPI.Ingame.IMyOxygenFarm) { new Facer(pathfinder, pseudo); } else { pathfinder.NavSet.Settings_Task_NavRot.NavigationBlock = pseudo; } }
/// <summary> /// Creates an Orbiter for a specific entity, fake orbit only. /// Does not add itself to navSet. /// </summary> /// <param name="faceBlock">The block that will be faced towards the orbited entity</param> /// <param name="entity">The entity to be orbited</param> /// <param name="distance">The distance between the orbiter and the orbited entity</param> /// <param name="name">What to call the orbited entity</param> public Orbiter(Mover mover, AllNavigationSettings navSet, PseudoBlock faceBlock, IMyEntity entity, float distance, string name) : base(mover, navSet) { this.m_logger = new Logger(GetType().Name, m_controlBlock.CubeBlock); this.m_navBlock = faceBlock; this.m_orbitEntity_name = name; Altitude = distance; OrbitEntity = entity; CalcFakeOrbitSpeedForce(); m_logger.debugLog("Orbiting: " + OrbitEntity.getBestName(), Logger.severity.INFO); }
/// <summary> /// Match orientation with the target block. /// </summary> /// <param name="block">The navigation block</param> /// <param name="destBlock">The destination block</param> /// <param name="forward">The direction of destBlock that will be matched to navigation block's forward</param> /// <param name="upward">The direction of destBlock that will be matched to navigation block's upward</param> /// <returns>True iff localMatrix is facing the same direction as destBlock's forward</returns> public void CalcRotate(PseudoBlock block, IMyCubeBlock destBlock, Base6Directions.Direction?forward, Base6Directions.Direction?upward) { //Log.DebugLog("entered CalcRotate(PseudoBlock block, IMyCubeBlock destBlock, Base6Directions.Direction? forward, Base6Directions.Direction? upward)", "CalcRotate()"); if (forward == null) { forward = Base6Directions.Direction.Forward; } RelativeDirection3F faceForward = RelativeDirection3F.FromWorld(block.Grid, destBlock.WorldMatrix.GetDirectionVector(forward.Value)); RelativeDirection3F faceUpward = upward.HasValue ? RelativeDirection3F.FromWorld(block.Grid, destBlock.WorldMatrix.GetDirectionVector(upward.Value)) : null; CalcRotate(block.LocalMatrix, faceForward, faceUpward); }
//private void CheckInterrupt() //{ // if (Interrupt) // throw new InterruptException(); //} /// <summary> /// Performs a fast test to see if the path is clear. /// </summary> /// <returns>True if path is clear. False if slow test needs to be run.</returns> public bool TestFast(PseudoBlock NavigationBlock, Vector3D worldDestination, bool ignoreAsteroid, MyEntity ignoreEntity, bool landing) { m_logger.debugLog(NavigationBlock.Grid != m_grid, "NavigationBlock.CubeGrid != m_grid", "TestFast()", Logger.severity.FATAL); //CheckInterrupt(); this.m_ignoreEntity = ignoreEntity; this.m_ignoreAsteroid = ignoreAsteroid; this.m_profiler.Init(m_grid, RelativePosition3F.FromWorld(m_grid, worldDestination), NavigationBlock.LocalPosition, landing); Vector3D Displacement = worldDestination - NavigationBlock.WorldPosition; //m_logger.debugLog("Displacement = " + Displacement, "TestPath()"); // entities in large AABB BoundingBoxD AtDest = m_grid.WorldAABB.Translate(Displacement); ICollection<MyEntity> offenders = EntitiesInLargeAABB(m_grid.WorldAABB, AtDest); if (offenders.Count == 0) { m_logger.debugLog("AABB is empty", "TestPath()", Logger.severity.TRACE); return true; } m_logger.debugLog("collected entities to test: " + offenders.Count, "TestPath()"); // perform capsule vs AABB test List<MyEntity> remove = new List<MyEntity>(); foreach (MyEntity offending in offenders) if (!m_path.IntersectsAABB(offending)) { //m_logger.debugLog("no AABB intersection: " + offending.getBestName(), "TestPath()"); remove.Add(offending); } foreach (MyEntity entity in remove) offenders.Remove(entity); if (offenders.Count == 0) { m_logger.debugLog("no entities intersect path", "TestFast()", Logger.severity.TRACE); return true; } m_logger.debugLog("entities intersecting path: " + offenders.Count, "TestPath()"); //foreach (var ent in offenders) // m_logger.debugLog("entity: " + ent.getBestName(), "TestPath()"); m_offendingEntities = offenders.OrderBy(entity => m_grid.WorldAABB.Distance(entity.PositionComp.WorldAABB)); return false; }
public Miner(Pathfinder pathfinder, byte[] oreTargets) : base(pathfinder) { m_oreTargets = oreTargets; CubeGridCache cache = CubeGridCache.GetFor(m_controlBlock.CubeGrid); if (cache == null) { return; } if (cache.CountByType(typeof(MyObjectBuilder_Drill)) == 0) { Logger.DebugLog("No drills", Logger.severity.WARNING); return; } // if a drill has been chosen by player, use it PseudoBlock navBlock = m_navSet.Settings_Current.NavigationBlock; MultiBlock <MyObjectBuilder_Drill> navDrill = navBlock.Block is IMyShipDrill ? new MultiBlock <MyObjectBuilder_Drill>(navBlock.Block) : navDrill = new MultiBlock <MyObjectBuilder_Drill>(() => m_mover.Block.CubeGrid); if (navDrill.FunctionalBlocks == 0) { Logger.DebugLog("no working drills", Logger.severity.WARNING); return; } m_navSet.Settings_Task_NavRot.NavigatorMover = this; m_navSet.Settings_Task_NavRot.NavigationBlock = navDrill; BoundingSphereD nearby = new BoundingSphereD(navDrill.WorldPosition, m_controlBlock.CubeGrid.LocalVolume.Radius * 2d); List <MyVoxelBase> nearbyVoxels = new List <MyVoxelBase>(); MyGamePruningStructure.GetAllVoxelMapsInSphere(ref nearby, nearbyVoxels); foreach (MyVoxelBase voxel in nearbyVoxels) { if ((voxel is IMyVoxelMap || voxel is MyPlanet) && voxel.ContainsOrIntersects(ref nearby)) { Log.DebugLog("near a voxel, escape first", Logger.severity.DEBUG); m_stage = Stage.Mining; new EscapeMiner(m_pathfinder, voxel); return; } } m_stage = Stage.GetDeposit; }
/// <param name="pathfinder">The mover to use</param> /// /// <param name="rotBlock">The block to rotate</param> public Facer(Pathfinder pathfinder, PseudoBlock rotBlock) : base(pathfinder) { this.m_pseudoBlock = rotBlock; this.m_laser = rotBlock.Block as IMyLaserAntenna; if (this.m_laser == null) { if (!(rotBlock.Block is Ingame.IMySolarPanel) && !(rotBlock.Block is Ingame.IMyOxygenFarm)) { Log.AlwaysLog("Block is of wrong type: " + rotBlock.Block.DisplayNameText, Logger.severity.FATAL); throw new Exception("Block is of wrong type: " + rotBlock.Block.DisplayNameText); } } m_navSet.Settings_Task_NavRot.NavigatorRotator = this; }
public EnemyLander(Pathfinder pathfinder, PseudoBlock landingGear) { this.m_pathfinder = pathfinder; if (landingGear == null) { Logger.DebugLog("landingGear param is null, not going to land"); return; } this.m_hasLandingGear = landingGear.Block is IMyLandingGear; if (!this.m_hasLandingGear) { Logger.DebugLog("landingGear param is not landing gear: " + landingGear.Block.getBestName() + ", not going to land"); return; } this.m_flyToGrid = new FlyToGrid(pathfinder, finder: m_navSet.Settings_Current.EnemyFinder, landingBlock: landingGear); }
/// <param name="mover">The mover to use</param> /// <param name="navSet">The settings to use</param> /// <param name="rotBlock">The block to rotate</param> public Facer(Mover mover, AllNavigationSettings navSet, PseudoBlock rotBlock) : base(mover, navSet) { this.m_logger = new Logger("Facer", m_controlBlock.CubeBlock); this.m_pseudoBlock = rotBlock; this.m_laser = rotBlock.Block as IMyLaserAntenna; if (this.m_laser == null) { if (!(rotBlock.Block is Ingame.IMySolarPanel) && !(rotBlock.Block is Ingame.IMyOxygenFarm)) { m_logger.alwaysLog("Block is of wrong type: " + rotBlock.Block.DisplayNameText, "Facer()", Logger.severity.FATAL); throw new Exception("Block is of wrong type: " + rotBlock.Block.DisplayNameText); } } m_navSet.Settings_Task_NavRot.NavigatorRotator = this; }
public EnemyLander(Mover mover, AllNavigationSettings navSet, PseudoBlock landingGear) { this.m_logger = new Logger(GetType().Name); this.m_navSet = navSet; if (landingGear == null) { m_logger.debugLog("landingGear param is null, not going to land"); return; } this.m_hasLandingGear = landingGear.Block is IMyLandingGear; if (!this.m_hasLandingGear) { m_logger.debugLog("landingGear param is not landing geat: " + landingGear.Block.getBestName() + ", not going to land"); return; } this.m_flyToGrid = new FlyToGrid(mover, navSet, finder: m_navSet.Settings_Current.EnemyFinder, landingBlock: landingGear); }
public WeldBlock(Pathfinder pathfinder, AllNavigationSettings navSet, PseudoBlock welder, IMySlimBlock block) : base(pathfinder) { this.m_offset = welder.Block.LocalAABB.GetLongestDim() * 0.5f; // this works for default welders, may not work if mod has an exotic design this.m_welder = welder; this.m_targetSlim = block; this.m_timeout_start = Globals.UpdateCount + TimeoutStart; IMyCubeBlock Projector = ((MyCubeGrid)block.CubeGrid).Projector; if (Projector != null) { this.m_weldProjection = true; this.m_otherGrid = Projector.CubeGrid; this.m_slimTarget_initDmg = 1f; this.m_targetCell = Projector.CubeGrid.WorldToGridInteger(block.CubeGrid.GridIntegerToWorld(block.Position)); } else { this.m_weldProjection = false; this.m_slimTarget_initDmg = block.Damage(); this.m_targetCell = block.Position; } m_navSet.Settings_Task_NavEngage.NavigatorMover = this; m_navSet.Settings_Task_NavEngage.NavigatorRotator = this; m_navSet.Settings_Task_NavEngage.DestinationEntity = m_realGrid; IEnumerator <Vector3I> neighbours = this.m_targetSlim.ForEachNeighbourCell(); while (neighbours.MoveNext()) { Vector3I cell = m_weldProjection ? Projector.CubeGrid.WorldToGridInteger(block.CubeGrid.GridIntegerToWorld(neighbours.Current)) : neighbours.Current; m_neighbours.Add(cell); if (this.m_realGrid.GetCubeBlock(cell) == null) { m_emptyNeighbours.Add(cell); } } m_targetSlim.ComputeWorldCenter(out m_targetWorld); m_lineUp.To = m_targetWorld; }
/// <summary> /// Creates the top-level SettingLevel, which has defaults set. /// </summary> internal SettingsLevel(IMyCubeBlock NavBlock) { m_navigationBlock = new PseudoBlock(NavBlock); m_waitUntil = DateTime.UtcNow.AddSeconds(1); m_destinationOffset = Vector3D.Zero; m_destRadius = 100f; m_distance = float.NaN; m_distanceAngle = float.NaN; m_speedTarget = ServerSettings.GetSetting<float>(ServerSettings.SettingName.fDefaultSpeed); m_speedMaxRelative = float.MaxValue; m_ignoreAsteroid = false; m_destChanged = true; m_collisionAvoidance = true; m_pathfindeCanChangeCourse = true; m_formation = false; }
public WeldBlock(Mover mover, AllNavigationSettings navSet, PseudoBlock welder, IMySlimBlock block) : base(mover, navSet) { this.m_logger = new Logger(GetType().Name, () => mover.Block.CubeGrid.DisplayName, () => block.getBestName(), () => m_stage.ToString()); this.m_offset = welder.Block.LocalAABB.GetLongestDim() * 0.5f; // this works for default welders, may not work if mod has an exotic design this.m_welder = welder; this.m_targetSlim = block; this.m_timeout_start = Globals.UpdateCount + TimeoutStart; IMyCubeBlock Projector = ((MyCubeGrid)block.CubeGrid).Projector; if (Projector != null) { this.m_weldProjection = true; this.m_otherGrid = Projector.CubeGrid; this.m_slimTarget_initDmg = 1f; this.m_targetCell = Projector.CubeGrid.WorldToGridInteger(block.CubeGrid.GridIntegerToWorld(block.Position)); } else { this.m_weldProjection = false; this.m_slimTarget_initDmg = block.Damage(); this.m_targetCell = block.Position; } m_navSet.Settings_Task_NavEngage.NavigatorMover = this; m_navSet.Settings_Task_NavEngage.NavigatorRotator = this; m_navSet.Settings_Task_NavEngage.DestinationEntity = m_realGrid; IEnumerator<Vector3I> neighbours = this.m_targetSlim.ForEachNeighbourCell(); while (neighbours.MoveNext()) { Vector3I cell = m_weldProjection ? Projector.CubeGrid.WorldToGridInteger(block.CubeGrid.GridIntegerToWorld(neighbours.Current)) : neighbours.Current; m_neighbours.Add(cell); if (this.m_realGrid.GetCubeBlock(cell) == null) m_emptyNeighbours.Add(cell); } m_targetSlim.ComputeWorldCenter(out m_targetWorld); m_lineUp.To = m_targetWorld; }
protected void SetOutsideTarget(Vector3D direction) { PseudoBlock navBlock = m_navBlock; MyVoxelBase voxel = (MyVoxelBase)m_target.Entity; CapsuleD capsule; Vector3D offset; Vector3D.Multiply(ref direction, voxel.PositionComp.LocalVolume.Radius * 2d, out offset); capsule.P1 = navBlock.WorldPosition; Vector3D.Add(ref capsule.P1, ref offset, out capsule.P0); capsule.Radius = m_grid.LocalVolume.Radius * 4f; Vector3D hitPos; if (!CapsuleDExtensions.Intersects(ref capsule, voxel, out hitPos)) { Log.DebugLog("capsule: " + capsule.String() + ", does not intersect voxel", Logger.severity.DEBUG); hitPos = capsule.P0; } //Log.DebugLog((tunnel ? "Tunnel target: " : "Backout target: ") + hitPos, Logger.severity.DEBUG); m_target.SetWorld(ref hitPos); }
/// <summary> /// Calculates the force necessary to move the grid. /// </summary> /// <param name="block">To get world position from.</param> /// <param name="destPoint">The world position of the destination</param> /// <param name="destVelocity">The speed of the destination</param> /// <param name="landing">Puts an emphasis on not overshooting the target.</param> public void CalcMove(PseudoBlock block, Vector3D destPoint, Vector3 destVelocity, bool landing = false) { const float landingSpeedFactor = 0.2f; CheckGrid(); // using world vectors m_lastMoveAttempt = Globals.UpdateCount; Pathfinder.TestPath(destPoint, landing); switch (Pathfinder.m_pathState) { case Autopilot.Pathfinder.Pathfinder.PathState.Not_Running: m_logger.debugLog("Pathfinder not run yet"); m_lastMove = Globals.UpdateCount; return; case Autopilot.Pathfinder.Pathfinder.PathState.No_Obstruction: break; default: m_logger.debugLog("Pathfinder not allowing rotation: " + Pathfinder.m_rotateState); return; } Thrust.Update(); Vector3 destDisp = destPoint - block.WorldPosition; // this is why we need double for destPoint Vector3 velocity = LinearVelocity; // switch to using local vectors MatrixD positionToLocal = Block.CubeBlock.WorldMatrixNormalizedInv; MatrixD directionToLocal = positionToLocal.GetOrientation(); destVelocity = Vector3.Transform(destVelocity, directionToLocal); velocity = Vector3.Transform(velocity, directionToLocal); Vector3 targetVelocity; float distance; if (destDisp != Vector3.Zero) { destDisp = Vector3.Transform(destDisp, directionToLocal); distance = destDisp.Length(); if (distance + (landing ? landingSpeedFactor : 1f) < m_bestDistance || distance - 10f > m_bestDistance || float.IsNaN(m_navSet.Settings_Current.Distance)) { m_bestDistance = distance; m_lastMove = Globals.UpdateCount; } // while on a planet, take a curved path to target instead of making pathfinder do all the work if (SignificantGravity() && distance > PlanetMoveDist) { // adjust for curvature of the planet Vector3D planetCentre = MyPlanetExtensions.GetClosestPlanet(Block.CubeBlock.GetPosition()).GetCentre(); float deltaAltitude = (float)(Vector3D.Distance(destPoint, planetCentre) - Vector3D.Distance(Block.CubeBlock.GetPosition(), planetCentre)); //m_logger.debugLog("displacement: " + destDisp + ", gravity: " + gravityDirection + ", dispReject: " + dispReject + ", delta altitude: " + deltaAltitude + // ", altitude adjustment: " + (-gravityDirection * deltaAltitude) + ", new disp: " + (dispReject - gravityDirection * deltaAltitude), "CalcMove()"); // keep a minimum height from the ground float heightAboveSurfaceSquared = (float)Vector3D.DistanceSquared(Block.CubeBlock.GetPosition(), Pathfinder.ClosestSurfacePoint); float minimumHeight = Math.Min(1000f, distance * 0.3f); deltaAltitude += minimumHeight; if (heightAboveSurfaceSquared < minimumHeight * minimumHeight) { float height = (float)Math.Sqrt(heightAboveSurfaceSquared); deltaAltitude += distance * (minimumHeight - height) / height; } Vector3 gravityDirection = Thrust.WorldGravity.ToBlock(Block.CubeBlock).vector / Thrust.GravityStrength; Vector3 dispReject; Vector3.Reject(ref destDisp, ref gravityDirection, out dispReject); m_logger.debugLog("changed dest disp from " + destDisp + " to " + (dispReject - gravityDirection * deltaAltitude)); destDisp = dispReject - gravityDirection * deltaAltitude; } targetVelocity = MaximumVelocity(destDisp); // project targetVelocity onto destination direction (take shortest path) Vector3 destDir = destDisp / distance; targetVelocity = Vector3.Dot(targetVelocity, destDir) * destDir; // apply relative speed limit float relSpeedLimit = m_navSet.Settings_Current.SpeedMaxRelative; if (landing) { float landingSpeed = Math.Max(distance * landingSpeedFactor, landingSpeedFactor); if (relSpeedLimit > landingSpeed) relSpeedLimit = landingSpeed; } if (relSpeedLimit < float.MaxValue) { float tarSpeedSq_1 = targetVelocity.LengthSquared(); if (tarSpeedSq_1 > relSpeedLimit * relSpeedLimit) { targetVelocity *= relSpeedLimit / (float)Math.Sqrt(tarSpeedSq_1); //myLogger.debugLog("imposing relative speed limit: " + relSpeedLimit + ", targetVelocity: " + targetVelocity, "CalcMove()"); } } } else { targetVelocity = Vector3.Zero; distance = 0f; m_lastMove = Globals.UpdateCount; } m_navSet.Settings_Task_NavWay.Distance = distance; targetVelocity += destVelocity; // apply speed limit float tarSpeedSq = targetVelocity.LengthSquared(); float speedRequest = m_navSet.Settings_Current.SpeedTarget; if (tarSpeedSq > speedRequest * speedRequest) { targetVelocity *= speedRequest / (float)Math.Sqrt(tarSpeedSq); //myLogger.debugLog("imposing speed limit: " + speedRequest + ", targetVelocity: " + targetVelocity, "CalcMove()"); } else { float velocityTowardsDest = velocity.Dot(Vector3.Normalize(destDisp)); if (velocityTowardsDest * velocityTowardsDest > tarSpeedSq) m_navSet.Settings_Task_NavWay.NearingDestination = true; } m_moveAccel = targetVelocity - velocity; CalcMove(ref velocity); m_logger.debugLog(string.Empty //+ "block: " + block.Block.getBestName() //+ ", dest point: " + destPoint //+ ", position: " + block.WorldPosition + "destDisp: " + destDisp + ", destVelocity: " + destVelocity + ", targetVelocity: " + targetVelocity + ", velocity: " + velocity + ", m_moveAccel: " + m_moveAccel + ", moveForceRatio: " + m_moveForceRatio); }
public UnLander(Mover mover, AllNavigationSettings navSet, PseudoBlock unlandBlock = null) : base(mover, navSet) { this.m_logger = new Logger(GetType().Name, m_controlBlock.CubeBlock); this.m_unlandBlock = unlandBlock ?? m_navSet.Settings_Current.LandingBlock ?? m_navSet.LastLandingBlock; if (this.m_unlandBlock == null) { m_logger.debugLog("No unland block", "UnLander()", Logger.severity.INFO); return; } m_logger.debugLog(this.m_unlandBlock.Block == null, "Unland block is missing Block property", "UnLander()", Logger.severity.FATAL); IMyLandingGear asGear = m_unlandBlock.Block as IMyLandingGear; if (asGear != null) { m_attachedEntity = asGear.GetAttachedEntity(); m_logger.debugLog("m_attachedEntity: " + m_attachedEntity, "UnLander()"); if (m_attachedEntity == null) { m_logger.debugLog("Not attached: " + m_unlandBlock.Block.DisplayNameText, "UnLander()", Logger.severity.INFO); return; } m_logger.debugLog("Got attached entity from Landing Gear : " + m_unlandBlock.Block.DisplayNameText, "UnLander()", Logger.severity.DEBUG); } else { Ingame.IMyShipConnector asConn = m_unlandBlock.Block as Ingame.IMyShipConnector; if (asConn != null) { m_logger.debugLog("connector", "UnLander()"); Ingame.IMyShipConnector other = asConn.OtherConnector; if (other == null) { m_logger.debugLog("Not connected: " + m_unlandBlock.Block.DisplayNameText, "UnLander()", Logger.severity.INFO); return; } m_logger.debugLog("Got attached connector from Connector : " + m_unlandBlock.Block.DisplayNameText, "UnLander()", Logger.severity.DEBUG); m_attachedEntity = other.CubeGrid; } else { m_logger.debugLog("Cannot unland block: " + m_unlandBlock.Block.DisplayNameText, "UnLander()", Logger.severity.INFO); return; } } IMyCubeBlock block = this.m_unlandBlock.Block; if (block is IMyLandingGear) MyAPIGateway.Utilities.TryInvokeOnGameThread(() => { (block as IMyFunctionalBlock).RequestEnable(true); if ((block.GetObjectBuilderCubeBlock() as MyObjectBuilder_LandingGear).AutoLock) asGear.ApplyAction("Autolock"); }, m_logger); Vector3D attachOffset = m_unlandBlock.Block.GetPosition() - m_attachedEntity.GetPosition(); Vector3 leaveDirection = m_unlandBlock.WorldMatrix.Backward; m_detatchedOffset = attachOffset + leaveDirection * 20f; m_logger.debugLog("m_detatchedOffset: " + m_detatchedOffset, "UnLander()", Logger.severity.DEBUG); m_navSet.Settings_Task_NavMove.NavigatorMover = this; m_navSet.Settings_Task_NavMove.NavigatorRotator = this; }
public MinerVoxel(Mover mover, byte[] OreTargets) : base(mover) { this.m_logger = new Logger(m_controlBlock.CubeBlock, () => m_state.ToString()); this.OreTargets = OreTargets; // get blocks var cache = CubeGridCache.GetFor(m_controlBlock.CubeGrid); var allDrills = cache.GetBlocksOfType(typeof(MyObjectBuilder_Drill)); if (allDrills == null || allDrills.Count == 0) { m_logger.debugLog("No Drills!", Logger.severity.INFO); return; } // if a drill has been chosen by player, use it PseudoBlock navBlock = m_navSet.Settings_Current.NavigationBlock; if (navBlock.Block is IMyShipDrill) { m_navDrill = new MultiBlock <MyObjectBuilder_Drill>(navBlock.Block); } else { m_navDrill = new MultiBlock <MyObjectBuilder_Drill>(() => m_mover.Block.CubeGrid); } if (m_navDrill.FunctionalBlocks == 0) { m_logger.debugLog("no working drills", Logger.severity.INFO); return; } m_longestDimension = m_controlBlock.CubeGrid.GetLongestDim(); m_navSet.Settings_Task_NavRot.NavigatorMover = this; // check for currently touching voxel, usually resume from save BoundingSphereD nearby = new BoundingSphereD(m_navDrill.WorldPosition, m_longestDimension * 4d); List <MyVoxelBase> nearbyVoxels = new List <MyVoxelBase>(); MyGamePruningStructure.GetAllVoxelMapsInSphere(ref nearby, nearbyVoxels); foreach (MyVoxelBase voxel in nearbyVoxels) { // skip planet physics, ship should be near planet as well if (voxel is IMyVoxelMap || voxel is MyPlanet) { m_logger.debugLog("near a voxel, escape first", Logger.severity.DEBUG); m_targetVoxel = voxel; m_state = State.Mining_Escape; var setLevel = m_navSet.GetSettingsLevel(AllNavigationSettings.SettingsLevelName.NavMove); setLevel.IgnoreAsteroid = true; setLevel.SpeedTarget = 1f; return; } } m_state = State.GetTarget; }
/// <summary> /// Finds a primary weapon for m_weapon_primary and m_weapon_primary_pseudo. /// A primary weapon can be any working weapon with ammo. /// Preference is given to fixed weapons and weapons with targets. /// If no weapons have ammo, m_weapon_primary and m_weapon_primary_pseudo will be null. /// </summary> private void GetPrimaryWeapon() { if (m_weapon_primary != null && m_weapon_primary.CubeBlock.IsWorking && m_weapon_primary.CurrentTarget.Entity != null) return; WeaponTargeting weapon_primary = null; bool removed = false; foreach (FixedWeapon weapon in m_weapons_fixed) if (weapon.CubeBlock.IsWorking) { if (weapon.HasAmmo) { weapon_primary = weapon; if (weapon.CurrentTarget.Entity != null) { m_logger.debugLog("has target: " + weapon.CubeBlock.DisplayNameText); break; } } else m_logger.debugLog("no ammo: " + weapon.CubeBlock.DisplayNameText); } else { m_logger.debugLog("not working: " + weapon.CubeBlock.DisplayNameText); m_weapons_fixed.Remove(weapon); weapon.EngagerReleaseControl(); removed = true; } if (weapon_primary == null) foreach (WeaponTargeting weapon in m_weapons_all) if (weapon.CubeBlock.IsWorking) { if (weapon.HasAmmo) { weapon_primary = weapon; if (weapon.CurrentTarget.Entity != null) { m_logger.debugLog("has target: " + weapon.CubeBlock.DisplayNameText); break; } } else m_logger.debugLog("no ammo: " + weapon.CubeBlock.DisplayNameText); } else { m_logger.debugLog("not working: " + weapon.CubeBlock.DisplayNameText); m_weapons_all.Remove(weapon); removed = true; } if (removed) { m_weapons_fixed.ApplyRemovals(); m_weapons_all.ApplyRemovals(); m_weaponDataDirty = true; } if (weapon_primary == null) { m_weapon_primary = null; m_weapon_primary_pseudo = null; return; } if (m_weapon_primary != weapon_primary) { m_weapon_primary = weapon_primary; if (m_mover.SignificantGravity()) { if (m_mover.Thrust.Standard.LocalMatrix.Forward == weapon_primary.CubeBlock.LocalMatrix.Forward) { m_logger.debugLog("primary forward matches Standard forward"); Matrix localMatrix = m_mover.Thrust.Standard.LocalMatrix; localMatrix.Translation = weapon_primary.CubeBlock.LocalMatrix.Translation; m_weapon_primary_pseudo = new PseudoBlock(() => weapon_primary.CubeBlock.CubeGrid, localMatrix); return; } if (m_mover.Thrust.Gravity.LocalMatrix.Forward == weapon_primary.CubeBlock.LocalMatrix.Forward) { m_logger.debugLog("primary forward matches Gravity forward"); Matrix localMatrix = m_mover.Thrust.Gravity.LocalMatrix; localMatrix.Translation = weapon_primary.CubeBlock.LocalMatrix.Translation; m_weapon_primary_pseudo = new PseudoBlock(() => weapon_primary.CubeBlock.CubeGrid, localMatrix); return; } m_logger.debugLog("cannot match primary forward to a standard flight matrix. primary forward: " + weapon_primary.CubeBlock.LocalMatrix.Forward + ", Standard forward: " + m_mover.Thrust.Standard.LocalMatrix.Forward + ", gravity forward: " + m_mover.Thrust.Gravity.LocalMatrix.Forward); } m_weapon_primary_pseudo = new PseudoBlock(weapon_primary.CubeBlock); } }
public void TestRotate(Vector3 displacement) { if (Globals.UpdateCount < m_nextRunRotate) return; m_nextRunRotate = Globals.UpdateCount + 10ul; m_navBlock = m_navSet.Settings_Current.NavigationBlock; m_pathHigh.Enqueue(() => { Vector3 axis; Vector3.Normalize(ref displacement, out axis); IMyEntity obstruction; if (m_rotateChecker.TestRotate(axis, m_ignoreAsteroid, out obstruction)) m_rotateState = PathState.No_Obstruction; else m_rotateState = PathState.Path_Blocked; RotateObstruction = obstruction; RunItem(); }); RunItem(); }
public void TestPath(Vector3D destination, bool landing) { if (m_navSet.Settings_Current.DestinationChanged || m_prevMover != m_navSet.Settings_Current.NavigatorMover) { m_logger.debugLog("new destination: " + destination, Logger.severity.INFO); m_navSet.Settings_Task_NavWay.DestinationChanged = false; m_prevMover = m_navSet.Settings_Current.NavigatorMover; m_runId++; m_pathLow.Clear(); ClearAltPath(); m_pathState = PathState.Not_Running; m_planetCheckDest.Stop(); m_planetCheckSpeed.Stop(); } //else // m_logger.debugLog("destination unchanged", "TestPath()"); if (Globals.UpdateCount < m_nextRunPath) { return; } m_nextRunPath = Globals.UpdateCount + 10ul; if (m_pathLow.Count != 0) { m_logger.debugLog("path low is running"); return; } m_navBlock = m_navSet.Settings_Current.NavigationBlock; m_destination = destination; m_ignoreAsteroid = m_navSet.Settings_Current.IgnoreAsteroid; m_landing = landing; m_canChangeCourse = m_navSet.Settings_Current.PathfinderCanChangeCourse; MyEntity destEntity = m_navSet.Settings_Current.DestinationEntity as MyEntity; m_logger.debugLog("DestinationEntity: " + m_navSet.Settings_Current.DestinationEntity.getBestName()); byte runId = m_runId; const float minimumDistance = 100f; const float minDistSquared = minimumDistance * minimumDistance; const float seconds = 10f; const float distOverSeconds = minimumDistance / seconds; Vector3 displacement = destination - m_navBlock.WorldPosition; float distanceSquared = displacement.LengthSquared(); float testDistance; Vector3 move_direction = m_grid.Physics.LinearVelocity; float speedSquared = move_direction.LengthSquared(); if (distanceSquared > minDistSquared) { // only look ahead 10 s / 100 m testDistance = speedSquared < distOverSeconds ? minimumDistance : (float)Math.Sqrt(speedSquared) * seconds; if (testDistance * testDistance < distanceSquared) { Vector3 direction = displacement / (float)Math.Sqrt(distanceSquared); destination = m_navBlock.WorldPosition + testDistance * direction; m_logger.debugLog("moved destination: " + destination + ", distance: " + testDistance + ", direction: " + direction); } } else { m_logger.debugLog("using actual destination: " + destination); } m_pathHigh.Enqueue(() => TestPath(destination, destEntity, runId, isAlternate: false, tryAlternates: true)); if (m_ignoreAsteroid) { m_planetCheckDest.Stop(); } else { m_planetCheckDest.Start(destination - m_navBlock.WorldPosition); } // given velocity and distance, calculate destination if (speedSquared > 1f) { Vector3D moveDest = m_navBlock.WorldPosition + move_direction * LookAheadSpeed_Seconds; m_pathHigh.Enqueue(() => TestPath(moveDest, null, runId, isAlternate: false, tryAlternates: false, slowDown: true)); if (m_ignoreAsteroid) { m_planetCheckSpeed.Stop(); } else { m_planetCheckSpeed.Start(moveDest - m_navBlock.WorldPosition); } } else { m_navSet.Settings_Task_NavWay.SpeedMaxRelative = float.MaxValue; m_navSet.Settings_Task_NavWay.SpeedTarget = float.MaxValue; } RunItem(); }
bool RemoveAllPredicate(PseudoBlock p) { return(true); }
private bool getAction_navigationBlock(out Action instructionAction, string instruction) { IMyCubeBlock navigationBlock; Base6Directions.Direction? forward, upward; if (!GetLocalBlock(instruction, out navigationBlock, out forward, out upward)) { instructionAction = null; return false; } instructionAction = () => { PseudoBlock asPB = new PseudoBlock(navigationBlock, forward, upward); if (navigationBlock is IMyLaserAntenna || navigationBlock is Ingame.IMySolarPanel || navigationBlock is Ingame.IMyOxygenFarm) new Facer(Mover, NavSet, asPB); m_logger.debugLog("setting NavigationBlock to " + navigationBlock.DisplayNameText, "GetLocalBlock()"); NavSet.Settings_Task_NavRot.NavigationBlock = asPB; }; return true; }
private bool getAction_landingBlock(out Action instructionAction, string instruction) { IMyCubeBlock landingBlock; Base6Directions.Direction? forward, upward; if (!GetLocalBlock(instruction, out landingBlock, out forward, out upward)) { instructionAction = null; return false; } instructionAction = () => { PseudoBlock asPB = new PseudoBlock(landingBlock, forward, upward); m_logger.debugLog("setting LandingBlock to " + landingBlock.DisplayNameText, "GetLocalBlock()"); NavSet.Settings_Task_NavRot.LandingBlock = asPB; NavSet.LastLandingBlock = asPB; }; return true; }
private bool getAction_unlandBlock(out Action instructionAction, string instruction) { IMyCubeBlock unlandBlock; Base6Directions.Direction? forward, upward; if (!GetLocalBlock(instruction, out unlandBlock, out forward, out upward)) { instructionAction = null; return false; } instructionAction = () => { PseudoBlock asPB = new PseudoBlock(unlandBlock, forward, upward); m_logger.debugLog("unlanding " + unlandBlock.DisplayNameText, "GetLocalBlock()"); new UnLander(Mover, NavSet, asPB); }; return true; }
public VoxelLander(Pathfinder pathfinder, bool planet, PseudoBlock landBlock = null) : base(pathfinder) { this.m_landBlock = landBlock ?? m_navSet.Settings_Current.LandingBlock; this.m_targetType = planet ? "Planet" : "Asteroid"; if (this.m_landBlock == null) { Log.DebugLog("No landing block", Logger.severity.INFO); return; } IMyLandingGear asGear = m_landBlock.Block as IMyLandingGear; if (asGear != null) { ITerminalProperty <bool> autolock = asGear.GetProperty("Autolock") as ITerminalProperty <bool>; Log.DebugLog("autolock == null", Logger.severity.FATAL, condition: autolock == null); if (!autolock.GetValue(asGear)) { autolock.SetValue(asGear, true); } } Vector3D currentPostion = m_landBlock.WorldPosition; MyVoxelBase closest = null; if (planet) { closest = MyPlanetExtensions.GetClosestPlanet(m_landBlock.WorldPosition); if (closest == null) { Log.DebugLog("No planets in the world", Logger.severity.WARNING); return; } } else { BoundingSphereD search = new BoundingSphereD(currentPostion, 10000d); List <MyVoxelBase> nearby = new List <MyVoxelBase>(); MyGamePruningStructure.GetAllVoxelMapsInSphere(ref search, nearby); double closestDistSquared = double.MaxValue; foreach (MyVoxelBase voxel in nearby) { if (!(voxel is MyVoxelMap)) { continue; } double distSquared = Vector3D.DistanceSquared(currentPostion, voxel.GetCentre()); if (distSquared < closestDistSquared) { closestDistSquared = distSquared; closest = voxel; } } if (closest == null) { Log.DebugLog("No asteroids nearby", Logger.severity.WARNING); return; } } Vector3D end = closest.GetCentre(); MyVoxelBase hitVoxel; Vector3D hitPosition; if (!RayCast.RayCastVoxels(ref currentPostion, ref end, out hitVoxel, out hitPosition)) { throw new Exception("Failed to intersect voxel"); } m_targetPostion = Destination.FromWorld(hitVoxel, hitPosition); m_navSet.Settings_Task_NavRot.NavigatorMover = this; m_navSet.Settings_Task_NavRot.IgnoreAsteroid = true; Log.DebugLog("Landing on " + m_targetType + " at " + m_targetPostion, Logger.severity.DEBUG); }
public VoxelLander(Mover mover, AllNavigationSettings navSet, bool planet, PseudoBlock landBlock = null) : base(mover, navSet) { this.m_landBlock = landBlock ?? m_navSet.Settings_Current.LandingBlock; this.m_logger = new Logger(GetType().Name, m_controlBlock.CubeBlock, () => m_landBlock.Block.getBestName()); this.m_targetType = planet ? "Planet" : "Asteroid"; if (this.m_landBlock == null) { m_logger.debugLog("No landing block", Logger.severity.INFO); return; } IMyLandingGear asGear = m_landBlock.Block as IMyLandingGear; if (asGear != null) { ITerminalProperty<bool> autolock = asGear.GetProperty("Autolock") as ITerminalProperty<bool>; m_logger.debugLog(autolock == null, "autolock == null", Logger.severity.FATAL); if (!autolock.GetValue(asGear)) autolock.SetValue(asGear, true); } Vector3D currentPostion = m_landBlock.WorldPosition; MyVoxelBase closest = null; if (planet) { closest = MyPlanetExtensions.GetClosestPlanet(m_landBlock.WorldPosition); if (closest == null) { m_logger.debugLog("No planets in the world", Logger.severity.WARNING); return; } } else { BoundingSphereD search = new BoundingSphereD(currentPostion, 10000d); List<MyVoxelBase> nearby = new List<MyVoxelBase>(); MyGamePruningStructure.GetAllVoxelMapsInSphere(ref search, nearby); double closestDistSquared = double.MaxValue; foreach (MyVoxelBase voxel in nearby) { if (!(voxel is MyVoxelMap)) continue; double distSquared = Vector3D.DistanceSquared(currentPostion, voxel.GetCentre()); if (distSquared < closestDistSquared) { closestDistSquared = distSquared; closest = voxel; } } if (closest == null) { m_logger.debugLog("No asteroids nearby", Logger.severity.WARNING); return; } } Vector3D? contact; if (!RayCast.RayCastVoxel(closest, new LineD(currentPostion, closest.GetCentre()), out contact)) throw new Exception("Failed to intersect voxel"); m_targetPostion = contact.Value; m_navSet.Settings_Task_NavRot.NavigatorMover = this; m_navSet.Settings_Task_NavRot.IgnoreAsteroid = true; m_logger.debugLog("Landing on " + m_targetType + " at " + m_targetPostion, Logger.severity.DEBUG); }
public void CalcMove(PseudoBlock block, Vector3 destPoint, Vector3 destVelocity, bool landing = false) { CalcMove(block, (Vector3D)destPoint, destVelocity, landing); }
/// <summary> /// Set the move acceleration. /// </summary> /// <param name="block">Block that will be moved to destination</param> /// <param name="destPoint">For pathfinding.</param> /// <param name="acceleration">Move acceleration, local to autopilot block.</param> public void SetMove(PseudoBlock block, Vector3D destPoint, DirectionBlock acceleration) { CheckGrid(); Pathfinder.TestPath(destPoint, false); if (!Pathfinder.CanMove) { m_logger.debugLog("Pathfinder not allowing movement"); return; } Thrust.Update(); Vector3 blockVelocity = LinearVelocity.ToBlock(Block.CubeBlock); m_moveAccel = acceleration; CalcMove(ref blockVelocity); }
private void GetPrimaryWeapon() { if (m_weapon_primary != null && m_weapon_primary.CubeBlock.IsWorking && m_weapon_primary.CurrentTarget.Entity != null) return; m_weapon_primary = null; m_weapon_primary_pseudo = null; bool removed = false; foreach (FixedWeapon weapon in m_weapons_fixed) if (weapon.CubeBlock.IsWorking) { m_weapon_primary = weapon; if (weapon.CurrentTarget.Entity != null) break; } else { m_weapons_fixed.Remove(weapon); weapon.EngagerReleaseControl(); removed = true; } if (m_weapon_primary == null) foreach (WeaponTargeting weapon in m_weapons_all) if (weapon.CubeBlock.IsWorking) { m_weapon_primary = weapon; if (weapon.CurrentTarget.Entity != null) break; } else { m_weapons_all.Remove(weapon); removed = true; } if (removed) { m_weapons_fixed.ApplyRemovals(); m_weapons_all.ApplyRemovals(); m_weaponDataDirty = true; } if (m_weapon_primary != null) m_weapon_primary_pseudo = new PseudoBlock(m_weapon_primary.CubeBlock); }
/// <summary> /// Match orientation with the target block. /// </summary> /// <param name="block">The navigation block</param> /// <param name="destBlock">The destination block</param> /// <param name="forward">The direction of destBlock that will be matched to navigation block's forward</param> /// <param name="upward">The direction of destBlock that will be matched to navigation block's upward</param> /// <returns>True iff localMatrix is facing the same direction as destBlock's forward</returns> public void CalcRotate(PseudoBlock block, IMyCubeBlock destBlock, Base6Directions.Direction? forward, Base6Directions.Direction? upward) { if (forward == null) forward = Base6Directions.Direction.Forward; //if (upward == null) // upward = Base6Directions.Direction.Up; //myLogger.debugLog(forward.Value == upward.Value || forward.Value == Base6Directions.GetFlippedDirection(upward.Value), // "Invalid orienation: " + forward + ", " + upward, "CalcRotate()", Logger.severity.FATAL); RelativeDirection3F faceForward = RelativeDirection3F.FromWorld(block.Grid, destBlock.WorldMatrix.GetDirectionVector(forward.Value)); RelativeDirection3F faceUpward = upward.HasValue ? RelativeDirection3F.FromWorld(block.Grid, destBlock.WorldMatrix.GetDirectionVector(upward.Value)) : null; CalcRotate(block, faceForward, faceUpward); }
public FlyToGrid(Pathfinder pathfinder, string targetGrid = null, AttachedGrid.AttachmentKind allowedAttachment = AttachedGrid.AttachmentKind.Permanent, GridFinder finder = null, PseudoBlock landingBlock = null) : base(pathfinder) { this.m_targetBlock = m_navSet.Settings_Current.DestinationBlock; string blockName = m_targetBlock == null ? null : m_targetBlock.BlockName; if (finder != null) { this.m_gridFinder = finder; } else { this.m_gridFinder = new GridFinder(m_navSet, m_controlBlock, targetGrid, blockName, allowedAttachment); } this.m_landingFriend = !(this.m_gridFinder is EnemyFinder); if (landingBlock == null) { landingBlock = m_navSet.Settings_Current.LandingBlock; } m_navSet.Settings_Task_NavRot.NavigationBlock = landingBlock; if (landingBlock != null) { if (landingBlock.Block is IMyFunctionalBlock) { m_landingState = LandingState.Approach; } else { Log.DebugLog("landingBlock is not functional, player error? : " + landingBlock.Block.DisplayNameText, Logger.severity.INFO); m_landingState = LandingState.None; } if (m_targetBlock == null) { if (!(landingBlock.Block is IMyLandingGear)) { Log.DebugLog("cannot land block without a target", Logger.severity.INFO); m_landingState = LandingState.None; } else { Log.DebugLog("golden retriever mode enabled", Logger.severity.INFO); m_landGearWithoutTargetBlock = true; } } else if (landingBlock.Block is Ingame.IMyShipConnector) { m_gridFinder.BlockCondition = block => { Ingame.IMyShipConnector connector = block as Ingame.IMyShipConnector; return(connector != null && (connector.Status == Ingame.MyShipConnectorStatus.Unconnected || connector.OtherConnector == m_navBlock.Block) && CanReserveTarget(connector.EntityId)); }; m_landingDirection = m_targetBlock.Forward ?? Base6Directions.GetFlippedDirection(landingBlock.Block.FirstFaceDirection()); } else if (landingBlock.Block is IMyShipMergeBlock) { m_gridFinder.BlockCondition = block => block is IMyShipMergeBlock && CanReserveTarget(block.EntityId); m_landingDirection = m_targetBlock.Forward ?? Base6Directions.GetFlippedDirection(landingBlock.Block.FirstFaceDirection()); (landingBlock.Block as IMyShipMergeBlock).BeforeMerge += MergeBlock_BeforeMerge; } else if (m_targetBlock.Forward.HasValue) { m_landingDirection = m_targetBlock.Forward.Value; } else { Log.DebugLog("Player failed to specify landing direction and it could not be determined.", Logger.severity.INFO); m_landingState = LandingState.None; } if (m_landingState != LandingState.None) { //float minDestRadius = m_controlBlock.CubeGrid.GetLongestDim() * 5f; //if (m_navSet.Settings_Current.DestinationRadius < minDestRadius) //{ // Log.DebugLog("Increasing DestinationRadius from " + m_navSet.Settings_Current.DestinationRadius + " to " + minDestRadius, "FlyToGrid()", Logger.severity.DEBUG); // m_navSet.Settings_Task_NavRot.DestinationRadius = minDestRadius; //} new UnLander(m_pathfinder, landingBlock); m_landingHalfSize = landingBlock.Block.GetLengthInDirection(landingBlock.Block.LocalMatrix.GetClosestDirection(landingBlock.LocalMatrix.Forward)) * 0.5f; Log.DebugLog("m_landing direction: " + m_landingDirection + ", m_landingBlockSize: " + m_landingHalfSize); } } m_settingLevel = m_landingState != LandingState.None ? AllNavigationSettings.SettingsLevelName.NavRot : AllNavigationSettings.SettingsLevelName.NavMove; m_navSet.GetSettingsLevel(m_settingLevel).NavigatorMover = this; }
/// <summary> /// Calculates the force necessary to rotate the grid. /// </summary> /// <param name="Direction">The direction to face the localMatrix in.</param> /// <param name="block"></param> /// <returns>True iff localMatrix is facing Direction</returns> public void CalcRotate(PseudoBlock block, RelativeDirection3F Direction, RelativeDirection3F UpDirect = null) { Vector3 angleVelocity; CalcRotate(block.LocalMatrix, Direction, UpDirect, out angleVelocity); updated_prevAngleVel = Globals.UpdateCount; prevAngleVel = angleVelocity; //myLogger.debugLog("displacement.LengthSquared(): " + displacement.LengthSquared(), "CalcRotate()"); //return displacement.LengthSquared() < 0.01f; //if (NavSet.Settings_Current.CollisionAvoidance) // myPathfinder.TestRotate(displacement); }
bool _TrySpawn() { float meanX = 0f; float meanY = 0f; //Achando o pivot e calculando a media dos blocos selecinados e verificando se ja esses blocos ja estão ocupados //O pivot sera as cordenadas deltaX deltaY que seram utilizadad para calcular a posição na matriz de boleano float deltaX = _SelectedTiles[0].transform.position.x; float deltaY = _SelectedTiles[0].transform.position.y; for (int i = 0; i < _SelectedTiles.Count; i++) { //Verificando se ja não tem um bloco spawnado nesta posição if (_SelectedTiles [i]._IsOccupied) { return(false); } //Calculando a média das posições meanX += _SelectedTiles [i].transform.position.x; meanY += _SelectedTiles [i].transform.position.y; //Selecionando o pivot if (_SelectedTiles [i].transform.position.x < deltaX) { deltaX = (int)_SelectedTiles[i].transform.position.x; } if (_SelectedTiles [i].transform.position.y < deltaY) { deltaY = (int)_SelectedTiles [i].transform.position.y; } } meanX /= _SelectedTiles.Count; meanY /= _SelectedTiles.Count; //Converter os tiles para uma matriz bool[,] matrix = new bool[_SelectedTiles.Count, _SelectedTiles.Count]; for (int i = 0; i < _SelectedTiles.Count; i++) { int x = (int)(_SelectedTiles [i].transform.position.x - deltaX); int y = (int)(_SelectedTiles [i].transform.position.y - deltaY); if (0 <= x && x < _SelectedTiles.Count && 0 <= y && y < _SelectedTiles.Count) { matrix [x, y] = true; } else { Debug.Log("ERRO em _TrySpawn codigo 0"); return(false); } } int Blockindex = -1; bool WillRotate = false; switch (_SelectedTiles.Count) { case 1: //instanciar bloco 1x1 Blockindex = 0; break; case 2: //instanciar bloco 2x1 ou 1x2 if (matrix[0, 0] && matrix[0, 1]) { Blockindex = 1; WillRotate = true; } if (matrix[0, 0] && matrix[1, 0]) { Blockindex = 1; } break; case 3: //instanciar bloco 3x1 ou 1x3 if (matrix[0, 0] && matrix[0, 1] && matrix[0, 2]) { Blockindex = 2; WillRotate = true; } if (matrix[0, 0] && matrix[1, 0] && matrix[2, 0]) { Blockindex = 2; } break; case 4: if (matrix[0, 0] && matrix[0, 1] && matrix[0, 2] && matrix[0, 3]) { Blockindex = 3; WillRotate = true; } if (matrix[0, 0] && matrix[1, 0] && matrix[2, 0] && matrix[3, 0]) { Blockindex = 3; } if (matrix[0, 0] && matrix[1, 0] && matrix[0, 1] && matrix[1, 1]) { Blockindex = 4; } //instanciar bloco 4x1 ou 1x4 ou 2x2 break; default: break; } //verificando se encontrou algum bloco valido if (Blockindex < 0) { return(false); } //Spawnar um bloco valido PseudoBlock block = Instantiate(_ListOfBlocks [Blockindex]).GetComponent <PseudoBlock>(); _PseudoBlockList.Add(block); block.transform.position = new Vector3(meanX, meanY, 0); if (WillRotate) { block.transform.Rotate(0, 0, 90f); } for (int i = 0; i < _SelectedTiles.Count; i++) { block._ListOfTiles.Add(_SelectedTiles[i]); //_SelectedTiles [i]._IsOccupied = true; _SelectedTiles [i].gameObject.SetActive(false); } block._MyGrid = this; //adicionando o numero de blocos a contagem de blocos _ActualNumberOfBlocks += _SelectedTiles.Count; return(true); }
public bool CanMoveForward(PseudoBlock block) { CheckGrid(); return myThrust.CanMoveAnyDirection(); }
public UnLander(Pathfinder pathfinder, PseudoBlock unlandBlock = null) : base(pathfinder) { this.m_unlandBlock = unlandBlock ?? m_navSet.Settings_Current.LandingBlock ?? m_navSet.LastLandingBlock; if (this.m_unlandBlock == null) { Log.DebugLog("No unland block", Logger.severity.INFO); return; } Log.DebugLog("Unland block is missing Block property", Logger.severity.FATAL, condition: this.m_unlandBlock.Block == null); IMyLandingGear asGear = m_unlandBlock.Block as IMyLandingGear; if (asGear != null) { m_destination.Entity = asGear.GetAttachedEntity(); Log.DebugLog("m_destination.Entity: " + m_destination.Entity); if (m_destination.Entity == null) { Log.DebugLog("Not attached: " + m_unlandBlock.Block.DisplayNameText, Logger.severity.INFO); return; } Log.DebugLog("Got attached entity from Landing Gear : " + m_unlandBlock.Block.DisplayNameText, Logger.severity.DEBUG); } else { IMyShipConnector asConn = m_unlandBlock.Block as IMyShipConnector; if (asConn != null) { Log.DebugLog("connector"); IMyShipConnector other = asConn.OtherConnector; if (other == null) { Log.DebugLog("Not connected: " + m_unlandBlock.Block.DisplayNameText, Logger.severity.INFO); return; } Log.DebugLog("Got attached connector from Connector : " + m_unlandBlock.Block.DisplayNameText, Logger.severity.DEBUG); m_destination.Entity = other.CubeGrid; } else { Log.DebugLog("Cannot unland block: " + m_unlandBlock.Block.DisplayNameText, Logger.severity.INFO); m_unlandBlock.Block.EnableGameThread(false); } } MyLandingGear landingGear = this.m_unlandBlock.Block as MyLandingGear; if (landingGear != null) { MyAPIGateway.Utilities.TryInvokeOnGameThread(() => { landingGear.Enabled = true; landingGear.AutoLock = true; }); } m_detachOffset = m_unlandBlock.Block.GetPosition() - m_destination.Entity.GetPosition(); //m_detachDirection = m_unlandBlock.WorldMatrix.Backward; //m_detachLength = 2f; //m_detatchedOffset = attachOffset + leaveDirection * (20f + m_navSet.Settings_Current.DestinationRadius); //Log.DebugLog("m_detatchedOffset: " + m_detatchedOffset, "UnLander()", Logger.severity.DEBUG); //m_detatchDirection = attachOffset + leaveDirection //Log.DebugLog("offset: " + m_detachOffset + ", direction: " + m_detachDirection); m_destination.Position = m_unlandBlock.WorldMatrix.Backward * 100f; m_navSet.Settings_Task_NavMove.NavigatorMover = this; m_navSet.Settings_Task_NavMove.NavigatorRotator = this; }
/// <summary> /// Calculates the force necessary to move the grid. /// </summary> /// <param name="block">To get world position from.</param> /// <param name="destPoint">The world position of the destination</param> /// <param name="destVelocity">The speed of the destination</param> /// <param name="landing">Puts an emphasis on not overshooting the target.</param> public void CalcMove(PseudoBlock block, Vector3 destPoint, Vector3 destVelocity, bool landing = false) { CheckGrid(); // using world vectors if (NavSet.Settings_Current.CollisionAvoidance) { myPathfinder.TestPath(destPoint, landing); if (!myPathfinder.CanMove) { myLogger.debugLog("Pathfinder not allowing movement", "CalcMove()"); return; } } Vector3 destDisp = destPoint - block.WorldPosition; Vector3 velocity = Block.CubeGrid.Physics.LinearVelocity; // switch to using local vectors Matrix positionToLocal = Block.CubeBlock.WorldMatrixNormalizedInv; Matrix directionToLocal = positionToLocal.GetOrientation(); destDisp = Vector3.Transform(destDisp, directionToLocal); destVelocity = Vector3.Transform(destVelocity, directionToLocal); velocity = Vector3.Transform(velocity, directionToLocal); float distance = destDisp.Length(); NavSet.Settings_Task_NavWay.Distance = distance; Vector3 targetVelocity = MaximumVelocity(destDisp) * 0.5f; // project targetVelocity onto destination direction (take shortest path) Vector3 destDir = destDisp / distance; targetVelocity = Vector3.Dot(targetVelocity, destDir) * destDir; // apply relative speed limit float relSpeedLimit = NavSet.Settings_Current.SpeedMaxRelative; if (landing) { float landingSpeed = distance * 0.5f; if (relSpeedLimit > landingSpeed) relSpeedLimit = landingSpeed; } if (relSpeedLimit < float.MaxValue) { float tarSpeedSq_1 = targetVelocity.LengthSquared(); if (tarSpeedSq_1 > relSpeedLimit * relSpeedLimit) { targetVelocity *= relSpeedLimit / (float)Math.Sqrt(tarSpeedSq_1); myLogger.debugLog("imposing relative speed limit: " + relSpeedLimit + ", targetVelocity: " + targetVelocity, "CalcMove()"); } } targetVelocity += destVelocity; // apply speed limit float tarSpeedSq = targetVelocity.LengthSquared(); float speedRequest = NavSet.Settings_Current.SpeedTarget; if (tarSpeedSq > speedRequest * speedRequest) targetVelocity *= speedRequest / (float)Math.Sqrt(tarSpeedSq); Vector3 accel = targetVelocity - velocity; moveForceRatio = ToForceRatio(accel); // dampeners bool enableDampeners = false; for (int i = 0; i < 3; i++) { // if target velocity is close to 0, use dampeners float targetDim = targetVelocity.GetDim(i); if (targetDim < 0.1f && targetDim > -0.1f) { //myLogger.debugLog("close to 0, i: " + i + ", targetDim: " + targetDim, "CalcMove()"); moveForceRatio.SetDim(i, 0); enableDampeners = true; continue; } // if there is not enough force available for braking, use dampeners float forceRatio = moveForceRatio.GetDim(i); if (forceRatio < 1f && forceRatio > -1f) continue; float velDim = velocity.GetDim(i); if (velDim < 1f && velDim > -1f) continue; if (Math.Sign(forceRatio) * Math.Sign(velDim) < 0) { myLogger.debugLog("damping, i: " + i + ", force ratio: " + forceRatio + ", velocity: " + velDim + ", sign of forceRatio: " + Math.Sign(forceRatio) + ", sign of velocity: " + Math.Sign(velDim), "CalcMove()"); moveForceRatio.SetDim(i, 0); enableDampeners = true; } else myLogger.debugLog("not damping, i: " + i + ", force ratio: " + forceRatio + ", velocity: " + velDim + ", sign of forceRatio: " + Math.Sign(forceRatio) + ", sign of velocity: " + Math.Sign(velDim), "CalcMove()"); } //if (enableDampeners) // Logger.debugNotify("Damping", 16); Block.SetDamping(enableDampeners); myLogger.debugLog("destDisp: " + destDisp + ", destDir: " + destDir + ", destVelocity: " + destVelocity //+ ", relaVelocity: " + relaVelocity + ", targetVelocity: " + targetVelocity //+ ", diffVel: " + diffVel + ", accel: " + accel + ", moveForceRatio: " + moveForceRatio, "CalcMove()"); }
public void TestPath(Vector3 destination, bool landing) { if (m_navSet.Settings_Current.DestinationChanged) { m_logger.debugLog("new destination: " + destination, "TestPath()", Logger.severity.INFO); m_navSet.Settings_Task_NavWay.DestinationChanged = false; m_runId++; m_pathLow.Clear(); m_pathState = PathState.Not_Running; } //else // m_logger.debugLog("destination unchanged", "TestPath()"); if (Globals.UpdateCount < m_nextRunPath) return; m_nextRunPath = Globals.UpdateCount + 10ul; if (m_pathLow.Count != 0) { m_logger.debugLog("path low is running", "TestPath()"); return; } m_navBlock = m_navSet.Settings_Current.NavigationBlock; m_destination = destination; m_ignoreAsteroid = m_navSet.Settings_Current.IgnoreAsteroid; m_landing = landing; m_canChangeCourse = m_navSet.Settings_Current.PathfinderCanChangeCourse; MyEntity destEntity = m_navSet.Settings_Current.DestinationEntity as MyEntity; m_logger.debugLog("DestinationEntity: " + m_navSet.Settings_Current.DestinationEntity.getBestName(), "TestPath()"); byte runId = m_runId; const float minimumDistance = 100f; const float minDistSquared = minimumDistance * minimumDistance; const float seconds = 10f; const float distOverSeconds = minimumDistance / seconds; Vector3 displacement = destination - m_navBlock.WorldPosition; float distanceSquared = displacement.LengthSquared(); float testDistance; Vector3 move_direction = m_grid.Physics.LinearVelocity; float speedSquared = move_direction.LengthSquared(); if (distanceSquared > minDistSquared) { // only look ahead 10 s / 100 m testDistance = speedSquared < distOverSeconds ? minimumDistance : (float)Math.Sqrt(speedSquared) * seconds; if (testDistance * testDistance < distanceSquared) { Vector3 direction = displacement / (float)Math.Sqrt(distanceSquared); destination = m_navBlock.WorldPosition + testDistance * direction; m_logger.debugLog("moved destination: " + destination + ", distance: " + testDistance + ", direction: " + direction, "TestPath()"); } } else m_logger.debugLog("using actual destination: " + destination, "TestPath()"); m_pathHigh.Enqueue(() => TestPath(destination, destEntity, runId, isAlternate: false, tryAlternates: true)); // given velocity and distance, calculate destination if (speedSquared > 1f) { Vector3 moveDest = m_navBlock.WorldPosition + move_direction * LookAheadSpeed_Seconds; m_pathHigh.Enqueue(() => TestPath(moveDest, destEntity, runId, isAlternate: false, tryAlternates: false)); m_pathHigh.Enqueue(() => TestPath(moveDest, null, runId, isAlternate: false, tryAlternates: false, slowDown: true)); } else m_navSet.Settings_Task_NavWay.SpeedMaxRelative = float.MaxValue; RunItem(); }
/// <summary> /// Calculates the force necessary to rotate the grid. /// </summary> /// <param name="Direction">The direction to face the localMatrix in.</param> /// <param name="block"></param> /// <returns>True iff localMatrix is facing Direction</returns> public void CalcRotate(PseudoBlock block, RelativeDirection3F Direction, RelativeDirection3F UpDirect = null, IMyEntity targetEntity = null) { //Log.DebugLog("entered CalcRotate(PseudoBlock block, RelativeDirection3F Direction, RelativeDirection3F UpDirect = null, IMyEntity targetEntity = null)", "CalcRotate()"); CalcRotate(block.LocalMatrix, Direction, UpDirect, targetEntity: targetEntity); }
public static Logable Pseudo(PseudoBlock pseudo, string SecondaryState = null) { return(new Logable(pseudo.Grid?.nameWithId(), pseudo?.DisplayName, SecondaryState)); }
public FlyToGrid(Mover mover, AllNavigationSettings navSet, string targetGrid, AttachedGrid.AttachmentKind allowedAttachment = AttachedGrid.AttachmentKind.Permanent) : base(mover, navSet) { this.m_logger = new Logger(GetType().Name, m_controlBlock.CubeBlock, () => m_landingState.ToString()); this.m_targetBlock = m_navSet.Settings_Current.DestinationBlock; string blockName = m_targetBlock == null ? null : m_targetBlock.BlockName; this.m_gridFinder = new GridFinder(m_navSet, m_mover.Block, targetGrid, blockName, allowedAttachment); this.m_contBlock = m_navSet.Settings_Commands.NavigationBlock; PseudoBlock landingBlock = m_navSet.Settings_Current.LandingBlock; m_navBlock = landingBlock ?? m_navSet.Settings_Current.NavigationBlock; if (landingBlock != null) { if (landingBlock.Block is IMyFunctionalBlock) m_landingState = LandingState.Approach; else { m_logger.debugLog("landingBlock is not functional, player error? : " + landingBlock.Block.DisplayNameText, "FlyToGrid()", Logger.severity.INFO); m_landingState = LandingState.None; } if (m_targetBlock == null) { if (!(landingBlock.Block is IMyLandingGear)) { m_logger.debugLog("cannot land block without a target", "FlyToGrid()", Logger.severity.INFO); m_landingState = LandingState.None; } else { m_logger.debugLog("golden retriever mode enabled", "FlyToGrid()", Logger.severity.INFO); m_landGearWithoutTargetBlock = true; } } else if (landingBlock.Block is Ingame.IMyShipConnector) { m_gridFinder.BlockCondition = block => { Ingame.IMyShipConnector connector = block as Ingame.IMyShipConnector; return connector != null && (!connector.IsConnected || connector.OtherConnector == m_navBlock.Block); }; m_landingDirection = m_targetBlock.Forward ?? Base6Directions.GetFlippedDirection(landingBlock.Block.GetFaceDirection()[0]); } else if (landingBlock.Block is IMyShipMergeBlock) { m_gridFinder.BlockCondition = block => block is IMyShipMergeBlock; m_landingDirection = m_targetBlock.Forward ?? Base6Directions.GetFlippedDirection(landingBlock.Block.GetFaceDirection()[0]); (landingBlock.Block as IMyShipMergeBlock).BeforeMerge += MergeBlock_BeforeMerge; } else if (m_targetBlock.Forward.HasValue) m_landingDirection = m_targetBlock.Forward.Value; else { m_logger.debugLog("Player failed to specify landing direction and it could not be determined.", "FlyToGrid()", Logger.severity.INFO); m_landingState = LandingState.None; } if (m_landingState != LandingState.None) { float minDestRadius = m_controlBlock.CubeGrid.GetLongestDim() * 5f; if (m_navSet.Settings_Current.DestinationRadius < minDestRadius) { m_logger.debugLog("Increasing DestinationRadius from " + m_navSet.Settings_Current.DestinationRadius + " to " + minDestRadius, "FlyToGrid()", Logger.severity.DEBUG); m_navSet.Settings_Task_NavRot.DestinationRadius = minDestRadius; } new UnLander(mover, navSet, landingBlock); m_landingHalfSize = landingBlock.Block.GetLengthInDirection(landingBlock.Block.LocalMatrix.GetClosestDirection(landingBlock.LocalMatrix.Forward)) * 0.5f; m_logger.debugLog("m_landing direction: " + m_landingDirection + ", m_landingBlockSize: " + m_landingHalfSize, "FlyToGrid()"); } } m_navSet.Settings_Task_NavMove.NavigatorMover = this; }
/// <summary> /// Finds a primary weapon for m_weapon_primary and m_weapon_primary_pseudo. /// A primary weapon can be any working weapon with ammo. /// Preference is given to fixed weapons and weapons with targets. /// If no weapons have ammo, m_weapon_primary and m_weapon_primary_pseudo will be null. /// </summary> private void GetPrimaryWeapon() { if (m_weapon_primary != null && m_weapon_primary.CubeBlock.IsWorking && m_weapon_primary.CurrentTarget.Entity != null) { return; } WeaponTargeting weapon_primary = null; bool removed = false; foreach (FixedWeapon weapon in m_weapons_fixed) { if (weapon.CubeBlock.IsWorking) { if (weapon.HasAmmo) { weapon_primary = weapon; if (weapon.CurrentTarget.Entity != null) { Log.DebugLog("has target: " + weapon.CubeBlock.DisplayNameText); break; } } else { Log.DebugLog("no ammo: " + weapon.CubeBlock.DisplayNameText); } } else { Log.DebugLog("not working: " + weapon.CubeBlock.DisplayNameText); m_weapons_fixed.Remove(weapon); weapon.EngagerReleaseControl(); removed = true; } } if (weapon_primary == null) { foreach (WeaponTargeting weapon in m_weapons_all) { if (weapon.CubeBlock.IsWorking) { if (weapon.HasAmmo) { weapon_primary = weapon; if (weapon.CurrentTarget.Entity != null) { Log.DebugLog("has target: " + weapon.CubeBlock.DisplayNameText); break; } } else { Log.DebugLog("no ammo: " + weapon.CubeBlock.DisplayNameText); } } else { Log.DebugLog("not working: " + weapon.CubeBlock.DisplayNameText); m_weapons_all.Remove(weapon); removed = true; } } } if (removed) { m_weapons_fixed.ApplyRemovals(); m_weapons_all.ApplyRemovals(); m_weaponDataDirty = true; } if (weapon_primary == null) { m_weapon_primary = null; m_weapon_primary_pseudo = null; return; } if (m_weapon_primary != weapon_primary) { m_weapon_primary = weapon_primary; IMyCubeBlock faceBlock; FixedWeapon fixedWeapon = weapon_primary as FixedWeapon; if (fixedWeapon != null && fixedWeapon.CubeBlock.CubeGrid != m_controlBlock.CubeGrid) { faceBlock = fixedWeapon.MotorTurretFaceBlock(); Log.DebugLog("MotorTurretFaceBlock == null", Logger.severity.FATAL, condition: faceBlock == null); } else { faceBlock = weapon_primary.CubeBlock; } if (m_mover.SignificantGravity()) { if (m_mover.Thrust.Standard.LocalMatrix.Forward == faceBlock.LocalMatrix.Forward) { Log.DebugLog("primary forward matches Standard forward"); Matrix localMatrix = m_mover.Thrust.Standard.LocalMatrix; localMatrix.Translation = faceBlock.LocalMatrix.Translation; m_weapon_primary_pseudo = new PseudoBlock(() => faceBlock.CubeGrid, localMatrix); return; } if (m_mover.Thrust.Gravity.LocalMatrix.Forward == faceBlock.LocalMatrix.Forward) { Log.DebugLog("primary forward matches Gravity forward"); Matrix localMatrix = m_mover.Thrust.Gravity.LocalMatrix; localMatrix.Translation = faceBlock.LocalMatrix.Translation; m_weapon_primary_pseudo = new PseudoBlock(() => faceBlock.CubeGrid, localMatrix); return; } Log.DebugLog("cannot match primary forward to a standard flight matrix. primary forward: " + faceBlock.LocalMatrix.Forward + ", Standard forward: " + m_mover.Thrust.Standard.LocalMatrix.Forward + ", gravity forward: " + m_mover.Thrust.Gravity.LocalMatrix.Forward); } m_weapon_primary_pseudo = new PseudoBlock(faceBlock); } }
/// <summary> /// Calculates the force necessary to move the grid. /// </summary> /// <param name="block">To get world position from.</param> /// <param name="destPoint">The world position of the destination</param> /// <param name="destVelocity">The speed of the destination</param> /// <param name="landing">Puts an emphasis on not overshooting the target.</param> public void CalcMove(PseudoBlock block, ref Vector3 destDisp, ref Vector3 destVelocity) { Log.DebugLog("Not on autopilot thread: " + ThreadTracker.ThreadName, Logger.severity.ERROR, condition: !ThreadTracker.ThreadName.StartsWith("Autopilot")); CheckGrid(); m_lastMoveAttempt = Globals.UpdateCount; Thrust.Update(); // using local vectors Vector3 velocity = LinearVelocity; MatrixD positionToLocal = Block.CubeBlock.WorldMatrixNormalizedInv; MatrixD directionToLocal = positionToLocal.GetOrientation(); destVelocity = Vector3.Transform(destVelocity, directionToLocal); velocity = Vector3.Transform(velocity, directionToLocal); Vector3 targetVelocity; //float distance; if (destDisp.LengthSquared() > 0.01f) { destDisp = Vector3.Transform(destDisp, directionToLocal); float distance = destDisp.Length(); targetVelocity = MaximumVelocity(destDisp); // project targetVelocity onto destination direction (take shortest path) Vector3 destDir = destDisp / distance; targetVelocity = Vector3.Dot(targetVelocity, destDir) * destDir; // apply relative speed limit float relSpeedLimit = NavSet.Settings_Current.SpeedMaxRelative; float landingSpeed = Math.Max(distance * DistanceSpeedFactor, DistanceSpeedFactor); if (relSpeedLimit > landingSpeed) { relSpeedLimit = landingSpeed; } if (relSpeedLimit < float.MaxValue) { float tarSpeedSq_1 = targetVelocity.LengthSquared(); if (tarSpeedSq_1 > relSpeedLimit * relSpeedLimit) { targetVelocity *= relSpeedLimit / (float)Math.Sqrt(tarSpeedSq_1); //Log.DebugLog("imposing relative speed limit: " + relSpeedLimit + ", targetVelocity: " + targetVelocity, "CalcMove()"); } } } else { targetVelocity = Vector3.Zero; } targetVelocity += destVelocity; // apply speed limit float tarSpeedSq = targetVelocity.LengthSquared(); float speedRequest = NavSet.Settings_Current.SpeedTarget; if (tarSpeedSq > speedRequest * speedRequest) { targetVelocity *= speedRequest / (float)Math.Sqrt(tarSpeedSq); //Log.DebugLog("imposing speed limit: " + speedRequest + ", targetVelocity: " + targetVelocity, "CalcMove()"); } m_moveAccel = targetVelocity - velocity; if (m_moveAccel.LengthSquared() < 0.01f) { Log.DebugLog("Wriggle unstuck autopilot. Near target velocity, move accel: " + m_moveAccel + ". m_lastMoveAccel set to now", condition: (Globals.UpdateCount - m_lastAccel) > WriggleAfter); m_lastMoveAccel = m_moveAccel; m_lastAccel = Globals.UpdateCount; } else { float diffSq; Vector3.DistanceSquared(ref m_moveAccel, ref m_lastMoveAccel, out diffSq); if (diffSq > 1f) { Log.DebugLog("Wriggle unstuck autopilot. Change in move accel from " + m_lastMoveAccel + " to " + m_moveAccel + ". m_lastMoveAccel set to now", condition: (Globals.UpdateCount - m_lastAccel) > WriggleAfter); m_lastMoveAccel = m_moveAccel; m_lastAccel = Globals.UpdateCount; } } CalcMove(ref velocity); Log.TraceLog(string.Empty //+ "block: " + block.Block.getBestName() //+ ", dest point: " + destPoint //+ ", position: " + block.WorldPosition + "destDisp: " + destDisp + ", destVelocity: " + destVelocity + ", targetVelocity: " + targetVelocity + ", velocity: " + velocity + ", m_moveAccel: " + m_moveAccel + ", moveForceRatio: " + m_moveForceRatio); }
/// <summary> /// Calculates the force necessary to rotate the grid. /// </summary> /// <param name="Direction">The direction to face the localMatrix in.</param> /// <param name="block"></param> /// <returns>True iff localMatrix is facing Direction</returns> public void CalcRotate(PseudoBlock block, RelativeDirection3F Direction, RelativeDirection3F UpDirect = null, IMyEntity targetEntity = null) { //m_logger.debugLog("entered CalcRotate(PseudoBlock block, RelativeDirection3F Direction, RelativeDirection3F UpDirect = null, IMyEntity targetEntity = null)", "CalcRotate()"); CalcRotate(block.LocalMatrix, Direction, UpDirect, targetEntity: targetEntity); }
/// <summary> /// Match orientation with the target block. /// </summary> /// <param name="block">The navigation block</param> /// <param name="destBlock">The destination block</param> /// <param name="forward">The direction of destBlock that will be matched to navigation block's forward</param> /// <param name="upward">The direction of destBlock that will be matched to navigation block's upward</param> /// <returns>True iff localMatrix is facing the same direction as destBlock's forward</returns> public void CalcRotate(PseudoBlock block, IMyCubeBlock destBlock, Base6Directions.Direction? forward, Base6Directions.Direction? upward) { //m_logger.debugLog("entered CalcRotate(PseudoBlock block, IMyCubeBlock destBlock, Base6Directions.Direction? forward, Base6Directions.Direction? upward)", "CalcRotate()"); if (forward == null) forward = Base6Directions.Direction.Forward; RelativeDirection3F faceForward = RelativeDirection3F.FromWorld(block.Grid, destBlock.WorldMatrix.GetDirectionVector(forward.Value)); RelativeDirection3F faceUpward = upward.HasValue ? RelativeDirection3F.FromWorld(block.Grid, destBlock.WorldMatrix.GetDirectionVector(upward.Value)) : null; CalcRotate(block.LocalMatrix, faceForward, faceUpward); }