diff --git a/A320-main.xml b/A320-main.xml index 4d4302b1..0667bb75 100644 --- a/A320-main.xml +++ b/A320-main.xml @@ -614,6 +614,9 @@ S + + E 4500 4500 @@ -4818,6 +4821,7 @@ Aircraft/A320-family/Nasal/Panels/efis.nas + Aircraft/A320-family/Nasal/FMGC/flightplan-delegates.nas Aircraft/A320-family/Nasal/FMGC/flightplan-waypoints.nas Aircraft/A320-family/Nasal/FMGC/flightplan.nas Aircraft/A320-family/Nasal/FMGC/FMGC.nas diff --git a/Models/Instruments/MCDU/MCDU.nas b/Models/Instruments/MCDU/MCDU.nas index 987f648b..50a20adc 100644 --- a/Models/Instruments/MCDU/MCDU.nas +++ b/Models/Instruments/MCDU/MCDU.nas @@ -170,11 +170,13 @@ var canvas_MCDU_base = { me["Simple_L6S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_C1S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_C2S"].setFont("HoneywellMCDUSmall.ttf"); + me["Simple_C3S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_C4S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_C5S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_C6S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_R1S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_R2S"].setFont("HoneywellMCDUSmall.ttf"); + me["Simple_R3S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_R4S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_R5S"].setFont("HoneywellMCDUSmall.ttf"); me["Simple_R6S"].setFont("HoneywellMCDUSmall.ttf"); @@ -519,9 +521,7 @@ var canvas_MCDU_base = { me.hideAllArrows(); - me.fontSizeLeft(normal, normal, normal, normal, normal, normal); - me.fontSizeCenter(normal, normal, normal, normal, normal, normal); - me.fontSizeRight(normal, normal, normal, normal, normal, normal); + me.standardFontSize(); pageSwitch[i].setBoolValue(1); } @@ -553,6 +553,7 @@ var canvas_MCDU_base = { me.colorLeftS("wht", "wht", "wht", "wht", "wht", "wht"); me.colorLeftArrow("wht", "wht", "wht", "wht", "wht", "wht"); + me.colorCenterS("wht", "wht", "wht", "wht", "wht", "wht"); me.colorRightS("wht", "wht", "wht", "wht", "wht", "wht"); me.colorRightArrow("wht", "wht", "wht", "wht", "wht", "wht"); @@ -2991,6 +2992,19 @@ var canvas_MCDU_base = { me.colorRightS("wht", "amb", "wht", "wht", "wht", "wht"); me.colorRightArrow("wht", "wht", "wht", "wht", "wht", "wht"); + me["Simple_L1S"].setText("CO RTE"); + me["Simple_L2S"].setText("ALTN/CO RTE"); + me["Simple_L3S"].setText("FLT NBR"); + me["Simple_L5S"].setText("COST INDEX"); + me["Simple_L6S"].setText("CRZ FL/TEMP"); + me["Simple_R1S"].setText("FROM/TO "); + me["Simple_R2S"].setText("INIT "); + me["Simple_R5S"].setText("TROPO"); + me["Simple_R6S"].setText("GND TEMP"); + me["Simple_R2"].setText("REQUEST "); + me["Simple_R3"].setText("IRS INIT "); + me["Simple_R4"].setText("WIND "); + pageSwitch[i].setBoolValue(1); } @@ -3023,13 +3037,13 @@ var canvas_MCDU_base = { } else if (fmgc.FMGCInternal.crzSet and fmgc.FMGCInternal.crzTempSet) { me["INITA_CruiseFLTemp"].hide(); me["Simple_L6"].setColor(BLUE); - me["Simple_L6"].setText(sprintf("%s", "FL" ~ fmgc.FMGCInternal.crzFl) ~ sprintf("/%s°", fmgc.FMGCInternal.crzTemp)); + me["Simple_L6"].setText(sprintf("%s", "FL" ~ fmgc.FMGCInternal.crzFl) ~ sprintf("/%+3.0f°", fmgc.FMGCInternal.crzTemp)); } else if (fmgc.FMGCInternal.crzSet) { me["INITA_CruiseFLTemp"].hide(); me["Simple_L6"].setColor(BLUE); fmgc.FMGCInternal.crzTemp = 15 - (2 * fmgc.FMGCInternal.crzFl / 10); fmgc.FMGCInternal.crzTempSet = 1; - me["Simple_L6"].setText(sprintf("%s", "FL" ~ fmgc.FMGCInternal.crzFl) ~ sprintf("/%s°", fmgc.FMGCInternal.crzTemp)); + me["Simple_L6"].setText(sprintf("%s", "FL" ~ fmgc.FMGCInternal.crzFl) ~ sprintf("/%+3.0f°", fmgc.FMGCInternal.crzTemp)); } else { me["INITA_CruiseFLTemp"].show(); me["Simple_L6"].setColor(AMBER); @@ -3072,6 +3086,7 @@ var canvas_MCDU_base = { me["INITA_InitRequest"].hide(); } } + if (ADIRSMCDUBTN.getValue() != 1) { me["INITA_AlignIRS"].show(); me["Simple_R3"].setColor(AMBER); @@ -3081,41 +3096,34 @@ var canvas_MCDU_base = { me["Simple_R3"].setColor(WHITE); showRightArrow(me,0, 0, 1, 0, 0, 0); } + if (fmgc.FMGCInternal.tropoSet) { me["Simple_R5"].setFontSize(normal); } else { me["Simple_R5"].setFontSize(small); } - me["Simple_R6S"].setText("GND TEMP"); - if (fmgc.FMGCInternal.phase == 0 and !fmgc.FMGCInternal.gndTempSet) { - fmgc.FMGCInternal.gndTemp = 15 - (2 * getprop("/position/gear-agl-ft") / 1000); - me["Simple_R6"].setText(sprintf("%.0f°", fmgc.FMGCInternal.gndTemp)); - me["Simple_R6"].setFontSize(small); - } else { + if (fmgc.FMGCInternal.phase == 0) { if (fmgc.FMGCInternal.gndTempSet) { + me["Simple_R6"].setText(sprintf("%.0f°", fmgc.FMGCInternal.gndTemp)); me["Simple_R6"].setFontSize(normal); + } else if (fmgc.FMGCInternal.toFromSet) { + fmgc.FMGCInternal.gndTemp = 15 - (2 * (fmgc.flightPlanController.flightplans[2].departure.elevation * 3.28084) / 1000); + me["Simple_R6"].setText(sprintf("%.0f°", fmgc.FMGCInternal.gndTemp)); + me["Simple_R6"].setFontSize(small); } else { + me["Simple_R6"].setText(sprintf("%.0f°", fmgc.FMGCInternal.gndTemp)); me["Simple_R6"].setFontSize(small); } - me["Simple_R6"].setText(sprintf("%.0f°", fmgc.FMGCInternal.gndTemp)); + } else { + me["Simple_R6"].setText("---"); + me["Simple_R6"].setFontSize(small); } - me["Simple_L1S"].setText("CO RTE"); - me["Simple_L2S"].setText("ALTN/CO RTE"); - me["Simple_L3S"].setText("FLT NBR"); - me["Simple_L5S"].setText("COST INDEX"); - me["Simple_L6S"].setText("CRZ FL/TEMP"); #me["Simple_L1"].setText("NONE"); # manage before (coRoute) me["Simple_L3"].setText(sprintf("%s", fmgc.FMGCInternal.flightNum)); - me["Simple_R1S"].setText("FROM/TO "); - me["Simple_R2S"].setText("INIT "); - me["Simple_R5S"].setText("TROPO"); me["Simple_R1"].setText(sprintf("%s", fmgc.FMGCInternal.depApt ~ "/" ~ fmgc.FMGCInternal.arrApt)); - me["Simple_R2"].setText("REQUEST "); - me["Simple_R3"].setText("IRS INIT "); - me["Simple_R4"].setText("WIND "); me["Simple_R5"].setText(sprintf("%5.0f", fmgc.FMGCInternal.tropo)); } else if (page == "IRSINIT") { if (!pageSwitch[i].getBoolValue()) { @@ -3189,9 +3197,9 @@ var canvas_MCDU_base = { degrees = getprop("/FMGC/internal/align-ref-lat-degrees"); minutes = getprop("/FMGC/internal/align-ref-lat-minutes"); sign = getprop("/FMGC/internal/align-ref-lat-sign"); - dms_lat = getprop("/FMGC/flightplan[2]/wp[0]/lat"); - degrees_lat = int(dms_lat); - minutes_lat = sprintf("%.1f",abs((dms_lat - degrees_lat) * 60)); + apt = airportinfo(fmgc.FMGCInternal.depApt); + degrees_lat = int(apt.lat); + minutes_lat = sprintf("%.1f",abs((apt.lat - degrees_lat) * 60)); sign_lat = degrees_lat >= 0 ? "N" : "S"; lat_same = degrees_lat == degrees and minutes_lat == minutes and sign_lat == sign; me["Simple_L1"].setText(abs(sprintf("%.0f", degrees)) ~ "°" ~ sprintf("%.1f", minutes) ~ sign); @@ -3199,15 +3207,14 @@ var canvas_MCDU_base = { degrees = getprop("/FMGC/internal/align-ref-long-degrees"); minutes = getprop("/FMGC/internal/align-ref-long-minutes"); sign = getprop("/FMGC/internal/align-ref-long-sign"); - dms_long = getprop("/FMGC/flightplan[2]/wp[0]/lon"); - degrees_long = int(dms_long); - minutes_long = sprintf("%.1f",abs((dms_long - degrees_long) * 60)); + degrees_long = int(apt.lon); + minutes_long = sprintf("%.1f",abs((apt.lon - degrees_long) * 60)); sign_long = degrees_long >= 0 ? "E" : "W"; long_same = degrees_long == degrees and minutes_long == minutes and sign_long == sign; me["Simple_R1"].setText(abs(sprintf("%.0f", degrees)) ~ "°" ~ sprintf("%.1f", minutes) ~ sign); if (lat_same and long_same) { - me["Simple_C1"].setText(getprop("/FMGC/flightplan[2]/wp[0]/id")); + me["Simple_C1"].setText(getprop("/autopilot/route-manager/route/wp[0]/id")); me["Simple_C1"].setColor(GREEN); } else { me["Simple_C1"].setText("----"); @@ -3837,18 +3844,6 @@ var canvas_MCDU_base = { me["Simple_L2"].setText(fmgc.FMGCInternal.altAirport); } - me["Simple_L1S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_L3S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_L4S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_L5S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_L6S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_C1S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_R1S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_R3S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_R4S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_R5S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_R6S"].setFont("HoneywellMCDUSmall.ttf"); - me["Simple_L1S"].setText("AT"); me["Simple_L3S"].setText("RTE RSV/%"); me["Simple_L4S"].setText("ALTN /TIME"); diff --git a/Models/Instruments/ND/canvas/map/RTE.lcontroller b/Models/Instruments/ND/canvas/map/RTE.lcontroller index 42343196..4e22ea44 100644 --- a/Models/Instruments/ND/canvas/map/RTE.lcontroller +++ b/Models/Instruments/ND/canvas/map/RTE.lcontroller @@ -12,9 +12,9 @@ SymbolLayer.add(name, { type: name, # Symbol type df_controller: __self__, # controller to use by default -- this one df_options: { # default configuration options - active_node: "/FMGC/flightplan[2]/active", - current_wp_node: "/FMGC/flightplan[2]/current-wp", - wp_num: "/FMGC/flightplan[2]/num", + active_node: "/autopilot/route-manager/active", + current_wp_node: "/autopilot/route-manager/current-wp", + wp_num: "/autopilot/route-manager/route/num", display_inactive_rte: 0 } }); diff --git a/Models/Instruments/ND/canvas/map/WPT-airbus.symbol b/Models/Instruments/ND/canvas/map/WPT-airbus.symbol index 8320f312..472dd1a2 100644 --- a/Models/Instruments/ND/canvas/map/WPT-airbus.symbol +++ b/Models/Instruments/ND/canvas/map/WPT-airbus.symbol @@ -79,7 +79,7 @@ var init = func { } var draw = func{ - if (me.model.wp.hidden == 1 or me.model.name == "(DECEL)" or me.model.name == "(T/C)" or me.model.name == "(T/D)" or me.model.name == "(LIM)") { + if (me.model.wp.hidden == 1) { me.wp_sym.hide(); me.text_wps.hide(); if (me.text_alt != nil) { diff --git a/Models/Instruments/ND/canvas/style.nas b/Models/Instruments/ND/canvas/style.nas index 00d2f78d..b6cc371c 100644 --- a/Models/Instruments/ND/canvas/style.nas +++ b/Models/Instruments/ND/canvas/style.nas @@ -56,12 +56,12 @@ canvas.NDStyles["Airbus"] = { # that the lateral flight mode is managed. # You can easily override these options before creating the ND, example: # canvas.NDStyles["Airbus"].options.defaults.fplan_active = "my/autpilot/f-plan/active" - fplan_active: "/FMGC/flightplan[2]/active", + fplan_active: "/autopilot/route-manager/active", lat_ctrl: "/it-autoflight/output/lat", managed_val: 1, ver_ctrl: "/it-autoflight/output/vert", spd_ctrl: "/it-autoflight/input/spd-managed", - current_wp: "/FMGC/flightplan[2]/current-wp", + current_wp: "/autopilot/route-manager/current-wp", ap1: "/it-autoflight/output/ap1", ap2: "/it-autoflight/output/ap2", nav1_frq: "/instrumentation/nav[0]/frequencies/selected-mhz", @@ -72,7 +72,7 @@ canvas.NDStyles["Airbus"] = { adf2_frq: "/instrumentation/adf[1]/frequencies/selected-khz", dep_rwy: "/autopilot/route-manager/departure/runway", dest_rwy: "/autopilot/route-manager/destination/runway", - wp_count: "/FMGC/flightplan[2]/num", + wp_count: "/autopilot/route-manager/route/num", level_off_alt: "/autopilot/route-manager/vnav/level-off-alt", athr: "/it-autoflight/output/athr", app_mode: "/instrumentation/nd/app-mode", @@ -593,7 +593,7 @@ canvas.NDStyles["Airbus"] = { { name: "DECEL", isMapStructure: 1, - update_on: ["toggle_display_mode","toggle_range"], + update_on: [ {rate_hz: 1}, "toggle_display_mode","toggle_range"], predicate: func(nd, layer) { var visible = nd.in_mode("toggle_display_mode", ["MAP", "PLAN"]) and (nd.adirs_property.getValue() == 1 or (adirs_3.getValue() == 1 and att_switch.getValue() == nd.attitude_heading_setting)) and getprop("/instrumentation/nd/symbols/decel/show"); layer.group.setVisible( visible ); @@ -806,11 +806,10 @@ canvas.NDStyles["Airbus"] = { id: "wpActiveId", impl: { init: func(nd,symbol), - predicate: func(nd) getprop("/FMGC/flightplan[2]/current-leg") != nil and - getprop("/FMGC/flightplan[2]/active") and + predicate: func(nd) getprop("/autopilot/route-manager/wp[0]/id") != nil and getprop("/autopilot/route-manager/active") and nd.in_mode("toggle_display_mode", ["MAP", "PLAN"]) and (nd.adirs_property.getValue() == 1 or (adirs_3.getValue() == 1 and att_switch.getValue() == nd.attitude_heading_setting)), is_true: func(nd) { - nd.symbols.wpActiveId.setText(getprop("/FMGC/flightplan[2]/current-leg")); + nd.symbols.wpActiveId.setText(getprop("/autopilot/route-manager/wp[0]/id")); nd.symbols.wpActiveId.show(); }, is_false: func(nd) nd.symbols.wpActiveId.hide(), @@ -820,16 +819,14 @@ canvas.NDStyles["Airbus"] = { id: "wpActiveCrs", impl: { init: func(nd,symbol), - predicate: func(nd) getprop("/FMGC/flightplan[2]/current-leg") != nil and - getprop("/FMGC/flightplan[2]/active") and + predicate: func(nd) getprop("/autopilot/route-manager/wp[0]/id") != nil and getprop("/autopilot/route-manager/active") and nd.in_mode("toggle_display_mode", ["MAP", "PLAN"]) and (nd.adirs_property.getValue() == 1 or (adirs_3.getValue() == 1 and att_switch.getValue() == nd.attitude_heading_setting)), is_true: func(nd) { - #var cur_wp = getprop("/autopilot/route-manager/current-wp"); var deg = nil; if (nd.get_switch("toggle_true_north")) { - var deg = math.round(getprop("/FMGC/flightplan[2]/current-leg-course")) or 0; + var deg = math.round(getprop("/autopilot/route-manager/wp[0]/true-bearing-deg") or 0); } else { - var deg = math.round(getprop("/FMGC/flightplan[2]/current-leg-course-mag")) or 0; + var deg = math.round(getprop("/autopilot/route-manager/wp[0]/bearing-deg") or 0); } if (deg != nil) { nd.symbols.wpActiveCrs.setText(sprintf("%03.0f°", deg)); @@ -845,13 +842,11 @@ canvas.NDStyles["Airbus"] = { id: "wpActiveDist", impl: { init: func(nd,symbol), - predicate: func(nd) (getprop("/FMGC/flightplan[2]/current-leg-dist") != nil and - getprop("/FMGC/flightplan[2]/active") and + predicate: func(nd) (getprop("/autopilot/route-manager/wp[0]/dist") != nil and getprop("/autopilot/route-manager/active") and nd.in_mode("toggle_display_mode", ["MAP", "PLAN"]) and (nd.adirs_property.getValue() == 1 or (adirs_3.getValue() == 1 and att_switch.getValue() == nd.attitude_heading_setting))), is_true: func(nd) { - var dst = getprop("/FMGC/flightplan[2]/current-leg-dist"); - nd.symbols.wpActiveDist.setText(sprintf("%3.01f",dst)); + nd.symbols.wpActiveDist.setText(sprintf("%3.01f", getprop("/autopilot/route-manager/wp[0]/dist"))); nd.symbols.wpActiveDist.show(); }, is_false: func(nd) nd.symbols.wpActiveDist.hide(), @@ -861,11 +856,11 @@ canvas.NDStyles["Airbus"] = { id: "wpActiveDistLbl", impl: { init: func(nd,symbol), - predicate: func(nd) getprop("/FMGC/flightplan[2]/current-leg-dist") != nil and getprop("/FMGC/flightplan[2]/active") and nd.in_mode("toggle_display_mode", ["MAP", "PLAN"]) - and (nd.adirs_property.getValue() == 1 or (adirs_3.getValue() == 1 and att_switch.getValue() == nd.attitude_heading_setting)), + predicate: func(nd) getprop("/autopilot/route-manager/wp[0]/dist") != nil and getprop("/autopilot/route-manager/active") and + nd.in_mode("toggle_display_mode", ["MAP", "PLAN"]) and (nd.adirs_property.getValue() == 1 or (adirs_3.getValue() == 1 and att_switch.getValue() == nd.attitude_heading_setting)), is_true: func(nd) { nd.symbols.wpActiveDistLbl.show(); - if(getprop("/FMGC/flightplan[2]/current-leg-dist") > 1000) + if(getprop("/autopilot/route-manager/wp[0]/dist") > 1000) nd.symbols.wpActiveDistLbl.setText(" NM"); }, is_false: func(nd) nd.symbols.wpActiveDistLbl.hide(), @@ -875,8 +870,8 @@ canvas.NDStyles["Airbus"] = { id: "eta", impl: { init: func(nd,symbol), - predicate: func(nd) getprop("/autopilot/route-manager/wp/eta") != nil and getprop("/FMGC/flightplan[2]/active") and nd.in_mode("toggle_display_mode", ["MAP", "PLAN"]) - and (nd.adirs_property.getValue() == 1 or (adirs_3.getValue() == 1 and att_switch.getValue() == nd.attitude_heading_setting)), + predicate: func(nd) getprop("/autopilot/route-manager/wp/eta") != nil and getprop("/autopilot/route-manager/active") + and nd.in_mode("toggle_display_mode", ["MAP", "PLAN"]) and (nd.adirs_property.getValue() == 1 or (adirs_3.getValue() == 1 and att_switch.getValue() == nd.attitude_heading_setting)), is_true: func(nd) { var etaSec = getprop("/sim/time/utc/day-seconds")+ getprop("/autopilot/route-manager/wp/eta-seconds"); @@ -1904,7 +1899,7 @@ canvas.NDStyles["Airbus"] = { init: func(nd,symbol), predicate: func(nd) (nd.get_switch("toggle_display_mode") == "MAP" and !nd.get_switch("toggle_centered")), is_true: func(nd){ - var active = getprop("/FMGC/flightplan[2]/active"); + var active = getprop("/autopilot/route-manager/active"); var lat_ctrl = getprop(nd.options.defaults.lat_ctrl); var managed_v = nd.options.defaults.managed_val; var is_managed = (lat_ctrl == managed_v); @@ -1933,7 +1928,7 @@ canvas.NDStyles["Airbus"] = { init: func(nd,symbol), predicate: func(nd) (nd.get_switch("toggle_display_mode") == "MAP" and !nd.get_switch("toggle_centered")), is_true: func(nd){ - var active = getprop("/FMGC/flightplan[2]/active"); + var active = getprop("/autopilot/route-manager/active"); var lat_ctrl = getprop(nd.options.defaults.lat_ctrl); var managed_v = nd.options.defaults.managed_val; var is_managed = (lat_ctrl == managed_v); @@ -1962,7 +1957,7 @@ canvas.NDStyles["Airbus"] = { init: func(nd,symbol), predicate: func(nd) (nd.get_switch("toggle_display_mode") == "MAP" and nd.get_switch("toggle_centered")), is_true: func(nd){ - var active = getprop("/FMGC/flightplan[2]/active"); + var active = getprop("/autopilot/route-manager/active"); var lat_ctrl = getprop(nd.options.defaults.lat_ctrl); var managed_v = nd.options.defaults.managed_val; var is_managed = (lat_ctrl == managed_v); @@ -1991,7 +1986,7 @@ canvas.NDStyles["Airbus"] = { init: func(nd,symbol), predicate: func(nd) (nd.get_switch("toggle_display_mode") == "MAP" and nd.get_switch("toggle_centered")), is_true: func(nd){ - var active = getprop("/FMGC/flightplan[2]/active"); + var active = getprop("/autopilot/route-manager/active"); var lat_ctrl = getprop(nd.options.defaults.lat_ctrl); var managed_v = nd.options.defaults.managed_val; var is_managed = (lat_ctrl == managed_v); @@ -2020,7 +2015,7 @@ canvas.NDStyles["Airbus"] = { init: func(nd,symbol), predicate: func(nd) (nd.in_mode("toggle_display_mode", ["MAP", "PLAN"])), is_true: func(nd){ - var active = getprop("/FMGC/flightplan[2]/active"); + var active = getprop("/autopilot/route-manager/active"); var lat_ctrl = getprop(nd.options.defaults.lat_ctrl); var managed_v = nd.options.defaults.managed_val; var is_managed = (lat_ctrl == managed_v); diff --git a/Models/Instruments/PFD/PFD.nas b/Models/Instruments/PFD/PFD.nas index b1d87283..7db0395d 100644 --- a/Models/Instruments/PFD/PFD.nas +++ b/Models/Instruments/PFD/PFD.nas @@ -1702,7 +1702,7 @@ var canvas_pfd = { } notification.radioNo = fmgc.FMGCInternal.radioNo; - if (fmgc.FMGCInternal.phase < 3 or fmgc.flightPlanController.arrivalDist >= 250) { + if (fmgc.FMGCInternal.phase < 3 or fmgc.flightPlanController.arrivalDist.getValue() >= 250) { notification.showDecisionHeight = 0; } else { notification.showDecisionHeight = 1; diff --git a/Nasal/FMGC/FCU.nas b/Nasal/FMGC/FCU.nas index 7465109c..92d7d427 100644 --- a/Nasal/FMGC/FCU.nas +++ b/Nasal/FMGC/FCU.nas @@ -294,7 +294,10 @@ var FCUController = { HDGPush: func() { if (me.FCUworking) { if (fmgc.Output.fd1.getBoolValue() or fmgc.Output.fd2.getBoolValue() or fmgc.Output.ap1.getBoolValue() or fmgc.Output.ap2.getBoolValue()) { - fmgc.Input.lat.setValue(1); + var wp = fmgc.flightPlanController.flightplans[2].getWP(fmgc.flightPlanController.currentToWptIndex.getValue()); + if (wp != nil and wp.wp_type != "discontinuity" and wp.wp_type != "vectors") { + fmgc.Input.lat.setValue(1); + } } } }, diff --git a/Nasal/FMGC/FMGC-b.nas b/Nasal/FMGC/FMGC-b.nas index 5ae91693..713c99f6 100644 --- a/Nasal/FMGC/FMGC-b.nas +++ b/Nasal/FMGC/FMGC-b.nas @@ -14,21 +14,21 @@ var Controls = { }; var FPLN = { - active: props.globals.getNode("/FMGC/flightplan[2]/active", 1), + active: props.globals.getNode("/autopilot/route-manager/active", 1), activeTemp: 0, currentCourse: 0, - currentWp: props.globals.getNode("/FMGC/flightplan[2]/current-wp", 1), - currentWpTemp: 0, + currentWP: props.globals.getNode("/autopilot/route-manager/current-wp", 1), + currentWPTemp: 0, deltaAngle: 0, deltaAngleRad: 0, distCoeff: 0, maxBank: 0, maxBankLimit: 0, nextCourse: 0, - R: 0, radius: 0, + R: 0, turnDist: 0, - wp0Dist: props.globals.getNode("/FMGC/flightplan[2]/current-leg-dist", 1), + wp0Dist: props.globals.getNode("/autopilot/route-manager/wp[0]/dist", 1), wpFlyFrom: 0, wpFlyTo: 0, }; @@ -367,26 +367,21 @@ var ITAF = { slowLoop: func() { Velocities.trueAirspeedKtTemp = Velocities.trueAirspeedKt.getValue(); FPLN.activeTemp = FPLN.active.getValue(); - FPLN.currentWpTemp = FPLN.currentWp.getValue(); + FPLN.currentWPTemp = FPLN.currentWP.getValue(); # If in LNAV mode and route is not longer active, switch to HDG HLD if (Output.lat.getValue() == 1) { # Only evaulate the rest of the condition if we are in LNAV mode - if (flightPlanController.num[2].getValue() == 0 or !FPLN.active.getBoolValue()) { + if (flightPlanController.num[2].getValue() == 0 or !FPLN.activeTemp) { me.setLatMode(3); } } # Waypoint Advance Logic - if (flightPlanController.num[2].getValue() > 0 and FPLN.activeTemp == 1) { - if ((FPLN.currentWpTemp + 1) < flightPlanController.num[2].getValue()) { - Velocities.groundspeedMps = Velocities.groundspeedKt.getValue() * 0.5144444444444; - FPLN.wpFlyFrom = FPLN.currentWpTemp; - if (FPLN.wpFlyFrom < 0) { - FPLN.wpFlyFrom = 0; - } - FPLN.currentCourse = fmgc.wpCourse[2][FPLN.wpFlyFrom].getValue(); - FPLN.wpFlyTo = FPLN.currentWpTemp + 1; - FPLN.nextCourse = fmgc.wpCourse[2][FPLN.wpFlyTo].getValue(); + if (flightPlanController.num[2].getValue() > 0 and FPLN.activeTemp == 1 and FPLN.currentWPTemp != -1) { + if ((FPLN.currentWPTemp + 1) < flightPlanController.num[2].getValue()) { + Velocities.groundspeedMps = pts.Velocities.groundspeed.getValue() * 0.5144444444444; + FPLN.currentCourse = getprop("/autopilot/route-manager/route/wp[" ~ FPLN.currentWPTemp ~ "]/leg-bearing-true-deg"); + FPLN.nextCourse = getprop("/autopilot/route-manager/route/wp[" ~ (FPLN.currentWPTemp + 1) ~ "]/leg-bearing-true-deg"); FPLN.maxBankLimit = Internal.bankLimit.getValue(); FPLN.deltaAngle = math.abs(geo.normdeg180(FPLN.currentCourse - FPLN.nextCourse)); @@ -405,11 +400,17 @@ var ITAF = { if (Gear.wow0.getBoolValue() and FPLN.turnDist < 1) { FPLN.turnDist = 1; } - Internal.lnavAdvanceNm.setValue(FPLN.turnDist); - if (FPLN.wp0Dist.getValue() <= FPLN.turnDist and !Gear.wow1.getBoolValue() and fmgc.flightPlanController.flightplans[2].getWP(FPLN.currentWpTemp).fly_type == "flyBy") { + # This is removed because sequencing is done by the flightplan controller + # Internal.lnavAdvanceNm.setValue(FPLN.turnDist); + + # TODO - if the waypoint is the DEST waypoint, crosstrack error must be less than 0.5nm and course error less than 30 deg + # TODO - if in HDG mode, if no distance, then crosstrack error must be less than 5nm + # TODO - if in nav, no distance condition applies, but DEST course error must be less than 30 (CONFIRM) + + if (abs(FPLN.deltaAngle) < 120 and FPLN.wp0Dist.getValue() <= FPLN.turnDist and !Gear.wow1.getBoolValue() and fmgc.flightPlanController.flightplans[2].getWP(FPLN.currentWPTemp).fly_type == "flyBy") { flightPlanController.autoSequencing(); - } elsif (FPLN.wp0Dist.getValue() <= 0.15) { + } elsif (FPLN.wp0Dist.getValue() <= 0.15 and !Gear.wow1.getBoolValue()) { flightPlanController.autoSequencing(); } } @@ -961,6 +962,12 @@ var ITAF = { }, }; +setlistener(Gear.wow1, func(val) { + if (!val.getBoolValue() and FPLN.currentWP.getValue() == 0) { + flightPlanController.autoSequencing(); + } +}); + setlistener("/it-autoflight/input/ap1", func() { Input.ap1Temp = Input.ap1.getBoolValue(); if (Input.ap1Temp != Output.ap1.getBoolValue()) { diff --git a/Nasal/FMGC/FMGC.nas b/Nasal/FMGC/FMGC.nas index befbbe94..9ba21edd 100644 --- a/Nasal/FMGC/FMGC.nas +++ b/Nasal/FMGC/FMGC.nas @@ -29,6 +29,8 @@ var mng_alt_spd = 0; var mng_alt_mach = 0; var altsel = 0; var crzFl = 0; +var xtrkError = 0; +var courseDistanceDecel = 0; var windHdg = 0; var windSpeed = 0; var windsDidChange = 0; @@ -444,7 +446,7 @@ var updateFuel = func { if (FMGCInternal.toFromSet and FMGCInternal.crzSet and FMGCInternal.crzTempSet and FMGCInternal.zfwSet) { crz = FMGCInternal.crzFl; temp = FMGCInternal.crzTemp; - dist = flightPlanController.arrivalDist; + dist = flightPlanController.arrivalDist.getValue(); trpWind = FMGCInternal.tripWind; wind_value = FMGCInternal.tripWindValue; @@ -458,7 +460,7 @@ var updateFuel = func { trip_fuel = math.clamp(trip_fuel, 400, 80000); # cruize temp correction - trip_fuel = trip_fuel + (0.033 * (temp - 15 + (2 * crz / 10)) * flightPlanController.arrivalDist); + trip_fuel = trip_fuel + (0.033 * (temp - 15 + (2 * crz / 10)) * flightPlanController.arrivalDist.getValue()); trip_time = 9.095e-02 + (dist*-3.968e-02) + (dist*dist*4.302e-04) + (dist*dist*dist*2.005e-07) + (dist*dist*dist*dist*-6.876e-11) + (dist*dist*dist*dist*dist*1.432e-14) + (dist*dist*dist*dist*dist*dist*-1.177e-18) + (crz*7.348e-01) + (dist*crz*3.310e-03) + (dist*dist*crz*-8.700e-06) + (dist*dist*dist*crz*-4.214e-10) + (dist*dist*dist*dist*crz*5.652e-14) + (dist*dist*dist*dist*dist*crz*-6.379e-18) + (crz*crz*-1.449e-02) + (dist*crz*crz*-7.508e-06) + (dist*dist*crz*crz*4.529e-08) + (dist*dist*dist*crz*crz*3.699e-13) + (dist*dist*dist*dist*crz*crz*8.466e-18) + (crz*crz*crz*1.108e-04) + (dist*crz*crz*crz*-4.126e-08) + (dist*dist*crz*crz*crz*-9.645e-11) + (dist*dist*dist*crz*crz*crz*-1.544e-16) + (crz*crz*crz*crz*-4.123e-07) + (dist*crz*crz*crz*crz*1.831e-10) + (dist*dist*crz*crz*crz*crz*7.438e-14) + (crz*crz*crz*crz*crz*7.546e-10) + (dist*crz*crz*crz*crz*crz*-1.921e-13) + (crz*crz*crz*crz*crz*crz*-5.453e-13); trip_time = math.clamp(trip_time, 10, 480); @@ -643,12 +645,12 @@ var masterFMGC = maketimer(0.2, func { } } elsif (FMGCInternal.phase == 3) { if (FMGCInternal.crzFl >= 200) { - if ((flightPlanController.arrivalDist <= 200 and altSel < 20000)) { + if ((flightPlanController.arrivalDist.getValue() <= 200 or altSel < 20000)) { newphase = 4; systems.PNEU.pressMode.setValue("DE"); } } else { - if ((flightPlanController.arrivalDist <= 200 and altSel < (FMGCInternal.crzFl * 100))) { # todo - not sure about crzFl condition, investigate what happens! + if ((flightPlanController.arrivalDist.getValue() <= 200 or altSel < (FMGCInternal.crzFl * 100))) { # todo - not sure about crzFl condition, investigate what happens! newphase = 4; systems.PNEU.pressMode.setValue("DE"); } @@ -668,11 +670,18 @@ var masterFMGC = maketimer(0.2, func { newphase = 2; } } + + xtrkError = getprop("/instrumentation/gps/wp/wp[1]/course-error-nm"); - if (flightPlanController.num[2].getValue() > 0 and getprop("/FMGC/flightplan[2]/active") == 1 and - flightPlanController.arrivalDist <= 15 and (Modes.PFD.FMA.rollMode == "NAV" or Modes.PFD.FMA.rollMode == "LOC" or Modes.PFD.FMA.rollMode == "LOC*") and pts.Position.gearAglFt.getValue() < 9500) { #todo decel pseudo waypoint - FMGCInternal.decel = 1; - } elsif (FMGCInternal.decel and (FMGCInternal.phase == 0 or FMGCInternal.phase == 6)) { + if (flightPlanController.decelPoint != nil) { + courseDistanceDecel = courseAndDistance(flightPlanController.decelPoint.lat, flightPlanController.decelPoint.lon); + if (flightPlanController.num[2].getValue() > 0 and fmgc.flightPlanController.active.getBoolValue() and flightPlanController.decelPoint != nil and (courseDistanceDecel[1] <= 5 and (math.abs(courseDistanceDecel[0] - pts.Orientation.heading.getValue()) >= 90 and xtrkError <= 5) or courseDistanceDecel[1] <= 0.1) and (Modes.PFD.FMA.rollMode == "NAV" or Modes.PFD.FMA.rollMode == "LOC" or Modes.PFD.FMA.rollMode == "LOC*") and pts.Position.gearAglFt.getValue() < 9500) { + FMGCInternal.decel = 1; + setprop("/instrumentation/nd/symbols/decel/show", 0); + } elsif (FMGCInternal.decel and (FMGCInternal.phase == 0 or FMGCInternal.phase == 6)) { + FMGCInternal.decel = 0; + } + } else { FMGCInternal.decel = 0; } diff --git a/Nasal/FMGC/flightplan-delegates.nas b/Nasal/FMGC/flightplan-delegates.nas new file mode 100644 index 00000000..553e45fe --- /dev/null +++ b/Nasal/FMGC/flightplan-delegates.nas @@ -0,0 +1,311 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# NOTE! This copyright does *not* cover user models that use these Nasal +# services by normal function calls - this is merely considered normal use +# of the code, and does *not* fall under the heading of "derived work." +# +# Copyright (C) 2012-202 by James Turner + +# route_manager.nas - FlightPlan delegate(s) corresponding to the built- +# in route-manager dialog and GPS. Intended to provide a sensible default behaviour, +# but can be disabled by an aircraft-specific FMS / GPS system. + +# This delegate corresponds to functionality of the built-in route-manager dialog. +# if you disable it, the built-in route-manager dialog may not work as expected. +# Especially, this dialog is responsible for building departure, approach and +# arrival waypoints corresponding to the requested SID/STAR/approach, +# and replacing them when the inputs change (eg, user seelcted a different +# destination or STAR while enroute) +# +# You can disable the default GPS behaviour *without* touching this delegate : they are +# kept seperate since this first one is less likely to need changes + + +var A320RouteManagerDelegate = { + new: func(fp) { + var m = { parents: [A320RouteManagerDelegate] }; + + logprint(LOG_INFO, 'creating A320 Route Manager FPDelegate'); + + m.flightplan = fp; + return m; + }, + + departureChanged: func + { + logprint(LOG_INFO, 'saw departure changed'); + me.flightplan.clearWPType('sid'); + if (me.flightplan.departure == nil) + return; + + if (me.flightplan.departure_runway == nil) { + # no runway, only an airport, use that + var wp = createWPFrom(me.flightplan.departure); + wp.wp_role = 'sid'; + me.flightplan.insertWP(wp, 0); + return; + } + # first, insert the runway itself + var wp = createWPFrom(me.flightplan.departure_runway); + wp.wp_role = 'sid'; + me.flightplan.insertWP(wp, 0); + if (me.flightplan.sid == nil) + return; + + # and we have a SID + var sid = me.flightplan.sid; + logprint(LOG_INFO, 'routing via SID ' ~ sid.id); + + var wps = sid.route(me.flightplan.departure_runway, me.flightplan.sid_trans); + var lastWP = wps[-1]; + var foundIdx = -999; + + for (var wptIdx = 0; wptIdx < me.flightplan.getPlanSize(); wptIdx = wptIdx + 1) { + if (me.flightplan.getWP(wptIdx).id == lastWP.id) { + foundIdx = wptIdx; + break; + } + } + + if (foundIdx != -999) { + while (foundIdx > 0) { + me.flightplan.deleteWP(1); + foundIdx -= 1; + } + } + + me.flightplan.insertWaypoints(wps, 1); + }, + + arrivalChanged: func + { + me.flightplan.clearWPType('star'); + me.flightplan.clearWPType('approach'); + if (me.flightplan.destination == nil) + return; + + if (me.flightplan.destination_runway == nil) { + # no runway, only an airport, use that + var wp = createWPFrom(me.flightplan.destination); + wp.wp_role = 'approach'; + me.flightplan.appendWP(wp); + return; + } + + var initialApproachFix = nil; + if (me.flightplan.star != nil) { + logprint(LOG_INFO, 'routing via STAR ' ~ me.flightplan.star.id); + var wps = me.flightplan.star.route(me.flightplan.destination_runway, me.flightplan.star_trans); + if (wps != nil) { + me.flightplan.insertWaypoints(wps, -1); + initialApproachFix = wps[-1]; # final waypoint of STAR + } + } + + if (me.flightplan.approach != nil) { + var wps = nil; + var approachIdent = me.flightplan.approach.id; + + if (me.flightplan.approach_trans != nil) { + # if an approach transition was specified, let's use it explicitly + wps = me.flightplan.approach.route(me.flightplan.destination_runway, me.flightplan.approach_trans); + if (wps == nil) { + logprint(LOG_WARN, "couldn't route approach " ~ approachIdent ~ " based on specified transition:" ~ me.flightplan.approach_trans); + } + } else if (initialApproachFix != nil) { + # no explicit approach transition, let's use the IAF to guess one + wps = me.flightplan.approach.route(me.flightplan.destination_runway, initialApproachFix); + if (wps == nil) { + logprint(LOG_INFO, "couldn't route approach " ~ approachIdent ~ " based on IAF:" ~ initialApproachFix.wp_name); + } + } + + # depending on the order the user selects the approach or STAR, we might get into + # a mess here. If we failed to route so far, just try a direct to the approach + if (wps == nil) { + # route direct + wps = me.flightplan.approach.route(me.flightplan.destination_runway); + } + + if (wps == nil) { + logprint(LOG_WARN, 'routing via approach ' ~ approachIdent ~ ' failed entirely.'); + } else { + me.flightplan.insertWaypoints(wps, -1); + } + } else { + # no approach, just use the runway waypoint + var wp = createWPFrom(me.flightplan.destination_runway); + wp.wp_role = 'approach'; + me.flightplan.appendWP(wp); + } + }, + + cleared: func + { + logprint(LOG_INFO, "saw active flightplan cleared, deactivating"); + # see http://https://code.google.com/p/flightgear-bugs/issues/detail?id=885 + fgcommand("activate-flightplan", props.Node.new({"activate": 0})); + }, + + endOfFlightPlan: func + { + logprint(LOG_INFO, "end of flight-plan, deactivating"); + fgcommand("activate-flightplan", props.Node.new({"activate": 0})); + } +}; + +var GPSPath = "/instrumentation/gps"; + +# this delegate corresponds to the default behaviour of the built-in GPS. +# depending on the real GPS/FMS you are modelling, you probably need to +# replace this with your own. +# +# To do that, just set /autopilot/route-manager/disable-fms to true, which +# will block creation of this delegate. +# +# Of course you are then responsible for many basic FMS functions, such as +# route sequencing and activation +# + +var A320GPSDelegate = { + new: func(fp) { + var m = { parents: [A320GPSDelegate], flightplan:fp, landingCheck:nil }; + + logprint(LOG_INFO, 'creating A320 GPS FPDelegate'); + + # tell the GPS C++ code we will do sequencing ourselves, so it can disable + # its legacy logic for this + + setprop(GPSPath ~ '/config/delegate-sequencing', 1); + + # disable turn anticipation + setprop(GPSPath ~ '/config/enable-fly-by', 0); + + # flyOver maximum distance + setprop(GPSPath ~ '/config/over-flight-arm-distance', 5); + + fp.followLegTrackToFix = 1; + fp.aircraftCategory = 'C'; + + m._modeProp = props.globals.getNode(GPSPath ~ '/mode'); + return m; + }, + + _landingCheckTimeout: func + { + if (pts.Gear.wow[0].getValue() and pts.Velocities.groundspeed.getValue() < 25) { + logprint(LOG_INFO, 'GPS saw speed < 25kts on destination runway, end of route.'); + me.landingCheck.stop(); + # record touch-down time? + me.flightplan.finish(); + } + }, + + _captureCurrentCourse: func + { + setprop(GPSPath ~ "/selected-course-deg", getprop(GPSPath ~ "/desired-course-deg")); + }, + + _selectOBSMode: func + { + setprop(GPSPath ~ "/command", "obs"); + }, + + waypointsChanged: func + { + }, + + activated: func + { + if (!me.flightplan.active) + return; + + logprint(LOG_INFO,'flightplan activated, default GPS to LEG mode'); + setprop(GPSPath ~ "/command", "leg"); + }, + + deactivated: func + { + if (me._modeProp.getValue() == 'leg') { + logprint(LOG_INFO, 'flightplan deactivated, default GPS to OBS mode'); + me._captureCurrentCourse(); + me._selectOBSMode(); + } + }, + + endOfFlightPlan: func + { + if (me._modeProp.getValue() == 'leg') { + logprint(LOG_INFO, 'end of flight-plan, switching GPS to OBS mode'); + me._captureCurrentCourse(); + me._selectOBSMode(); + } + }, + + cleared: func + { + if (!me.flightplan.active) + return; + + if (me._modeProp.getValue() == 'leg') { + logprint(LOG_INFO, 'flight-plan cleared, switching GPS to OBS mode'); + me._captureCurrentCourse(); + me._selectOBSMode(); + } + }, + + sequence: func + { + if (!me.flightplan.active) + return; + + if (me._modeProp.getValue() == 'leg') { + if (me.flightplan.current + 1 >= me.flightplan.numWaypoints()) { + logprint(LOG_INFO, "default GPS sequencing, finishing flightplan"); + me.flightplan.finish(); + } elsif (me.flightplan.nextWP().wp_type != 'discontinuity' and me.flightplan.nextWP().wp_type != 'vectors') { + logprint(LOG_INFO, "default GPS sequencing to next WP"); + me.flightplan.current = me.flightplan.current + 1; + } else { + logprint(LOG_INFO, "default GPS sequencing to next WP (special)"); + fmgc.Input.lat.setValue(3); + if (me.flightplan.nextWP().wp_type == 'vectors') { + me.flightplan.current = me.flightplan.current + 2; + } + } + } else { + # OBS, do nothing + } + }, + + currentWaypointChanged: func + { + if (!me.flightplan.active) + return; + + if (me.landingCheck != nil) { + me.landingCheck.stop(); + me.landingCheck = nil; # delete timer + } + + var active = me.flightplan.currentWP(); + if (active == nil) return; + + var activeRunway = active.runway(); + # this check is needed to avoid problems with circular routes; when + # activating the FP we end up here, and without this check, immediately + # detect that we've 'landed' and finish the FP again. + + if (!pts.Gear.wow[0].getValue() and + (activeRunway != nil) and (me.flightplan.destination_runway != nil) and + (activeRunway.id == me.flightplan.destination_runway.id)) + { + me.landingCheck = maketimer(2.0, me, A320GPSDelegate._landingCheckTimeout); + me.landingCheck.start(); + } + } +}; + +registerFlightPlanDelegate(A320GPSDelegate.new); +registerFlightPlanDelegate(A320RouteManagerDelegate.new); + diff --git a/Nasal/FMGC/flightplan.nas b/Nasal/FMGC/flightplan.nas index 92b27e50..1be9fe10 100644 --- a/Nasal/FMGC/flightplan.nas +++ b/Nasal/FMGC/flightplan.nas @@ -17,50 +17,41 @@ var DEBUG_DISCONT = 0; var magHDG = props.globals.getNode("/orientation/heading-magnetic-deg", 1); var trueHDG = props.globals.getNode("/orientation/heading-deg", 1); -# Props.initNode -var wpID = [[props.globals.initNode("/FMGC/flightplan[0]/wp[0]/id", "", "STRING")], [props.globals.initNode("/FMGC/flightplan[1]/wp[0]/id", "", "STRING")], [props.globals.initNode("/FMGC/flightplan[2]/wp[0]/id", "", "STRING")]]; -var wpLat = [[props.globals.initNode("/FMGC/flightplan[0]/wp[0]/lat", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[1]/wp[0]/lat", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[2]/wp[0]/lat", 0, "DOUBLE")]]; -var wpLon = [[props.globals.initNode("/FMGC/flightplan[0]/wp[0]/lon", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[1]/wp[0]/lon", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[2]/wp[0]/lon", 0, "DOUBLE")]]; -var wpCourse = [[props.globals.initNode("/FMGC/flightplan[0]/wp[0]/course", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[1]/wp[0]/course", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[2]/wp[0]/course", 0, "DOUBLE")]]; -var wpDistance = [[props.globals.initNode("/FMGC/flightplan[0]/wp[0]/distance", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[1]/wp[0]/distance", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[2]/wp[0]/distance", 0, "DOUBLE")]]; -var wpCoursePrev = [[props.globals.initNode("/FMGC/flightplan[0]/wp[0]/course-from-prev", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[1]/wp[0]/course-from-prev", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[2]/wp[0]/course-from-prev", 0, "DOUBLE")]]; -var wpDistancePrev = [[props.globals.initNode("/FMGC/flightplan[0]/wp[0]/distance-from-prev", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[1]/wp[0]/distance-from-prev", 0, "DOUBLE")], [props.globals.initNode("/FMGC/flightplan[2]/wp[0]/distance-from-prev", 0, "DOUBLE")]]; - var flightPlanController = { flightplans: [createFlightplan(), createFlightplan(), createFlightplan(), nil], temporaryFlag: [0, 0], # These flags are only for the main flgiht-plan - active: props.globals.initNode("/FMGC/flightplan[2]/active", 0, "BOOL"), - - changed: props.globals.initNode("/FMGC/flightplan[2]/changed", 0, "BOOL"), + active: props.globals.initNode("/autopilot/route-manager/active", 0, "BOOL"), + changed: props.globals.initNode("/autopilot/route-manager/flightplan-changed", 0, "BOOL"), currentToWpt: nil, # container for the current TO waypoint ghost - currentToWptIndex: props.globals.initNode("/FMGC/flightplan[2]/current-wp", 0, "INT"), + currentToWptIndex: props.globals.initNode("/autopilot/route-manager/current-wp", 1, "INT"), currentToWptIndexTemp: 0, - currentToWptID: props.globals.initNode("/FMGC/flightplan[2]/current-leg", "", "STRING"), - courseToWpt: props.globals.initNode("/FMGC/flightplan[2]/current-leg-course", 0, "DOUBLE"), - courseMagToWpt: props.globals.initNode("/FMGC/flightplan[2]/current-leg-course-mag", 0, "DOUBLE"), - distToWpt: props.globals.initNode("/FMGC/flightplan[2]/current-leg-dist", 0, "DOUBLE"), + currentToWptIndexTemp2: 0, + currentToWptID: props.globals.initNode("/autopilot/route-manager/wp[0]/id", "", "STRING"), + courseToWpt: props.globals.initNode("/autopilot/route-manager/wp[0]/true-bearing-deg", 0, "DOUBLE"), + courseMagToWpt: props.globals.initNode("/autopilot/route-manager/wp[0]/bearing-deg", 0, "DOUBLE"), + distToWpt: props.globals.initNode("/autopilot/route-manager/wp[0]/dist", 0, "DOUBLE"), wptType: nil, wptTypeNoAdvanceDelete: 0, - distanceToDest: [0, 0, 0], - num: [props.globals.initNode("/FMGC/flightplan[0]/num", 0, "INT"), props.globals.initNode("/FMGC/flightplan[1]/num", 0, "INT"), props.globals.initNode("/FMGC/flightplan[2]/num", 0, "INT")], + # Temporary flightplan will use flightplan[0] and flightplan[1] + num: [props.globals.initNode("/FMGC/flightplan[0]/num", 0, "INT"), props.globals.initNode("/FMGC/flightplan[1]/num", 0, "INT"), props.globals.initNode("/autopilot/route-manager/route/num", 0, "INT")], arrivalIndex: [0, 0, 0], - arrivalDist: 0, - _arrivalDist: 0, + arrivalDist: props.globals.getNode("/autopilot/route-manager/distance-remaining-nm"), fromWptTime: nil, fromWptAlt: nil, _timeTemp: nil, _altTemp: nil, + decelPoint: nil, init: func() { me.resetFlightplan(2); me.insertPPOS(2); me.addDiscontinuity(1, 2, 1); - me.currentToWptIndex.setValue(0); me.flightPlanChanged(2); + me.flightplans[2].activate(); }, reset: func() { @@ -69,6 +60,9 @@ var flightPlanController = { me.resetFlightplan(0); me.resetFlightplan(1); me.resetFlightplan(2); + me.decelPoint = nil; + setprop("/instrumentation/nd/symbols/decel/show", 0); + me.flightplans[2].activate(); }, resetFlightplan: func(n) { @@ -80,8 +74,11 @@ var flightPlanController = { mcdu.isNoSid[n] = 0; mcdu.isNoStar[n] = 0; mcdu.isNoVia[n] = 0; + me.arrivalIndex[n] = 0; # reset arrival index calculations }, + oldCurrentWp: 0, + lastSequencedCurrentWP: 0, createTemporaryFlightPlan: func(n) { me.resetFlightplan(n); me.flightplans[n] = me.flightplans[2].clone(); @@ -96,11 +93,16 @@ var flightPlanController = { canvas_mcdu.myAirways[n].updateTmpy(); } fmgc.windController.createTemporaryWinds(n); + + me.oldCurrentWp = FPLN.currentWP.getValue(); + me.flightPlanChanged(n); }, loadFlightPlan: func(path) { - call(func {me.flightplans[3] = createFlightplan(path);}, nil, var err = []); + call(func { + me.flightplans[3] = createFlightplan(path); + }, nil, var err = []); if (size(err) or me.flightplans[3] == nil) { print(err[0]); print("Load failed."); @@ -108,12 +110,12 @@ var flightPlanController = { me.destroyTemporaryFlightPlan(3, 1); }, - destroyTemporaryFlightPlan: func(n, a) { # a = 1 activate, a = 0 erase + destroyTemporaryFlightPlan: func(n, a) { # a = 1 activate, a = 0 erase, s = 0 don't call flightplan changed if (a == 1) { flightPlanTimer.stop(); me.resetFlightplan(2); me.flightplans[2] = me.flightplans[n].clone(); - + me.flightplans[2].activate(); if (n != 3) { if (mcdu.isNoSid[n] == 1) { mcdu.isNoSid[2] = 1; @@ -145,17 +147,30 @@ var flightPlanController = { mcdu.isNoTransArr[2] = 0; } } - me.flightPlanChanged(2); flightPlanTimer.start(); } - if (n == 3) { return; } - me.resetFlightplan(n); + if (n == 3) { + me.flightPlanChanged(n); + return; + } me.temporaryFlag[n] = 0; + me.flightPlanChanged(2); + me.resetFlightplan(n); if (canvas_mcdu.myDirTo[n] != nil) { canvas_mcdu.myDirTo[n].updateTmpy(); } + if (me.DirToIndex != nil) { + me.currentToWptIndex.setValue(me.DirToIndex); + me.DirToIndex = nil; + } + fmgc.windController.destroyTemporaryWinds(n, a); + + if (FPLN.currentWP.getValue() != me.oldCurrentWp) { + FPLN.currentWP.setValue(me.oldCurrentWp); + } + me.flightPlanChanged(n); }, @@ -164,9 +179,8 @@ var flightPlanController = { me.flightplans[plan].departure = airportinfo(dep); me.flightplans[plan].destination = airportinfo(arr); if (plan == 2) { - me.destroyTemporaryFlightPlan(0, 0); - me.destroyTemporaryFlightPlan(1, 0); - me.currentToWptIndex.setValue(0); + if (me.temporaryFlag[0]) { me.destroyTemporaryFlightPlan(0, 0); } + if (me.temporaryFlag[1]) { me.destroyTemporaryFlightPlan(1, 0); } me.arrivalIndex = [0, 0, 0]; # reset arrival index calculations } me.addDiscontinuity(1, plan); @@ -177,7 +191,6 @@ var flightPlanController = { if (canvas_mcdu.myArrival[1] != nil) { canvas_mcdu.myArrival[1].reset(); } if (canvas_mcdu.myDeparture[0] != nil) { canvas_mcdu.myDeparture[0].reset(); } if (canvas_mcdu.myDeparture[1] != nil) { canvas_mcdu.myDeparture[1].reset(); } - #todo if plan = 2, kill any tmpy flightplan me.flightPlanChanged(plan); }, @@ -201,45 +214,31 @@ var flightPlanController = { }, autoSequencing: func() { - me.calculateTimeAltitudeOnSequence(); + if (!me.active.getBoolValue()) { return; } + if (pts.Sim.pause.getBoolValue()) { return; } - # todo setlistener on sim/time/warp to recompute predictions + me.calculateTimeAltitudeOnSequence(); # Advancing logic me.currentToWptIndexTemp = me.currentToWptIndex.getValue(); - if (me.currentToWptIndexTemp < 1) { - me.currentToWptIndex.setValue(1); - } else if (me.num[2].getValue() > 2) { - if (me.currentToWptIndexTemp == 2) { # Clean up after a no-sequence waypoint - me.currentToWptIndex.setValue(1); # MUST be set first - # TODO: Add support for deleting multiple waypoints at once, this will do for now - if (me.temporaryFlag[0] == 1 and wpID[0][0] == wpID[2][0]) { - me.deleteWP(0, 0); - } - if (me.temporaryFlag[1] == 1 and wpID[1][0] == wpID[2][0]) { - me.deleteWP(0, 1); - } - me.deleteWP(0, 2, 0, 1); - if (me.temporaryFlag[0] == 1 and wpID[0][0] == wpID[2][0]) { - me.deleteWP(0, 0); - } - if (me.temporaryFlag[1] == 1 and wpID[1][0] == wpID[2][0]) { - me.deleteWP(0, 1); - } - me.deleteWP(0, 2, 0, 1); - } else { - me.wptType = me.flightplans[2].getWP(me.currentToWptIndexTemp).wp_type; - me.wptTypeNoAdvanceDelete = me.wptType == "radialIntercept" or me.wptType == "vectors" or me.wptType == "dmeIntercept" or me.wptType == "hdgToAlt"; - if (me.wptTypeNoAdvanceDelete) { - me.currentToWptIndex.setValue(2); - } else { - if (me.temporaryFlag[0] == 1 and wpID[0][0] == wpID[2][0]) { - me.deleteWP(0, 0); + # TODO - after sequencing discontinuity, FPLN should show PPOS then DISCONTINUITY + # Clearing that discontinuity is not allowed, you must exit using DIRTO, or else using NAV ARM and overfly + # TODO - triple click - confirm, is it only with DES disengage, or also with the NAV loss? + # TODO - I think that it only goes to VS when in DES mode + + if (me.flightplans[2].getWP(me.currentToWptIndexTemp + 1).wp_type == "discontinuity" or me.flightplans[2].getWP(me.currentToWptIndexTemp + 1).wp_type == "vectors") { + fmgc.Input.lat.setValue(3); + me.currentToWptIndex.setValue(me.currentToWptIndexTemp + 2); + me.lastSequencedCurrentWP = me.currentToWptIndexTemp + 2; + } else { + me.currentToWptIndex.setValue(me.currentToWptIndexTemp + 1); + me.lastSequencedCurrentWP = me.currentToWptIndexTemp + 1; + + if (me.num[2].getValue() > 2 and me.currentToWptIndexTemp >= 1) { + for (var i = 0; i <= 2; i += 1) { + if (i == 2 or me.temporaryFlag[i]) { + me.flightplans[i].getWP(me.currentToWptIndexTemp - 1).hidden = 1; } - if (me.temporaryFlag[1] == 1 and wpID[1][0] == wpID[2][0]) { - me.deleteWP(0, 1); - } - me.deleteWP(0, 2, 0, 1); } } } @@ -262,15 +261,17 @@ var flightPlanController = { # addDiscontinuity - insert discontinuity at passed index # args: index, plan - # index: index to add at - # plan: plan to add to + # index: index to add at + # plan: plan to add to # Check if a discontinuity already exists either immediately before or at that index # If it does, don't add another one # Optional flag DEBUG_DISCONT to disable discontinuities totally addDiscontinuity: func(index, plan, force = 0) { if (DEBUG_DISCONT) { return; } + if (force) { me.flightplans[plan].insertWP(createDiscontinuity(), index); + return; } if (me.flightplans[plan].getWP(index) != nil) { # index is not nil @@ -288,18 +289,15 @@ var flightPlanController = { me.flightplans[plan].insertWP(createDiscontinuity(), index); } } else { # both are nil?? - print("Possible error in discontinuities!"); - me.flightplans[plan].insertWP(createDiscontinuity(), index); + debug.dump("Error in discontinuities; won't try to add one"); } }, # insertTP - insert PPOS waypoint denoted "T-P" at specified index # args: n, index - # n: flightplan to which the PPOS waypoint will be inserted - # index: optional argument, defaults to 1, index which the waypoint will be at. - # Default to one, as direct to will insert TP, then create leg to DIRTO waypoint, then delete waypoint[0] - - insertTP: func(n, index = 1) { + # n: flightplan to which the PPOS waypoint will be inserted + # index: index which the waypoint will be at. + insertTP: func(n, index) { me.flightplans[n].insertWP(createWP(geo.aircraft_position(), "T-P"), index); fmgc.windController.insertWind(n, index, 0, "T-P"); }, @@ -309,13 +307,14 @@ var flightPlanController = { fmgc.windController.insertWind(n, index, 0, "PPOS"); }, + # childWPBearingDistance - return waypoint at bearing and distance from specified waypoint ghost # args: wpt, bearing, dist, name, typeStr - # wpt: waypoint ghost - # bearing: bearing of waypoint to be created from specified waypoint - # distance: distance of waypoint to be created from specified waypoint, nautical miles - # name: name of waypoint to be created - # typeStr: optional argument to be passed to createWP, must be one of "sid", "star" "approach" "missed" or "pseudo" + # wpt: waypoint ghost + # bearing: bearing of waypoint to be created from specified waypoint + # distance: distance of waypoint to be created from specified waypoint, nautical miles + # name: name of waypoint to be created + # typeStr: optional argument to be passed to createWP, must be one of "sid", "star" "approach" "missed" or "pseudo" childWPBearingDistance: func(wpt, bearing, dist) { var coordinates = greatCircleMove(wpt.lat, wpt.lon, num(bearing), num(dist)); @@ -335,7 +334,9 @@ var flightPlanController = { } # fudge the altitude since we cannot create a hdgtoAlt from nasal. Assume 600 feet per mile - 2.5 miles - me.flightplans[n].insertWP(createWP(me.childWPBearingDistance(wptStore, me.flightplans[n].departure_runway.heading, 2.5), "1500", "sid"), 1); + me.flightplans[n].insertWP(createWP(me.childWPBearingDistance(wptStore, me.flightplans[n].departure_runway.heading, 2.5 + (me.flightplans[n].departure_runway.length * M2NM)), "1500", "sid"), 1); + me.flightplans[n].getWP(1).fly_type = "flyOver"; + me.flightplans[n].getWP(1).setAltitude(1500, "at"); fmgc.windController.insertWind(n, 1, 0, "1500"); } me.flightPlanChanged(n); @@ -357,6 +358,7 @@ var flightPlanController = { hdg = hdg - 360; } me.flightplans[n].insertWP(createWP(me.childWPBearingDistance(wptStore, hdg, 5), "CF", "star"), me.arrivalIndex[n]); + me.flightplans[n].getWP(me.arrivalIndex[n]).fly_type = "flyOver"; fmgc.windController.insertWind(n, me.arrivalIndex[n], 0, "CF"); } me.flightPlanChanged(n); @@ -364,8 +366,8 @@ var flightPlanController = { # directTo - create leg direct from present position to a specified waypoint # args: waypointGhost, plan - # waypointGost: waypoint ghost of the waypoint - # plan: plan on which the direct to leg will be created + # waypointGost: waypoint ghost of the waypoint + # plan: plan on which the direct to leg will be created # We first insert a PPOS waypoint at index 1 # We check if the flightplan already contains the waypoint passed to the function # If it exists, we delete intermediate waypoints @@ -373,49 +375,50 @@ var flightPlanController = { # In either case, we delete the current FROM waypoint, index 0, and call flightPlanChanged to recalculate # We attempt to get the distance from the aircraft current position to the chosen waypoint and update mcdu with it + DirToIndex: nil, directTo: func(waypointGhost, plan) { if (me.flightplans[plan].indexOfWP(waypointGhost) == -1) { - me.insertTP(plan, 1); + me.insertTP(plan, me.currentToWptIndex.getValue()); # use createWP here as createWPFrom doesn't accept waypoints # createWPFrom worked before... but be sure! - me.flightplans[plan].insertWP(createWP(waypointGhost, waypointGhost.id), 2); - fmgc.windController.insertWind(plan, 2, 0, waypointGhost.id); - me.addDiscontinuity(3, plan); + me.flightplans[plan].insertWP(createWP(waypointGhost, waypointGhost.id), me.currentToWptIndex.getValue() + 1); + fmgc.windController.insertWind(plan, me.currentToWptIndex.getValue() + 1, 0, waypointGhost.id); + me.addDiscontinuity(me.currentToWptIndex.getValue() + 2, plan); + me.DirToIndex = me.currentToWptIndex.getValue() + 1; } else { - # we want to delete the intermediate waypoints up to but not including the waypoint. Leave index 0, we delete it later. - # example - waypoint dirto is index 5, we want to delete indexes 1 -> 4. 5 - 1 = 4. - # so four individual deletions. Delete index 1 four times. + var indexWP = me.flightplans[plan].indexOfWP(waypointGhost); + me.insertTP(plan, indexWP); + me.deleteTillIndex(waypointGhost, me.currentToWptIndex.getValue(), plan, 1); - var timesToDelete = me.flightplans[plan].indexOfWP(waypointGhost); - while (timesToDelete > 1) { - me.deleteWP(1, plan, 1); - timesToDelete -= 1; - } - # Add TP afterwards, this is essential - me.insertTP(plan, 1); + indexWP = me.flightplans[plan].indexOfWP(waypointGhost); + me.hideTillIndex(indexWP - 2, plan); + me.DirToIndex = indexWP; } var curAircraftPosDirTo = geo.aircraft_position(); - canvas_mcdu.myDirTo[plan].updateDist(me.flightplans[plan].getWP(2).courseAndDistanceFrom(curAircraftPosDirTo)[1]); - me.deleteWP(0, plan); - me.flightPlanChanged(plan); + canvas_mcdu.myDirTo[plan].updateDist(me.flightplans[plan].getWP(me.currentToWptIndex.getValue() + 1).courseAndDistanceFrom(curAircraftPosDirTo)[1]); }, - deleteWP: func(index, n, a = 0, s = 0) { # a = 1, means adding a waypoint via deleting intermediate. s = 1, means autosequencing - var wp = wpID[n][index].getValue(); - if (((s == 0 and left(wp, 4) != FMGCInternal.depApt and left(wp, 4) != FMGCInternal.arrApt) or (s == 1)) and me.flightplans[n].getPlanSize() > 2) { - if (me.flightplans[n].getWP(index).id != "DISCONTINUITY" and a == 0) { # if it is a discont, don't make a new one + deleteWP: func(index, n, a = 0) { # a = 1, means adding a waypoint via deleting intermediate + var wp = me.flightplans[n].getWP(index); + if ((left(wp.wp_name, 4) != FMGCInternal.depApt and left(wp.wp_name, 4) != FMGCInternal.arrApt) and me.flightplans[n].getPlanSize() > 2) { + if (wp.id != "DISCONTINUITY" and a == 0) { # if it is a discont, don't make a new one me.flightplans[n].deleteWP(index); fmgc.windController.deleteWind(n, index); - if (me.flightplans[n].getWP(index) != nil and s == 0) { + if (me.flightplans[n].getWP(index) != nil) { # This refers to the next one after the one we deleted if (me.flightplans[n].getWP(index).id != "DISCONTINUITY") { # else, if the next one isn't a discont, add one me.addDiscontinuity(index, n); } } } else { - me.flightplans[n].deleteWP(index); - fmgc.windController.deleteWind(n, index); + if (wp.id == "DISCONTINUITY" and index > 0 and (me.flightplans[n].getWP(index - 1).id == "PPOS" or find("VECTORS", me.flightplans[n].getWP(index - 1).id) != -1)) { + return 1; + } else { + me.flightplans[n].deleteWP(index); + fmgc.windController.deleteWind(n, index); + } } + me.flightPlanChanged(n); canvas_nd.A3XXRouteDriver.triggerSignal("fp-removed"); return 2; @@ -427,8 +430,8 @@ var flightPlanController = { # deleteTillIndex - helper that deletes waypoints up to a passed waypoint already in flightplan # uses a while loop to delete a certain number of waypoints between passed index and # index of waypoint alredy in flightplan - deleteTillIndex: func(wpGhost, index, plan) { - var numToDel = me.flightplans[plan].indexOfWP(wpGhost) - index; + deleteTillIndex: func(wpGhost, index, plan, offset = 0) { + var numToDel = me.flightplans[plan].indexOfWP(wpGhost) - index - offset; while (numToDel > 0) { me.deleteWP(index, plan, 1); numToDel -= 1; @@ -436,6 +439,15 @@ var flightPlanController = { return 2; }, + hideTillIndex: func(index, plan) { + var numToDel = index; + while (numToDel >= 0) { + me.flightplans[plan].getWP(index - numToDel).hidden = 1; + numToDel -= 1; + } + return 2; + }, + # createDuplicateNames - helper to spawn DUPLICATENAMES page # args: ghostContainer, index, flag, plan # ghostContainer: vector of fgPositioned ghosts @@ -473,7 +485,7 @@ var flightPlanController = { } var indexPresent = me.flightplans[plan].indexOfWP(airport[indexToInsert]); - if (me.flightplans[plan].indexOfWP(airport[indexToInsert]) == -1) { + if (indexPresent == -1 or indexPresent > me.arrivalIndex[plan]) { me.flightplans[plan].insertWP(createWPFrom(airport[indexToInsert]), index); fmgc.windController.insertWind(plan, index, 0, text); me.addDiscontinuity(index + 1, plan); @@ -507,7 +519,7 @@ var flightPlanController = { } var indexPresent = me.flightplans[plan].indexOfWP(fix[indexToInsert]); - if (me.flightplans[plan].indexOfWP(fix[indexToInsert]) == -1) { + if (indexPresent == -1 or indexPresent > me.arrivalIndex[plan]) { me.flightplans[plan].insertWP(createWPFrom(fix[indexToInsert]), index); fmgc.windController.insertWind(plan, index, 1, text); me.addDiscontinuity(index + 1, plan); @@ -541,7 +553,7 @@ var flightPlanController = { } var indexPresent = me.flightplans[plan].indexOfWP(navaid[indexToInsert]); - if (me.flightplans[plan].indexOfWP(navaid[indexToInsert]) == -1) { + if (indexPresent == -1 or indexPresent > me.arrivalIndex[plan]) { me.flightplans[plan].insertWP(createWPFrom(navaid[indexToInsert]), index); fmgc.windController.insertWind(plan, index, 1, text); me.addDiscontinuity(index + 1, plan); @@ -561,7 +573,8 @@ var flightPlanController = { return 1; } - if (me.flightplans[plan].indexOfWP(wpGhost) == -1) { + var indexCurr = me.flightplans[plan].indexOfWP(wpGhost); + if (indexCurr == -1 or indexCurr > me.arrivalIndex[plan]) { # use createWP here as createWPFrom doesn't accept waypoints me.flightplans[plan].insertWP(createWP(wpGhost, wpGhost.wp_name), index); fmgc.windController.insertWind(plan, index, 1, wpGhost.wp_name); @@ -602,13 +615,13 @@ var flightPlanController = { # getWPforPBD - parse scratchpad text to find waypoint ghost for PBD # args: text, index, plan - # text: scratchpad text - # index: index at which waypoint will be inserted - # plan: plan to which waypoint will be inserted + # text: scratchpad text + # index: index at which waypoint will be inserted + # plan: plan to which waypoint will be inserted # return: - # 0: not in database - # 1: notAllowed - # 2: o.k. + # 0: not in database + # 1: notAllowed + # 2: o.k. getWPforPBD: func(text, index, plan, override = 0, overrideIndex = -1) { if (index == 0) { @@ -669,7 +682,6 @@ var flightPlanController = { getNavCount: func(plan) { var count = 0; for (var wpt = 0; wpt < me.flightplans[plan].getPlanSize(); wpt += 1) { - #print(me.flightplans[plan].getWP(wpt).wp_type); if (me.flightplans[plan].getWP(wpt).wp_type == "navaid") { count += 1; } @@ -680,7 +692,6 @@ var flightPlanController = { getDepartureCount: func(plan) { var count = 0; for (var wpt = 0; wpt < me.flightplans[plan].getPlanSize(); wpt += 1) { - #print(me.flightplans[plan].getWP(wpt).wp_role); if (me.flightplans[plan].getWP(wpt).wp_role == "sid") { count += 1; } @@ -698,12 +709,64 @@ var flightPlanController = { return count; }, + getPlanSizeNoDiscont: func(plan) { + var count = 0; + for (var wpt = 0; wpt < me.flightplans[plan].getPlanSize(); wpt += 1) { + if (me.flightplans[plan].getWP(wpt).wp_name != "DISCONTINUITY") { + count += 1; + } + } + return count; + }, + + calculateDecelPoint: func() { + if (me.getPlanSizeNoDiscont(2) <= 1 or fmgc.FMGCInternal.decel) { + setprop("/instrumentation/nd/symbols/decel/show", 0); + return; + } + + me.indexDecel = 0; + for (var wpt = 0; wpt < me.flightplans[2].getPlanSize(); wpt += 1) { + if (me.flightplans[2].getWP(wpt).wp_role == "approach") { + me.indexDecel = wpt; + break; + } + if (wpt == me.flightplans[2].getPlanSize()) { + me.indexDecel = me.arrivalIndex - 2; + break; + } + } + + me.dist = me.flightplans[2].getWP(me.indexDecel).leg_distance - 7; + if (me.dist < 0) { + me.dist = 0.1; + } + me.decelPoint = me.flightplans[2].pathGeod(me.indexDecel - 1, me.dist); + + setprop("/instrumentation/nd/symbols/decel/latitude-deg", me.decelPoint.lat); + setprop("/instrumentation/nd/symbols/decel/longitude-deg", me.decelPoint.lon); + setprop("/instrumentation/nd/symbols/decel/show", 1); + + me.indexTemp = me.indexDecel; + me.distTemp = 7; + + if (me.flightplans[2].getWP(me.indexTemp).leg_distance < 7) { + while (me.distTemp > 0 and me.indexTemp > 0) { + me.distTemp -= me.flightplans[2].getWP(me.indexTemp).leg_distance; + me.indexTemp -= 1; + } + me.indexTemp += 1; + } + + setprop("/instrumentation/nd/symbols/decel/index", me.indexTemp); + }, + # insertPlaceBearingDistance - insert PBD waypoint at specified index, # at some specified bearing, distance from a specified location # args: wp, index, plan - # wpt: waypoint ghost - # index: index to insert at in plan - # plan: plan to insert to + # wpt: waypoint ghost + # index: index to insert at in plan + # plan: plan to insert to insertPlaceBearingDistance: func(wp, bearing, distance, index, plan) { var waypoint = pilotWaypoint.new(me.childWPBearingDistance(wp, bearing, distance), "PBD"); @@ -724,8 +787,18 @@ var flightPlanController = { return 3; } - if (!fmgc.flightPlanController.temporaryFlag[plan]) { + if (index == me.currentToWptIndex.getValue()) { + return 1; + # TODO - implement the PPOS - DISCONT feature + # me.insertPPOS(thePlan, index - 1); + # me.addDiscontinuity(index - 1, thePlan, 1); + } + + if (!me.temporaryFlag[plan]) { if (text == "CLR" and me.flightplans[2].getWP(index).wp_name == "DISCONTINUITY") { + if (me.flightplans[2].getPlanSize() == 3 and me.flightplans[2].departure_runway == nil and me.flightplans[2].destination_runway == nil and index == 1) { + return 1; + } var thePlan = 2; } else { fmgc.flightPlanController.createTemporaryFlightPlan(plan); @@ -735,6 +808,7 @@ var flightPlanController = { var thePlan = plan; } + # check waypoints database here var wpFromDB = WaypointDatabase.getWP(text); if (wpFromDB != nil) { @@ -761,20 +835,9 @@ var flightPlanController = { }, flightPlanChanged: func(n) { - sizeWP = size(wpID[n]); - for (var counter = sizeWP; counter < me.flightplans[n].getPlanSize(); counter += 1) { # create new properties if they are required - append(wpID[n], props.globals.initNode("/FMGC/flightplan[" ~ n ~ "]/wp[" ~ counter ~ "]/text", "", "STRING")); - append(wpLat[n], props.globals.initNode("/FMGC/flightplan[" ~ n ~ "]/wp[" ~ counter ~ "]/lat", 0, "DOUBLE")); - append(wpLon[n], props.globals.initNode("/FMGC/flightplan[" ~ n ~ "]/wp[" ~ counter ~ "]/lon", 0, "DOUBLE")); - append(wpCourse[n], props.globals.initNode("/FMGC/flightplan[" ~ n ~ "]/wp[" ~ counter ~ "]/course", 0, "DOUBLE")); - append(wpDistance[n], props.globals.initNode("/FMGC/flightplan[" ~ n ~ "]/wp[" ~ counter ~ "]/distance", 0, "DOUBLE")); - append(wpCoursePrev[n], props.globals.initNode("/FMGC/flightplan[" ~ n ~ "]/wp[" ~ counter ~ "]/course-from-prev", 0, "DOUBLE")); - append(wpDistancePrev[n], props.globals.initNode("/FMGC/flightplan[" ~ n ~ "]/wp[" ~ counter ~ "]/distance-from-prev", 0, "DOUBLE")); - } - - me.updatePlans(); + me.updatePlans(1); fmgc.windController.updatePlans(); - + # push update to fuel if (fmgc.FMGCInternal.blockConfirmed) { fmgc.FMGCInternal.fuelCalculating = 0; @@ -788,47 +851,36 @@ var flightPlanController = { canvas_nd.A3XXRouteDriver.triggerSignal("fp-added"); }, - updatePlans: func() { - me.updateCurrentWaypoint(); - me._arrivalDist = 0; + # runDecel - used to ensure that only flightplanchanged will update the decel point + updatePlans: func(runDecel = 0) { + if (fmgc.FMGCInternal.toFromSet and me.flightplans[2].departure != nil and me.flightplans[2].destination != nil) { # check if flightplan exists + if (!me.active.getBoolValue()) { + if (me.currentToWptIndex.getValue() < 1) { + var errs = []; + call(func { + if (me.flightplans[2].getWP(1).id != "DISCONTINUITY") { + me.currentToWptIndex.setValue(1); + } + }, nil, nil, nil, errs); + if (size(errs) != 0) { debug.printerror(errs); } + } + me.active.setValue(1); + } + } elsif (me.active.getBoolValue()) { + me.active.setValue(0); + } + + if (me.active.getBoolValue() and me.currentToWptIndex.getValue() == -1) { + me.currentToWptIndex.setValue(me.lastSequencedCurrentWP); + } + for (var n = 0; n <= 2; n += 1) { for (var wpt = 0; wpt < me.flightplans[n].getPlanSize(); wpt += 1) { # Iterate through the waypoints and update their data - var curAircraftPos = geo.aircraft_position(); # don't want to get this corrupted so make sure it is a local variable var waypointHashStore = me.flightplans[n].getWP(wpt); - courseDistanceFrom = waypointHashStore.courseAndDistanceFrom(curAircraftPos); - wpID[n][wpt].setValue(waypointHashStore.wp_name); - wpLat[n][wpt].setValue(waypointHashStore.wp_lat); - wpLon[n][wpt].setValue(waypointHashStore.wp_lon); - - wpCourse[n][wpt].setValue(waypointHashStore.courseAndDistanceFrom(curAircraftPos)[0]); - wpDistance[n][wpt].setValue(waypointHashStore.courseAndDistanceFrom(curAircraftPos)[1]); - - if (wpt == 1) { - if (me.flightplans[n].getWP(wpt).wp_name != "DISCONTINUITY" and me.flightplans[n].getWP(wpt).wp_type != "vectors" and me.flightplans[n].getWP(wpt).wp_type != "hdgToAlt" and wpt <= me.arrivalIndex[n]) { - # print("Adding " ~ courseDistanceFrom[1] ~ " miles for waypoint " ~ me.flightplans[n].getWP(wpt).wp_name); - me._arrivalDist += courseDistanceFrom[1]; # distance to next waypoint, therafter to end of flightplan - } - } - - if (wpt > 0) { - wpCoursePrev[n][wpt].setValue(me.flightplans[n].getWP(wpt).leg_bearing); - wpDistancePrev[n][wpt].setValue(me.flightplans[n].getWP(wpt).leg_distance); - #if (wpt > 1) { - # if (me.flightplans[n].getWP(wpt - 1).wp_name != "DISCONTINUITY" and me.flightplans[n].getWP(wpt).wp_name != "DISCONTINUITY" and me.flightplans[n].getWP(wpt - 1).wp_type != "vectors" and me.flightplans[n].getWP(wpt - 1).wp_type != "hdgToAlt" and me.flightplans[n].getWP(wpt).wp_type != "vectors" and me.flightplans[n].getWP(wpt).wp_type != "hdgToAlt" and wpt <= me.arrivalIndex[n]) { - # me._arrivalDist += courseDistanceFromPrev[1]; - # } - #} - } else { - # use PPOS for the first waypoint - wpCoursePrev[n][wpt].setValue(courseDistanceFrom[0]); - wpDistancePrev[n][wpt].setValue(courseDistanceFrom[1]); - } - - if (left(wpID[n][wpt].getValue(), 4) == fmgc.FMGCInternal.arrApt and wpt != 0) { + if (left(waypointHashStore.wp_name, 4) == fmgc.FMGCInternal.arrApt and wpt != 0) { if (me.arrivalIndex[n] != wpt) { me.arrivalIndex[n] = wpt; - if (canvas_mcdu.myFpln[0] != nil) { canvas_mcdu.myFpln[0].destInfo(); } @@ -837,74 +889,13 @@ var flightPlanController = { } } } - } + } + } + + if (runDecel) { + me.calculateDecelPoint(); } - if (me.flightplans[2].getWP(me.arrivalIndex[2]) == nil or me.flightplans[2].getWP(1) == nil) { - me.arrivalDist = 9999; - #print(me.arrivalIndex[2]); - } else { - me.arrivalDist = me.flightplans[2].getWP(me.arrivalIndex[2]).distance_along_route - me.flightplans[2].getWP(1).leg_distance + me._arrivalDist; - } - - me.updateMCDUDriver(n); - }, - - updateCurrentWaypoint: func() { - for (var india = 0; india <= 2; india += 1) { - if (FMGCInternal.toFromSet and me.flightplans[india].departure != nil and me.flightplans[india].destination != nil) { # check if flightplan exists - var curAircraftPos = geo.aircraft_position(); # don't want to get this corrupted so make sure it is a local variable - - if (india == 2) { # main plan - if (!me.active.getBoolValue()) { - me.active.setValue(1); - } - - if (me.currentToWptIndex.getValue() > me.flightplans[india].getPlanSize()) { - me.currentToWptIndex.setValue(me.flightplans[india].getPlanSize()); - } - - me.currentToWpt = me.flightplans[india].getWP(me.currentToWptIndex.getValue()); - - if (me.currentToWptID.getValue() != me.currentToWpt.wp_name) { - me.currentToWptID.setValue(me.currentToWpt.wp_name); - } - me.courseToWpt.setValue(me.currentToWpt.courseAndDistanceFrom(curAircraftPos)[0]); - me.distToWpt.setValue(me.currentToWpt.courseAndDistanceFrom(curAircraftPos)[1]); - - magTrueError = magHDG.getValue() - trueHDG.getValue(); - - storeCourse = me.courseToWpt.getValue() + magTrueError; - if (storeCourse >= 360) { - storeCourse -= 360; - } elsif (storeCourse < 0) { - storeCourse += 360; - } - - me.courseMagToWpt.setValue(storeCourse); - } - - if (me.num[india].getValue() != me.flightplans[india].getPlanSize()) { - me.num[india].setValue(me.flightplans[india].getPlanSize()); - } - } else { - if (india == 2) { - if (me.active.getBoolValue()) { - me.active.setValue(0); - } - if (me.currentToWptID.getValue() != "") { - me.currentToWptID.setValue(""); - } - } - - if (me.num[india].getValue() != 0) { - me.num[india].setValue(0); - } - } - } - }, - - updateMCDUDriver: func() { for (var i = 0; i <= 1; i += 1) { if (canvas_mcdu.myFpln[i] != nil) { canvas_mcdu.myFpln[i].updatePlan(); @@ -916,4 +907,4 @@ var flightPlanController = { }, }; -var flightPlanTimer = maketimer(0.1, flightPlanController, flightPlanController.updatePlans); +var flightPlanTimer = maketimer(0.1, flightPlanController, flightPlanController.updatePlans); \ No newline at end of file diff --git a/Nasal/Libraries/libraries.nas b/Nasal/Libraries/libraries.nas index 153a1ad9..d6892efc 100644 --- a/Nasal/Libraries/libraries.nas +++ b/Nasal/Libraries/libraries.nas @@ -5,11 +5,13 @@ print("------------------------------------------------"); print("Copyright (c) 2016-2022 Josh Davidson (Octal450)"); print("------------------------------------------------"); +setprop("/autopilot/route-manager/disable-route-manager", 1); +setprop("/autopilot/route-manager/disable-fms", 1); + # Disable specific menubar items setprop("/sim/menubar/default/menu[0]/item[0]/enabled", 0); setprop("/sim/menubar/default/menu[2]/item[0]/enabled", 0); setprop("/sim/menubar/default/menu[2]/item[2]/enabled", 0); -setprop("/sim/menubar/default/menu[3]/enabled", 0); setprop("/sim/menubar/default/menu[5]/item[9]/enabled", 0); setprop("/sim/menubar/default/menu[5]/item[10]/enabled", 0); setprop("/sim/menubar/default/menu[5]/item[11]/enabled", 0); diff --git a/Nasal/MCDU/DIRTO.nas b/Nasal/MCDU/DIRTO.nas index 8fde4c50..ba0194ef 100644 --- a/Nasal/MCDU/DIRTO.nas +++ b/Nasal/MCDU/DIRTO.nas @@ -1,3 +1,6 @@ +# A3XX MCDU Direct To Page +# Copyright (c) 2022 Jonathan Redpath (legoboyvdlp) + var dirToFlag = 0; var dirTo = { @@ -77,16 +80,14 @@ var dirTo = { canvas_mcdu.myFpln[me.computer] = fplnPage.new(2, me.computer); } - var x = 0; + var dirToLeftIndex = 0; me.vector = []; for (var i = 1 + (me.scroll); i < size(canvas_mcdu.myFpln[me.computer].planList) - 2; i = i + 1) { - if (canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "DISCONTINUITY" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "VECTORS" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "T-P" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_type == "hdgToAlt") { continue; } - if (canvas_mcdu.myFpln[me.computer].planList[i].index > fmgc.flightPlanController.arrivalIndex[2]) { - continue; - } + if (canvas_mcdu.myFpln[me.computer].planList[i].wp == "PSEUDO" or canvas_mcdu.myFpln[me.computer].planList[i].wp == "STATIC" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "DISCONTINUITY" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "VECTORS" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_name == "T-P" or canvas_mcdu.myFpln[me.computer].planList[i].wp.wp_type == "hdgToAlt") { continue; } + if (canvas_mcdu.myFpln[me.computer].planList[i].index > fmgc.flightPlanController.arrivalIndex[2]) { continue; } append(me.vector, canvas_mcdu.myFpln[me.computer].planList[i].wp); - x += 1; - if (x == 4) { break; } + dirToLeftIndex += 1; + if (dirToLeftIndex == 4) { break; } } if (size(me.vector) > 0) { diff --git a/Nasal/MCDU/F-PLN.nas b/Nasal/MCDU/F-PLN.nas index 8a1f25b9..9b4d898d 100644 --- a/Nasal/MCDU/F-PLN.nas +++ b/Nasal/MCDU/F-PLN.nas @@ -1,3 +1,22 @@ +# A3XX FMGC Flightplan Page +# Copyright (c) 2022 Josh Davidson (Octal450) and Jonathan Redpath (legoboyvdlp) + +# Local vars +var decelIndex = 0; +var decelShow = 0; +var decelOffset = 0; +var destName = nil; + +var getSubTextFunc = func(meRef) { + var subText = nil; + call(func { + subText = me.wp.wp_owner.id; + }, nil, meRef, nil, + var errs = [] + ); + return nil; +} + var fplnItem = { new: func(wp, index, plan, computer, colour = "grn") { var fI = {parents:[fplnItem]}; @@ -19,10 +38,14 @@ var fplnItem = { if (wptName[0] == "VECTORS") { return ["MANUAL", me.getSubText(), me.colour]; } else { - if (size(wptName) == 2) { - return[wptName[0] ~ wptName[1 ~ (me.wp.fly_type == "flyOver" ? "@" : "")], me.getSubText(), me.colour]; + if (me.wp.fly_type == "Hold") { + return ["HOLD " ~ (me.wp.hold_is_left_handed ? "L" : "R"), me.getSubText(), me.colour]; } else { - return [me.wp.wp_name ~ (me.wp.fly_type == "flyOver" ? "@" : ""), me.getSubText(), me.colour]; + if (size(wptName) == 2) { + return[wptName[0] ~ wptName[1 ~ (me.wp.fly_type == "flyOver" ? "@" : "")], me.getSubText(), me.colour]; + } else { + return [me.wp.wp_name ~ (me.wp.fly_type == "flyOver" ? "@" : ""), me.getSubText(), me.colour]; + } } } } else { @@ -33,7 +56,11 @@ var fplnItem = { } }, getSubText: func() { - return nil; + if (me.wp.wp_parent_name != nil) { + return " " ~ me.wp.wp_parent_name; + } else { + return nil; + } }, updateCenterText: func() { if (me.wp != nil) { @@ -47,9 +74,9 @@ var fplnItem = { } if (me.index == fmgc.flightPlanController.currentToWptIndex.getValue()) { - me.assembledStr[1] = "BRG" ~ me.getBrg() ~ " "; + me.assembledStr[1] = "BRG" ~ me.getBrg() ~ "° "; } elsif (me.index == (fmgc.flightPlanController.currentToWptIndex.getValue() + 1) or me.index == (fmgc.flightPlanController.arrivalIndex[me.plan] + 1)) { - me.assembledStr[1] = "TRK" ~ me.getTrack() ~ " "; + me.assembledStr[1] = "TRK" ~ me.getTrack() ~ "° "; } else { me.assembledStr[1] = nil; } @@ -67,7 +94,6 @@ var fplnItem = { if (me.wp.wp_name != "DISCONTINUITY") { me.spd = me.getSpd(); me.alt = me.getAlt(); - me.dist = me.getDist(); if (me.colour != "yel") { # not temporary flightplan me._colour = "wht"; #if (me.spd[1] != "wht" or me.alt[1] != "wht") { @@ -84,7 +110,7 @@ var fplnItem = { } else { # temporary flightplan me._colour = "yel"; } - return [me.spd[0] ~ "/" ~ me.alt[0], " " ~ me.dist ~ "NM ", me._colour]; + return [me.spd[0] ~ "/" ~ me.alt[0], me.getDist() ~ "NM ", me._colour]; } else { return [nil, nil, "ack"]; } @@ -93,17 +119,19 @@ var fplnItem = { } }, getBrg: func() { - me.brg = fmgc.wpCourse[me.plan][me.index].getValue() - magvar(); - if (me.brg < 0) { me.brg += 360; } - if (me.brg > 360) { me.brg -= 360; } + var wp = fmgc.flightPlanController.flightplans[me.plan].getWP(me.index); + if (wp.wp_type == "vectors") { + me.brg = pts.Orientation.heading.getValue(); + } else { + var courseDistanceFrom = courseAndDistance(wp); + me.brg = courseDistanceFrom[0] - magvar(); + if (me.brg < 0) { me.brg += 360; } + if (me.brg > 360) { me.brg -= 360; } + } return sprintf("%03.0f", math.round(me.brg)); }, getTrack: func() { - if (me.index > (size(fmgc.wpCoursePrev[me.plan]) - 1)) { - me.trk = me.wp.leg_bearing - magvar(me.wp.lat, me.wp.lon); - } else { - me.trk = fmgc.wpCoursePrev[me.plan][me.index].getValue() - magvar(me.wp.lat, me.wp.lon); - } + me.trk = me.wp.leg_bearing - magvar(me.wp.lat, me.wp.lon); if (me.trk < 0) { me.trk += 360; } if (me.trk > 360) { me.trk -= 360; } return sprintf("%03.0f", math.round(me.trk)); @@ -112,7 +140,7 @@ var fplnItem = { if (me.index == 0 and left(me.wp.wp_name, 4) == fmgc.FMGCInternal.depApt and fmgc.FMGCInternal.v1set) { return [sprintf("%3.0f", math.round(fmgc.FMGCInternal.v1)), "grn"]; # why "mag"? I think "grn" } elsif (me.wp.speed_cstr != nil and me.wp.speed_cstr > 0) { - var tcol = (me.wp.speed_cstr_type == "computed" or me.wp.speed_cstr_type == "computed_mach") ? "grn" : "mag"; # TODO - check if only computed + var tcol = (me.wp.speed_cstr_type == "computed" or me.wp.speed_cstr_type == "computed_mach") ? "grn" : "mag"; return [sprintf("%3.0f", me.wp.speed_cstr), tcol]; } else { return ["---", "wht"]; @@ -124,7 +152,7 @@ var fplnItem = { } elsif (me.index == (fmgc.flightPlanController.currentToWptIndex.getValue() - 1) and fmgc.flightPlanController.fromWptAlt != nil) { return [" " ~ fmgc.flightPlanController.fromWptAlt, "mag"]; } elsif (me.wp.alt_cstr != nil and me.wp.alt_cstr > 0) { - var tcol = (me.wp.alt_cstr_type == "computed" or me.wp.alt_cstr_type == "computed_mach") ? "grn" : "mag"; # TODO - check if only computed + var tcol = (me.wp.alt_cstr_type == "computed" or me.wp.alt_cstr_type == "computed_mach") ? "grn" : "mag"; var cstrAlt = ""; if (me.wp.alt_cstr > fmgc.FMGCInternal.transAlt) { @@ -141,13 +169,19 @@ var fplnItem = { } }, getDist: func() { - if (me.index > size(fmgc.wpDistancePrev[me.plan]) - 1) { - return math.round(me.wp.leg_distance); + decelIndex = getprop("/instrumentation/nd/symbols/decel/index"); + decelShow = getprop("/instrumentation/nd/symbols/decel/show"); + var prevwp = fmgc.flightPlanController.flightplans[me.plan].getWP(me.index -1); + + if (me.index == fmgc.flightPlanController.currentToWptIndex.getValue()) { + return sprintf("%3.0f", math.round(courseAndDistance(me.wp)[1]));; } else { - if (me.index == fmgc.flightPlanController.currentToWptIndex.getValue()) { - return math.round(fmgc.wpDistance[me.plan][me.index].getValue()); + if (me.plan == 2 and decelShow and me.index == decelIndex and fmgc.flightPlanController.decelPoint != nil) { + return sprintf("%3.0f", courseAndDistance(fmgc.flightPlanController.decelPoint, me.wp)[1]); + } else if (prevwp != nil and (prevwp.wp_name != "DISCONTINUITY" or find(prevwp.wp_name, "VECTORS"))) { + return sprintf("%3.0f", math.round(me.wp.leg_distance)); } else { - return math.round(fmgc.wpDistancePrev[me.plan][me.index].getValue()); + return " --"; } } }, @@ -160,7 +194,7 @@ var fplnItem = { if (me.wp.wp_name == "DISCONTINUITY") { canvas_mcdu.myLatRev[me.computer] = latRev.new(4, me.wp, me.index, me.computer); } elsif (fmgc.flightPlanController.temporaryFlag[me.computer]) { - if (me.wp.wp_name == "PPOS" or me.index == (fmgc.flightPlanController.currentToWptIndex.getValue() - 1)) { + if (me.wp.wp_name == "PPOS") { canvas_mcdu.myLatRev[me.computer] = latRev.new(2, me.wp, me.index, me.computer); } elsif (me.index == fmgc.flightPlanController.arrivalIndex[me.computer]) { canvas_mcdu.myLatRev[me.computer] = latRev.new(1, me.wp, me.index, me.computer); @@ -170,7 +204,7 @@ var fplnItem = { canvas_mcdu.myLatRev[me.computer] = latRev.new(3, me.wp, me.index, me.computer); } } else { - if (me.wp.wp_name == "PPOS" or me.index == (fmgc.flightPlanController.currentToWptIndex.getValue() - 1)) { + if (me.wp.wp_name == "PPOS") { canvas_mcdu.myLatRev[me.computer] = latRev.new(2, me.wp, me.index, me.computer); } elsif (me.index == fmgc.flightPlanController.arrivalIndex[2]) { canvas_mcdu.myLatRev[me.computer] = latRev.new(1, me.wp, me.index, me.computer); @@ -271,6 +305,7 @@ var staticText = { var sT = {parents:[staticText]}; sT.computer = computer; sT.text = text; + sT.wp = "STATIC"; return sT; }, updateLeftText: func() { @@ -291,21 +326,34 @@ var staticText = { }; var pseudoItem = { - new: func(computer, text) { + new: func(computer, text, colour) { var pI = {parents:[pseudoItem]}; pI.computer = computer; pI.text = text; pI.colour = colour; + pI.wp = "PSEUDO"; return pI; }, updateLeftText: func() { return [me.text, nil, me.colour]; }, updateCenterText: func() { - return ["----", nil, "wht"]; + return ["---- ", nil, "wht"]; + }, + getDist: func() { + decelIndex = getprop("/instrumentation/nd/symbols/decel/index"); + decelShow = getprop("/instrumentation/nd/symbols/decel/show"); + if (decelShow) { + var prevWP = fmgc.flightPlanController.flightplans[2].getWP(decelIndex - 1); + if (prevWP != nil and prevWP.wp_name != "DISCONTINUITY") { + return sprintf("%3.0f", courseAndDistance(prevWP, fmgc.flightPlanController.decelPoint)[1]); + } else { + return " --"; + } + } }, updateRightText: func() { - return ["---/------", " --NM ", "wht"]; + return ["---/------", me.getDist() ~ "NM ", "wht"]; }, pushButtonLeft: func() { mcdu_message(me.computer, "NOT ALLOWED"); @@ -384,31 +432,56 @@ var fplnPage = { # this one is only created once, and then updated - remember th } else { colour = "grn"; } - for (var i = 0; i < me.plan.getPlanSize(); i += 1) { + + decelIndex = getprop("/instrumentation/nd/symbols/decel/index"); + decelShow = getprop("/instrumentation/nd/symbols/decel/show"); + + var startingIndex = fmgc.flightPlanController.currentToWptIndex.getValue() == -1 ? 0 : fmgc.flightPlanController.currentToWptIndex.getValue() - 1; + + # Situation where currentIndex is equal to 0 + startingIndex = (startingIndex == -1 ? 0 : startingIndex); + + for (var i = startingIndex; i < me.plan.getPlanSize(); i += 1) { + if (!me.temporaryFlagFpln and decelShow) { + if (i == decelIndex) { + append(me.planList, pseudoItem.new(me.computer, me.getText("decel"), colour)); + } + } + if (!me.temporaryFlagFpln and i > fmgc.flightPlanController.arrivalIndex[me.planIndex] and fmgc.FMGCInternal.phase != 6) { append(me.planList, fplnItem.new(me.plan.getWP(i), i, me.planIndex, me.computer, "blu")); } else { - append(me.planList, fplnItem.new(me.plan.getWP(i), i, me.planIndex, me.computer, colour)); + if (i == fmgc.flightPlanController.currentToWptIndex.getValue() and !me.temporaryFlagFpln) { + append(me.planList, fplnItem.new(me.plan.getWP(i), i, me.planIndex, me.computer, "wht")); + } else { + append(me.planList, fplnItem.new(me.plan.getWP(i), i, me.planIndex, me.computer, colour)); + } } } + append(me.planList, staticText.new(me.computer, me.getText("fplnEnd"))); if (!fmgc.FMGCInternal.altAirportSet) { append(me.planList, staticText.new(me.computer, me.getText("noAltnFpln"))); } else { - var altnApt = findAirportsByICAO(fmgc.FMGCInternal.altAirport)[0]; - append(me.planList, fplnItem.new({ - alt_cstr: nil, - alt_cstr_type: nil, - fly_type: "flyBy", - lat: altnApt.lat, - leg_bearing: courseAndDistance(findAirportsByICAO(fmgc.FMGCInternal.arrApt)[0], altnApt)[0], - leg_distance: courseAndDistance(findAirportsByICAO(fmgc.FMGCInternal.arrApt)[0], altnApt)[1], - lon: altnApt.lon, - speed_cstr: nil, - speed_cstr_type: nil, - wp_name: fmgc.FMGCInternal.altAirport, - }, i, me.planIndex, me.computer, "blu")); - append(me.planList, staticText.new(me.computer, me.getText("altnFplnEnd"))); + var altnApt = findAirportsByICAO(fmgc.FMGCInternal.altAirport); + if (size(altnApt) > 0) { + append(me.planList, fplnItem.new({ + alt_cstr: nil, + alt_cstr_type: nil, + fly_type: "flyBy", + lat: altnApt[0].lat, + leg_bearing: courseAndDistance(findAirportsByICAO(fmgc.FMGCInternal.arrApt)[0], altnApt[0])[0], + leg_distance: courseAndDistance(findAirportsByICAO(fmgc.FMGCInternal.arrApt)[0], altnApt[0])[1], + lon: altnApt[0].lon, + speed_cstr: nil, + speed_cstr_type: nil, + wp_name: fmgc.FMGCInternal.altAirport, + wp_parent_name: nil, + }, i, me.planIndex, me.computer, "blu")); + append(me.planList, staticText.new(me.computer, me.getText("altnFplnEnd"))); + } else { + append(me.planList, staticText.new(me.computer, me.getText("noAltnFpln"))); + } } me.basePage(); @@ -468,7 +541,7 @@ var fplnPage = { # this one is only created once, and then updated - remember th }, destInfo: func() { if (me.plan.getWP(fmgc.flightPlanController.arrivalIndex[me.planIndex]) != nil) { - var destName = split("-", me.plan.getWP(fmgc.flightPlanController.arrivalIndex[me.planIndex]).wp_name); + destName = split("-", me.plan.getWP(fmgc.flightPlanController.arrivalIndex[me.planIndex]).wp_name); if (size(destName) == 2) { me.L6 = [destName[0] ~ destName[1], " DEST", "wht"]; } else { @@ -478,8 +551,8 @@ var fplnPage = { # this one is only created once, and then updated - remember th me.L6 = ["----", " DEST", "wht"]; } me.C6 = ["---- ", "TIME ", "wht"]; - if (fmgc.flightPlanController.arrivalDist != nil) { - me.R6 = [sprintf("%4.0f", int(fmgc.flightPlanController.arrivalDist)) ~ " --.-", "DIST EFOB", "wht"]; + if (fmgc.flightPlanController.arrivalDist.getValue() != nil) { + me.R6 = [sprintf("%4.0f", int(fmgc.flightPlanController.arrivalDist.getValue())) ~ " --.-", "DIST EFOB", "wht"]; } else { me.R6 = ["---- --.-", "DIST EFOB", "wht"]; } @@ -487,15 +560,26 @@ var fplnPage = { # this one is only created once, and then updated - remember th update: func() { #me.basePage(); }, + planIndexFunc: func() { + decelIndex = getprop("/instrumentation/nd/symbols/decel/index"); + decelShow = getprop("/instrumentation/nd/symbols/decel/show"); + if (me.scroll < me.plan.getPlanSize()) { + decelOffset = 0; + if (decelShow) { + if (me.scroll > decelIndex) { + decelOffset = 1; + } + } + setprop("/instrumentation/efis[" ~ me.computer ~ "]/inputs/plan-wpt-index", (fmgc.flightPlanController.currentToWptIndex.getValue() - 1 + me.scroll - decelOffset)); + } + }, scrollUp: func() { if (size(me.planList) > 1) { me.scroll += 1; if (me.scroll > size(me.planList) - 3) { me.scroll = 0; } - if (me.scroll < me.plan.getPlanSize()) { - setprop("/instrumentation/efis[" ~ me.computer ~ "]/inputs/plan-wpt-index", me.scroll); - } + me.planIndexFunc(); } else { me.scroll = 0; setprop("/instrumentation/efis[" ~ me.computer ~ "]/inputs/plan-wpt-index", -1); @@ -507,9 +591,7 @@ var fplnPage = { # this one is only created once, and then updated - remember th if (me.scroll < 0) { me.scroll = size(me.planList) - 3; } - if (me.scroll < me.plan.getPlanSize()) { - setprop("/instrumentation/efis[" ~ me.computer ~ "]/inputs/plan-wpt-index", me.scroll); - } + me.planIndexFunc(); } else { me.scroll = 0; setprop("/instrumentation/efis[" ~ me.computer ~ "]/inputs/plan-wpt-index", -1); @@ -535,17 +617,9 @@ var fplnPage = { # this one is only created once, and then updated - remember th setprop("MCDU[" ~ me.computer ~ "]/page", "LATREV"); } } else { - if ((index - 1 + me.scroll) < size(me.planList) and !mcdu_scratchpad.scratchpads[me.computer].showTypeIMsg and !mcdu_scratchpad.scratchpads[me.computer].showTypeIIMsg) { + if ((index - 1 + me.scroll) < size(me.planList) and me.outputList[index - 1].wp != "STATIC" and me.outputList[index - 1].wp != "PSEUDO" and !mcdu_scratchpad.scratchpads[me.computer].showTypeIMsg and !mcdu_scratchpad.scratchpads[me.computer].showTypeIIMsg) { if (size(mcdu_scratchpad.scratchpads[me.computer].scratchpad) > 0) { - # Use outputList.index to correct the index the call goes to after sequencing - - if (mcdu_scratchpad.scratchpads[me.computer].scratchpad == "CLR") { - if (me.outputList[index - 1].wp.wp_name == "(DECEL)") { - mcdu_message(me.computer, "NOT ALLOWED"); - return; - } - } var returny = fmgc.flightPlanController.scratchpad(mcdu_scratchpad.scratchpads[me.computer].scratchpad, me.outputList[index - 1].index, me.computer); if (returny == 3) { mcdu_message(me.computer, "DIR TO IN PROGRESS"); @@ -595,8 +669,9 @@ var decimalToShortString = func(dms, type) { var degrees = split(".", sprintf(dms))[0]; if (type == "lat") { var sign = degrees >= 0 ? "N" : "S"; + return sprintf("%02d", abs(degrees)) ~ sign; } else { var sign = degrees >= 0 ? "E" : "W"; + return sprintf("%03d", abs(degrees)) ~ sign; } - return abs(degrees) ~ sign; } \ No newline at end of file diff --git a/Nasal/MCDU/HOLD.nas b/Nasal/MCDU/HOLD.nas index 1bb16b33..68ed4fbd 100644 --- a/Nasal/MCDU/HOLD.nas +++ b/Nasal/MCDU/HOLD.nas @@ -39,38 +39,50 @@ var holdPage = { _setupPageWithData: func() { me.title = ["HOLD", " AT ", me.waypoint.wp_name]; me.titleColour = "wht"; - me.arrowsMatrix = [[0, 0, 0, 0, 0, 1], [1, 1, 0, 0, 0, 0]]; + me.arrowsMatrix = [[0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0]]; me.arrowsColour = [["ack", "ack", "ack", "ack", "ack", "wht"], ["blu", "blu", "ack", "ack", "ack", "ack"]]; + if (me.waypoint.fly_type == "Hold") { - me.makeTmpy(); - me.L1 = [sprintf("%03.0f°", me.waypoint.hold_inbound_radial), "INB CRS", "blu"]; - - if (me.waypoint.hold_is_left_handed) { - me.L2 = ["L", " TURN", "blu"]; - } else { - me.L2 = ["R", " TURN", "blu"]; - } - - if (me.waypoint.hold_is_distance) { - me.L3 = [" -.-/" ~ me.waypoint.hold_time_or_distance, "TIME/DIST", "blu"]; - } else { - me.L3 = [sprintf("%3.1f", (me.waypoint.hold_time_or_distance / 60)) ~ "/----", "TIME/DIST", "blu"]; - } - me.R1 = ["COMPUTED ", nil, "blu"]; - me.R2 = ["DATABASE ", nil, "yel"]; + me.R1 = ["COMPUTED ", nil, "wht"]; + me.R2 = ["DATABASE ", nil, "blu"]; + me.arrowsColour[1][0] = "wht"; + me.arrowsColour[1][1] = "blu"; + me.arrowsMatrix[1][0] = 1; me.arrowsMatrix[1][1] = 0; } else { - me.L1 = ["100°", "INB CRS", "blu"]; - me.L2 = ["R", " TURN", "blu"]; + # waypoint is a leg, figure out how to handle it + return; + me.waypoint.hold_count = 999; + me.waypoint.hold_is_left_handed = 0; + me.waypoint.hold_is_distance = 0; + me.waypoint.hold_inbound_radial = me.waypoint.leg_bearing; + if (pts.Instrumentation.Altimeter.indicatedFt.getValue() >= 14000) { - me.L3 = ["1.5/----", "TIME/DIST", "blu"]; + me.waypoint.hold_time_or_distance = 90; } else { - me.L3 = ["1.0/----", "TIME/DIST", "blu"]; + me.waypoint.hold_time_or_distance = 60; } - me.R1 = ["COMPUTED ", nil, "blu"]; - me.R2 = ["DATABASE ", nil, "blu"]; + + me.R1 = ["COMPUTED ", nil, "yel"]; + me.R2 = ["DATABASE ", nil, "wht"]; + me.arrowsColour[1][0] = "yel"; + me.arrowsColour[1][1] = "wht"; + me.arrowsMatrix[1][0] = 0; + me.arrowsMatrix[1][1] = 1; } - me.L6 = [" RETURN", nil, "wht"]; + + me.L1 = [sprintf("%03.0f°", me.waypoint.hold_inbound_radial), "INB CRS", "blu"]; + if (me.waypoint.hold_is_left_handed) { + me.L2 = ["L", " TURN", "blu"]; + } else { + me.L2 = ["R", " TURN", "blu"]; + } + if (me.waypoint.hold_is_distance) { + me.L3 = [" -.-/" ~ me.waypoint.hold_time_or_distance, "TIME/DIST", "blu"]; + } else { + me.L3 = [sprintf("%3.1f", (me.waypoint.hold_time_or_distance / 60)) ~ "/----", "TIME/DIST", "blu"]; + } + me.C4 = ["LAST EXIT", nil, "wht"]; me.C5 = ["---- ---.-", "UTC FUEL", "wht"]; canvas_mcdu.pageSwitch[me.computer].setBoolValue(0); @@ -82,23 +94,67 @@ var holdPage = { }, updateTmpy: func() { if (fmgc.flightPlanController.temporaryFlag[me.computer]) { - me.L1[2] = "yel"; - me.L2[2] = "yel"; - me.L3[2] = "yel"; me.L6 = [" F-PLN", " TMPY", "yel"]; me.R6 = ["INSERT ", " TMPY", "yel"]; me.arrowsColour[0][5] = "yel"; me.titleColour = "yel"; canvas_mcdu.pageSwitch[me.computer].setBoolValue(0); } else { - me.L1[2] = "blu"; - me.L2[2] = "blu"; - me.L3[2] = "blu"; me.L6 = [" RETURN", nil, "wht"]; me.R6 = [nil, nil, "ack"]; me.arrowsColour[0][5] = "wht"; me.titleColour = "wht"; canvas_mcdu.pageSwitch[me.computer].setBoolValue(0); } - } + }, + pushbuttonLeft: func(index) { + me.scratchpad = mcdu_scratchpad.scratchpads[me.computer].scratchpad; + if (index == 1) { + if (size(me.scratchpad) <= 3 and num(me.scratchpad) != nil) { + me.waypoint.hold_inbound_radial = me.scratchpad; + mcdu_scratchpad.scratchpads[me.computer].empty(); + me._setupPageWithData(); + } else { + mcdu_message(me.computer, "NOT ALLOWED"); + } + } else if (index == 2) { + if (me.scratchpad == "L") { + me.waypoint.hold_is_left_handed = 1; + mcdu_scratchpad.scratchpads[me.computer].empty(); + me._setupPageWithData(); + } elsif (me.scratchpad == "R") { + me.waypoint.hold_is_left_handed = 0; + mcdu_scratchpad.scratchpads[me.computer].empty(); + me._setupPageWithData(); + } else { + mcdu_message(me.computer, "NOT ALLOWED"); + } + } elsif (index == 3) { + if (num(me.scratchpad) != nil) { + me.waypoint.hold_time_or_distance = me.scratchpad; + mcdu_scratchpad.scratchpads[me.computer].empty(); + me._setupPageWithData(); + } else { + mcdu_message(me.computer, "NOT ALLOWED"); + } + } else { + mcdu_message(me.computer, "NOT ALLOWED"); + } + }, + pushbuttonRight: func(index) { + me.scratchpad = mcdu_scratchpad.scratchpads[me.computer].scratchpad; + if (size(me.scratchpad) != 0) { + mcdu_message(me.computer, "NOT ALLOWED"); + } else { + if (index == 6) { + if (fmgc.flightPlanController.temporaryFlag[me.computer]) { + setprop("/MCDU[" ~ me.computer ~ "]/page", "F-PLNA"); + } else { + mcdu_message(me.computer, "NOT ALLOWED"); + } + } else { + mcdu_message(me.computer, "NOT ALLOWED"); + } + } + }, }; \ No newline at end of file diff --git a/Nasal/MCDU/INITA.nas b/Nasal/MCDU/INITA.nas index b1360af9..c6e221f2 100644 --- a/Nasal/MCDU/INITA.nas +++ b/Nasal/MCDU/INITA.nas @@ -79,20 +79,23 @@ var initInputA = func(key, i) { #setprop("MCDU[" ~ i ~ "]/page", "ROUTESELECTION"); } else if (fmgc.FMGCInternal.toFromSet) { if (!fmgc.flightPlanController.temporaryFlag[i]) { - var tfs = size(scratchpad); - if (tfs == 4) { - fmgc.FMGCInternal.altAirport = scratchpad; - fmgc.FMGCInternal.altAirportSet = 1; - atsu.ATISInstances[2].newStation(scratchpad); - fmgc.windController.updatePlans(); - if (fmgc.FMGCInternal.blockConfirmed) { - fmgc.FMGCInternal.fuelCalculating = 0; - fmgc.fuelCalculating.setValue(0); - fmgc.FMGCInternal.fuelCalculating = 1; - fmgc.fuelCalculating.setValue(1); + if (size(scratchpad) == 4) { + if (size(findAirportsByICAO(scratchpad)) > 0) { + fmgc.FMGCInternal.altAirport = scratchpad; + fmgc.FMGCInternal.altAirportSet = 1; + atsu.ATISInstances[2].newStation(scratchpad); + fmgc.windController.updatePlans(); + if (fmgc.FMGCInternal.blockConfirmed) { + fmgc.FMGCInternal.fuelCalculating = 0; + fmgc.fuelCalculating.setValue(0); + fmgc.FMGCInternal.fuelCalculating = 1; + fmgc.fuelCalculating.setValue(1); + } + mcdu_scratchpad.scratchpads[i].empty(); + fmgc.updateARPT(); + } else { + mcdu_message(i, "NOT IN DATA BASE"); } - mcdu_scratchpad.scratchpads[i].empty(); - fmgc.updateARPT(); #fmgc.FMGCInternal.altSelected = 1; #setprop("MCDU[" ~ i ~ "]/page", "ROUTESELECTION"); } else { @@ -249,25 +252,26 @@ var initInputA = func(key, i) { #setprop("MCDU[" ~ i ~ "]/page", "ROUTESELECTION"); } else { if (!fmgc.flightPlanController.temporaryFlag[i]) { - var tfs = size(scratchpad); - if (tfs == 9 and find("/", scratchpad) != -1) { + if (size(scratchpad) == 9 and find("/", scratchpad) != -1) { var fromto = split("/", scratchpad); - var froms = size(fromto[0]); - var tos = size(fromto[1]); - if (froms == 4 and tos == 4) { - resetFlightplan(i); - fmgc.FMGCInternal.depApt = fromto[0]; - fmgc.FMGCInternal.arrApt = fromto[1]; - atsu.ATISInstances[0].newStation(fromto[0]); - atsu.ATISInstances[1].newStation(fromto[1]); - fmgc.FMGCInternal.toFromSet = 1; - fmgc.FMGCNodes.toFromSet.setValue(1); - mcdu_scratchpad.scratchpads[i].empty(); - - fmgc.flightPlanController.updateAirports(fromto[0], fromto[1], 2); - fmgc.FMGCInternal.altSelected = 0; - fmgc.updateARPT(); - fmgc.updateArptLatLon(); + if (size(fromto[0]) == 4 and size(fromto[1]) == 4) { + if (size(findAirportsByICAO(fromto[0])) > 0 and size(findAirportsByICAO(fromto[1])) > 0) { + resetFlightplan(i); + fmgc.FMGCInternal.depApt = fromto[0]; + fmgc.FMGCInternal.arrApt = fromto[1]; + atsu.ATISInstances[0].newStation(fromto[0]); + atsu.ATISInstances[1].newStation(fromto[1]); + fmgc.FMGCInternal.toFromSet = 1; + fmgc.FMGCNodes.toFromSet.setValue(1); + mcdu_scratchpad.scratchpads[i].empty(); + + fmgc.flightPlanController.updateAirports(fromto[0], fromto[1], 2); + fmgc.FMGCInternal.altSelected = 0; + fmgc.updateARPT(); + fmgc.updateArptLatLon(); + } else { + mcdu_message(i, "NOT IN DATA BASE"); + } #setprop("MCDU[" ~ i ~ "]/page", "ROUTESELECTION"); } else { mcdu_message(i, "NOT ALLOWED"); diff --git a/Nasal/MCDU/MCDU.nas b/Nasal/MCDU/MCDU.nas index d83f0619..8797f0ed 100644 --- a/Nasal/MCDU/MCDU.nas +++ b/Nasal/MCDU/MCDU.nas @@ -6,6 +6,7 @@ var pageNode = [props.globals.getNode("/MCDU[0]/page"), props.globals.getNode("/MCDU[1]/page")]; var page = nil; var msg = nil; +var airportPress = [0,0]; var scratchpadNode = [nil, nil]; var MCDU_init = func(i) { @@ -68,7 +69,7 @@ var MCDU_reset = func(i) { fmgc.FMGCInternal.depApt = ""; fmgc.FMGCInternal.flightNum = ""; fmgc.FMGCInternal.flightNumSet = 0; - fmgc.FMGCInternal.gndTemp = -99; + fmgc.FMGCInternal.gndTemp = 15; fmgc.FMGCInternal.gndTempSet = 0; fmgc.FMGCInternal.toFromSet = 0; fmgc.FMGCNodes.toFromSet.setValue(0); @@ -356,6 +357,8 @@ var lskbutton = func(btn, i) { mcdu_scratchpad.scratchpads[i].empty(); } } + } else if (page == "HOLD") { + canvas_mcdu.myHold[i].pushbuttonLeft(1); } else if (page == "MCDUTEXT") { atsu.freeTexts[i].selection = 0; atsu.freeTexts[i].changed = 1; @@ -503,6 +506,8 @@ var lskbutton = func(btn, i) { } } else if (page == "VERTREV") { canvas_mcdu.myVertRev[i].pushButtonLeft(2); + } else if (page == "HOLD") { + canvas_mcdu.myHold[i].pushbuttonLeft(2); } else if (page == "MCDUTEXT") { atsu.freeTexts[i].selection = 1; atsu.freeTexts[i].changed = 1; @@ -631,6 +636,8 @@ var lskbutton = func(btn, i) { } } else if (page == "VERTREV") { canvas_mcdu.myVertRev[i].pushButtonLeft(3); + } else if (page == "HOLD") { + canvas_mcdu.myHold[i].pushbuttonLeft(3); } else if (page == "MCDUTEXT") { atsu.freeTexts[i].selection = 2; atsu.freeTexts[i].changed = 1; @@ -848,6 +855,8 @@ var lskbutton = func(btn, i) { } else { if (canvas_mcdu.myDuplicate[i] != nil and canvas_mcdu.myDuplicate[i].flagPROG) { pagebutton("prog",i); + } else { + pageNode[i].setValue("F-PLNA"); } } } else if (page == "ARRIVAL") { @@ -1499,25 +1508,32 @@ var pagebutton = func(btn, i) { } else if (btn == "mcdu") { mcdu_message(i, "SELECT DESIRED SYSTEM"); pageNode[i].setValue("MCDU"); - } else if (btn == "f-pln" or btn == "airport") { + } else if (btn == "f-pln") { if (canvas_mcdu.myFpln[i] == nil) { canvas_mcdu.myFpln[i] = fplnPage.new(2, i); } - if (btn == "airport") { - if (fmgc.FMGCInternal.phase == 0 or fmgc.FMGCInternal.phase == 1) { - canvas_mcdu.myFpln[i].scroll = 0; - } else { - if (fmgc.flightPlanController.temporaryFlag[i]) { - canvas_mcdu.myFpln[i].scroll = fmgc.flightPlanController.arrivalIndex[i]; + canvas_mcdu.myFpln[i].scroll = 0; + pageNode[i].setValue("F-PLNA"); + } else if (btn == "airport") { + if (airportPress[i] == 0 or fmgc.FMGCInternal.phase >= 1) { + if (fmgc.flightPlanController.temporaryFlag[i]) { + if (fmgc.flightPlanController.currentToWptIndex.getValue() == fmgc.flightPlanController.arrivalIndex[i]) { + canvas_mcdu.myFpln[i].scroll = (fmgc.flightPlanController.arrivalIndex[i] - fmgc.flightPlanController.currentToWptIndex.getValue()); } else { - canvas_mcdu.myFpln[i].scroll = fmgc.flightPlanController.arrivalIndex[2]; + canvas_mcdu.myFpln[i].scroll = (fmgc.flightPlanController.arrivalIndex[i] - fmgc.flightPlanController.currentToWptIndex.getValue()) - 1; + } + } else { + if (fmgc.flightPlanController.currentToWptIndex.getValue() == fmgc.flightPlanController.arrivalIndex[2]) { + canvas_mcdu.myFpln[i].scroll = (fmgc.flightPlanController.arrivalIndex[2] - fmgc.flightPlanController.currentToWptIndex.getValue()); + } else { + canvas_mcdu.myFpln[i].scroll = (fmgc.flightPlanController.arrivalIndex[2] - fmgc.flightPlanController.currentToWptIndex.getValue()) - 1; } } - } else { + airportPress[i] = 1; + } else if (fmgc.FMGCInternal.phase == 0 or fmgc.FMGCInternal.phase == 1) { canvas_mcdu.myFpln[i].scroll = 0; + airportPress[i] = 0; } - pageNode[i].setValue("F-PLNA"); - } else if (btn == "fuel-pred") { pageNode[i].setValue("FUELPRED"); } else if (btn == "dirto") { diff --git a/Nasal/MCDU/PERFCLB.nas b/Nasal/MCDU/PERFCLB.nas index ee45ead1..cbf4af0a 100644 --- a/Nasal/MCDU/PERFCLB.nas +++ b/Nasal/MCDU/PERFCLB.nas @@ -39,6 +39,7 @@ var perfCLBInput = func(key, i) { setprop("/FMGC/internal/activate-twice", 1); fmgc.FMGCInternal.phase = 5; fmgc.FMGCInternal.decel = 1; + setprop("/instrumentation/nd/symbols/decel/show", 0); setprop("MCDU[" ~ i ~ "]/page", "PERFAPPR"); } else { mcdu_message(i, "NOT ALLOWED"); diff --git a/Nasal/MCDU/PERFCRZ.nas b/Nasal/MCDU/PERFCRZ.nas index 87d041e7..801bdfb8 100644 --- a/Nasal/MCDU/PERFCRZ.nas +++ b/Nasal/MCDU/PERFCRZ.nas @@ -33,6 +33,7 @@ var perfCRZInput = func(key, i) { setprop("/FMGC/internal/activate-twice", 1); fmgc.FMGCInternal.phase = 5; fmgc.FMGCInternal.decel = 1; + setprop("/instrumentation/nd/symbols/decel/show", 0); setprop("MCDU[" ~ i ~ "]/page", "PERFAPPR"); } else { mcdu_message(i, "NOT ALLOWED"); diff --git a/Nasal/MCDU/PERFDES.nas b/Nasal/MCDU/PERFDES.nas index def27ef8..ab92bfc5 100644 --- a/Nasal/MCDU/PERFDES.nas +++ b/Nasal/MCDU/PERFDES.nas @@ -33,6 +33,7 @@ var perfDESInput = func(key, i) { setprop("/FMGC/internal/activate-twice", 1); fmgc.FMGCInternal.phase = 5; fmgc.FMGCInternal.decel = 1; + setprop("/instrumentation/nd/symbols/decel/show", 0); setprop("MCDU[" ~ i ~ "]/page", "PERFAPPR"); } else { mcdu_message(i, "NOT ALLOWED"); diff --git a/Nasal/MCDU/RECEIVEDMESSAGES.nas b/Nasal/MCDU/RECEIVEDMESSAGES.nas index 8c41e118..bf6d9279 100644 --- a/Nasal/MCDU/RECEIVEDMESSAGES.nas +++ b/Nasal/MCDU/RECEIVEDMESSAGES.nas @@ -1,3 +1,6 @@ +# A3XX MCDU Received Messages Page +# Copyright (c) 2022 Jonathan Redpath (legoboyvdlp) + var receivedMessagesPage = { title: nil, arrowsMatrix: [[0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0]], diff --git a/Systems/fmgc-drivers.xml b/Systems/fmgc-drivers.xml index 0c2fa3e9..fae0bc9b 100644 --- a/Systems/fmgc-drivers.xml +++ b/Systems/fmgc-drivers.xml @@ -434,6 +434,24 @@ + + Get Back on Magenta + gain + + + + /fdm/jsbsim/velocities/vc-kts + 14050 + 36020 +
+
+
+ /instrumentation/gps/wp/wp[1]/course-error-nm + /it-autoflight/internal/course-error-deg + -45 + 45 +
+ Heading Error Deg gain @@ -485,7 +503,8 @@ - /FMGC/flightplan[2]/current-leg-course + /instrumentation/gps/wp/leg-true-course-deg + /it-autoflight/internal/course-error-deg /it-autoflight/internal/drift-angle-deg -1.0