private void UpdateWaypoint() { int currentTime = MySandboxGame.TotalGamePlayTimeInMilliseconds; //find new target player if ((m_target == null && currentTime - m_lastTargetUpdate >= 5000) || currentTime - m_lostStartTimeMs >= m_lostTimeMs) { MyPlayer player = m_remoteControl.GetNearestPlayer(); m_target = player != null ? player.Character as MyEntity : null; m_lastTargetUpdate = currentTime; if (m_target != null) { m_lostStartTimeMs = currentTime; m_farAwayFromTarget = true; } else { m_lostStartTimeMs += 5000; } } if (m_farAwayFromTarget && currentTime - m_lastTargetUpdate >= 5000) { m_lastTargetUpdate = currentTime; NeedUpdate = true; } //weapon/suicide update float distSq = -1f; if (m_operational && currentTime - m_lastWeaponUpdate >= 300) { m_lastWeaponUpdate = currentTime; distSq = Vector3.DistanceSquared((Vector3)m_target.PositionComp.GetPosition(), (Vector3)m_remoteControl.PositionComp.GetPosition()); WeaponsUpdate(distSq); } if (currentTime - m_waypointReachedTimeMs >= m_waypointMaxTime) { NeedUpdate = true; } if (!NeedUpdate || m_target == null) { return; } //active and prepare waypoints IsActive = true; if (distSq < 0) { distSq = Vector3.DistanceSquared((Vector3)m_target.PositionComp.GetPosition(), (Vector3)m_remoteControl.PositionComp.GetPosition()); } m_farAwayFromTarget = distSq > m_maxManeuverDistanceSq; bool origUpdate = NeedUpdate; if (m_remoteControl.HasWaypoints()) { m_remoteControl.ClearWaypoints(); //MyGuiAudio.PlaySound(MyGuiSounds.PlayTakeItem); //debug } m_remoteControl.SetAutoPilotEnabled(true); NeedUpdate = origUpdate; Vector3D newWaypoint; if (m_firstWaypoint != Vector3D.Zero) { newWaypoint = m_firstWaypoint; m_firstWaypoint = Vector3D.Zero; } else if (!m_operational && m_kamikazeBehavior) { //no functional weapons -> ram the player if (m_remoteControl.TargettingAimDelta > 0.02f) { return; } newWaypoint = m_target.PositionComp.GetPosition() + m_target.WorldMatrix.Up * PlayerYAxisOffset * 2 - Vector3D.Normalize(m_remoteControl.PositionComp.GetPosition() - m_target.PositionComp.GetPosition()) * m_kamikazeBehaviorDistance; } else if (!m_operational && !m_kamikazeBehavior) { //no functional weapons -> try to escape newWaypoint = ReturnPosition + Vector3.One * 0.01f; } else if (m_farAwayFromTarget) { //too far away from target newWaypoint = m_target.PositionComp.GetPosition() + Vector3D.Normalize(m_remoteControl.PositionComp.GetPosition() - m_target.PositionComp.GetPosition()) * m_playerTargetDistance; } else { //in proximity to target m_lostStartTimeMs = currentTime; if (currentTime - m_waypointReachedTimeMs <= m_waypointDelayMs) { return; } newWaypoint = GetRandomPoint(); } //Add new point to waypoints Vector3D currentToWaypoint = newWaypoint - m_remoteControl.WorldMatrix.Translation; currentToWaypoint.Normalize(); m_waypointReachedTimeMs = currentTime; var strafeLocalDir = Vector3.TransformNormal((Vector3)currentToWaypoint, m_remoteControl.PositionComp.WorldMatrixNormalizedInv); Base6Directions.Direction strafeDir = Base6Directions.GetClosestDirection(ref strafeLocalDir); bool commitKamikadze = m_kamikazeBehavior && !m_operational; m_remoteControl.ChangeFlightMode(MyRemoteControl.FlightMode.OneWay); m_remoteControl.SetAutoPilotSpeedLimit(commitKamikadze ? 100f : m_speedLimit); m_remoteControl.SetCollisionAvoidance(commitKamikadze ? false : m_avoidCollisions); m_remoteControl.ChangeDirection(strafeDir); m_remoteControl.AddWaypoint(newWaypoint, m_farAwayFromTarget || commitKamikadze ? "Player Vicinity" : "Strafe"); NeedUpdate = false; IsActive = true; }
public void InitControl() { //sets direction of angular force and steering for concrete block based on position in grid var mat = MySession.Static.ControlledEntity.Entity.WorldMatrix * PositionComp.WorldMatrixNormalizedInv; Vector3 revolveAxis; if (Base6Directions.GetClosestDirection(mat.Forward) == Base6Directions.Direction.Up || Base6Directions.GetClosestDirection(mat.Forward) == Base6Directions.Direction.Down) { revolveAxis = MySession.Static.ControlledEntity.Entity.WorldMatrix.Forward; } else if (Base6Directions.GetClosestDirection(mat.Up) == Base6Directions.Direction.Up || Base6Directions.GetClosestDirection(mat.Up) == Base6Directions.Direction.Down) { revolveAxis = MySession.Static.ControlledEntity.Entity.WorldMatrix.Up; } else { revolveAxis = MySession.Static.ControlledEntity.Entity.WorldMatrix.Right; } // - "epsilon" var dotCockpit1 = Vector3.Dot(MySession.Static.ControlledEntity.Entity.WorldMatrix.Up, WorldMatrix.Translation - MySession.Static.ControlledEntity.Entity.WorldMatrix.Translation) - 0.0001 > 0; Vector3 steerAxis; if (Base6Directions.GetClosestDirection(mat.Forward) == Base6Directions.Direction.Forward || Base6Directions.GetClosestDirection(mat.Forward) == Base6Directions.Direction.Backward) { steerAxis = MySession.Static.ControlledEntity.Entity.WorldMatrix.Forward; } else if (Base6Directions.GetClosestDirection(mat.Up) == Base6Directions.Direction.Forward || Base6Directions.GetClosestDirection(mat.Up) == Base6Directions.Direction.Backward) { steerAxis = MySession.Static.ControlledEntity.Entity.WorldMatrix.Up; } else { steerAxis = MySession.Static.ControlledEntity.Entity.WorldMatrix.Right; } // - "epsilon" if (CubeGrid.Physics != null) { var dotMass = Vector3.Dot(MySession.Static.ControlledEntity.Entity.WorldMatrix.Forward, (WorldMatrix.Translation - CubeGrid.Physics.CenterOfMassWorld)) - 0.0001; var dotCockpit = Vector3.Dot(WorldMatrix.Forward, steerAxis); m_steerInvert = ((dotMass * dotCockpit) < 0) ^ dotCockpit1; m_revolveInvert = ((WorldMatrix.Up - revolveAxis).Length() > 0.1f) ^ dotCockpit1; } }
/// <summary> /// Returns true if the given small block connects to large one. /// </summary> /// <param name="smallBlock">small block</param> /// <param name="smallBlockWorldAabb">small block world AABB</param> /// <param name="largeBlock">large block</param> /// <param name="largeBlockWorldAabb">large block wotld AABB</param> /// <returns>true when connected</returns> private bool SmallBlockConnectsToLarge(MySlimBlock smallBlock, ref BoundingBoxD smallBlockWorldAabb, MySlimBlock largeBlock, ref BoundingBoxD largeBlockWorldAabb) { Debug.Assert(GetCubeSize(smallBlock) == MyCubeSize.Small); Debug.Assert(GetCubeSize(largeBlock) == MyCubeSize.Large); Debug.Assert(!(smallBlock.FatBlock is MyCompoundCubeBlock)); Debug.Assert(!(largeBlock.FatBlock is MyCompoundCubeBlock)); BoundingBoxD smallBlockWorldAabbReduced = smallBlockWorldAabb; smallBlockWorldAabbReduced.Inflate(-smallBlock.CubeGrid.GridSize / 4); // Small block aabb penetrates large block aabb (large timbers). bool penetratesAabbs = largeBlockWorldAabb.Contains(smallBlockWorldAabbReduced) == ContainmentType.Intersects; if (!penetratesAabbs) { Vector3D centerToCenter = smallBlockWorldAabb.Center - largeBlockWorldAabb.Center; Vector3I addDir = Base6Directions.GetIntVector(Base6Directions.GetClosestDirection(centerToCenter)); // Check small grid mount points Quaternion smallBlockRotation; smallBlock.Orientation.GetQuaternion(out smallBlockRotation); smallBlockRotation = Quaternion.CreateFromRotationMatrix(smallBlock.CubeGrid.WorldMatrix) * smallBlockRotation; if (!MyCubeGrid.CheckConnectivitySmallBlockToLargeGrid(largeBlock.CubeGrid, smallBlock.BlockDefinition, ref smallBlockRotation, ref addDir)) { return(false); } } BoundingBoxD smallBlockWorldAabbInflated = smallBlockWorldAabb; smallBlockWorldAabbInflated.Inflate(2 * smallBlock.CubeGrid.GridSize / 3); // Trim small block aabb with large block aabb. BoundingBoxD intersectedBox = smallBlockWorldAabbInflated.Intersect(largeBlockWorldAabb); Vector3D intersectedBoxCenter = intersectedBox.Center; HkShape shape = new HkBoxShape((Vector3)intersectedBox.HalfExtents); Quaternion largeRotation; largeBlock.Orientation.GetQuaternion(out largeRotation); largeRotation = Quaternion.CreateFromRotationMatrix(largeBlock.CubeGrid.WorldMatrix) * largeRotation; Vector3D largeTranslation; largeBlock.ComputeWorldCenter(out largeTranslation); bool result = false; try { if (largeBlock.FatBlock != null) { MyModel model = largeBlock.FatBlock.Model; if (model != null) { HkShape[] shapes = model.HavokCollisionShapes; if (shapes == null || shapes.Length == 0) { return(false); } for (int i = 0; i < shapes.Length; ++i) { result = MyPhysics.IsPenetratingShapeShape(shape, ref intersectedBoxCenter, ref Quaternion.Identity, shapes[i], ref largeTranslation, ref largeRotation); if (result) { break; } } } else { HkShape shapeLarge = new HkBoxShape(largeBlock.BlockDefinition.Size * largeBlock.CubeGrid.GridSize / 2); result = MyPhysics.IsPenetratingShapeShape(shape, ref intersectedBoxCenter, ref Quaternion.Identity, shapeLarge, ref largeTranslation, ref largeRotation); shapeLarge.RemoveReference(); } } else { HkShape shapeLarge = new HkBoxShape(largeBlock.BlockDefinition.Size * largeBlock.CubeGrid.GridSize / 2); result = MyPhysics.IsPenetratingShapeShape(shape, ref intersectedBoxCenter, ref Quaternion.Identity, shapeLarge, ref largeTranslation, ref largeRotation); shapeLarge.RemoveReference(); } } finally { shape.RemoveReference(); } return(result); }
protected bool GetBlockAddPosition(float gridSize, bool placingSmallGridOnLargeStatic, out MySlimBlock intersectedBlock, out Vector3D intersectedBlockPos, out Vector3D intersectExactPos, out Vector3I addPositionBlock, out Vector3I addDirectionBlock, out ushort?compoundBlockId) { intersectedBlock = null; intersectedBlockPos = new Vector3D(); intersectExactPos = new Vector3(); addDirectionBlock = new Vector3I(); addPositionBlock = new Vector3I(); compoundBlockId = null; if (CurrentVoxelMap != null) { Vector3 hitInfoNormal = m_hitInfo.Value.HkHitInfo.Normal; Base6Directions.Direction closestDir = Base6Directions.GetClosestDirection(hitInfoNormal); Vector3I hitNormal = Base6Directions.GetIntVector(closestDir); double distance = IntersectionDistance * m_hitInfo.Value.HkHitInfo.HitFraction; Vector3D rayStart = IntersectionStart; Vector3D rayDir = Vector3D.Normalize(IntersectionDirection); Vector3D intersection = rayStart + distance * rayDir; // Get cube block placement position (add little threshold to hit normal direction to avoid wavy surfaces). addPositionBlock = MyCubeGrid.StaticGlobalGrid_WorldToUGInt(intersection + 0.1f * Vector3.Half * hitNormal * gridSize, gridSize, MyPerGameSettings.BuildingSettings.StaticGridAlignToCenter); addDirectionBlock = hitNormal; intersectedBlockPos = addPositionBlock - hitNormal; // Exact intersection in uniform grid coords. intersectExactPos = MyCubeGrid.StaticGlobalGrid_WorldToUG(intersection, gridSize, MyPerGameSettings.BuildingSettings.StaticGridAlignToCenter); // Project exact intersection to cube face of intersected block. intersectExactPos = ((Vector3.One - Vector3.Abs(hitNormal)) * intersectExactPos) + ((intersectedBlockPos + 0.5f * hitNormal) * Vector3.Abs(hitNormal)); //Vector3 position = MyCubeGrid.StaticWorldGrid_UGToWorld(addPositionBlock); //Vector3 halfExtent = new Vector3(gridSize * 0.5f); //BoundingBox cubeBox = new BoundingBox(-halfExtent, halfExtent); //Matrix matrix = Matrix.CreateTranslation(position); //Vector4 blue = Color.Blue.ToVector4(); //MySimpleObjectDraw.DrawTransparentBox(ref matrix, ref cubeBox, ref blue, MySimpleObjectRasterizer.Wireframe, 1, 0.04f); return(true); } Vector3D?intersectedObjectPos = GetIntersectedBlockData(ref m_invGridWorldMatrix, out intersectExactPos, out intersectedBlock, out compoundBlockId); if (intersectedObjectPos == null) { return(false); } intersectedBlockPos = intersectedObjectPos.Value; Vector3I removePos; if (!GetCubeAddAndRemovePositions(Vector3I.Round(intersectedBlockPos), placingSmallGridOnLargeStatic, out addPositionBlock, out addDirectionBlock, out removePos)) { return(false); } if (!placingSmallGridOnLargeStatic) { if (MyFakes.ENABLE_BLOCK_PLACING_ON_INTERSECTED_POSITION) { Vector3I newRemovepos = Vector3I.Round(intersectedBlockPos); if (newRemovepos != removePos) { if (m_hitInfo.HasValue) { Vector3 hitInfoNormal = m_hitInfo.Value.HkHitInfo.Normal; Base6Directions.Direction closestDir = Base6Directions.GetClosestDirection(hitInfoNormal); Vector3I hitNormal = Base6Directions.GetIntVector(closestDir); addDirectionBlock = hitNormal; } removePos = newRemovepos; addPositionBlock = removePos + addDirectionBlock; } } else { if (CurrentGrid.CubeExists(addPositionBlock)) { return(false); } } } if (placingSmallGridOnLargeStatic) { removePos = Vector3I.Round(intersectedBlockPos); } intersectedBlockPos = removePos; intersectedBlock = CurrentGrid.GetCubeBlock(removePos); if (intersectedBlock == null) { Debug.Assert(false, "No intersected block"); return(false); } return(true); }
/// <summary> /// Returns subblock data from dummy, subblock matrix can be offset (according to useOffset parameter) so the dummy position output is also provided. /// </summary> /// <returns>true when dummy is subblock otherwise false</returns> public static bool GetSubBlockDataFromDummy(MyCubeBlockDefinition ownerBlockDefinition, string dummyName, MyModelDummy dummy, bool useOffset, out MyCubeBlockDefinition subBlockDefinition, out MatrixD subBlockMatrix, out Vector3 dummyPosition) { subBlockDefinition = null; subBlockMatrix = MatrixD.Identity; dummyPosition = Vector3.Zero; if (!dummyName.ToLower().StartsWith(MyCubeBlock.DUMMY_SUBBLOCK_ID)) { return(false); } if (ownerBlockDefinition.SubBlockDefinitions == null) { return(false); } string dummyNameShort = dummyName.Substring(MyCubeBlock.DUMMY_SUBBLOCK_ID.Length); MyDefinitionId definitiondId; if (!ownerBlockDefinition.SubBlockDefinitions.TryGetValue(dummyNameShort, out definitiondId)) { Debug.Assert(false, "SubBlock definition not found!"); return(false); } MyDefinitionManager.Static.TryGetCubeBlockDefinition(definitiondId, out subBlockDefinition); if (subBlockDefinition == null) { Debug.Assert(false, "SubBlock definition not found!"); return(false); } const double dotEpsilon = 0.00000001; subBlockMatrix = MatrixD.Normalize(dummy.Matrix); Vector3I forward = Base6Directions.GetIntVector(Base6Directions.GetClosestDirection(subBlockMatrix.Forward)); double forwardDot = Vector3D.Dot(subBlockMatrix.Forward, (Vector3D)forward); if (Math.Abs(1 - forwardDot) <= dotEpsilon) { subBlockMatrix.Forward = forward; } Vector3I right = Base6Directions.GetIntVector(Base6Directions.GetClosestDirection(subBlockMatrix.Right)); double rightDot = Vector3D.Dot(subBlockMatrix.Right, (Vector3D)right); if (Math.Abs(1 - rightDot) <= dotEpsilon) { subBlockMatrix.Right = right; } Vector3I up = Base6Directions.GetIntVector(Base6Directions.GetClosestDirection(subBlockMatrix.Up)); double upDot = Vector3D.Dot(subBlockMatrix.Up, (Vector3D)up); if (Math.Abs(1 - upDot) <= dotEpsilon) { subBlockMatrix.Up = up; } dummyPosition = subBlockMatrix.Translation; if (useOffset) { Vector3 offset = MyCubeBlock.GetBlockGridOffset(subBlockDefinition); subBlockMatrix.Translation -= Vector3D.TransformNormal(offset, subBlockMatrix); } return(true); }
protected bool GetBlockAddPosition(float gridSize, bool placingSmallGridOnLargeStatic, out MySlimBlock intersectedBlock, out Vector3D intersectedBlockPos, out Vector3D intersectExactPos, out Vector3I addPositionBlock, out Vector3I addDirectionBlock, out ushort?compoundBlockId) { Vector3I vectori; intersectedBlock = null; intersectedBlockPos = new Vector3D(); Vector3 vector = new Vector3(); intersectExactPos = vector; addDirectionBlock = new Vector3I(); addPositionBlock = new Vector3I(); compoundBlockId = 0; if (this.CurrentVoxelBase != null) { Vector3I intVector = Base6Directions.GetIntVector(Base6Directions.GetClosestDirection(this.m_hitInfo.Value.HkHitInfo.Normal)); Vector3D worldPos = IntersectionStart + ((IntersectionDistance * this.m_hitInfo.Value.HkHitInfo.HitFraction) * Vector3D.Normalize(IntersectionDirection)); addPositionBlock = MyCubeGrid.StaticGlobalGrid_WorldToUGInt(worldPos + (((0.1f * Vector3.Half) * intVector) * gridSize), gridSize, CubeBuilderDefinition.BuildingSettings.StaticGridAlignToCenter); addDirectionBlock = intVector; intersectedBlockPos = (Vector3D)(addPositionBlock - intVector); intersectExactPos = MyCubeGrid.StaticGlobalGrid_WorldToUG(worldPos, gridSize, CubeBuilderDefinition.BuildingSettings.StaticGridAlignToCenter); intersectExactPos = ((Vector3D.One - Vector3.Abs((Vector3)intVector)) * intersectExactPos) + ((intersectedBlockPos + (0.5f * intVector)) * Vector3.Abs((Vector3)intVector)); return(true); } Vector3D?nullable = this.GetIntersectedBlockData(ref this.m_invGridWorldMatrix, out intersectExactPos, out intersectedBlock, out compoundBlockId); if (nullable == null) { return(false); } intersectedBlockPos = nullable.Value; if (!this.GetCubeAddAndRemovePositions(Vector3I.Round(intersectedBlockPos), placingSmallGridOnLargeStatic, out addPositionBlock, out addDirectionBlock, out vectori)) { return(false); } if (!placingSmallGridOnLargeStatic) { if (!MyFakes.ENABLE_BLOCK_PLACING_ON_INTERSECTED_POSITION) { if (this.CurrentGrid.CubeExists(addPositionBlock)) { return(false); } } else { Vector3I vectori3 = Vector3I.Round(intersectedBlockPos); if (vectori3 != vectori) { if (this.m_hitInfo != null) { Vector3I intVector = Base6Directions.GetIntVector(Base6Directions.GetClosestDirection(this.m_hitInfo.Value.HkHitInfo.Normal)); addDirectionBlock = intVector; } vectori = vectori3; addPositionBlock = (Vector3I)(vectori + addDirectionBlock); } } } if (placingSmallGridOnLargeStatic) { vectori = Vector3I.Round(intersectedBlockPos); } intersectedBlockPos = (Vector3D)vectori; intersectedBlock = this.CurrentGrid.GetCubeBlock(vectori); return(intersectedBlock != null); }
/// <summary> /// Move blocks in m_projectedBlocks to m_damagedBlocks if they are touching any real blocks /// </summary> private void ProjectedToDamaged() { foreach (IMySlimBlock block in m_projectedBlocks) { MyCubeGrid projected = (MyCubeGrid)block.CubeGrid; MyCubeGrid projectorGrid = projected.Projector.CubeGrid; if (projected.Closed || projected.Projector.Closed || !projected.Projector.IsWorking || projectorGrid.Closed) { Log.DebugLog("projection closed"); continue; } Vector3I min = projectorGrid.WorldToGridInteger(projected.GridIntegerToWorld(block.Min())); if (projectorGrid.GetCubeBlock(min) != null) { Log.DebugLog("space is occupied: " + min); m_projectedBlocks.Remove(block); continue; } IMyCubeBlock cubeBlock = block.FatBlock; if (cubeBlock != null) { Vector3I max = projectorGrid.WorldToGridInteger(projected.GridIntegerToWorld(block.Max())); MatrixD invOrient = projectorGrid.PositionComp.WorldMatrixNormalizedInv.GetOrientation(); Vector3 forward = Vector3D.Transform(cubeBlock.WorldMatrix.Forward, ref invOrient); Vector3 up = Vector3D.Transform(cubeBlock.WorldMatrix.Up, ref invOrient); MyBlockOrientation orient = new MyBlockOrientation(Base6Directions.GetClosestDirection(ref forward), Base6Directions.GetClosestDirection(ref up)); if (projectorGrid.CanPlaceBlock(min, max, orient, ((MyCubeBlock)cubeBlock).BlockDefinition)) { Log.DebugLog("can place fatblock: " + cubeBlock.DisplayNameText + ", position: " + min + ", world: " + projectorGrid.GridIntegerToWorld(min)); m_damagedBlocks.Add(block); m_projectedBlocks.Remove(block); } continue; } // no fatblock, cannot get definition if (projectorGrid.IsTouchingAnyNeighbor(min, min)) { Log.DebugLog("can place slimblock: " + block.ToString() + ", position: " + min + ", world: " + projectorGrid.GridIntegerToWorld(min)); m_damagedBlocks.Add(block); m_projectedBlocks.Remove(block); } } m_projectedBlocks.ApplyRemovals(); }