| Scripts/hudselector.js | "use strict";
this.name = "hudselector";
this.author = "Norby";
this.copyright = "2014 Norby";
this.description = "Change your HUD during flight between the supported ones.";
this.license = "CC BY-NC-SA 4.0";
this.version = "1.25";
this._hairSpace = String.fromCharCode(31);
this._hairSpaceLength = defaultFont.measureString(this._hairSpace);
this._ellip = "…";
this.$HUDSelectorHUDs = [ //worldscript, name and .plists
    [null, "Default HUD", "hud"],
    //the first plist for 4:3, then optionally for 16:10 and 16:9 screens if different
    ["hudselector", "ExtraLarge HUD with 10 MFDs and custom dials", "hudselector-extralarge",
        "hudselector-extralarge10"], //for 16:10
    //large is a copy of the oolite's stock hud.plist but with large scanner and more MFDs
    ["hudselector", "Large HUD with 10 MFDs and custom dials", "hudselector-large"],
    //copy of stock hud-small.plist but with more MFDs
    ["hudselector", "Small HUD with 10 MFDs and custom dials", "hudselector-small"]
];
this.$HUDSelectorOldHUDs = [
    [null, "Default HUD", "hud"], //without custom dials for Oolite 1.80 and below
    ["hudselector", "ExtraLarge HUD with 10 MFDs", "hudselector-oldextralarge"],
    ["hudselector", "Large HUD with 10 MFDs", "hudselector-oldlarge"],
    ["hudselector", "Small HUD with 10 MFDs", "hudselector-oldsmall"],
];
//default MFD 1-10 worldScript names
this.$HUDSelectorMFDs = [
    ["combat_MFD", "combat_MFD", "Combat MFD"],
    ["telescope", "TelescopeMFD", "Telescope MFD"],
    ["telescope", "TelescopeAuxMFD", "Telescope Auxiliary MFD"],
    ["escortdeck", "escortdeck", "Escort Deck MFD"],
    ["CommsLogMFD", "CommsLogMFD", "Comms Log MFD"],
    ["BroadcastCommsMFD", "BroadcastCommsMFD", "Broadcast Comms MFD"],
    ["trophy_col", "trophy_mfd", "Trophy Collector MFD"], //mfd name is different
    ["navi_mfd", "navi_mfd", "Navigation MFD"],
    ["market_inquirer", "inquirer_mfd", "Market Inquirer MFD"], //mfd name is not equal with worldScript name
    ["manifest_mfd", "manifest_mfd", "Manifest MFD"],
    ["useful_MFDs", "useful_MFD_general_info", "Useful MFDs - General Info"], //mfd name is different
    ["useful_MFDs", "useful_MFD_market", "Useful MFDs - Market"],
    ["PrimeableEquipmentMFD", "nm_primeable-mfd", "Primeable Equipment MFD"],
    ["GalCopBB_RangeFinder_MFD", "RangeFinderMFD", "Range Finder MFD"],
    ["NavBeaconsMFD", "NavigationBeaconsMFD", "Navigation Beacons MFD"],
    ["Waypoint_Here_MFD", "Waypoint_Here_MFD", "Waypoint Here MFD"],
    ["StationDockControl_MFD", "LaunchQueueMFD", "Station Launch Queue MFD"],
    ["DamageReportMFD", "DamageReportMFD", "Damage Report MFD"],
    ["BountySystem_WarrantScanner", "BountySystem_WarrantScanner", "Warrant Scanner MFD"],
    ["RandomStationNames", "RandomStationNames", "Galactic Almanac MFD"],
    ["EQ_ADVANCED_SYSTEM_DATA_MFD", "EQ_ADVANCED_SYSTEM_DATA_MFD", "Advanced System Data MFD"],
    ["Fighters", "Fighters", "Fighters MFD"],
    ["SSLaneIndicator", "SSLaneIndicator", "Star System Lane Indicator MFD"],
    ["TargetSystemPlugins_ShortRangeSnapshot", "tsplugins_srs", "Short Range Snapshot MFD"],
    ["TargetSystemPlugins_TargetMemoryInterface", "tsplugins_tmi", "Target Memory Interface MFD"],
    ["Ships Library", "ships-library", "Ships Library MFD"],
];
this.$HUDSelectorScanSet = [
    "Linear, NormalZoom",
    "NonLinear, NormalZoom",
    "Linear, UltraZoom",
    "NonLinear, UltraZoom"
];
//internal properties, should not touch
this.$BG = null; //mission screen background
this.$combatWS = null; //pointer to the worldScript of CombatMFD
this.$HUDSelectorDefaultMFDs = []; //load the default MFD settings into this array
this.$HUDSelectorDialNo = 0; //where will start the Dial Interface
this.$HUDSelectorChoice = null; //store the last selection in missionscreens
this.$HUDSelectorEqSel = 2; //number of the selected HUD ( 2 = Large HUD )
this.$HUDSelectorFix = false; //turn on the fix of scanner settings problem caused by Auto Crosshairs OXP
this.$HUDSelectorFixInEveryFrame = false; //needed if both Auto Crosshairs OXP and Telescope OXP is installed
this.$HUDSelectorFixFCB = null; //FCB for fixing crosshairs change bug
this.$HUDSelectorScanner = 0; //store the combined number of NonLinear and UltraZoom scanner settings
this.$HUDSelectorTimer = null; //store a 0.1s delay timer for other startUps
this.$C = -1; //store the last crosshairs setting for FixFCB
this.$H = -1; //store the last hud setting for FixFCB
this.$L = -1; //store the last scanner linearity setting for FixFCB
this.$Z = -1; //store the last scanner zoom setting for FixFCB
this.$debug = true;
//equipment events
//---------------------------------------------------------------------------------
this.activated = function () {
    var h = worldScripts.hudselector;
    var prev = h.$HUDSelectorEqSel;
    h.$HUDSelectorEqSel++; //select next HUD
    if (h.$HUDSelectorEqSel >= h.$HUDSelectorHUDs.length) h.$HUDSelectorEqSel = 0;
    player.consoleMessage(h.$HUDSelectorHUDs[h.$HUDSelectorEqSel][1] + " selected", 10);
    h.$HUDSelectorSetHUD(prev);
}
//---------------------------------------------------------------------------------
this.mode = function () {
    var h = worldScripts.hudselector;
    var b = 0;
    if (player.ship.scannerNonLinear) b += 1;
    if (player.ship.scannerUltraZoom) b += 2;
    b++;
    if (b > 3) b = 0;
    player.consoleMessage("Scanner: " + h.$HUDSelectorScanSet[b], 10);
    h.$HUDSelectorSetScanner(b);
}
//worldscript events
//---------------------------------------------------------------------------------
this.startUp = function () {
    this.$BG = null; //mission screen background
    if (worldScripts["BGS-M"]) this.$BG = "bgs-i_interface_parcel1.png";
    else if (worldScripts["Better Screens"]) this.$BG = "bs-base-bg.png";
    this.$combatWS = worldScripts.combat_MFD;
    var s = missionVariables.$HUDSelectorDataShow;
    if (this.$combatWS && this.$combatWS.$DataShow && s) {
        var d = JSON.parse(s);
        for (var key in d) {
            this.$combatWS.$DataShow[key] = d[key];
        }
        //do not use this.$combatWS.$DataShow=d; to avoid cropping DataShow array
    }   //in the case of a new CombatMFD with longer array and loading an old savegame
    if (!player.ship.setCustomHUDDial) {//for Oolite 1.80 and below
        this.$HUDSelectorHUDs[1] = this.$HUDSelectorOldHUDs[1]; //oldextralarge
        this.$HUDSelectorHUDs[2] = this.$HUDSelectorOldHUDs[2]; //oldlarge
        this.$HUDSelectorHUDs[3] = this.$HUDSelectorOldHUDs[3]; //oldsmall
    }
    this.$HUDSelectorScanner = missionVariables.$HUDSelectorScanner;
    // check for the previous version of the default MFD dataset
    if (missionVariables.$HUDSelectorDefaultMFDs) {
        var d = missionVariables.$HUDSelectorDefaultMFDs;
        if (!d) this.$HUDSelectorDefaultMFDs = [];
        else if ((d + "").indexOf(",")) this.$HUDSelectorDefaultMFDs = (d + "").split(","); //need +"" for bugfix of a single item
        else this.$HUDSelectorDefaultMFDs = [d];
        delete missionVariables.$HUDSelectorDefaultMFDs;
    }
    // check for the new version of the default MFD data set.
    if (missionVariables.$HUDSelectorDefaultMFDs_new) {
        this.$HUDSelectorDefaultMFDs = JSON.parse(missionVariables.$HUDSelectorDefaultMFDs_new);
    }
    if (player.ship && player.ship.docked) this.shipDockedWithStation(player.ship.dockedStation); //set interface
    else if (system) this.shipDockedWithStation(system.mainStation);//fallback
    if (worldScripts["Auto Crosshairs"] && worldScripts.telescope)
       this.$HUDSelectorFixInEveryFrame = true; //needed if both Auto Crosshairs OXP and Telescope OXP is installed
    if (this.$HUDSelectorFix) //FCB for fixing crosshairs change bug
        this.$HUDSelectorFixFCB = addFrameCallback(this.$HUDSelector_FixFCB.bind(this));
}
//---------------------------------------------------------------------------------
this.startUpComplete = function () {
    // start the process of switching to the saved HUD
    // first, make the current hud the saved one, but don't do any of the callbacks yet
    // this is so other OXP's that might need to check on the type/size of the HUD can do so reliably
    this.$HUDSelectorRestoreHUD();
    this.$HUDSelectorSetHUD();
    if (!this.$HUDSelectorDefaultMFDs || !(this.$HUDSelectorDefaultMFDs.length > 0)) {
        //set default MFDs first time in order of $HUDSelectorMFDs array
        this.$HUDSelectorDefaultMFDs = [];
        for (var i = 0; i < this.$HUDSelectorMFDs.length; i++) {
            if (this.$HUDSelectorMFDs[i] && this.$HUDSelectorMFDs[i][0]) {
                var w = this.$HUDSelectorMFDs[i][0]; //worldScript name
                if (worldScripts[w]) {
                    this.$HUDSelectorDefaultMFDs[i] = w;
                }
            }
        }
    }
    if (this.$debug) {
        log(this.name, "HUDs: " + this.$HUDSelectorHUDs);//debug
        for (var i = 0; i < this.$HUDSelectorHUDs.length; i++)
            log(this.name, i + ": " + this.$HUDSelectorHUDs[i]);
    }
    this.$setInterface();
}
//---------------------------------------------------------------------------------
this.guiScreenChanged = function (to, from) {
    if (!player.ship) return;
    if (to === "GUI_SCREEN_OPTIONS") {
        player.ship.hudHidden = false; //fix problems in other addons
    }
}
//---------------------------------------------------------------------------------
this.playerBoughtEquipment = function (equipmentKey) {
    if (equipmentKey == "EQ_HUDSELECTOR_REMOVE") {
        var eq = equipmentKey.substr(0, equipmentKey.length - 7);//the real eq
        player.ship.removeEquipment(eq); //remove it
        player.ship.removeEquipment(equipmentKey); //remove the "bought" remove eq
    }
}
//---------------------------------------------------------------------------------
this.playerWillSaveGame = function (message) {
    missionVariables.$HUDSelectorHUD = this.$HUDSelectorHUDs[this.$HUDSelectorEqSel][2];
    //missionVariables.$HUDSelectorDefaultMFDs = this.$HUDSelectorDefaultMFDs;  //store default MFDs
    missionVariables.$HUDSelectorDefaultMFDs_new = JSON.stringify(this.$HUDSelectorDefaultMFDs);
    missionVariables.$HUDSelectorScanner = this.$HUDSelectorScanner;
    if (this.$combatWS && this.$combatWS.$DataShow)
        missionVariables.$HUDSelectorDataShow = JSON.stringify(this.$combatWS.$DataShow);
}
//---------------------------------------------------------------------------------
this.shipLaunchedFromStation = function () {
    this.$HUDSelectorSetScanner(this.$HUDSelectorScanner); //restore the scanner linear and zoom settings
    var p = player.ship;
    p.hudHidden = false; //fix problems in other addons
    if (p.hud == "hudselector-extralarge.plist" || p.hud == "hudselector-extralarge10.plist" || p.hud == "hudselector-large.plist") {
        if (p.cargoSpaceCapacity == 0) {
            p.hud = p.hud.replace(".plist", "-nocargo.plist");
        }
    }
}
//---------------------------------------------------------------------------------
/*this.shipTargetAcquired = this.shipTargetLost = function () {
    //Must fix after each target loss due to Auto Crosshairs OXP break the scanner settings
    if (worldScripts["Auto Crosshairs"]) this.$C = -1;
}*/
//---------------------------------------------------------------------------------
this.shipWillDockWithStation = function (station) {
    var p = player.ship;
    var l = p.multiFunctionDisplayList;
    if (l) { //from Oolite 1.81
        //        log(this.name, "MFDList: "+l);//debug
        worldScripts.hudselector.$HUDSelectorDefaultMFDs = l; //save in-flight changes
    }
    if (p.hud.indexOf("hudselector-") == 0 && p.hud.indexOf("-nocargo") != -1) {
        p.hud = p.hud.replace("-nocargo", "");
    }
}
//---------------------------------------------------------------------------------
this.shipDockedWithStation = function (station) {
    this.$setInterface();
}
//---------------------------------------------------------------------------------
this.shipWillLaunchFromStation = function () {
    this.$HUDSelectorSetMFDs(); //must setup MFDs here and not earlier in startup()
    player.ship.hudHidden = false; //fix problems in other addons
}
//
//HUDSelector methods
//
//---------------------------------------------------------------------------------
this.$setInterface = function () {
    this.$HUDSelectorDialNo = 0;
    player.ship.dockedStation.setInterface("HUD and MFD selector", {
        title: "HUD and MFD selector",
        category: "Ship Systems",
        summary: "Select your HUD and the default Multi-Function Displays (MFDs).",
        callback: this.$HUDSelector_Interface.bind(this)
    });
}
//---------------------------------------------------------------------------------
this.$HUDSelectorAddHUD = function (hudname, plist4, plist10, plist9) { //for 4:3, 16:10 and 16:9
    var ws = null;
    if (worldScripts[plist4])
        ws = plist4;
    else {
        var i = plist4.indexOf("-");
        if (i >= 0 && worldScripts[plist4.slice(0, i)])
            ws = plist4.slice(0, i);
    }
    worldScripts.hudselector.$HUDSelectorHUDs.push([ws, hudname, plist4, plist10, plist9]);
}
//---------------------------------------------------------------------------------
this.$HUDSelectorAddMFD = function (mfdworldscript, mfdname, displayName) {
    if (!mfdworldscript) return; //this one is really needed
    if (!mfdname) mfdname = mfdworldscript; //if the mfd name is missing then assume than equal with wsname
    if (!displayName) displayName = mfdname;
    var mfdin = false;
    for (var i = 0; i < this.$HUDSelectorMFDs.length; i++) {
        if (this.$HUDSelectorMFDs[i] && mfdworldscript == this.$HUDSelectorMFDs[i][0] &&
            (!mfdname || mfdname === mfdworldscript || mfdname === this.$HUDSelectorMFDs[i][1]))
            mfdin = true;
    }
    if (!mfdin) this.$HUDSelectorMFDs.push([mfdworldscript, mfdname, displayName]);
}
//---------------------------------------------------------------------------------
this.$HUDSelectorRestoreHUD = function $HUDSelectorRestoreHUD() { //call after all startUp finished where other worldScripts can add HUDs
    var hud = missionVariables.$HUDSelectorHUD; //restore saved HUD
    if (hud && hud.length > 0) {
        var i = this.$HUDSelectorHUDs.length;
        while (i--) {
            if (this.$HUDSelectorHUDs[i][2] == hud) {
                this.$HUDSelectorEqSel = i;
                break;
            }
        }
    }
}
//---------------------------------------------------------------------------------
this.$HUDSelectorSetHUD = function $HUDSelectorSetHUD(prev) {
    var s = this.$HUDSelectorHUDs[this.$HUDSelectorEqSel];
    var p = s[2]; //plist for 4:3, universal plist or scripted in the oxp of the selected HUD
    if (s[3] || s[4]) {
        var o = oolite.gameSettings.gameWindow;
        var wide = o.width / o.height; ///
        var wn = 2; //4:3 (default)
        if (wide > 1.75) wn = 4; //1.77 = 16:9 screen
        else if (wide > 1.55) wn = 3; //1.6 = 16:10 screen, used in extralarge hud
        //        log(this.name, "Wide: "+w+" "+wn);//debug
        if (s[wn]) p = s[wn];
    }
    if (player.ship.cargoSpaceCapacity == 0) {
        switch (p) {
            case "hudselector-extralarge": 
            case "hudselector-extralarge10":
            case "hudselector-large":
                p += "-nocargo";
                break;
        }
    }
    player.ship.hud = p + ".plist"; //set the selected HUD
    this.$HUDSelectorSetScanner(this.$HUDSelectorScanner); //restore the scanner linear and zoom settings
    var sel_ws = this.$HUDSelectorHUDs[this.$HUDSelectorEqSel][0];
    // there might be more than one HUD in the same worldScript, and the chosen might not be the last...
    // first de-activate the un-chosen ones
    if (prev && prev >= 0 && prev < this.$HUDSelectorHUDs.length) {
        // just call the previous hud's callback
        var wh = worldScripts[this.$HUDSelectorHUDs[prev][0]];
        if (wh && wh.$HUDSelectorCallBack)
            wh.$HUDSelectorCallBack(true);
    } else {
        var i = this.$HUDSelectorHUDs.length;
        var calls = [];
        while (i--) { //call callback functions
            if (i != this.$HUDSelectorEqSel) {
                var ws = this.$HUDSelectorHUDs[i][0];
                var wh = worldScripts[ws];
                // only call the callback if it's valid, the function exists, 
                //  it's not the worldscript of our selected hud and we haven't called this worldscript already
                if (wh && wh.$HUDSelectorCallBack && ws != sel_ws && calls.indexOf(ws) == -1) {
                    calls.push(ws);
                    wh.$HUDSelectorCallBack(true);
                }
            }
        }
    }
    // activate the chosen one 
    wh = worldScripts[sel_ws];
    if (wh && wh.$HUDSelectorCallBack) {
        wh.$HUDSelectorCallBack(false);
    }
    this.$HUDSelectorSetMFDs();
}
//---------------------------------------------------------------------------------
this.$HUDSelectorSetMFDs = function () {
    var def_mfds = this.$HUDSelectorDefaultMFDs;
    var mfds = this.$HUDSelectorMFDs;
    var i = def_mfds.length;
    while (i--) {
        if (def_mfds[i]) {
            var w = def_mfds[i]; //worldScript or MFD name
            var mfd = -1;
            if (w && w.length > 0 && w != "undefined") {
                var j = mfds.length;
                while (j--) {
                    if (mfds[j][0] == w || mfds[j][1] == w) {
                        mfd = j; 
                        break;
                    }
                }
            }
            var m = null;
            if (mfd > -1) m = mfds[mfd][1]; //MFD name
            if (!m) m = w; //mfd name is equal with worldScript name
            if (m && w != "undefined" && worldScripts[w])
                player.ship.setMultiFunctionDisplay(i, m);
            else if (w && w.length > 0 && w != "undefined") 
                player.ship.setMultiFunctionDisplay(i, w);
            else 
                player.ship.setMultiFunctionDisplay(i, "");
        }
    }
}
//---------------------------------------------------------------------------------
this.$HUDSelectorSetScanner = function (b) {
    if (b == 1 || b == 3) player.ship.scannerNonLinear = true;
    else player.ship.scannerNonLinear = false;
    if (b == 2 || b == 3) player.ship.scannerUltraZoom = true;
    else player.ship.scannerUltraZoom = false;
    this.$HUDSelectorScanner = b;
}
//---------------------------------------------------------------------------------
this.$HUDSelector_FixFCB = function (delta) { //FrameCallBack for fixing crosshairs change bug
    if (player && player.ship) {
        //detect crosshairs change made by Auto Crosshairs OXP
        if (this.$C != player.ship.crosshairs && this.$HUDSelectorFix) { //can be disabled by this variable
            this.$C = player.ship.crosshairs;
            this.$HUDSelectorSetScanner(this.$HUDSelectorScanner); //fix scanner settings cleared by crosshairs change
        }
        if (this.$H != player.ship.hud && this.$HUDSelectorFix) { //can be disabled by this variable
            this.$H = player.ship.hud; //a scripted hud changed the actual plist and reverted back the scanner settings
            this.$HUDSelectorSetScanner(this.$HUDSelectorScanner); //fix scanner settings cleared by crosshairs change
        }
        var l = player.ship.scannerNonLinear;
        var z = player.ship.scannerUltraZoom;
        if (this.$L != l || this.$Z != z) { //log scanner settings changes and crosshair problems
            this.$L = l;
            this.$Z = z;
            if (this.$HUDSelectorFixInEveryFrame) this.$HUDSelectorSetScanner(this.$HUDSelectorScanner);
            else log(this.name, "Scanner NonLinear:" + l + " UltraZoom:" + z
                + " HUD:" + player.ship.hud + " Crosshairs: " + player.ship.crosshairs
                + ", scanner settings is not fixed.");
        }
    }
}
//---------------------------------------------------------------------------------
this.$HUDSelector_Interface = function () {
    player.ship.hudHidden = false;
    //this.$HUDSelectorSetHUD();
    var c = [];
    var title = "HUD selector";
    var len = this.$HUDSelectorHUDs.length;
    var maxc = 18; //max.22 lines in total with mfd, custom dials, more and exit
    if (!player.ship.hudAllowsBigGui) maxc = 14;
    var dialno = this.$HUDSelectorDialNo;
    if (dialno >= len) dialno = this.$HUDSelectorDialNo = 0; //go back to the start
    for (var j = dialno; j < dialno + maxc && j < len; j++)
        c[j] = this.$padText((j + 1) + ". " + this.$HUDSelectorHUDs[j][1], 20);
    var cds = "Combat MFD custom dials setup";
    if (!player.ship.setCustomHUDDial) cds += " (need Oolite 1.81)";
    if (!this.$combatWS || !this.$combatWS.$DataArray) cds += " (need CombatMFD 1.8)";
    var ch = {
        "_0": { text: "MFD setup", color: "orangeColor" },
        "_00": { text: cds, color: "orangeColor" },
        "_ME": { text: "Exit", color: "orangeColor" },
    };
    for (var i = 0; i < maxc; i++) {
        if (dialno + i < len) ch["_" + (i + 10).toString()] = c[dialno + i];
    }
    if (len > maxc) {
        ch["_M"] = { text: "More", color: "orangeColor" };
    }
    var ic = "_ME";
    if (this.$HUDSelectorEqSel >= dialno && this.$HUDSelectorEqSel < dialno + maxc)
        ic = "_" + (10 + this.$HUDSelectorEqSel - dialno);
    mission.runScreen(
        {
            title: title,
            screenID: "HUDSelector_HUDs",
            message: "Select your preferred HUD from the options below.\nUp/down arrows to select a HUD.\nPress Enter to make it your default.",
            background: this.$BG,
            allowInterrupt: true,
            exitScreen: "GUI_SCREEN_INTERFACES",
            registerKeys: {"esc":[{key:"esc"}]},
            spinModel: false,
            initialChoicesKey: ic,
            choices: ch
        },
        this.$hudSelector_Choice, this);
}
//-------------------------------------------------------------------------------------------------------------
this.$hudSelector_Choice = function (choice, key) {
    var maxc = 18; //max.22 lines in total with mfd, custom dials, more and exit
    this.$HUDSelectorChoice = choice;
    if (choice == "_ME" || key== "esc") {
        this.$HUDSelectorDialNo = 0; //start in the first page next time
        return;
    }
    if (choice == "_0") {
        this.$HUDSelectorChoice = null;
        this.$HUDSelectorDialNo = 0;
        this.$HUDSelector_InterfaceMFD();
        this.$HUDSelectorDialNo = 0; //start in the first page next time
        return;
    }
    if (choice == "_00") {
        if (!player.ship.setCustomHUDDial) {
            player.consoleMessage("Custom dials need Oolite 1.81", 10);
        } else if (!this.$combatWS || !this.$combatWS.$DataArray) {
            player.consoleMessage("Custom dials need CombatMFD 1.8", 10);
        } else {
            this.$HUDSelectorChoice = null;
            this.$HUDSelectorDialNo = 0;
            this.$HUDSelector_InterfaceDial();
            this.$HUDSelectorDialNo = 0; //start in the first page next time
            return;
        }
    }
    if (choice == "_M") {
        this.$HUDSelectorChoice = null;
        this.$HUDSelectorDialNo += maxc;
    } else if (choice != "_00") {
        var t = -1;
        if (choice) t = choice.substr(1) - 10; //cut starting "_"
        //               log(this.name, "MFD choice: "+choice+" "+t);//debug
        if (t >= 0) {
            t += this.$HUDSelectorDialNo;
            var prev = this.$HUDSelectorEqSel;
            this.$HUDSelectorEqSel = t;
            player.consoleMessage("HUD set to " + $HUDSelectorHUDs[t][1]);
            this.$HUDSelectorSetHUD(prev);
        }
    }
    this.$HUDSelector_Interface();
}
//---------------------------------------------------------------------------------
this.$HUDSelector_InterfaceMFD = function () {
    //    player.ship.hudHidden = true; - cause MarketObserver disappear from F8 screen
    var title = "Default MFD selector";
    var p = player.ship;
    var len = 40;
    if (p && p.isValid) len = p.multiFunctionDisplays;
    var maxc = 20; //max.22 lines in total with done and exit
    var dialno = this.$HUDSelectorDialNo;
    if (dialno >= len) dialno = this.$HUDSelectorDialNo = 0; //go back to the start
    var index = 10;
    var ch = {};
    for (var j = dialno; j < dialno + maxc && j < len; j++) {
        var z = this.$lookupMFDDisplayName(this.$HUDSelectorDefaultMFDs[j]);
        if (!z) z = "undefined";
        ch["_" + index.toString()] = this.$padText("MFD slot " + (j + 1) + ":", 6) + this.$padText(z, 17);
        index += 1;
    }
    // only put the "more" item on if there are more to show
    if (len > maxc) ch["_M"] = { text: "More", color: "orangeColor" };
    ch["_ME"] = { text: "Return", color: "orangeColor" };
    var ic = "_ME";
    if (this.$HUDSelectorChoice) ic = this.$HUDSelectorChoice;
    // checking for the presence of a new function in the global object that indicates the version of Oolite is sufficient for the extra keys to work
    mission.runScreen(
        {
            title: title,
            screenID: "HUDSelector_MFDs",
            message: "Select which MFDs will be displayed in the available slots of your HUD by default. " +
                "These settings will be saved with your game and restored whenever you launch.\n\nUp/down arrows select MFD slot. " +
                (global.getColorSaturation ? "Left/right arrows select MFD content." : "Enter to cycle MFD content."),
            background: this.$BG,
            spinModel: false,
            registerKeys: { "left": [{ key: "arrowLeft" }], "right": [{ key: "arrowRight" }], "esc":[{key:"esc"}] },
            allowInterrupt: true,
            initialChoicesKey: ic,
            exitScreen: "GUI_SCREEN_INTERFACES",
            choices: ch
        },
        this.$mfdSelector_Choice, this);
}
//-------------------------------------------------------------------------------------------------------------
this.$mfdSelector_Choice = function (choice, key) {
    var maxc = 20; //max.22 lines in total with done and exit
    this.$HUDSelectorChoice = choice;
    if (((!key || key == null || key == "enter") && choice == "_ME") || key == "esc") {
        this.$HUDSelector_Interface();
        return;
    }
    if ((key == null || key == "enter") && choice == "_M") {
        this.$HUDSelectorChoice = null;
        this.$HUDSelectorDialNo += maxc;
    } else {
        var t = -1;
        if (choice) t = choice.substr(1) - 10; //cut starting "_"
        //            log(this.name, "MFD choice: "+choice+" "+t);//debug
        if (t >= 0) {
            t += this.$HUDSelectorDialNo;
            var m = this.$HUDSelectorDefaultMFDs[t];
            var mfd = 0;
            if (m && m.length > 0 && m != "undefined") {
                for (var i = 0; i < this.$HUDSelectorMFDs.length; i++) {
                    if (this.$HUDSelectorMFDs[i] &&
                        (m == this.$HUDSelectorMFDs[i][0] || m == this.$HUDSelectorMFDs[i][1]))
                        mfd = i + (key == "left" ? -1 : 1); //step to the next MFD
                }
            }
            if (mfd >= this.$HUDSelectorMFDs.length || mfd < 0) {
                this.$HUDSelectorDefaultMFDs[t] = "undefined";
                if (mfd == -1) mfd = this.$HUDSelectorMFDs.length - 1;
            } else {
                var f = this.$HUDSelectorMFDs[mfd][1]; //mfdname
                if (!f) f = this.$HUDSelectorMFDs[mfd][0]; //worldscriptname
                this.$HUDSelectorDefaultMFDs[t] = f;
            }
        }
    }
    this.$HUDSelector_InterfaceMFD();
}
//---------------------------------------------------------------------------------
this.$lookupMFDDisplayName = function (mfdname) {
    for (var i = 0; i < this.$HUDSelectorMFDs.length; i++) {
        if (this.$HUDSelectorMFDs[i][1] == mfdname || this.$HUDSelectorMFDs[i][0] == mfdname) return this.$HUDSelectorMFDs[i][2];
    }
    return mfdname;
}
//---------------------------------------------------------------------------------
this.$HUDSelector_InterfaceDial = function () {
    var c = [];
    var title = "Combat MFD Custom dials setup";
    var len = this.$combatWS.$DataArray.length;
    var maxc = 20;//max.22 lines in total with more and exit
    if (!player.ship.hudAllowsBigGui) maxc = 14;
    var more = null;
    if (len > maxc) more = "More";
    var dialno = this.$HUDSelectorDialNo;
    if (dialno >= len) dialno = this.$HUDSelectorDialNo = 0; //go back to the start
    for (var j = dialno; j < dialno + maxc && j < len; j++) {
        var combatKey = this.$combatWS.$DataArray[j];
        if (combatKey) {
            c[j] = this.$padText((j + 1) + ". " + combatKey + ": ", 10) + this.$padText(this.$combatWS.$DataShow[combatKey].toString(), 5);
        }
    }
    var ch = {
        "_M": { text: more, color: "orangeColor" },
        "_ME": { text: "Return", color: "orangeColor" },
    };
    for (var i = 0; i < maxc; i++) {
        if (dialno + i < len) ch["_" + (i + 10).toString()] = c[dialno + i];
    }
    var ic = "_M";
    if (this.$HUDSelectorChoice) ic = this.$HUDSelectorChoice;
    mission.runScreen(
        {
            title: title,
            screenID: "HUDSelector_Dials",
            message: "Controls which of the values from Combat MFD will be updated in any custom HUD dials that have been set up in the HUD." +
                "\nNote: Only HUDs which have added custom dials linked to these Combat HUD values will be impacted.\nUp/down arrows to select value. Enter to change value.",
            background: this.$BG,
            allowInterrupt: true,
            exitScreen: "GUI_SCREEN_INTERFACES",
            registerKeys: {"esc":[{key:"esc"}]},
            spinModel: false,
            initialChoicesKey: ic,
            choices: ch
        },
        this.$dialSelector_Choice, this);
}
//-------------------------------------------------------------------------------------------------------------
this.$dialSelector_Choice = function (choice, key) {
    var maxc = 20;//max.22 lines in total with more and exit
    if (player.ship.hudAllowsBigGui == false) maxc = 14;
    this.$HUDSelectorChoice = choice;
    if (choice == "_ME" || key == "esc") {
        this.$HUDSelector_Interface();
        return;
    }
    if (choice == "_M") {
        this.$HUDSelectorChoice = null;
        this.$HUDSelectorDialNo += maxc;
    } else {
        var t = -1;
        if (choice) t = choice.substr(1) - 10; //cut starting "_"
        if (t >= 0) {
            t += this.$HUDSelectorDialNo;
            var combatKey = this.$combatWS.$DataArray[t];
            this.$combatWS.$DataShow[combatKey] = //inverse
                !this.$combatWS.$DataShow[combatKey];
            if (!this.$combatWS.$DataShow[combatKey]) //clear the old content
                player.ship.setCustomHUDDial(combatKey, "");
        }
    }
    this.$HUDSelector_InterfaceDial();
}
//-------------------------------------------------------------------------------------------------------------
// appends space to currentText to the specified length in 'em'
this.$padText = function $padText(currentText, desiredLength, leftSwitch, centreSwitch) {
    var that = $padText;
    var hairSpace = (that.hairSpace = that.hairSpace || this._hairSpace);
    var ellip = (that.ellip = that.ellip || this._ellip);
    var hairSpaceLength = (that.hairSpaceLength = that.hairSpaceLength || this._hairSpaceLength);
    var measure = (that.measure = that.measure || defaultFont.measureString);
    if (currentText == null) currentText = "";
    var currentLength = measure(currentText.replace(/%%/g, "%"));
    // calculate number needed to fill remaining length
    var padsNeeded = Math.floor((desiredLength - currentLength) / hairSpaceLength);
    if (padsNeeded < 1) {
        // text is too long for column, so start pulling characters off
        var tmp = currentText;
        do {
            tmp = tmp.substring(0, tmp.length - 2) + ellip;
            if (tmp === ellip) break;
        } while (measure(tmp.replace(/%%/g, "%")) > desiredLength);
        currentLength = measure(tmp.replace(/%%/g, "%"));
        padsNeeded = Math.floor((desiredLength - currentLength) / hairSpaceLength);
        currentText = tmp;
    }
    // quick way of generating a repeated string of that number
    if (!leftSwitch || leftSwitch === false) {
        if (!centreSwitch || centreSwitch === false) {
            return currentText + new Array(padsNeeded).join(hairSpace);
        } else {
            return currentText + new Array(parseInt(padsNeeded / 2)).join(hairSpace);
        }
    } else {
        if (!centreSwitch || centreSwitch === false) {
            return new Array(padsNeeded).join(hairSpace) + currentText;
        } else {
            return new Array(parseInt(padsNeeded / 2)).join(hairSpace) + currentText;
        }
    }
}
 |