@lazyglobal off. wait until ship:unpacked. rcs off. lock throttle to 0. runoncepath("0:/lib/common.ks"). runoncepath("0:/lib/moonmath.ks"). runoncepath("0:/lib/stage/atlas.ks"). runoncepath("0:/lib/stage/agena.ks"). local state is lex(). local function ship_volume { return ship:rootpart:getmodule("kosprocessor"):volume. } local function phase { switch to ship_volume(). if not ship_volume():exists("state.json") { set_phase("prelaunch"). } set state to readjson("state.json"). return state["phase"]. } local function set_phase { parameter new_phase. switch to ship_volume(). set state["phase"] to new_phase. writejson(state, "state.json"). kuniverse:quicksaveto("moon-impactor-"+new_phase). } if phase() = "prelaunch" { local target_inclination is max(moon:obt:inclination,ship:latitude). local target_alt is 500_000. set state["azimuth"] to launch_azimuth(target_inclination, target_alt). local launch_params is moonmath:calculate_launch(target_inclination, state["azimuth"], target_alt). local launch_time is launch_params:launch_time. set state["moon_altitude"] to launch_params:moon_altitude. set state["burn_longitude"] to launch_params:burn_longitude. print "Burning for moon at " + state["burn_longitude"] + " right ascension". wait 2. until launch_time - time:seconds < 10 { print "Not ready to launch yet, warping...". warpto(launch_time-9). wait 0. wait until warp = 0. wait until kuniverse:timewarp:issettled. print "Maybe done warping?". } wait until time:seconds > launch_time. atlas:launch(state["azimuth"], target_alt, 4). stage. set_phase("circularize"). } if phase() = "circularize" { agena:orbit(state["azimuth"]). agena:power_down(). wait 1. set_phase("parkingorbit"). } local function ship_longitude { return mod(ship:longitude + ship:body:rotationangle + 360, 360). } local function transfer_lead_angle { parameter moon_alt. local moon_range is moon:apoapsis - moon:periapsis. local moon_frac is (moon_alt - moon:periapsis) / moon_range. local lead_angle_frac is 1.0 - moon_frac. return 1.1 + 0.65 * lead_angle_frac. } if phase() = "parkingorbit" { // Just in case our burn point is RIGHT HERE, we want to go around at least once. set warpmode to "physics". set warp to 3. wait until abs(ship_longitude() - state["burn_longitude"]) > 10. set warp to 0. wait until kuniverse:timewarp:issettled. wait 1. // Rails warp until we're nearish to the burn point print "Warping to dLongitude < 15". set warpmode to "rails". set warp to 2. wait until abs(ship_longitude() - state["burn_longitude"]) < 15. set warp to 0. wait until kuniverse:timewarp:issettled. wait 1. // Physics warp until we're nearish-er print "Warping to dLongitude < 7". set warpmode to "physics". set warp to 3. wait until abs(ship_longitude() - state["burn_longitude"]) < 4. set warp to 0. wait until kuniverse:timewarp:issettled. wait 1. agena:power_up(). rcs on. lock steering to ship:prograde. local lead_angle is transfer_lead_angle(state["moon_altitude"]). wait until abs(ship_longitude() - state["burn_longitude"]) < lead_angle. // Hand-picked rather than computing burn time & time to target longitude local transfer_vel is circular_vel() + hohmann_transfer_dv(earth, ship:altitude, state["moon_altitude"]). print "Moon altitude is: " + state["moon_altitude"]. print "Transfer DV is: " + (transfer_vel - ship:velocity:orbit:mag). print "Burn lead angle is: " + lead_angle. agena:transfer_burn(transfer_vel). wait 1. stage. set_phase("adjust"). } if phase() = "adjust" { panels on. rcs on. lock throttle to 0.0. lock steering to lookdirup(ship:prograde:forevector, ship:up:forevector). local adjustment is 8_000_000. // 1.5%..2.0%? print "Alt Adjustment is " + adjustment. local target_alt is state["moon_altitude"] + adjustment. local max_alt_delta is 1_000_000. local threshold is 0.1. until false { local p is threshold / max_alt_delta. local da is target_alt - ship:orbit:apoapsis. local horz_factor is da * p. if abs(horz_factor) < threshold { set ship:control:fore to 0. break. } set ship:control:fore to horz_factor. wait 0. } set_phase("pretransfer"). } if phase() = "pretransfer" { rcs on. lock steering to sun:direction. wait 1. wait until steering_locked(). wait 1. local avi_mod is ship:rootpart:getmodule("ModuleProceduralAvionics"). avi_mod:doaction("shutdown avionics", true). wait 1. set_phase("transfer"). } if phase() = "transfer" { set warpmode to "rails". warpto(eta:transition + time:seconds). wait until ship:obt:body = moon. wait until kuniverse:timewarp:issettled. set_phase("done"). } if phase() <> "done" { print "Phase logic failed, expected to be in phase '" + phase() + "'". } print "Done".