public bool CanTarget(IMyCubeGrid grid) { CubeGridCache cache = null; if (m_destroySet) { cache = CubeGridCache.GetFor(grid); if (cache.TerminalBlocks > 0) { Log.DebugLog("destoy: " + grid.DisplayName); return(true); } else { Log.DebugLog("destroy set but no terminal blocks found: " + grid.DisplayName); } } if (m_currentTarget != null && grid == m_currentTarget.Entity && m_weapon_primary.CurrentTarget.TType != TargetType.None) { return(true); } TargetType gridType = grid.GridSizeEnum == MyCubeSize.Small ? TargetType.SmallGrid : grid.IsStatic ? TargetType.Station : TargetType.LargeGrid; BlockTypeList targetBlocks; if (m_cumulative_targeting.TryGetValue(gridType, out targetBlocks)) { if (cache == null) { cache = CubeGridCache.GetFor(grid); } foreach (IMyCubeBlock block in targetBlocks.Blocks(cache)) { return(true); } } else { Log.DebugLog("no targeting at all for grid type of: " + grid.DisplayName); } return(false); }
/// <summary> /// Determines if the ship is capable of digging a tunnel. /// </summary> private bool CanTunnel() { CubeGridCache cache = CubeGridCache.GetFor(m_grid); if (cache == null) { return(false); } BoundingSphere[] sensors = new BoundingSphere[cache.CountByType(typeof(MyObjectBuilder_Drill))]; int drillIndex = 0; foreach (MyShipDrill drill in cache.BlocksOfType(typeof(MyObjectBuilder_Drill))) { float offset = (float)MyShipDrillDefinition__SensorOffset.GetValue(drill.BlockDefinition); float radius = (float)MyShipDrillDefinition__SensorRadius.GetValue(drill.BlockDefinition); sensors[drillIndex++] = new BoundingSphere(drill.LocalPosition() + drill.PositionComp.LocalMatrix.Forward * offset, radius + MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF); } Vector3 forward = m_navBlock.LocalMatrix.Forward; foreach (Vector3I cell in m_grid.FirstBlocks(m_navBlock.LocalMatrix.Backward)) { IMySlimBlock block = m_grid.GetCubeBlock(cell); if (!(block.FatBlock is IMyShipDrill)) { Ray ray = new Ray(cell * m_grid.GridSize, forward); foreach (BoundingSphere sensor in sensors) { if (ray.Intersects(sensor).HasValue) { //Log.DebugLog(block.getBestName() + " is behind a drill"); goto NextBlock; } } //Log.DebugLog(block.getBestName() + " is not behind any drill"); return(false); } NextBlock :; } return(true); }
/// <summary> /// <para>In survival, returns fraction of drills filled</para> /// <para>In creative, returns content per drill * 0.01</para> /// </summary> private float DrillFullness() { if (Globals.UpdateCount < m_nextCheck_drillFull) { return(m_current_drillFull); } m_nextCheck_drillFull = Globals.UpdateCount + 100ul; MyFixedPoint content = 0, capacity = 0; int drillCount = 0; var cache = CubeGridCache.GetFor(m_controlBlock.CubeGrid); if (cache == null) { m_logger.debugLog("Failed to get cache", Logger.severity.INFO); return(float.MaxValue); } var allDrills = cache.GetBlocksOfType(typeof(MyObjectBuilder_Drill)); if (allDrills == null) { m_logger.debugLog("Failed to get block list", Logger.severity.INFO); return(float.MaxValue); } foreach (IMyShipDrill drill in allDrills) { MyInventoryBase drillInventory = ((MyEntity)drill).GetInventoryBase(0); content += drillInventory.CurrentVolume; capacity += drillInventory.MaxVolume; drillCount++; } if (MyAPIGateway.Session.CreativeMode) { m_current_drillFull = (float)content * 0.01f / drillCount; } else { m_current_drillFull = (float)content / (float)capacity; } return(m_current_drillFull); }
private int WorkingDecoys(IMyEntity target) { IMyCubeGrid grid = target as IMyCubeGrid; if (grid == null || RelationsBlock.canConsiderFriendly(grid)) { return(0); } CubeGridCache cache = CubeGridCache.GetFor(grid); if (cache == null) { return(0); } return(cache.CountByType(typeof(MyObjectBuilder_Decoy), block => block.IsWorking)); }
private void calculateLocalMatrix() { if (Grid.MarkedForClose) { return; } CubeGridCache cache = CubeGridCache.GetFor(Grid); if (cache == null) { return; } Block = null; FunctionalBlocks = 0; Matrix LocalMatrix = Matrix.Zero; Vector3 Translation = Vector3.Zero; foreach (IMyCubeBlock block in cache.BlocksOfType(typeof(T))) { if (Block == null) { Block = block; LocalMatrix = block.LocalMatrix; } if (block.IsFunctional) { FunctionalBlocks++; Translation += block.LocalMatrix.Translation; block.OnClose -= block_OnClose; block.OnClose += block_OnClose; } } if (FunctionalBlocks == 0) { return; } LocalMatrix.Translation = Translation / FunctionalBlocks; this.LocalMatrix = LocalMatrix; return; }
private void CalcGyroForce() { float force = 0f; CubeGridCache cache = CubeGridCache.GetFor(myGrid); if (cache == null) { return; } foreach (MyGyro g in cache.BlocksOfType(typeof(MyObjectBuilder_Gyro))) { if (g.IsWorking) { force += g.MaxGyroForce; // MaxGyroForce accounts for power ratio and modules } } GyroForce = force; }
private bool BatteriesCharged(IMyCubeGrid startGrid) { foreach (IMyCubeGrid attachedGrid in AttachedGrid.AttachedGrids(startGrid, AttachedGrid.AttachmentKind.Permanent, true)) { CubeGridCache cache = CubeGridCache.GetFor(attachedGrid); if (cache == null) { return(false); } foreach (IMyBatteryBlock battery in cache.BlocksOfType(typeof(MyObjectBuilder_BatteryBlock))) { if (battery.IsCharging) { return(false); } } } Logger.DebugLog("All batteries are recharged", Logger.severity.DEBUG); return(true); }
public TextPanelMonitor GetTextPanelMonitor(IMyTerminalBlock autopilot, AutopilotCommands autoCmds) { string panelName = m_panelName.ToString(); IMyTextPanel textPanel = null; int bestMatchLength = int.MaxValue; foreach (IMyCubeGrid grid in Attached.AttachedGrid.AttachedGrids((IMyCubeGrid)autopilot.CubeGrid, Attached.AttachedGrid.AttachmentKind.Permanent, true)) { CubeGridCache cache = CubeGridCache.GetFor(grid); if (cache == null) { continue; } foreach (IMyTextPanel panel in cache.BlocksOfType(typeof(MyObjectBuilder_TextPanel))) { if (!((IMyCubeBlock)autopilot).canControlBlock((IMyCubeBlock)panel)) { continue; } string name = panel.DisplayNameText; if (name.Length < bestMatchLength && name.Contains(panelName)) { textPanel = panel; bestMatchLength = name.Length; if (name.Length == panelName.Length) { return(new TextPanelMonitor(textPanel, autoCmds, m_identifier.ToString())); } } } } if (textPanel == null) { return(null); } return(new TextPanelMonitor(textPanel, autoCmds, m_identifier.ToString())); }
/// <summary> /// Yields CubeGridCache for each attached grid, if the grid is closed it is skipped. /// </summary> /// <param name="startGrid">Grid to start search from.</param> /// <param name="allowedConnections">The types of connections allowed between grids.</param> /// <param name="runOnStartGrid">If true, yields the startGrid.</param> /// <returns>CubeGridCache for each attached grid.</returns> public static IEnumerable <CubeGridCache> AttachedGridCache(IMyCubeGrid startGrid, AttachmentKind allowedConnections, bool runOnStartGrid) { if (runOnStartGrid) { CubeGridCache cache = CubeGridCache.GetFor(startGrid); if (cache != null) { yield return(cache); } } AttachedGrid attached = GetFor(startGrid); if (attached == null) { yield break; } HashSet <AttachedGrid> search = s_searchSet.Get(); try { foreach (IMyCubeGrid grid in attached.Attached(allowedConnections, search)) { CubeGridCache cache = CubeGridCache.GetFor(grid); if (cache != null) { yield return(cache); } } } finally { search.Clear(); s_searchSet.Return(search); } }
private void EnableDrills(bool enable) { if (enable) { m_logger.debugLog("Enabling drills", Logger.severity.DEBUG); } else { m_logger.debugLog("Disabling drills", Logger.severity.DEBUG); } var cache = CubeGridCache.GetFor(m_controlBlock.CubeGrid); if (cache == null) { m_logger.debugLog("Failed to get cache", Logger.severity.INFO); return; } var allDrills = cache.GetBlocksOfType(typeof(MyObjectBuilder_Drill)); if (allDrills == null) { m_logger.debugLog("Failed to get block list", Logger.severity.INFO); return; } MyAPIGateway.Utilities.TryInvokeOnGameThread(() => { foreach (IMyShipDrill drill in allDrills) { if (!drill.Closed) { drill.RequestEnable(enable); } } }); }
/// <summary> /// Tests a grid for obstructing the ship via vector rejection. /// </summary> /// <param name="oGrid">The grid that may obstruct this one.</param> /// <param name="ignoreBlock">Block to ignore, or null</param> /// <param name="input"><see cref="TestInput"/></param> /// <param name="result"><see cref="GridTestResult"/></param> /// <returns>True if oGrid is blocking the ship.</returns> private bool RejectionIntersects(MyCubeGrid oGrid, MyCubeBlock ignoreBlock, ref TestInput input, ref GridTestResult result) { //Logger.DebugLog("Rejection vector is not normalized, length squared: " + rejectionVector.LengthSquared(), Logger.severity.FATAL, condition: Math.Abs(rejectionVector.LengthSquared() - 1f) > 0.001f); //Logger.DebugLog("Testing for rejection intersection: " + oGrid.nameWithId() + ", starting from: " + (AutopilotGrid.GetCentre() + offset) + ", rejection vector: " + rejectionVector + ", distance: " + rejectionDistance + // ", final: " + (AutopilotGrid.GetCentre() + offset + rejectionVector * rejectionDistance)); //Logger.DebugLog("rejction distance < 0: " + rejectionDistance, Logger.severity.ERROR, condition: rejectionDistance < 0f); IEnumerable <CubeGridCache> myCaches = AttachedGrid.AttachedGrids(AutopilotGrid, AttachedGrid.AttachmentKind.Physics, true).Select(CubeGridCache.GetFor); Vector3D currentPosition = AutopilotGrid.GetCentre(); CubeGridCache oCache = CubeGridCache.GetFor(oGrid); if (oCache == null) { Logger.DebugLog("Failed to get cache for other grid", Logger.severity.DEBUG); return(false); } bool checkBlock = ignoreBlock != null && oGrid == ignoreBlock.CubeGrid; Vector3 v; input.Direction.CalculatePerpendicularVector(out v); Vector3 w; Vector3.Cross(ref input.Direction, ref v, out w); Matrix to3D = new Matrix(v.X, v.Y, v.Z, 0f, w.X, w.Y, w.Z, 0f, input.Direction.X, input.Direction.Y, input.Direction.Z, 0f, 0f, 0f, 0f, 1f); Matrix to2D; Matrix.Invert(ref to3D, out to2D); float roundTo; int minDistanceSquared; if (AutopilotGrid.GridSizeEnum == oGrid.GridSizeEnum) { roundTo = AutopilotGrid.GridSize; minDistanceSquared = 1; } else { roundTo = Math.Min(AutopilotGrid.GridSize, oGrid.GridSize); minDistanceSquared = (int)Math.Ceiling(Math.Max(AutopilotGrid.GridSize, oGrid.GridSize) / roundTo); minDistanceSquared *= minDistanceSquared; } int maxDistanceSquared = minDistanceSquared * 100; Profiler.StartProfileBlock("RejectionIntersects:Build ship"); Vector2IMatrix <bool> apShipRejections; ResourcePool.Get(out apShipRejections); MatrixD worldMatrix = AutopilotGrid.WorldMatrix; float gridSize = AutopilotGrid.GridSize; float minProjection = float.MaxValue, maxProjection = float.MinValue; // the permitted range when rejecting the other grids cells foreach (CubeGridCache cache in myCaches) { if (cache == null) { Logger.DebugLog("Missing a cache", Logger.severity.DEBUG); Profiler.EndProfileBlock(); return(false); } foreach (Vector3I cell in cache.OccupiedCells()) { Vector3 local = cell * gridSize; MyCubeBlock block = (MyCubeBlock)cache.CubeGrid.GetCubeBlock(cell)?.FatBlock; if (block != null && block.Subparts != null && block.Subparts.Count != 0 && !CellOccupiedByBlock(cell, block)) { continue; } Vector3D world; Vector3D.Transform(ref local, ref worldMatrix, out world); Vector3D relative; Vector3D.Subtract(ref world, ref currentPosition, out relative); Vector3 relativeF = relative; float projectionDistance; Vector3 rejection; VectorExtensions.RejectNormalized(ref relativeF, ref input.Direction, out projectionDistance, out rejection); if (projectionDistance < minProjection) { minProjection = projectionDistance; } else if (projectionDistance > maxProjection) { maxProjection = projectionDistance; } Vector3 planarComponents; Vector3.Transform(ref rejection, ref to2D, out planarComponents); //Logger.DebugLog("Math fail: rejection: " + rejection + ", planar components: " + planarComponents + "\nto3D: " + to3D, Logger.severity.WARNING, condition: planarComponents.Z > 0.001f || planarComponents.Z < -0.001f); Vector2 pc2 = new Vector2(planarComponents.X, planarComponents.Y); apShipRejections[ToCell(pc2, roundTo)] = true; //Logger.DebugLog("My rejection: " + rejection + ", planar: " + ToCell(pc2, roundTo)); } } Profiler.EndProfileBlock(); minProjection += StartRayCast; // allow autopilot to move away from a touching object //Logger.DebugLog("projection min: " + minProjection + ", max: " + maxProjection + ", max for other: " + (maxProjection + rejectionDistance)); maxProjection += input.Length; //Logger.DebugLog("checking other grid cells"); Profiler.StartProfileBlock("RejectionIntersects:other grid"); Vector2IMatrix <bool> otherGridRejections; ResourcePool.Get(out otherGridRejections); worldMatrix = oGrid.WorldMatrix; gridSize = oGrid.GridSize; foreach (Vector3I cell in oCache.OccupiedCells()) { //Logger.DebugLog("cell: " + cell); Vector3 local = cell * gridSize; Vector3D world; Vector3D.Transform(ref local, ref worldMatrix, out world); Vector3D offsetWorld; Vector3D.Subtract(ref world, ref input.Offset, out offsetWorld); Vector3D relative; Vector3D.Subtract(ref offsetWorld, ref currentPosition, out relative); Vector3 relativeF = relative; Vector3 rejection; VectorExtensions.RejectNormalized(ref relativeF, ref input.Direction, out result.Distance, out rejection); if (result.Distance < minProjection || result.Distance > maxProjection) { continue; } Vector3 planarComponents; Vector3.Transform(ref rejection, ref to2D, out planarComponents); //Logger.DebugLog("Math fail: rejection: " + rejection + ", planar components: " + planarComponents + "\nto3D: " + to3D, Logger.severity.WARNING, condition: planarComponents.Z > 0.001f || planarComponents.Z < -0.001f); Vector2 pc2 = new Vector2(planarComponents.X, planarComponents.Y); Vector2I cell2D = ToCell(pc2, roundTo); if (!otherGridRejections.Add(cell2D, true)) { //Logger.DebugLog("Already tested: " + cell2D); continue; } //Logger.DebugLog("Rejection: " + rejection + ", planar: " + cell2D); //Logger.DebugLog("testing range. x: " + (cell2D.X - steps) + " - " + (cell2D.X + steps)); ExpandingRings.Ring ring = default(ExpandingRings.Ring); for (int ringIndex = 0; ring.DistanceSquared <= maxDistanceSquared; ringIndex++) { ring = ExpandingRings.GetRing(ringIndex); for (int squareIndex = 0; squareIndex < ring.Squares.Length; squareIndex++) { if (apShipRejections.Contains(cell2D + ring.Squares[squareIndex])) { if (ring.DistanceSquared <= minDistanceSquared) { IMySlimBlock slim = oGrid.GetCubeBlock(cell); if (slim != null) { if (checkBlock && slim.FatBlock == ignoreBlock) { continue; } MyCubeBlock fat = (MyCubeBlock)slim.FatBlock; if (fat != null && fat.Subparts != null && fat.Subparts.Count != 0 && !CellOccupiedByBlock(cell, fat)) { continue; } result.ObstructingBlock = fat; } else { result.ObstructingBlock = null; } result.Proximity = 0f; Logger.DebugLog("Hit, projectionDistance: " + result.Distance + ", min: " + minProjection + ", max: " + maxProjection + ", ring: " + ringIndex + ", ring dist sq: " + ring.DistanceSquared + ", min dist sq: " + minDistanceSquared + ", max dist sq: " + maxDistanceSquared); Profiler.EndProfileBlock(); apShipRejections.Clear(); otherGridRejections.Clear(); ResourcePool.Return(apShipRejections); ResourcePool.Return(otherGridRejections); return(true); } else { maxDistanceSquared = ring.DistanceSquared; goto NextCell; } } } } NextCell :; } Profiler.EndProfileBlock(); apShipRejections.Clear(); otherGridRejections.Clear(); ResourcePool.Return(apShipRejections); ResourcePool.Return(otherGridRejections); result.Proximity = (float)Math.Sqrt(maxDistanceSquared); return(false); }
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; }
private void Move_Grind() { if (m_stage < Stage.Grind) { Log.DebugLog("Now grinding", Logger.severity.DEBUG); //m_navSet.OnTaskComplete_NavMove(); m_stage = Stage.Grind; //m_navSet.Settings_Task_NavMove.PathfinderCanChangeCourse = false; EnableGrinders(true); } CubeGridCache cache = CubeGridCache.GetFor(m_enemy); if (cache == null) { return; } m_previousCell = cache.GetClosestOccupiedCell(m_controlBlock.CubeGrid.GetCentre(), m_previousCell); IMySlimBlock block = m_enemy.GetCubeBlock(m_previousCell); if (block == null) { Log.DebugLog("No block found at cell position: " + m_previousCell, Logger.severity.INFO); return; } //Log.DebugLog("block: " + block); m_targetPosition = m_enemy.GridIntegerToWorld(m_enemy.GetCubeBlock(m_previousCell).Position); //Log.DebugLog("cellPosition: " + m_previousCell + ", block: " + m_enemy.GetCubeBlock(m_previousCell) + ", world: " + m_targetPosition); if (m_navSet.Settings_Current.DistanceAngle > MaxAngleRotate) { if (m_pathfinder.RotateCheck.ObstructingEntity != null) { Log.DebugLog("Extricating ship from target"); m_navSet.Settings_Task_NavMove.SpeedMaxRelative = float.MaxValue; Destination dest = Destination.FromWorld(m_enemy, m_targetPosition + m_navGrind.WorldMatrix.Backward * 100f); m_pathfinder.MoveTo(destinations: dest); } else { Log.DebugLog("Waiting for angle to match"); m_pathfinder.HoldPosition(m_enemy); } return; } Vector3D grindPosition = m_navGrind.WorldPosition; float distSq = (float)Vector3D.DistanceSquared(m_targetPosition, grindPosition); float offset = m_grinderOffset + m_enemy.GridSize; float offsetEpsilon = offset + 5f; if (distSq > offsetEpsilon * offsetEpsilon) { Vector3D targetToGrinder = grindPosition - m_targetPosition; targetToGrinder.Normalize(); //Log.DebugLog("far away(" + distSq + "), moving to " + (m_targetPosition + targetToGrinder * offset)); m_navSet.Settings_Task_NavMove.SpeedMaxRelative = float.MaxValue; Destination dest = Destination.FromWorld(m_enemy, m_targetPosition + targetToGrinder * offset); m_pathfinder.MoveTo(destinations: dest); } else { //Log.DebugLog("close(" + distSq + "), moving to " + m_targetPosition); m_navSet.Settings_Task_NavMove.SpeedMaxRelative = 1f; Destination dest = Destination.FromWorld(m_enemy, m_targetPosition); m_pathfinder.MoveTo(destinations: dest); } }
protected Disruption(IMyCubeGrid grid, MyObjectBuilderType[] affects) { m_logger = new Logger(GetType().Name, () => grid.DisplayName); m_cache = CubeGridCache.GetFor(grid); m_affects = affects; }
public override void Move() { Log.DebugLog("m_gridFinder == null", Logger.severity.FATAL, condition: m_gridFinder == null); Log.DebugLog("m_navSet == null", Logger.severity.FATAL, condition: m_navSet == null); Log.DebugLog("m_mover == null", Logger.severity.FATAL, condition: m_mover == null); Log.DebugLog("m_navBlock == null", Logger.severity.FATAL, condition: m_navBlock == null); m_gridFinder.Update(); if (m_gridFinder.Grid == null) { Log.DebugLog("searching"); m_mover.StopMove(); // only timeout if (Grid == null), ship could simply be waiting its turn if (Globals.ElapsedTime > m_searchTimeoutAt) { Log.DebugLog("Search timed out", Logger.severity.INFO); m_navSet.OnTaskComplete(m_settingLevel); UnreserveTarget(); m_mover.StopMove(); m_mover.StopRotate(); return; } if (m_landingState > LandingState.Approach) { Log.DebugLog("Decreasing landing state from " + m_landingState + " to " + LandingState.Approach, Logger.severity.DEBUG); m_landingState = LandingState.Approach; } return; } else { m_searchTimeoutAt = Globals.ElapsedTime + SearchTimeout; if (!m_gridFinder.Grid.isRecent()) { m_pathfinder.MoveTo(m_gridFinder.Grid); return; } if (m_gridFinder.Block != null) { m_destination = Destination.FromWorld(m_gridFinder.Block, m_navSet.Settings_Current.DestinationOffset.ToWorld(m_gridFinder.Block)); } else { IMyCubeGrid grid = (IMyCubeGrid)m_gridFinder.Grid.Entity; CubeGridCache cache = CubeGridCache.GetFor(grid); if (cache == null) { return; } m_previousCell = cache.GetClosestOccupiedCell(m_navBlock.WorldPosition, m_previousCell); m_destination = Destination.FromWorld(grid, grid.GridIntegerToWorld(m_previousCell)); } if (m_landingState > LandingState.Approach) { Move_Land(); return; } if (m_landingState == LandingState.None && m_navSet.Settings_Current.Stay_In_Formation) { Log.DebugLog("Maintaining offset position from target", condition: m_navSet.DistanceLessThanDestRadius()); m_pathfinder.MoveTo(destinations: m_destination); return; } if (m_navSet.DistanceLessThanDestRadius()) { if (m_landingState == LandingState.None) { if (m_targetBlock != null && m_targetBlock.Forward.HasValue ? m_navSet.DirectionMatched() : m_navBlock.Physics.AngularVelocity.LengthSquared() < 0.01f) { Log.DebugLog("Arrived at target", Logger.severity.INFO); m_navSet.OnTaskComplete(m_settingLevel); UnreserveTarget(); m_mover.StopRotate(); } m_mover.StopMove(); return; } Move_Land(); return; } m_pathfinder.MoveTo(destinations: m_destination); } }
/// <summary> /// Test if it is safe for the grid to rotate. /// </summary> /// <param name="axis">Normalized axis of rotation in world space.</param> /// <returns>True iff the path is clear.</returns> private bool in_TestRotate(Vector3 axis) { IMyCubeGrid myGrid = m_block.CubeGrid; Vector3 centreOfMass = myGrid.Physics.CenterOfMassWorld; float longestDim = myGrid.GetLongestDim(); // calculate height Matrix toMyLocal = myGrid.WorldMatrixNormalizedInv; Vector3 myLocalCoM = Vector3.Transform(centreOfMass, toMyLocal); Vector3 myLocalAxis = Vector3.Transform(axis, toMyLocal.GetOrientation()); Vector3 myLocalCentre = myGrid.LocalAABB.Center; // CoM may not be on ship (it now considers mass from attached grids) Ray upper = new Ray(myLocalCentre + myLocalAxis * longestDim * 2f, -myLocalAxis); float? upperBound = myGrid.LocalAABB.Intersects(upper); if (!upperBound.HasValue) { Log.AlwaysLog("Math fail, upperBound does not have a value", Logger.severity.FATAL); } Ray lower = new Ray(myLocalCentre - myLocalAxis * longestDim * 2f, myLocalAxis); float?lowerBound = myGrid.LocalAABB.Intersects(lower); if (!lowerBound.HasValue) { Log.AlwaysLog("Math fail, lowerBound does not have a value", Logger.severity.FATAL); } //Log.DebugLog("LocalAABB: " + myGrid.LocalAABB + ", centre: " + myLocalCentre + ", axis: " + myLocalAxis + ", longest dimension: " + longestDim + ", upper ray: " + upper + ", lower ray: " + lower); float height = longestDim * 4f - upperBound.Value - lowerBound.Value; float furthest = 0f; foreach (IMyCubeGrid grid in AttachedGrid.AttachedGrids(myGrid, Attached.AttachedGrid.AttachmentKind.Physics, true)) { CubeGridCache cache = CubeGridCache.GetFor(grid); if (cache == null) { return(false); } foreach (Vector3I cell in cache.OccupiedCells()) { Vector3 rejection = Vector3.Reject(cell * myGrid.GridSize, myLocalAxis); float cellDistSquared = Vector3.DistanceSquared(myLocalCoM, rejection); if (cellDistSquared > furthest) { furthest = cellDistSquared; } } } float length = (float)Math.Sqrt(furthest) + myGrid.GridSize; //Log.DebugLog("height: " + height + ", length: " + length); BoundingSphereD surroundingSphere = new BoundingSphereD(centreOfMass, Math.Max(length, height) * MathHelper.Sqrt2); m_obstructions.Clear(); MyGamePruningStructure.GetAllTopMostEntitiesInSphere(ref surroundingSphere, m_obstructions); LineSegment axisSegment = new LineSegment(); m_closestPlanet = null; foreach (MyEntity entity in m_collector.Invoke(m_obstructions)) { if (entity is IMyVoxelBase) { IMyVoxelMap voxel = entity as IMyVoxelMap; if (voxel != null) { if (voxel.GetIntersectionWithSphere(ref surroundingSphere)) { Log.DebugLog("Too close to " + voxel.getBestName() + ", CoM: " + centreOfMass.ToGpsTag("Centre of Mass") + ", required distance: " + surroundingSphere.Radius); ObstructingEntity = voxel; return(false); } continue; } if (m_closestPlanet == null) { MyPlanet planet = entity as MyPlanet; if (planet == null) { continue; } double distToPlanetSq = Vector3D.DistanceSquared(centreOfMass, planet.PositionComp.GetPosition()); if (distToPlanetSq < planet.MaximumRadius * planet.MaximumRadius) { m_closestPlanet = planet; if (m_planetObstruction) { Log.DebugLog("planet blocking"); ObstructingEntity = m_closestPlanet; return(false); } } } continue; } IMyCubeGrid grid = entity as IMyCubeGrid; if (grid != null) { Matrix toLocal = grid.WorldMatrixNormalizedInv; Vector3 localAxis = Vector3.Transform(axis, toLocal.GetOrientation()); Vector3 localCentre = Vector3.Transform(centreOfMass, toLocal); axisSegment.From = localCentre - localAxis * height; axisSegment.To = localCentre + localAxis * height; CubeGridCache cache = CubeGridCache.GetFor(grid); if (cache == null) { return(false); } foreach (Vector3I cell in cache.OccupiedCells()) { if (axisSegment.PointInCylinder(length, cell * grid.GridSize)) { Log.DebugLog("axis segment: " + axisSegment.From + " to " + axisSegment.To + ", radius: " + length + ", hit " + grid.nameWithId() + " at " + cell); ObstructingEntity = grid; return(false); } } continue; } Log.DebugLog("No tests for object: " + entity.getBestName(), Logger.severity.INFO); ObstructingEntity = entity; return(false); } MyAPIGateway.Utilities.TryInvokeOnGameThread(TestPlanet); ObstructingEntity = null; return(true); }
public string HostileName() { switch (Type) { case EntityType.Character: if (string.IsNullOrEmpty(Entity.DisplayName)) { return("Creature"); } return(Entity.DisplayName); case EntityType.Grid: break; default: return(Type.ToString()); } if (!isRecent_Broadcast()) { return(((IMyCubeGrid)Entity).SimpleName()); } CubeGridCache cache = CubeGridCache.GetFor((IMyCubeGrid)Entity); if (cache == null) { return("Error"); } float longestRange = float.MinValue; string name = null; foreach (IMyCubeBlock b in cache.BlocksOfType(typeof(MyObjectBuilder_Beacon))) { if (b.IsWorking) { float radius = ((Sandbox.ModAPI.Ingame.IMyBeacon)b).Radius; if (radius > longestRange) { longestRange = radius; name = b.DisplayNameText; } } } foreach (IMyCubeBlock ra in cache.BlocksOfType(typeof(MyObjectBuilder_RadioAntenna))) { if (ra.IsWorking) { Sandbox.ModAPI.Ingame.IMyRadioAntenna asRA = (Sandbox.ModAPI.Ingame.IMyRadioAntenna)ra; if (asRA.IsBroadcasting && asRA.Radius > longestRange) { longestRange = asRA.Radius; name = ra.DisplayNameText; } } } return(name ?? ((IMyCubeGrid)Entity).SimpleName()); }
/// <summary> /// Adds a disruption effect to a grid. /// </summary> /// <param name="grid">Grid that will be disrupted</param> /// <param name="duration">Duration of disruption</param> /// <param name="strength">Strength of disruption (in hackyness)</param> /// <param name="effectOwner">The owner of the disruption.</param> public void Start(IMyCubeGrid grid, TimeSpan duration, ref float strength, long effectOwner) { if (strength < MinCost) { Logger.DebugLog("strength: " + strength + ", below minimum: " + MinCost); return; } CubeGridCache cache = CubeGridCache.GetFor(grid); float applied = 0; if (!EffectOwnerCanAccess) { effectOwner = long.MinValue; } m_effectOwner = effectOwner; foreach (MyObjectBuilderType type in BlocksAffected) { foreach (IMyCubeBlock block in cache.BlocksOfType(type).OrderBy(OrderBy)) { if (!block.IsWorking || m_allAffected.Contains(block)) { Logger.DebugLog("cannot disrupt: " + block); continue; } float cost = BlockCost(block); if (cost > strength) { Logger.DebugLog("cannot disrupt block: " + block + ", cost: " + cost + " is greater than strength available: " + strength); continue; } StartEffect(block); Logger.DebugLog("disrupting: " + block + ", cost: " + cost + ", remaining strength: " + strength); strength -= cost; applied += cost; MyCubeBlock cubeBlock = block as MyCubeBlock; MyIDModule idMod = new MyIDModule() { Owner = cubeBlock.IDModule.Owner, ShareMode = cubeBlock.IDModule.ShareMode }; m_affected.Add(block, idMod); m_allAffected.Add(block); block.SetDamageEffect(true); cubeBlock.ChangeOwner(effectOwner, MyOwnershipShareModeEnum.Faction); if (strength < MinCost) { goto FinishedBlocks; } } } FinishedBlocks: if (m_affected.Count != 0) { Logger.DebugLog("Added new effect, strength: " + applied); m_expire = Globals.ElapsedTime.Add(duration); UpdateManager.Register(UpdateFrequency, UpdateEffect); // don't unregister on grid close, blocks can still be valid AllDisruptions.Add(this); } }
/// <summary> /// Gets the best block to target from a grid. /// </summary> /// <param name="grid">The grid to search</param> /// <param name="tType">Checked for destroy</param> /// <param name="target">The best block fromt the grid</param> /// <param name="distanceValue">The value assigned based on distance and position in blocksToTarget.</param> /// <remarks> /// <para>Decoy blocks will be given a distanceValue of the distance squared to weapon.</para> /// <para>Blocks from blocksToTarget will be given a distanceValue of the distance squared * (index + 1)^3.</para> /// <para>Other blocks will be given a distanceValue of the distance squared * (1e12).</para> /// </remarks> public bool GetTargetBlock(IMyCubeGrid grid, TargetType tType, out IMyCubeBlock target, out double distanceValue, bool doRangeTest = true) { Vector3D myPosition = ProjectilePosition(); CubeGridCache cache = CubeGridCache.GetFor(grid); target = null; distanceValue = double.MaxValue; if (cache == null) { return(false); } if (cache.TerminalBlocks == 0) { Log.TraceLog("no terminal blocks on grid: " + grid.DisplayName); return(false); } // get decoy block { foreach (IMyCubeBlock block in cache.BlocksOfType(typeof(MyObjectBuilder_Decoy))) { if (!TargetableBlock(block, true)) { continue; } double distanceSq = Vector3D.DistanceSquared(myPosition, block.GetPosition()); if (doRangeTest && distanceSq > Options.TargetingRangeSquared) { continue; } if (distanceSq < distanceValue && CanConsiderHostile(block)) { target = block; distanceValue = distanceSq; } } if (target != null) { Log.TraceLog("for type = " + tType + " and grid = " + grid.DisplayName + ", found a decoy block: " + target.DisplayNameText + ", distanceValue: " + distanceValue); return(true); } } // get block from blocksToTarget if (!Options.blocksToTarget.IsNullOrEmpty()) { int index = 0; IMyCubeBlock in_target = target; double in_distValue = distanceValue; foreach (MyDefinitionId[] ids in Options.listOfBlocks.IdGroups()) { index++; foreach (MyDefinitionId id in ids) { //Log.TraceLog("searching for blocks of type: " + id + ", count: " + cache.BlocksOfType(id).Count()); foreach (IMyCubeBlock block in cache.BlocksOfType(id)) { if (!TargetableBlock(block, true)) { continue; } double distSq = Vector3D.DistanceSquared(myPosition, block.GetPosition()); if (doRangeTest && distSq > Options.TargetingRangeSquared) { Log.TraceLog("out of range: " + block.nameWithId()); continue; } distSq *= index * index * index; if (distSq < in_distValue && CanConsiderHostile(block)) { in_target = block; in_distValue = distSq; } } } } target = in_target; distanceValue = in_distValue; if (target != null) // found a block from blocksToTarget { Log.TraceLog("for type = " + tType + " and grid = " + grid.DisplayName + ", target = " + target.DisplayNameText + ", distance = " + Vector3D.Distance(myPosition, target.GetPosition()) + ", distanceValue = " + distanceValue); return(true); } } // get any IMyTerminalBlock bool destroy = (tType & TargetType.Moving) != 0 || (tType & TargetType.Destroy) != 0; if (destroy || Options.blocksToTarget.IsNullOrEmpty()) { double closest = double.MaxValue; foreach (MyCubeBlock block in cache.AllCubeBlocks()) { if (block is IMyTerminalBlock && TargetableBlock(block, !destroy)) { double distanceSq = Vector3D.DistanceSquared(myPosition, block.PositionComp.GetPosition()); if (doRangeTest && distanceSq > Options.TargetingRangeSquared) { continue; } distanceSq *= 1e12; if (distanceSq < closest && CanConsiderHostile(block)) { target = block; distanceValue = distanceSq; } } } if (target != null) { Log.TraceLog("for type = " + tType + " and grid = " + grid.DisplayName + ", found a block: " + target.DisplayNameText + ", distanceValue = " + distanceValue); return(true); } } return(false); }
/// <summary> /// Creates the parameter for the block and runs the program. /// </summary> private void HandleDetected() { if (m_progBlock.IsRunning) { return; } StringBuilder parameter = new StringBuilder(); bool first = true; RelayStorage store = m_networkClient.GetStorage(); if (store == null) { return; } store.ForEachLastSeen((LastSeen seen) => { ExtensionsRelations.Relations relations = (m_progBlock as IMyCubeBlock).getRelationsTo(seen.Entity, ExtensionsRelations.Relations.Enemy).highestPriority(); bool friendly = ExtensionsRelations.toIsFriendly(relations); string bestName = friendly ? seen.Entity.getBestName() : seen.HostileName(); TimeSpan sinceSeen; Vector3D predictedPosition = seen.predictPosition(out sinceSeen); if (first) { first = false; } else { parameter.Append(entitySeparator); } parameter.Append(seen.Entity.EntityId); parameter.Append(fieldSeparator); parameter.Append((byte)relations); parameter.Append(fieldSeparator); parameter.Append((byte)seen.Type); parameter.Append(fieldSeparator); parameter.Append(bestName); parameter.Append(fieldSeparator); parameter.Append(seen.isRecent_Radar()); parameter.Append(fieldSeparator); parameter.Append(seen.isRecent_Jam()); parameter.Append(fieldSeparator); parameter.Append((int)sinceSeen.TotalSeconds); parameter.Append(fieldSeparator); parameter.Append(Math.Round(predictedPosition.X, 1)); parameter.Append(fieldSeparator); parameter.Append(Math.Round(predictedPosition.Y, 1)); parameter.Append(fieldSeparator); parameter.Append(Math.Round(predictedPosition.Z, 1)); parameter.Append(fieldSeparator); parameter.Append(Math.Round(seen.LastKnownVelocity.X, 1)); parameter.Append(fieldSeparator); parameter.Append(Math.Round(seen.LastKnownVelocity.Y, 1)); parameter.Append(fieldSeparator); parameter.Append(Math.Round(seen.LastKnownVelocity.Z, 1)); parameter.Append(fieldSeparator); if (seen.RadarInfoIsRecent()) { parameter.Append(seen.Info.Volume); } else { parameter.Append(0f); } if (!friendly && seen.Type == LastSeen.EntityType.Grid && m_blockCountList_sb.Length > 2 && seen.isRecent() && m_blockCountList_btl != null) { int[] blockCounts = m_blockCountList_btl.Count(CubeGridCache.GetFor((IMyCubeGrid)seen.Entity)); if (blockCounts.Length != 0) { parameter.Append(fieldSeparator); parameter.Append(string.Join(fieldSeparator.ToString(), blockCounts)); } } }); if (parameter.Length == 0) { Log.DebugLog("no detected entities"); return; } //Log.DebugLog("parameters:\n" + parameter.ToString().Replace(string.Empty + entitySeparator, entitySeparator + "\n")); if (!m_progBlock.TryRun(parameter.ToString())) { Log.AlwaysLog("Failed to run program", Logger.severity.INFO); } }
private void Arm() { if (!ServerSettings.GetSetting <bool>(ServerSettings.SettingName.bAllowWeaponControl)) { Log.DebugLog("Cannot arm, weapon control is disabled.", Logger.severity.WARNING); return; } Log.DebugLog("Arming", Logger.severity.DEBUG); Log.DebugLog("Fixed weapons has not been cleared", Logger.severity.FATAL, condition: m_weapons_fixed.Count != 0); Log.DebugLog("All weapons has not been cleared", Logger.severity.FATAL, condition: m_weapons_all.Count != 0); m_weaponRange_min = float.MaxValue; CubeGridCache cache = CubeGridCache.GetFor(m_controlBlock.CubeGrid); foreach (FixedWeapon weapon in Registrar.Scripts <FixedWeapon, WeaponTargeting>()) { if (weapon.CubeBlock.CubeGrid == m_controlBlock.CubeGrid) { if (weapon.EngagerTakeControl()) { Log.DebugLog("Took control of " + weapon.CubeBlock.DisplayNameText); m_weapons_fixed.Add(weapon); m_weapons_all.Add(weapon); weapon.CubeBlock.OnClosing += Weapon_OnClosing; } else { Log.DebugLog("failed to get control of: " + weapon.CubeBlock.DisplayNameText); } } if (weapon.MotorTurretBaseGrid() == m_controlBlock.CubeGrid) { Log.DebugLog("Active motor turret: " + weapon.CubeBlock.DisplayNameText); m_weapons_all.Add(weapon); weapon.CubeBlock.OnClosing += Weapon_OnClosing; } } foreach (MyObjectBuilderType weaponType in TurretWeaponTypes) { foreach (IMyCubeBlock block in cache.BlocksOfType(weaponType)) { WeaponTargeting weapon; if (!Registrar.TryGetValue(block.EntityId, out weapon)) { Logger.AlwaysLog("Failed to get block: " + block.nameWithId(), Logger.severity.WARNING); continue; } if (weapon.CurrentControl != WeaponTargeting.Control.Off) { Log.DebugLog("Active turret: " + weapon.CubeBlock.DisplayNameText); m_weapons_all.Add(weapon); weapon.CubeBlock.OnClosing += Weapon_OnClosing; } } } m_weapons_fixed.ApplyAdditions(); m_weapons_all.ApplyAdditions(); m_weaponArmed = m_weapons_all.Count != 0; m_weaponDataDirty = m_weaponArmed; if (m_weaponArmed) { Log.DebugLog("Now armed", Logger.severity.DEBUG); } else { Log.DebugLog("Failed to arm", Logger.severity.DEBUG); } }
/// <summary> /// Tests if a section of space can be travelled without hitting the specified entity. /// </summary> /// <param name="entity">The potential obstruction</param> /// <param name="ignoreBlock">Null or the block autopilot is trying to connect with.</param> /// <param name="input"><see cref="TestInput"/></param> /// <param name="result"><see cref="GridTestResult"/></param> /// <returns>True if the specified entity obstructs the path.</returns> public bool ObstructedBy(MyEntity entity, MyCubeBlock ignoreBlock, ref TestInput input, out GridTestResult result) { //Logger.DebugLog("checking: " + entity.getBestName() + ", offset: " + offset + ", rejection vector: " + rejectionVector + ", rejection distance: " + rejectionDistance); #if DEBUG if (!input.Direction.IsValid() || Math.Abs(1f - input.Direction.LengthSquared()) > 0.01f) { throw new Exception("rejection vector is invalid. entity: " + entity.nameWithId() + ", input: " + input); } #endif result = GridTestResult.Default; result.Distance = input.Length; MyCubeGrid grid = entity as MyCubeGrid; if (grid != null) { // check for dangerous tools on grid CubeGridCache cache = CubeGridCache.GetFor(grid); if (cache == null) { return(false); } Profiler.StartProfileBlock("Checking Tools"); foreach (MyShipDrill drill in cache.BlocksOfType(typeof(MyObjectBuilder_Drill))) { if (drill.IsShooting) { if (SphereTest(drill, ref input, ref result)) { Profiler.EndProfileBlock(); return(true); } } } foreach (MyShipGrinder grinder in cache.BlocksOfType(typeof(MyObjectBuilder_ShipGrinder))) { if (grinder.IsShooting) { if (SphereTest(grinder, ref input, ref result)) { Profiler.EndProfileBlock(); return(true); } } } Profiler.EndProfileBlock(); if (ExtensionsRelations.canConsiderFriendly(Controller.CubeBlock, grid) && EndangerGrid(grid, ref input, ref result)) { Logger.DebugLog("Movement would endanger: " + grid.getBestName()); return(true); } Profiler.StartProfileBlock("RejectionIntersects"); if (RejectionIntersects(grid, ignoreBlock, ref input, ref result)) { Profiler.EndProfileBlock(); return(true); } Profiler.EndProfileBlock(); } else { return(SphereTest(entity, ref input, ref result)); } return(false); }