private void CalcRotate_InGravity(RelativeDirection3F direction) { //Log.DebugLog("entered CalcRotate_InGravity(RelativeDirection3F direction)", "CalcRotate_InGravity()"); float secondaryAccel = Thrust.SecondaryForce / Block.Physics.Mass; RelativeDirection3F fightGrav = RelativeDirection3F.FromLocal(Block.CubeGrid, -Thrust.LocalGravity.vector); if (secondaryAccel > Thrust.GravityStrength) { // secondary thrusters are strong enough to fight gravity if (Vector3.Dot(direction.ToLocalNormalized(), fightGrav.ToLocalNormalized()) > 0f) { // direction is away from gravity Log.DebugLog("Facing primary towards direction(" + direction.ToLocalNormalized() + "), rolling secondary away from gravity(" + fightGrav.ToLocalNormalized() + ")"); CalcRotate(Thrust.Standard.LocalMatrix, direction, fightGrav, gravityAdjusted: true); return; } else { // direction is towards gravity Log.DebugLog("Facing secondary away from gravity(" + fightGrav.ToLocalNormalized() + "), rolling primary towards direction(" + direction.ToLocalNormalized() + ")"); CalcRotate(Thrust.Gravity.LocalMatrix, fightGrav, direction, gravityAdjusted: true); return; } } // secondary thrusters are not strong enough to fight gravity if (secondaryAccel > 1f) { Log.DebugLog("Facing primary towards gravity(" + fightGrav.ToLocalNormalized() + "), rolling secondary towards direction(" + direction.ToLocalNormalized() + ")"); CalcRotate(Thrust.Standard.LocalMatrix, fightGrav, direction, gravityAdjusted: true); return; } // helicopter float primaryAccel = Math.Max(Thrust.PrimaryForce / Block.Physics.Mass - Thrust.GravityStrength, 1f); // obviously less than actual value but we do not need maximum theoretical acceleration DirectionGrid moveAccel = m_moveAccel != Vector3.Zero ? ((DirectionBlock)m_moveAccel).ToGrid(Block.CubeBlock) : LinearVelocity.ToGrid(Block.CubeGrid) * -0.5f; if (moveAccel.vector.LengthSquared() > primaryAccel * primaryAccel) { //Log.DebugLog("move accel is over available acceleration: " + moveAccel.vector.Length() + " > " + primaryAccel, "CalcRotate_InGravity()"); moveAccel = Vector3.Normalize(moveAccel.vector) * primaryAccel; } //Log.DebugLog("Facing primary away from gravity and towards direction, moveAccel: " + moveAccel + ", fight gravity: " + fightGrav.ToLocal() + ", direction: " + direction.ToLocalNormalized() + ", new direction: " + (moveAccel + fightGrav.ToLocal())); Vector3 dirV = moveAccel + fightGrav.ToLocal(); direction = RelativeDirection3F.FromLocal(Block.CubeGrid, dirV); CalcRotate(Thrust.Standard.LocalMatrix, direction, gravityAdjusted: true); Vector3 fightGravDirection = fightGrav.ToLocal() / Thrust.GravityStrength; // determine acceleration needed in forward direction to move to desired altitude or remain at current altitude float projectionMagnitude = Vector3.Dot(dirV, fightGravDirection) / Vector3.Dot(Thrust.Standard.LocalMatrix.Forward, fightGravDirection); Vector3 projectionDirection = ((DirectionGrid)Thrust.Standard.LocalMatrix.Forward).ToBlock(Block.CubeBlock); m_moveForceRatio = projectionDirection * projectionMagnitude * Block.CubeGrid.Physics.Mass / Thrust.PrimaryForce; Log.DebugLog("changed moveForceRatio, projectionMagnitude: " + projectionMagnitude + ", projectionDirection: " + projectionDirection + ", moveForceRatio: " + m_moveForceRatio); }