void Control() { var TargetVecLoc = CustVectorTransform(Controller.GetTotalGravity(), HingeNeck.WorldMatrix.GetOrientation()); var Roll = Math.Atan2(-TargetVecLoc.X, TargetVecLoc.Z); var Pitch = Math.Atan2(TargetVecLoc.Y, TargetVecLoc.Z); HingeNeck.TargetVelocityRad = Turn(-(float)Roll, HingeNeck.Angle); DampSuspRot(RotorSusp); foreach (var h in Hinges) { DampSuspHinge(h, Roll, Pitch); } }
public void Main(string argument, UpdateType updateSource) { if ((updateSource & UpdateType.Trigger) != 0) { if (argument == "HDamp") { hDamp = !hDamp; } if (argument == "ManualAlt") { manualAlt = !manualAlt; targAltitude = GetAltitude(); targSpd = 0; } if (argument == "VDamp") { vDamp = !vDamp; } if (argument == "Spd+") { SetSpd(curSpeed + 1); } if (argument == "Spd-") { SetSpd(curSpeed - 1); } } bool trueHDamp = hDamp; Vector3D pos = sc.CenterOfMass; Vector3D spd = sc.GetShipVelocities().LinearVelocity; Vector3D grav = Vector3D.Normalize(sc.GetTotalGravity()); double gravNorm = sc.GetTotalGravity().Length(); Vector3D gravin = Vector3D.TransformNormal(grav, MatrixD.Transpose(sc.WorldMatrix)); Vector3D spdin = Vector3D.TransformNormal(spd, MatrixD.Transpose(sc.WorldMatrix)); Vector3D MoveIndic = sc.MoveIndicator; Vector3D COM = PosToShip(sc.CenterOfMass); if (gravin.Y > 0) { hDamp = false; } //orientation if (MoveIndic.X != 0 || MoveIndic.Z != 0) { trueHDamp = false; } double inclCommand = rotAngles[curSpeed]; double angleToRotSpd = 1.0; // new orientation lastHeading -= grav * grav.Dot(lastHeading); lastHeading.Normalize(); Vector3D right = grav.Cross(lastHeading); right.Normalize(); lastHeading += 0.001 * right * sc.RotationIndicator.Y; lastHeading.Normalize(); Vector3D ntarget = grav; double targetX = 0.0, targetZ = 0.0; if (trueHDamp) { targetZ = Clamp(-(spdin.Z) * 0.05, -0.5, 0.5); targetX = Clamp(-(spdin.X) * 0.05, -0.5, 0.5); } else { targetX = inclCommand * MoveIndic.X; targetZ = inclCommand * MoveIndic.Z; } ntarget -= targetX * right; ntarget += targetZ * lastHeading; ntarget.Normalize(); Vector3D headtarget = right.Cross(ntarget); headtarget.Normalize(); Vector3D ntargetin = Vector3D.TransformNormal(ntarget, MatrixD.Transpose(sc.WorldMatrix)); Vector3D headtargetin = Vector3D.TransformNormal(headtarget, MatrixD.Transpose(sc.WorldMatrix)); QuaternionD targq = QuaternionD.CreateFromForwardUp(headtargetin, -ntargetin); Vector3D axis; double angle; targq.GetAxisAngle(out axis, out angle); axis *= angle; axis *= angleToRotSpd; SetRotSpd(axis); // new altitude double curAltitude = GetAltitude(); double curVSpeed = (curAltitude - lastAltitude) * 60; double targAcc = 0; if (vDamp) { targAcc = Clamp(-targSpd, -accelerations[curSpeed], accelerations[curSpeed]); } if (MoveIndic.Y != 0) { targAcc = MoveIndic.Y * accelerations[curSpeed]; } targSpd += targAcc / 60; targSpd = Clamp(targSpd, curVSpeed - maxSpdDrift, curVSpeed + maxSpdDrift); targAltitude += targSpd / 60; targAltitude = Clamp(targAltitude, curAltitude - maxAltDrift, curAltitude + maxAltDrift); double compTargSpd = targSpd + (targAltitude - curAltitude); double compTargAcc = targAcc + gravNorm / (-gravin.Y) + (compTargSpd - curVSpeed); if (manualAlt) { ClearThrust(); } else { SetThrust(compTargAcc * mass); } if (tick >= 10) { tick = 0; /*lcd.WriteText($@"grav X={gravin.X:F3} Y={gravin.Y:F3} Z={gravin.Z:F3} * Spd X={spdin.X:F3} Y={spdin.Y:F3} Z={spdin.Z:F3} * AA X={axis.X:F3} Y={axis.Y:F3} Z={axis.Z:F3} * NT {ntargetin} {headtargetin} * hDamp {hDamp} vDamp {vDamp} ManualAlt {manualAlt} * Spd: {speedNames[curSpeed]} * Alt cur {curAltitude:F3} targ {targAltitude:F3} * Spd cur {curVSpeed:F10} targ {targSpd:F10} ctarg {compTargSpd:F10} * Acc targ {targAcc:F10} ctarg {compTargAcc:F10} * pos {sc.GetPosition()} scal {Vector3D.Dot(grav, sc.GetPosition())} * cam X {COM.X:F3} Y {COM.Y:F3} Z {COM.Z:F3} * th back {backT:F3} front {frontT:F3} * dist back {distback:F3} front{distfront:F3} * ");*/ lcd.WriteText($@"Helico control software Horizontal Dampeners (4) {OnOff(hDamp)} Vertical Dampeners (5) {OnOff(vDamp)} Manual Altitude (6) {OnOff(manualAlt)} Current Altitude {curAltitude:F2}m Vertical Speed {targSpd:F2}m/s Speed mode (^8/v9) {speedNames[curSpeed]} "); } else { tick++; } lastAltitude = curAltitude; }
private void UpdateThrusterGroups() { if (_controller == null) { return; } if (_config.LiftThrustersGroupName != "") { _liftThrusters.FindBlocks(true, null, _config.LiftThrustersGroupName); } else { _liftThrusters.FindBlocks(true, thruster => { Vector3D thrusterDirection = -thruster.WorldMatrix.Forward; //double forwardDot = Vector3D.Dot(thrusterDirection, _controller.WorldMatrix.Forward); double upDot = Vector3D.Dot(thrusterDirection, -Vector3.Normalize(_controller.GetTotalGravity())); //double leftDot = Vector3D.Dot(thrusterDirection, _controller.WorldMatrix.Left); if (upDot >= 0.2) { return(true); } return(false); }); } if (_config.StopThrustersGroupName != "") { _stopThrusters.FindBlocks(true, null, _config.StopThrustersGroupName); } else { _stopThrusters.FindBlocks(true, thruster => { Vector3D thrusterDirection = -thruster.WorldMatrix.Forward; double forwardDot = Vector3D.Dot(thrusterDirection, _controller.GetShipVelocities().LinearVelocity); //double upDot = Vector3D.Dot(thrusterDirection, _controller.WorldMatrix.Up); //double leftDot = Vector3D.Dot(thrusterDirection, _controller.WorldMatrix.Left); if (forwardDot <= -0.7) { return(true); } return(false); }); } _cruiseThrusters.FindBlocks(true, thruster => { var facing = thruster.Orientation.TransformDirection(Base6Directions.Direction.Forward); return(facing == Base6Directions.Direction.Backward); }); _cruiseReverseThrusters.FindBlocks(true, thruster => { var facing = thruster.Orientation.TransformDirection(Base6Directions.Direction.Forward); return(facing == Base6Directions.Direction.Forward); }); }
public void Update(TimeSpan timestamp, UpdateFrequency updateFlags) { if (timestamp == TimeSpan.Zero) { return; } foreach (var bird in Hummingbirds) { if (bird.IsAlive()) { bird.Update(); } else { DeadBirds.Add(bird); } } foreach (var bird in DeadBirds) { DeregisterBird(bird); } runs++; if (runs % 20 == 0) { var intelItems = IntelProvider.GetFleetIntelligences(timestamp); // Get the top targets TopEnemies.Clear(); EnemyToScore.Clear(); foreach (var intelItem in intelItems) { if (intelItem.Key.Item1 == IntelItemType.Enemy) { var esi = (EnemyShipIntel)intelItem.Value; var dist = (esi.GetPositionFromCanonicalTime(timestamp + IntelProvider.CanonicalTimeDiff) - Context.Reference.WorldMatrix.Translation).Length(); if (dist > MaxEngagementDist) { continue; } var priority = IntelProvider.GetPriority(esi.ID); var size = esi.Radius; if (size < MinEngagementSize && priority < 3) { continue; } if (priority < 2) { continue; } int score = (int)(priority * 10000 + size); EnemyToScore[esi] = score; for (int i = 0; i <= TopEnemies.Count; i++) { if (i == TopEnemies.Count || score > EnemyToScore[TopEnemies[i]]) { TopEnemies.Insert(i, esi); break; } } } } // Determine how many birds should be assigned to each enemy EnemyToNumBirds.Clear(); int totalNeededBirds = 0; for (int i = 0; i < TopEnemies.Count && i < 4; i++) { EnemyToNumBirds[TopEnemies[i]] = EnemyCountToNumBirdsPerEnemy[TopEnemies.Count][i]; EnemyToAssignedBirds[TopEnemies[i]] = 0; totalNeededBirds += EnemyToNumBirds[TopEnemies[i]]; } // Remove excess birds from enemies foreach (var bird in Hummingbirds) { var birdTargetID = BirdToEnemy[bird]; if (birdTargetID == 0) { continue; } if (!bird.IsCombatCapable()) { BirdToEnemy[bird] = 0; continue; } var birdTargetKey = MyTuple.Create(IntelItemType.Enemy, birdTargetID); if (!intelItems.ContainsKey(birdTargetKey)) { BirdToEnemy[bird] = 0; continue; } var birdTarget = (EnemyShipIntel)intelItems[birdTargetKey]; if (!EnemyToNumBirds.ContainsKey(birdTarget) || EnemyToNumBirds[birdTarget] == 0) { BirdToEnemy[bird] = 0; continue; } EnemyToNumBirds[birdTarget]--; totalNeededBirds--; } // Assign birds to enemies foreach (var bird in Hummingbirds) { if (totalNeededBirds == 0) { break; } // Bird can't fight, keep looking if (!bird.IsCombatCapable()) { continue; } // Bird already has target, keep looking if (BirdToEnemy[bird] != 0) { continue; } EnemyShipIntel targetEnemy = null; foreach (var enemy in EnemyToNumBirds.Keys) { if (EnemyToNumBirds[enemy] > 0) { targetEnemy = enemy; break; } } BirdToEnemy[bird] = targetEnemy.ID; EnemyToNumBirds[targetEnemy]--; totalNeededBirds--; } NeedsMoreBirds = totalNeededBirds > 0; int birdIndex; // ASSUME birds are not far enough from main controller that gravity direction matters too much var gravDir = Controller.GetTotalGravity(); gravDir.Normalize(); // For each enemy, assign bird target and destination foreach (var enemy in TopEnemies) { birdIndex = 0; foreach (var bird in Hummingbirds) { if (BirdToEnemy[bird] != enemy.ID) { continue; } if (bird.Gats.Count == 0) { continue; } var birdAltitudeTheta = Math.PI * ((runs / (BirdSineConstantSeconds * 30) % 2) - 1); var birdSwayTheta = Math.PI * ((runs / (BirdPendulumConstantSeconds * 30) % 2) - 1); var targetPos = enemy.GetPositionFromCanonicalTime(timestamp + IntelProvider.CanonicalTimeDiff); bird.SetTarget(targetPos, enemy.GetVelocity() - gravDir * (float)TrigHelpers.FastCos(birdAltitudeTheta) * 2); var targetToBase = bird.Base.WorldMatrix.Translation - targetPos; targetToBase -= VectorHelpers.VectorProjection(targetToBase, gravDir); var targetToBaseDist = targetToBase.Length(); targetToBase.Normalize(); var engageLocationLocus = targetToBase * Math.Min(600, targetToBaseDist + 400) + targetPos; var engageLocationSwayDir = targetToBase.Cross(gravDir); var engageLocationSwayDist = (TrigHelpers.FastCos(birdSwayTheta) - EnemyToAssignedBirds[enemy] * 0.5 + birdIndex + 0.5) * 100; bird.SetDest(engageLocationLocus + engageLocationSwayDist * engageLocationSwayDir); var birdDir = bird.Controller.WorldMatrix.Translation - Controller.WorldMatrix.Translation; birdDir -= VectorHelpers.VectorProjection(birdDir, gravDir);; var birdDist = birdDir.Length(); bird.Drive.DesiredAltitude = birdDist < 100 ? Hummingbird.RecommendedServiceCeiling : (float)TrigHelpers.FastSin(birdAltitudeTheta + Math.PI * 0.5) * (Hummingbird.RecommendedServiceCeiling - Hummingbird.RecommendedServiceFloor) + Hummingbird.RecommendedServiceFloor; birdIndex++; } } // Assign orbit task for unassigned birds int numReserveBirds = 0; foreach (var bird in Hummingbirds) { if (BirdToEnemy[bird] == 0 && bird.IsCombatCapable()) { numReserveBirds++; } } birdIndex = 0; var randomPoint = new Vector3D(190, 2862, 809); randomPoint -= VectorHelpers.VectorProjection(randomPoint, gravDir); randomPoint.Normalize(); var randomPointCross = randomPoint.Cross(gravDir); foreach (var bird in Hummingbirds) { if (BirdToEnemy[bird] != 0) { continue; } bird.SetTarget(Vector3D.Zero, Vector3D.Zero); bird.Drive.DesiredAltitude = 30; if (bird.IsCombatCapable() && !bird.IsRetiring) { var birdOrbitTheta = Math.PI * (((2 * birdIndex / (float)numReserveBirds) + runs / (BirdOrbitSeconds * 30)) % 2 - 1); var birdOrbitDest = Controller.WorldMatrix.Translation + TrigHelpers.FastCos(birdOrbitTheta) * randomPoint * BirdOrbitDist + TrigHelpers.FastSin(birdOrbitTheta) * randomPointCross * BirdOrbitDist; bird.SetDest(birdOrbitDest); birdIndex++; } else if (!bird.IsRetiring) { RetireBird(bird); } else if (bird.IsRetiring) { if (!bird.IsLanding) { var birdDir = bird.Controller.WorldMatrix.Translation - bird.Destination; birdDir -= VectorHelpers.VectorProjection(birdDir, gravDir); var birdDist = birdDir.Length(); birdDir.Normalize(); if (birdDist < 50) { bird.SetDest(Vector3D.Zero); bird.Drive.Flush(); foreach (var engine in bird.Drive.HoverEngines) { engine.AltitudeMin = 0; } bird.IsLanding = true; } } else { double altitude; bird.Controller.TryGetPlanetElevation(MyPlanetElevation.Surface, out altitude); if (altitude < 6) { foreach (var engine in bird.Drive.HoverEngines) { engine.Block.Enabled = false; DeadBirds.Add(bird); } } } } } } foreach (var cradle in Cradles) { if (cradle == null) { continue; } cradle.Update(); } if (runs % 60 == 0) { BirdReleaseTimeout--; for (int i = 0; i < Cradles.Count(); i++) { if (Cradles[i] == null) { continue; } if (Cradles[i].Hummingbird == null) { Cradles[i].CheckHummingbird(); } else if (NeedsMoreBirds && BirdReleaseTimeout <= 0) { Hummingbird bird = Cradles[i].Release(); bird.Base = Context.Reference; RegisterBird(bird); BirdReleaseTimeout = 5; } } } DeadBirds.Clear(); }