"use strict";
this.name = "VimanaX_HUD";
this.author = "Gnievmir, phkb";
this.license = "CC-BY-NC-SA 3.0";

this._hairSpace = String.fromCharCode(31);
this._hairSpaceLength = defaultFont.measureString(this._hairSpace);
this._ellip = "…";

this._debug = false;
this._style = "dark";
this._nonLinear = true;
this._ultraZoom = true;
this._AMS = null; // antimissile system
this._SRS = null; // self repair system
this._TLS = null; // telescope
this._TFS = null; // target filtering system
this._SLS = null; // sniper lock        
this._SLP = null; // sniper lock plus       
this._ACH = null; // autocrosshair
this._SEC = null; // shield equalizer-capacitors
this._SC = null;  // Shield Cycler
this._LMSS = null; // LMSS
this._MS = null; // Manifest scanner
this._combatMFD = null;
this._telescopeVersion = 0;
this._specialSlots = [];
this._setSlot1 = 1;
this._setSlot2 = 2;
this._reqFuel = 0;
this._lastUsed = [];
this._hullAnim = [];
this._infoTimer = null; //store pointer to text info timer
this._iconTimer = null; //store pointer to graphical info timer
this._maintenance = false;
this._cbf = null;
this._govs = [];
this._ecos = [];
this._eqDamaged = [];
this._inflightHUD = "VimanaX_HUD-10mfds.plist"; // default hud when HUD selector isn't installed
this._dockedHUD = "VimanaX_HUD_docked-10mfds.plist";
this._checkMFDCycle = 0;
this._SC_Armour = false;
this._spacer = "";
this._staticText = {};
this._default = "";
this._killsOnLaunch = 0;
this._timer1Ping = false;
this._timer2Ping = false;
this._timer3Ping = false;
this._mapScreenChangeTimer = null;
this._destination = -1; // current witchspace destination
this._lastSource = -1; // used to establish the start point for destination system calculations
this._holdTarget = 0;
this._widthLookup = 0; // index of the width value in the _widths dictionary 0 = normal, 1 = narrow
this._clockFCB = null;
this._img = 0;
this._hostilesAge = 0;
this._wsi = null;
this._gameShips = {};

this._widths = {
    "VimanaX_ASCName": [9.64, 12.65],
    "VimanaX_SpecialSlot1": [8.9, 11.12],
    "VimanaX_SpecialSlot2": [8.9, 11.12],
    "VimanaX_LaserName": [8.15, 10.38],
    "VimanaX_EQMode": [7.42, 9.64],
    "VimanaX_PSName": [9.74, 10.38],
    "VimanaX_L0": [11.12, 13.35],
    "VimanaX_Lh": [9.64, 11.86],
    "VimanaX_R0": [11.12, 13.35],
    "VimanaX_Rh1": [9.74, 10.38],
};

this._operationalFunctionNames = [ // list of functions to enable/disable at HUDSelector callback
    "shipDockedWithStation",
    "shipWillLaunchFromStation",
    "shipExitedWitchspace",
    "shipDied",
    "guiScreenChanged",
    "alertConditionChanged",
    "compassTargetChanged",
    "shipTargetAcquired",
    "playerBoughtNewShip",
    "missionScreenEnded",
    "mfdKeyChanged"
];

//----------------------------------------------------------------------------------------
this.startUp = function _vimanaXHUD_startUp() {
    var i = 0;
    this._combatMFD = worldScripts["combat_MFD"];
    worldScripts.VimanaX_Alerts._combatMFD = this._combatMFD;
    this.$measureText();
    var p = player.ship;
    p.crosshairs = "vx_crosshair_off.plist";
    p.setCustomHUDDial("VimanaX_Rh", "");
    if (!missionVariables.ironHide_percentage) missionVariables.ironHide_percentage = 0;
    for (i = 0; i < 8; i++) {
        this._govs.push(String.fromCharCode(i));
        this._ecos.push(String.fromCharCode(23 - i));
    }

    if (worldScripts["telescope"]) {
        this._TLS = worldScripts["telescope"];
        this._TLS.$TelescopeVSize = 4;
        this._TLS.$TelescopeVZoomSize = 4;
        // check what version of telescope is in play
        var ver = worldScripts["telescope"].version.split(".");
        this._telescopeVersion = 2;
        if (parseInt(ver[0]) == 1) this._telescopeVersion = 1;
        if (parseInt(ver[0]) >= 2) {
            if (ver.length > 1 && parseInt(ver[1]) > 0) this._telescopeVersion = 2.1;
            else if (ver.length > 2 && parseInt(ver[2]) > 1) this._telescopeVersion = 2.1;
        }
    }

    if (worldScripts.shieldequalizercapacitors) this._SEC = worldScripts.shieldequalizercapacitors;
    if (worldScripts.sniperlock) this._SLS = worldScripts.sniperlock;
    if (worldScripts.sniperlock_plus) this._SLP = worldScripts.sniperlock_plus;
    if (worldScripts["Auto Crosshairs"]) this._ACH = worldScripts["Auto Crosshairs"];
    if (worldScripts.ams_system) this._AMS = worldScripts.ams_system; else this._setSlot1 = 0;
    if (worldScripts["Target Filtering System"]) this._TFS = worldScripts["Target Filtering System"];
    if (worldScripts.ManifestScanner) this._MS = worldScripts.ManifestScanner;
    this._SRS = worldScripts["Repair System"];
    if (this._SRS) {
        if (this._SRS.version) {
            var bits = this._SRS.version.split(".");
            var major = parseInt(bits[0]);
            var minor = parseInt(bits[1]);
            if (major < 2 || (major == 2 && minor < 14)) {
                this._setSlot2 = 0;
                this._SRS = null;
            }
        } 
    } 
    this._SC = worldScripts["Shield Cycler"];
    //if (this._SC && this._SC.version && this._SC.version >= "2.1") this._SC = null;
    if (worldScripts.LMSS_Core) this._LMSS = worldScripts.LMSS_Core;

    i = p.equipment.length;
    while (i--) {
        if (p.equipmentStatus(p.equipment[i].equipmentKey) === "EQUIPMENT_DAMAGED") this._eqDamaged.push(p.equipment[i].name);
    }

    // if the player has already bought the original modules, auto-award them in this new save game (should only happen one time)
    if (!missionVariables.VimanaX_HUD_Style) {
        if (p.equipmentStatus("EQ_VIMANA_TARGET_MODULE") == "EQUIPMENT_OK" && p.equipmentStatus("EQ_VIMANAX_TARGET_MODULE") == "EQUIPMENT_UNAVAILABLE") p.awardEquipment("EQ_VIMANAX_TARGET_MODULE");
        if (p.equipmentStatus("EQ_VIMANA_TRAVEL_MODULE") == "EQUIPMENT_OK" && p.equipmentStatus("EQ_VIMANAX_TRAVEL_MODULE") == "EQUIPMENT_UNAVAILABLE") p.awardEquipment("EQ_VIMANAX_TRAVEL_MODULE");
        if (p.equipmentStatus("EQ_VIMANA_SHIP_MODULE") == "EQUIPMENT_OK" && p.equipmentStatus("EQ_VIMANAX_SHIP_MODULE") == "EQUIPMENT_UNAVAILABLE") p.awardEquipment("EQ_VIMANAX_SHIP_MODULE");
    }

    if (missionVariables.VimanaX_HUD_SpecialSlot1) this._setSlot1 = parseInt(missionVariables.VimanaX_HUD_SpecialSlot1);
    if (missionVariables.VimanaX_HUD_SpecialSlot2) this._setSlot2 = parseInt(missionVariables.VimanaX_HUD_SpecialSlot2);
    if (missionVariables.VimanaX_HUD_DisableAlerts) worldScripts.VimanaX_Alerts._disabled = (missionVariables.VimanaX_HUD_DisableAlerts == "1" ? true : false);
    if (missionVariables.VimanaX_HUD_Style) this._style = missionVariables.VimanaX_HUD_Style;
    if (missionVariables.VimanaX_HUD_NonLinear) this._nonLinear = (missionVariables.VimanaX_HUD_NonLinear == "1" ? true : false);
    if (missionVariables.VimanaX_HUD_UltraZoom) this._ultraZoom = (missionVariables.VimanaX_HUD_UltraZoom == "1" ? true : false);
    if (missionVariables.VimanaX_HUD_Inflight) this._inflightHUD = missionVariables.VimanaX_HUD_Inflight;
    switch (this._inflightHUD) {
        case "VimanaX_HUD-6mfds.plist": this._dockedHUD = "VimanaX_HUD_docked-6mfds.plist"; break;
        case "VimanaX_HUD-10mfds.plist": this._dockedHUD = "VimanaX_HUD_docked-10mfds.plist"; break;
        case "VimanaX_HUD-12mfds.plist": this._dockedHUD = "VimanaX_HUD_docked-12mfds.plist"; break;
    }

    var hs = worldScripts.hudselector;
    if (hs) {
        hs.$HUDSelectorAddHUD("Vimana-X HUD 6 MFDs", this.name + "-6mfds");
        hs.$HUDSelectorAddHUD("Vimana-X HUD 10 MFDs", this.name + "-10mfds");
        hs.$HUDSelectorAddHUD("Vimana-X HUD 12 MFDs", this.name + "-12mfds");
        this.$updateHUDSelectorSettings();
    }

    if (p.hud.indexOf("VimanaX") >= 0) p.hud = this._dockedHUD;

    this.$updateShipConfigHUD();

    if (p.equipmentStatus("EQ_AMS") === "EQUIPMENT_UNAVAILABLE") {
        if (this._setSlot1 == 1) this._setSlot1 = 0;
        if (this._setSlot2 == 1) this._setSlot2 = 0;
    }
    if (this._SRS && !this._SRS.$controllerVersion) {
        if (this._setSlot1 == 2) this._setSlot1 = 0;
        if (this._setSlot2 == 2) this._setSlot2 = 0;
    }
    this.$changeSettings();

    this._wsi = worldScripts.WireframeShipImages;
    // add a reference ot the gameShips dictionary, in case another mod references it here.
    this._gameShips = this._wsi._gameShips;
}

//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function _vimanaXHUD_startUpComplete() {
    this._clockFCB = addFrameCallback(this.$updateClock.bind(this));

    this.$switchDockedColor();

    this.$initInterface(player.ship.dockedStation);
    if (worldScripts.ShipConfiguration_F3HUDControl) {
        if (player.ship.hud.indexOf(this.name) >= 0) this.$updateShipConfigHUD();
    }

    // pre-calc the centering function on these text items, so we don't have to do it repeatedly later
    this._staticText.targetHeader = this.$padText(".: TARGET INFO :.", 9.16, false, true);
    this._staticText.travelHeader = this.$padText(".: TRAVEL INFO :.", 9.16, false, true);
    this._staticText.checkList = this.$padText("..:: CheckList ::..", this._widths["VimanaX_R0"][this._widthLookup], true, true);
    this._staticText.shipDamaged = this.$padText("SHIP DAMAGED!", this._widths["VimanaX_Rh1"][this._widthLookup], true, true);
    this._staticText.shipInfo = this.$padText(".: SHIP INFO :.", 9.16, true, true);
    this._staticText.nextHops = this.$padText("...: NEXT HOPS :...", this._widths["VimanaX_L0"][this._widthLookup], true, true);
    this._staticText.unavailable = this.$padText("UNAVAILABLE", this._widths["VimanaX_L0"][this._widthLookup], true, true);
    this._staticText.moduleNotInstalled = this.$padText("Module not installed", this._widths["VimanaX_L0"][this._widthLookup], true, true);
    this._staticText.moduleDamaged = this.$padText("Module damaged", this._widths["VimanaX_L0"][this._widthLookup], true, true);

    this._lastSource = system.ID;
}

//-------------------------------------------------------------------------------------------------------------
this.playerBoughtNewShip = function _vimanaXHUD_playerBoughtNewShip(ship, price) {
    this.$setDestination();
    this.$initInterface(player.ship.dockedStation);
}

//----------------------------------------------------------------------------------------
this.playerWillSaveGame = function _vimanaXHUD_playerWillSaveGame() {
    missionVariables.VimanaX_HUD_SpecialSlot1 = this._setSlot1;
    missionVariables.VimanaX_HUD_SpecialSlot2 = this._setSlot2;
    missionVariables.VimanaX_HUD_DisableAlerts = (worldScripts.VimanaX_Alerts._disabled ? "1" : "0");
    missionVariables.VimanaX_HUD_Style = this._style;
    missionVariables.VimanaX_HUD_NonLinear = (this._nonLinear ? "1" : "0");
    missionVariables.VimanaX_HUD_UltraZoom = (this._ultraZoom ? "1" : "0");
    missionVariables.VimanaX_HUD_Inflight = this._inflightHUD;
}

//----------------------------------------------------------------------------------------
this.$HUDSelectorCallBack = function _vimanaXHUD_HUDSelectorCallBack(off) {
    var ws = worldScripts.VimanaX_HUD;
    var pship = player.ship;
    var funcNames = this._operationalFunctionNames;
    var i = funcNames.length;
    if (ws._debug) log(this.name, "HUDSelectorCallBack, off:" + off + ", pship.hud:" + pship.hud);
    if (off) {
        // disable
        ws.$stopTimers();
        if (isValidFrameCallback(ws._clockFCB)) removeFrameCallback(ws._clockFCB);

        while (i--)
            if (ws[funcNames[i]]) {
                ws["$save_" + funcNames[i]] = ws[funcNames[i]];
                delete ws[funcNames[i]];
            }
        if (pship.dockedStation) pship.dockedStation.setInterface(ws.name, null);
        worldScripts.VimanaX_Alerts.$disableAlerts();
        ws.$revertShipConfigHUD();
    } else {
        // enable
        this.$switchDockedColor();
        while (i--)
            if (!ws[funcNames[i]]) {
                ws[funcNames[i]] = ws["$save_" + funcNames[i]];
            }
        ws._inflightHUD = pship.hud;
        if (!pship.docked) {
            ws.shipWillLaunchFromStation();
            worldScripts.VimanaX_Alerts.shipExitedWitchspace();
        } else {
            switch (ws._inflightHUD) {
                case "VimanaX_HUD-6mfds.plist": ws._dockedHUD = "VimanaX_HUD_docked-6mfds.plist"; break;
                case "VimanaX_HUD-10mfds.plist": ws._dockedHUD = "VimanaX_HUD_docked-10mfds.plist"; break;
                case "VimanaX_HUD-12mfds.plist": ws._dockedHUD = "VimanaX_HUD_docked-12mfds.plist"; break;
            }
            pship.hud = ws._dockedHUD;
            if (!isValidFrameCallback(ws._clockFCB))
                ws._clockFCB = addFrameCallback(ws.$updateClock.bind(ws));
        }
        this.$updateHUDSelectorSettings();
        if (pship.dockedStation) this.$initInterface(pship.dockedStation);
        worldScripts.VimanaX_Alerts.$enableAlerts();
        ws.$updateShipConfigHUD();
    }
}

//----------------------------------------------------------------------------------------
this.missionScreenEnded = function() {
    this.$switchDockedColor();
}

//----------------------------------------------------------------------------------------
this.shipDockedWithStation = function _vimanaXHUD_shipDockedWithStation(station) {
    var p = player.ship;

    this.$stopTimers();
    if (isValidFrameCallback(this._cbf)) removeFrameCallback(this._cbf);
    if (!isValidFrameCallback(this._clockFCB)) this._clockFCB = addFrameCallback(this.$updateClock.bind(this));

    this._cbf = null;
    
    this._lastUsed[13] = "";
    this._inflightHUD = p.hud;
    switch (this._inflightHUD) {
        case "VimanaX_HUD-6mfds.plist": this._dockedHUD = "VimanaX_HUD_docked-6mfds.plist"; break;
        case "VimanaX_HUD-10mfds.plist": this._dockedHUD = "VimanaX_HUD_docked-10mfds.plist"; break;
        case "VimanaX_HUD-12mfds.plist": this._dockedHUD = "VimanaX_HUD_docked-12mfds.plist"; break;
    }
    p.hud = this._dockedHUD;
    this.$updateDockedHUDLabels();
    this.$initInterface(station);
}

//----------------------------------------------------------------------------------------
this.shipDied = function _vimanaXHUD_shipDied() {
    this.$stopTimers();
    if (isValidFrameCallback(this._cbf)) removeFrameCallback(this._cbf);
    this._cbf = null;
    this._lastUsed[13] = "";
}

//----------------------------------------------------------------------------------------
this.shipWillLaunchFromStation = function _vimanaXHUD_shipWillLaunchFromStation() {
    var p = player.ship;

    this._lastSource = system.ID;

    if (this._inflightHUD && p.hud.indexOf("VimanaX_HUD_docked") >= 0) p.hud = this._inflightHUD;
    if (isValidFrameCallback(this._clockFCB)) removeFrameCallback(this._clockFCB);

    this.$setHUDEquipment(false);
    this._timer1Ping = false;
    this._timer2Ping = false;
    this._timer3Ping = false;
    this._killsOnLaunch = player.score;

    var i = 20;
    while (i--) { this._lastUsed[i] = null; }

    if (!isValidFrameCallback(this._cbf))
        this._cbf = addFrameCallback(this.$showIndicators.bind(this));

    this.$checkMaint();

    //set player ship image
    var img = this._wsi.$getShipImage(p);
    this._hullAnim[0] = img;
    this.$AlertNo = 0;

    var eq = p.equipment;
    i = eq.length;
    while (i--) {
        if (eq[i].damageProbability > 0) this._lastUsed[16]++;
    }

    var sc = worldScripts.ShipConfiguration_Core;
    if (sc) {
        var a = sc._armour;
        if (a && a.length > 0) {
            i = a.length;
            while (i--) {
                if (a[i] && p.equipmentStatus(a[i]) === "EQUIPMENT_OK") {
                    this._SC_Armour = true;
                    break;
                }
            }
        }
    }

    if (!this._infoTimer) this._infoTimer = new Timer(this, this.$showInfo.bind(this), 2, 0.25);
    if (!this._iconTimer) this._iconTimer = new Timer(this, this.$showIcon.bind(this), 1, 0.5);
    this.$startAnim();
    this.$equipmentStatus();
    this._lastUsed[12] = 1;
    this.$setLPanel();

    // this will be redundant if HUD selector gets there first, but just in case
    p.hud.scannerUltraZoom = this._ultraZoom;
    p.hud.scannerNonLinear = this._nonLinear;

    if (worldScripts.ManualWitchspaceAlignment) {
        var mwa = worldScripts.ManualWitchspaceAlignment;
        if (mwa._userOverride === false) { // only do the change if the player hasn't told us not to
            mwa._color = 2; // 0 = blue, 1 = amber/orange, 2 = green, 3 = pink, 4 = purple, 5 = white
        }
    }  
}

//----------------------------------------------------------------------------------------
this.guiScreenChanged = function _vimanaXHUD_guiScreenChanged(to, from) {
	this._mapScreen = from;
	if (from !== "GUI_SCREEN_MAIN") {
		if (this._mapScreenChangeTimer == null || this._mapScreenChangeTimer.isRunning === false) 
            this._mapScreenChangeTimer = new Timer(this, this.$checkForNewDestination, 0.3, 0);
	}
    if (from === "GUI_SCREEN_SHORT_RANGE_CHART" || from === "GUI_SCREEN_LONG_RANGE_CHART") {
        this._lastUsed[12] = 1;
        this.$setLPanel();
    }
    if (from == "GUI_SCREEN_LOAD" && to == "GUI_SCREEN_STATUS") {
        this.$switchDockedColor();
    }
}

//----------------------------------------------------------------------------------------
this.equipmentRepaired = function _vimanaXHUD_equipmentRepaired(equipment) { //repaired
    var p = player.ship;
    var i = p.equipment.length;
    while (i--) {
        if (this._eqDamaged[i] == EquipmentInfo.infoForKey(equipment).name) this._eqDamaged.splice(i, 1);
    }
    if (p.isInSpace) {
        this.$equipmentStatus();
        if (equipment == "EQ_VIMANAX_SHIP_MODULE") this.$startAnim();
    }
}

//----------------------------------------------------------------------------------------
this.equipmentDamaged = function _vimanaXHUD_equipmentDamaged(equipment) {    //damaged
    var eq = EquipmentInfo.infoForKey(equipment);
    if (eq.isVisible) {
        this._eqDamaged.push(EquipmentInfo.infoForKey(equipment).name);
        if (player.ship.isInSpace) this.$equipmentStatus();
    }
}

//----------------------------------------------------------------------------------------
this.shipTargetAcquired = function _vimanaXHUD_shipTargetAcquired(target) {
    if (target.isWormhole) return;
    var p = player.ship;
    p.setCustomHUDDial("VimanaX_LPTitle", this._staticText.targetHeader);
    p.setCustomHUDDial("VimanaX_SClock", "");
    p.setCustomHUDDial("VimanaX_CEnergy", "");
    p.setCustomHUDDial("VimanaX_CSpeed", "");
    p.setCustomHUDDial("VimanaX_CMissile", "");

    if (p.equipmentStatus("EQ_VIMANAX_TARGET_MODULE") === "EQUIPMENT_OK") {
        var model = this._wsi.$getShipImage(target);
        p.setCustomHUDDial("VimanaX_PTarget", model);
    }
}

//----------------------------------------------------------------------------------------
this.shipExitedWitchspace = function _vimanaXHUD_shipExitedWitchspace() {
	if (system.ID != -1) this._lastSource = system.ID;
    this.$checkMaint();
	this._destination = this.$playerTargetSystem();
	this.$setDestination();
    this._lastUsed[12] = 1;
    this._lastUsed[13] = "";
    this.$setLPanel();
}

//----------------------------------------------------------------------------------------
this.alertConditionChanged = function _vimanaXHUD_alertConditionChanged(newState, oldState) {
    var cond = ["", "green_", "", "red_"][newState];
    if (this._debug) log(this.name, "Setting player's crosshairs to vx_" + cond + "crosshair_off.plist");
    player.ship.crosshairs = "vx_" + cond + "crosshair_off.plist";
    if (this._ACH) {
        this._ACH.$crosshairs.default.off = this._ACH.$offTargetCrosshairs = "vx_" + cond + "crosshair_off.plist";
        this._ACH.$onTargetCrosshairs = this._ACH.$crosshairs.default.on = "vx_" + cond + "crosshair_on.plist";
    }
}

//----------------------------------------------------------------------------------------
this.compassTargetChanged = function _vimanaXHUD_compassTargetChanged(whom, mode) {
    if (!whom) return;
    var target = "";
    if (mode === "COMPASS_MODE_BASIC") {
        if (whom.isPlanet) target = "Planet";
        else target = "Main Station";
    } else if (mode === "COMPASS_MODE_PLANET") {
        var s = System.infoForSystem(galaxyNumber, system.info.systemID);
        var ex = this._ecos[s.economy] + this._govs[s.government] + (s.techlevel + 1);
        target = whom.name + " " + ex;
    } else if (mode === "COMPASS_MODE_TARGET") {
        target = "Target";
    } else {
        if (whom.beaconLabel) target = whom.beaconLabel;
        else if (whom.displayName) target = whom.displayName;
        else if (whom.name) target = whom.name;
        else if (whom.beaconCode) target = whom.beaconCode;
        else target = "Unidentified";
    }

    player.ship.setCustomHUDDial("VimanaX_ASCName", this.$padText(target, this._widths["VimanaX_ASCName"][this._widthLookup]));
}

//----------------------------------------------------------------------------------------
this.playerBoughtEquipment = function _vimanaXHUD_playerBoughtEquipment(equipment) {
    var p = player.ship;
    if (equipment == "EQ_VIMANAX_SELL_TARGET_MODULE") {
        p.removeEquipment("EQ_VIMANAX_TARGET_MODULE");
        p.removeEquipment(equipment);
    }
    if (equipment == "EQ_VIMANAX_SELL_TRAVEL_MODULE") {
        p.removeEquipment("EQ_VIMANAX_TRAVEL_MODULE");
        p.removeEquipment(equipment);
    }
    if (equipment == "EQ_VIMANAX_SELL_SHIP_MODULE") {
        p.removeEquipment("EQ_VIMANAX_SHIP_MODULE");
        p.removeEquipment(equipment);
    }
}

/*******************************************************************
*             display hud icons (pictograms)
* ******************************************************************/

//----------------------------------------------------------------------------------------
this.$updateClock = function _vimanaXHUD_updateClock() {
    player.ship.setCustomHUDDial("VimanaX_Clock", clock.clockString);
}

//----------------------------------------------------------------------------------------
this.$setHUDEquipment = function _vimanaXHUD_setHUDEquipment(remove) {
    var p = player.ship;
    p.setCustomHUDDial("VimanaX_HUD_Main", "vx_vimana_hud_main_" + this._style + ".png");
    p.setCustomHUDDial("VimanaX_HUD_Surrounds", "vx_vimana_hud_surrounds_" + this._style + ".png");
    p.setCustomHUDDial("VimanaX_HUD_Compass", "vx_compass.png");
    p.setCustomHUDDial("VimanaX_WeaponLabel", "WEAPON");
    p.setCustomHUDDial("VimanaX_PrimedLabel", "PRIMED");
    p.setCustomHUDDial("VimanaX_EquipLabel", "EQUIP");
    p.setCustomHUDDial("VimanaX_ModeLabel", "MODE");
    p.setCustomHUDDial("VimanaX_SpeedLabel", "SPEED");
    p.setCustomHUDDial("VimanaX_FuelLabel", "FUEL");
    p.setCustomHUDDial("VimanaX_AltLabel", "ALT");
    p.setCustomHUDDial("VimanaX_CargoLabel", "CARGO");
    p.setCustomHUDDial("VimanaX_CTempLabel", "C.TEMP");
    p.setCustomHUDDial("VimanaX_EnergyLabel", "ENERGY");
    p.setCustomHUDDial("VimanaX_LTempLabel", "L.TEMP");
    p.setCustomHUDDial("VimanaX_FshLabel", "F.SH");
    p.setCustomHUDDial("VimanaX_AshLabel", "A.SH");

    p.removeEquipment("EQ_VIMANAX_FONT_NARROW");
    p.removeEquipment("EQ_VIMANAX_FONT_NORMAL");
    if (!remove) {
        if (this._widthLookup == 1) {
            p.awardEquipment("EQ_VIMANAX_FONT_NARROW");
        } else {
            p.awardEquipment("EQ_VIMANAX_FONT_NORMAL");
        }
    }

    var mfd = p.multiFunctionDisplayList;
    var i = p.multiFunctionDisplays;
    while (i--) {
        if (this._style == "light" || (mfd[i] == null || mfd[i] == "" || mfd[i] === undefined || mfd[i] === "undefined" || !this.$confirmMFDEquipment(mfd[i]))) {
            p.setCustomHUDDial("VimanaX_MFDBackground_" + (i + 1).toString(), "vx_blank.png");
        } else {
            p.setCustomHUDDial("VimanaX_MFDBackground_" + (i + 1).toString(), "vx_mfd_underlay.png");
        }
    }
}

//-------------------------------------------------------------------------------------------------------------
this.mfdKeyChanged = function(index, key) {
    var p = player.ship;
    if (this._style == "light" || (key == null || key == "" || key === undefined || key === "undefined" || !this.$confirmMFDEquipment(key))) {
        p.setCustomHUDDial("VimanaX_MFDBackground_" + (index + 1).toString(), "vx_blank.png");
    } else {
        p.setCustomHUDDial("VimanaX_MFDBackground_" + (index + 1).toString(), "vx_mfd_underlay.png");
    }
}

//-------------------------------------------------------------------------------------------------------------
this.$checkMFD = function $checkMFD(index) {
    var p = player.ship;
    if (!p || !p.isValid) return;
    var mfd = p.multiFunctionDisplayList;
    if (this._style == "light" || (mfd[index] == null || mfd[index] == "" || mfd[index] === undefined || !this.$confirmMFDEquipment(mfd[index]))) {
        p.setCustomHUDDial("VimanaX_MFDBackground_" + (index + 1).toString(), "vx_blank.png");
    } else {
        p.setCustomHUDDial("VimanaX_MFDBackground_" + (index + 1).toString(), "vx_mfd_underlay.png");
    }
}

//----------------------------------------------------------------------------------------
this.$stopTimers = function _vimanaXHUD_stopTimers() {
    if (this._infoTimer) {
        this._infoTimer.stop();
        delete this._infoTimer;
    }
    if (this._iconTimer) {
        this._iconTimer.stop();
        delete this._iconTimer;
    }
    if (this._animTimer) {
        this._animTimer.stop();
        delete this._animTimer;
    }
}

//----------------------------------------------------------------------------------------
this.$startAnim = function _vimanaXHUD_StartAnim() {
    if (player.ship.equipmentStatus("EQ_VIMANAX_SHIP_MODULE") === "EQUIPMENT_OK") {
        if (!this._animTimer) this._animTimer = new Timer(this, this.$animHull.bind(this), 3, 1);
        this._hullAnim[1] = 11;
    }
}

//----------------------------------------------------------------------------------------
this.$showIcon = function _vimanaXHUD_showIcon() {
    var that = _vimanaXHUD_showIcon;
    var _player = (that._player = that._player || player);
    var p = _player.ship;
    if (!p || !p.isValid) return;
    if (!this._timer1Ping) { this._timer1Ping = true; this.$playSound(); }
    var alerts = worldScripts.VimanaX_Alerts;

    var h = (p.alertCondition == 3 ? this.$getHostileShips(0.5) : null);

    if (h && h.length) {
        if (Math.floor((this._iconTimer.nextTime * 10) % 2))
            p.setCustomHUDDial("VimanaX_HCG", "vx_combat.png");
        else
            p.setCustomHUDDial("VimanaX_HCG", "vx_blank.png");
    } else {
        p.setCustomHUDDial("VimanaX_HCG", "vx_blank.png");
    }

    if (this._LMSS) { //lmss icon
        var ws = this._LMSS;
        switch (p.viewDirection) {
            case "VIEW_FORWARD":
                if (p.equipmentStatus("EQ_LMSS_FRONT") === "EQUIPMENT_OK")
                    this.$LMSSIcons(ws._forwardTimer);
                else if (p.equipmentStatus("EQ_LMSS_FRONT") === "EQUIPMENT_DAMAGED")
                    this.$blinkingIcons("VimanaX_Lmss", "vx_lmss_d.png");
                else
                    p.setCustomHUDDial("VimanaX_Lmss", "vx_blank.png");
                break;
            case "VIEW_AFT":
                if (p.equipmentStatus("EQ_LMSS_AFT") === "EQUIPMENT_OK")
                    this.$LMSSIcons(ws._aftTimer);
                else if (p.equipmentStatus("EQ_LMSS_AFT") === "EQUIPMENT_DAMAGED")
                    this.$blinkingIcons("VimanaX_Lmss", "vx_lmss_d.png");
                else
                    p.setCustomHUDDial("VimanaX_Lmss", "vx_blank.png");
                break;
            case "VIEW_PORT":
                if (p.equipmentStatus("EQ_LMSS_PORT") === "EQUIPMENT_OK")
                    this.$LMSSIcons(ws._portTimer);
                else if (p.equipmentStatus("EQ_LMSS_PORT") === "EQUIPMENT_DAMAGED")
                    this.$blinkingIcons("VimanaX_Lmss", "vx_lmss_d.png");
                else
                    p.setCustomHUDDial("VimanaX_Lmss", "vx_blank.png");
                break;
            case "VIEW_STARBOARD":
                if (p.equipmentStatus("EQ_LMSS_STARBOARD") === "EQUIPMENT_OK")
                    this.$LMSSIcons(ws._starboardTimer);
                else if (p.equipmentStatus("EQ_LMSS_STARBOARD") === "EQUIPMENT_DAMAGED")
                    this.$blinkingIcons("VimanaX_Lmss", "vx_lmss_d.png");
                else
                    p.setCustomHUDDial("VimanaX_Lmss", "vx_blank.png");
        }

        if (p.equipmentStatus("EQ_LMSS_ACTUATOR") === "EQUIPMENT_OK")
            p.setCustomHUDDial("VimanaX_LmsA", "vx_lmsa.png");
        else if (p.equipmentStatus("EQ_LMSS_ACTUATOR") === "EQUIPMENT_DAMAGED")
            this.$blinkingIcons("VimanaX_LmsA", "vx_lmsa_d.png");
        else
            p.setCustomHUDDial("VimanaX_LmsA", "vx_blank.png");
    }

    if (p.equipmentStatus("EQ_CLOAKING_DEVICE") === "EQUIPMENT_DAMAGED") this.$blinkingIcons("VimanaX_Cloaking", "vx_invisible_d.png");
    else if (p.isCloaked) this.$blinkingIcons("VimanaX_Cloaking", "vx_invisible.png");
    else p.setCustomHUDDial("VimanaX_Cloaking", "vx_blank.png");

    if (this._SEC) {
        //forward capacitor
        if (p.equipmentStatus("EQ_FORWARD_SHIELD_CAPACITOR") === "EQUIPMENT_DAMAGED")
            this.$blinkingIcons("VimanaX_CapacitorF", "vx_cap_f_d.png");
        else if (p.equipmentStatus("EQ_FORWARD_SHIELD_CAPACITOR") === "EQUIPMENT_OK") {
            if (this._SEC.secforwardshieldcapacitor == 0)
                p.setCustomHUDDial("VimanaX_CapacitorF", "vx_blank.png");
            else if (this._SEC.secforwardshieldcapacitor < this._SEC.$maxCapacitorCharge - p.forwardShieldRecharge)
                this.$blinkingIcons("VimanaX_CapacitorF", "vx_cap_f.png");
            else
                p.setCustomHUDDial("VimanaX_CapacitorF", "vx_cap_f.png");
        } else
            p.setCustomHUDDial("VimanaX_CapacitorF", "vx_blank.png");

        //center dot
        if (p.equipmentStatus("EQ_AFT_SHIELD_CAPACITOR") === "EQUIPMENT_DAMAGED" && p.equipmentStatus("EQ_FORWARD_SHIELD_CAPACITOR") === "EQUIPMENT_DAMAGED")
            p.setCustomHUDDial("VimanaX_CapacitorC", "vx_cap_c_d.png");
        else if (p.equipmentStatus("EQ_AFT_SHIELD_CAPACITOR") === "EQUIPMENT_OK" && p.equipmentStatus("EQ_FORWARD_SHIELD_CAPACITOR") === "EQUIPMENT_OK")
            p.setCustomHUDDial("VimanaX_CapacitorC", "vx_cap_c.png");
        else if (p.equipmentStatus("EQ_AFT_SHIELD_CAPACITOR") === "EQUIPMENT_OK" || p.equipmentStatus("EQ_FORWARD_SHIELD_CAPACITOR") === "EQUIPMENT_OK")
            this.$blinkingIcons("VimanaX_CapacitorC", "vx_cap_b.png", "vx_cap_c.png");
        else
            p.setCustomHUDDial("VimanaX_CapacitorC", "vx_blank.png");

        //aft capacitor    
        if (p.equipmentStatus("EQ_AFT_SHIELD_CAPACITOR") === "EQUIPMENT_DAMAGED")
            this.$blinkingIcons("VimanaX_CapacitorA", "vx_cap_a_d.png");
        else if (p.equipmentStatus("EQ_AFT_SHIELD_CAPACITOR") === "EQUIPMENT_OK") {
            if (this._SEC.secaftshieldcapacitor == 0)
                p.setCustomHUDDial("VimanaX_CapacitorA", "vx_blank.png");
            else if (this._SEC.secaftshieldcapacitor < this._SEC.$maxCapacitorCharge - p.aftShieldRecharge)
                this.$blinkingIcons("VimanaX_CapacitorA", "vx_cap_a.png");
            else
                p.setCustomHUDDial("VimanaX_CapacitorA", "vx_cap_a.png");
        } else
            p.setCustomHUDDial("VimanaX_CapacitorA", "vx_blank.png");
    } else {
        p.setCustomHUDDial("VimanaX_CapacitorF", "vx_blank.png");
        p.setCustomHUDDial("VimanaX_CapacitorC", "vx_blank.png");
        p.setCustomHUDDial("VimanaX_CapacitorA", "vx_blank.png");
    }

    if (p.equipmentStatus("EQ_SHIELD_EQUALIZER") === "EQUIPMENT_OK")
        p.setCustomHUDDial("VimanaX_SCycler", "vx_sc.png");
    else if (p.equipmentStatus("EQ_SHIELD_EQUALIZER") === "EQUIPMENT_DAMAGED")
        this.$blinkingIcons("VimanaX_SCycler", "vx_sc_d.png");
    else if (this._SC && this._SC._sc_settings && this._SC._sc_settings.sc.version) {
        if (this._SC._sc_settings.sc.functional == 100)
            p.setCustomHUDDial("VimanaX_SCycler", "vx_sc.png");
        else
            this.$blinkingIcons("VimanaX_SCycler", "vx_sc_d.png");
    } else
        p.setCustomHUDDial("VimanaX_SCycler", "vx_blank.png");

    //EQ_NAVAL_ENERGY_UNIT
    if (p.equipmentStatus("EQ_ENERGY_UNIT") === "EQUIPMENT_UNAVAILABLE" && p.equipmentStatus("EQ_NAVAL_ENERGY_UNIT") === "EQUIPMENT_UNAVAILABLE")
        p.setCustomHUDDial("VimanaX_EEnergy", "vx_blank.png");
    else {
        if (p.equipmentStatus("EQ_ENERGY_UNIT") === "EQUIPMENT_OK")
            p.setCustomHUDDial("VimanaX_EEnergy", "vx_eeu.png");
        else if (p.equipmentStatus("EQ_ENERGY_UNIT") === "EQUIPMENT_DAMAGED")
            this.$blinkingIcons("VimanaX_EEnergy", "vx_eeu_d.png");
        else if (p.equipmentStatus("EQ_NAVAL_ENERGY_UNIT") === "EQUIPMENT_OK")
            p.setCustomHUDDial("VimanaX_EEnergy", "vx_neu.png");
        else if (p.equipmentStatus("EQ_NAVAL_ENERGY_UNIT") === "EQUIPMENT_DAMAGED")
            this.$blinkingIcons("VimanaX_EEnergy", "vx_eeu_d.png");
    }

    if (p.equipmentStatus("EQ_ECM") === "EQUIPMENT_OK") p.setCustomHUDDial("VimanaX_ECM", "vx_ecm_o.png");
    else if (p.equipmentStatus("EQ_ECM") === "EQUIPMENT_DAMAGED") this.$blinkingIcons("VimanaX_ECM", "vx_ecm_d.png");

    if (this._maintenance == true) this.$blinkingIcons("VimanaX_Service", "vx_maintenance.png");
    else p.setCustomHUDDial("VimanaX_Service", "vx_blank.png");

    if (p.equipmentStatus("EQ_FUEL_INJECTION") === "EQUIPMENT_DAMAGED" || p.fuel < 0.1) this.$blinkingIcons("VimanaX_FInjector", "vx_injector_d.png");
    else if (p.equipmentStatus("EQ_FUEL_INJECTION") === "EQUIPMENT_OK") p.setCustomHUDDial("VimanaX_FInjector", "vx_injector.png");
    else p.setCustomHUDDial("VimanaX_FInjector", "vx_blank.png");

    if (((p.fuel).toFixed(1) < this._reqFuel && system.ID != p.targetSystem) || p.fuel < 0.1) this.$blinkingIcons("VimanaX_FuelAlert", "vx_low_fuel.png");
    else if (p.fuelLeakRate > 0 && p.fuel > 0) this.$blinkingIcons("VimanaX_FuelAlert", "vx_low_fuel.png");
    else p.setCustomHUDDial("VimanaX_FuelAlert", "vx_blank.png");

    //self repair system icons 
    var eqKey = (this._SRS && this._SRS.$controllerVersion ? this._SRS.$controllerVersion : null);
    if (eqKey) {
        if (this._SRS.$selfRepairsSystemStatus === "Active")
            this.$blinkingIcons("VimanaX_RepIcon", "vx_srs_0.png", "vx_srs_1.png");
        else if (this._SRS.$selfRepairsSystemStatus === "Self-repair")
            this.$blinkingIcons("VimanaX_RepIcon", "vx_srs_d.png", "vx_blank.png");
        else if (this._SRS.$selfRepairsSystemStatus === "Standby")
            p.setCustomHUDDial("VimanaX_RepIcon", "vx_srs.png");
        else if (this._SRS.$selfRepairsSystemStatus === "Shutdown")
            p.setCustomHUDDial("VimanaX_RepIcon", "vx_srs_d.png");
        else
            p.setCustomHUDDial("VimanaX_RepIcon", "vx_blank.png");
    } else
        p.setCustomHUDDial("VimanaX_RepIcon", "vx_blank.png");

    if (p.energy < p.maxEnergy / 3) this.$blinkingIcons("VimanaX_EnergyAlert", "vx_alert_red.png");
    else if (p.energy < p.maxEnergy / 2) this.$blinkingIcons("VimanaX_EnergyAlert", "vx_alert_orange.png");
    else p.setCustomHUDDial("VimanaX_EnergyAlert", "vx_blank.png");

    var ctmp = Math.round(100 * p.temperature);
    if (ctmp > 70) this.$blinkingIcons("VimanaX_CTempAlert", "vx_alert_red.png");
    else if (ctmp > 50) this.$blinkingIcons("VimanaX_CTempAlert", "vx_alert_orange.png");
    else p.setCustomHUDDial("VimanaX_CTempAlert", "vx_blank.png");

    if (p.forwardShield < p.maxForwardShield * 0.2) this.$blinkingIcons("VimanaX_FshAlert", "vx_alert_red.png");
    else if (!p.torusEngaged && p.forwardShield < p.maxForwardShield / 2) this.$blinkingIcons("VimanaX_FshAlert", "vx_alert_orange.png");
    else p.setCustomHUDDial("VimanaX_FshAlert", "vx_blank.png");

    if (p.aftShield < p.maxAftShield * 0.2) this.$blinkingIcons("VimanaX_AshAlert", "vx_alert_red.png");
    else if (!p.torusEngaged && p.aftShield < p.maxAftShield / 2) this.$blinkingIcons("VimanaX_AshAlert", "vx_alert_orange.png");
    else p.setCustomHUDDial("VimanaX_AshAlert", "vx_blank.png");

    if (alerts._lastAlert[4] < 10000) this.$blinkingIcons("VimanaX_AltAlert", "vx_alert_orange.png");
    else p.setCustomHUDDial("VimanaX_AltAlert", "vx_blank.png");

    if (alerts._incomingMiss) this.$blinkingIcons("VimanaX_MissAlert", "vx_target.png");
    else p.setCustomHUDDial("VimanaX_MissAlert", "vx_blank.png");
}

//----------------------------------------------------------------------------------------
this.$LMSSIcons = function _vimanaXHUD_LMSSIcons(tmr) {
    var p = player.ship;
    if (tmr && tmr.isRunning) {
        if (Math.floor(this._iconTimer.nextTime * 10) & 1) p.setCustomHUDDial("VimanaX_Lmss", "vx_lmss1.png");
        else p.setCustomHUDDial("VimanaX_Lmss", "vx_lmss0.png");
    } else {
        p.setCustomHUDDial("VimanaX_Lmss", "vx_lmss0.png");
    }
}

//----------------------------------------------------------------------------------------
this.$blinkingIcons = function _vimanaXHUD_blinkingIcons(key, ico, blank) {
    if (blank == null) blank = "vx_blank.png";
    if (Math.floor(this._iconTimer.nextTime * 10) & 1) {
        player.ship.setCustomHUDDial(key, ico);
    } else {
        player.ship.setCustomHUDDial(key, blank);
    }
}

//----------------------------------------------------------------------------------------
this.$getHostileShips = function _vimanaXHUD_getHostileShips(delta) {
    this._hostilesAge += delta;
    if (this._hostilesAge > 1) {
        this._hostiles = this.$filterEntities(
            function (e) { return (e.isShip && e.hasHostileTarget && e.target === player.ship); }
        );
    }
    return this._hostiles;
};

//----------------------------------------------------------------------------------------
this.$filterEntities = function _vimanaXHUD_filterEntities(filterFunc) {
    return system.filteredEntities(
        this,
        filterFunc,
        player.ship,
        player.ship.scannerRange
    );
}

//----------------------------------------------------------------------------------------
this.$showInfo = function _vimanaXHUD_showInfo() { //txt information on the hud
    var that = _vimanaXHUD_showInfo;
    var _padText = (that._padText = that._padText || this.$padText);
    var _p = (that._p = that._p || player.ship);
    if (!this._timer2Ping) { this._timer2Ping = true; this.$playSound(); }

    var col1 = 1.1;
    var col2 = 10.9;
    if (this._widthLookup == 1) {col1 = 2; col2 = 11.35;}
    /**************************************
     * display a list of damaged equipment
     **************************************/
    //right panel
    _p.setCustomHUDDial("VimanaX_RPTitle", this._staticText.shipInfo);
    if (_p.equipmentStatus("EQ_VIMANAX_SHIP_MODULE") === "EQUIPMENT_OK") {
        if (this._eqDamaged.length && !(Math.floor(this._infoTimer.nextTime * 100) % 4)) {
            if (this._eqDamaged.length < 9) {
                var poz = this._lastUsed[14] = 0;
            } else {
                if (this._lastUsed[14] > this._eqDamaged.length - 1) this._lastUsed[14] = 0;
                var poz = this._lastUsed[14];
                this._lastUsed[14]++;
            }
            for (let i = 0; i < 9; i++) {
                if (i > this._eqDamaged.length - 1) break;
                let y = poz + i;
                if (y > this._eqDamaged.length - 1) y -= this._eqDamaged.length;
                let dsp = _padText((1 + y).toString(), col1, true) + _padText(". " + this._eqDamaged[y], col2);
                let ln = i + 1;
                _p.setCustomHUDDial("VimanaX_R" + ln, dsp);
            }
        }
    }

    if (_p.alertCondition === 3) {
        if ((this._SLS && this._SLS.sniperlockchangeflag && this._SLS.sniperlockchangeflag === "ON") ||
            (this._SLP && this._SLP._SLPState === "ON"))
            _p.setCustomHUDDial("VimanaX_TLock", "LOCKED");
        else
            _p.setCustomHUDDial("VimanaX_TLock", "");
        //hostile counter
        var hc = [];
        hc = this.$getHostileShips();
        if (hc && hc.length > 0) {
            if (hc.length > 9)
                _p.setCustomHUDDial("VimanaX_HC", hc.length);
            else
                _p.setCustomHUDDial("VimanaX_HC", " " + hc.length);
        }
    } else {
        _p.setCustomHUDDial("VimanaX_TLock", "");
    }
    this.$setLPanel();

    //special slots 
    //repairbots status/ams system/heat sinks/ore processor
    var i = this._specialSlots.length;
    while (i--) {
        var slotData = "VimanaX_SpecialSlot" + (i + 1).toString();
        var slotLabel = "VimanaX_SpecialSlot" + (i + 1).toString() + "Label";
        var outputLabel = "";
        var outputData = "";
        switch (this._specialSlots[i]) {
            case "SRS":
                outputLabel = "SR.SYS";
                if (this._SRS && this._SRS.$controllerVersion)
                    outputData = this._SRS.$selfRepairsSystemStatus + ", Charges: " + missionVariables.repairCounter;
                break;
            case "AMS":
                outputLabel = "AM.SYS";
                if (_p.equipmentStatus("EQ_AMS") === "EQUIPMENT_OK" && missionVariables.amActive === "ACTIVE" && this._AMS.amCount)
                    outputData = "Darts: " + this._AMS.amCount;
                else if (_p.equipmentStatus("EQ_AMS") === "EQUIPMENT_OK") outputData = "OFFLINE";
                else if (_p.equipmentStatus("EQ_AMS") === "EQUIPMENT_DAMAGED") outputData = "DAMAGED";
                else outputData = "";
                break;
            case "HEATSINK":
                outputLabel = "H.SINK";
                if (_p.equipmentStatus("EQ_HEAT_SINK_CONTROL") === "EQUIPMENT_OK") outputData = "Manual deploy: ";
                if (_p.equipmentStatus("EQ_HEAT_SINK_CONTROL") === "EQUIPMENT_DAMAGED") outputData = "DAMAGED";
                if (_p.equipmentStatus("EQ_HEAT_SINK_CONTROL_PASSIVE") === "EQUIPMENT_OK") outputData = "Auto deploy: ";
                if (_p.equipmentStatus("EQ_HEAT_SINK_CONTROL_PASSIVE") === "EQUIPMENT_DAMAGED") outputData = "DAMAGED";
                if (outputData != "DAMAGED") {
                    var allhs = _p.equipmentStatus("EQ_HEAT_SINK", true);
                    if (allhs) {
                        var hs = allhs["EQUIPMENT_OK"];
                        if (hs >= 0) outputData += hs + " avail";
                    }
                }
                break;
            case "OREPROC":
                outputLabel = "ORE.PR";
                var op = worldScripts.oreProcessor;
                // Idle
                var idle = !op._oreTimer.isRunning;
                // Processing: x remaining
                var sp = op._splinter.length;
                // Damaged
                var sts = _p.equipmentStatus("EQ_ORE_PROCESSOR");
                if (sts != "EQUIPMENT_UNAVAILABLE" && sts != "EQUIPMENT_UNKNOWN") {
                    outputData = (sts == "EQUIPMENT_DAMAGED" ? "DAMAGED" : (idle ? "Idle: " : "Working: ") + sp + " remain");
                }
                break;
            case "RANK":
                outputLabel = "RANK";
                var rnk = player.rank;
                var score = player.score;
                if (score >= 6400) rnk = "★ ELITE ★";
                outputData = rnk + (score < 6400 ? " (->" + this.$killsUntilNextRank() + ")" : "") + ": " + (score - this._killsOnLaunch).toString();
                break;
            case "STATUS":
                outputLabel = "LEGAL";
                outputData = player.legalStatus + " (" + player.bounty + ")";
                break;
        }
        _p.setCustomHUDDial(slotLabel, outputLabel);
        _p.setCustomHUDDial(slotData, _padText(outputData, this._widths[slotData][this._widthLookup], true));
    }

    /*
     *     equip mode
     */
    var eq_mode = "";
    switch (_p.primedEquipment) {
        case "EQ_ENEMY_TARGETER_UPGRADE":
            var w = worldScripts["Target System Upgrade"];
            if (w.hasOwnProperty("_mode")) {
                eq_mode = ["Target hostile/outlaw","Target neutral","Target cargo"][w._mode];
            }
            break;
        case "EQ_TARGETSELECTOR":
            var w = worldScripts.FastTargetSelector;
            eq_mode = ["Standard targets", "All targets"][w._scanMode];
            break;
        case "EQ_GCM_EJECTION_DAMPER":
            var w = worldScripts.GalCopBB_EjectionDamper;
            var state = w._unitOn;
            eq_mode = (state == true ? "On" : "Off");
            var uses = w._usesLeft;
            eq_mode += " (" + uses + (uses == 1 ? " use": " uses") + " left)";
            break;
        case "EQ_MFD_FAST_CONFIG":
            var mfd = worldScripts.MFDFastConfiguration;
            if (mfd) {
                var modes = [
                    "Set current as set 1",
                    "Set current as set 2",
                    "Set current as set 3",
                    "Set current as Cond Green set",
                    "Set current as Cond Yellow set",
                    "Set current as Cond Red set",
                    "Set current as docking set",
                    "Make set 1 default",
                    "Make set 2 default",
                    "Make set 3 default",
                    "Make Cond Green set default",
                    "Make Cond Yellow set default",
                    "Make Cond Red set default",
                    "Delete set 1",
                    "Delete set 2",
                    "Delete set 3",
                    "Delete Cond Green set",
                    "Delete Cond Yellow set",
                    "Delete Cond Red set",
                    "Delete docking set",
                    "Hide setting functions from list",
                    "Activate default set",
                    "Activate set 1",
                    "Activate set 2",
                    "Activate set 3",
                    "Activate Cond Green set",
                    "Activate Cond Yellow set",
                    "Activate Cond Red set",
                    "Activate docking set",
                    "Disable auto-update mode",
                    "Restore setting functions to list"
                ];
                eq_mode = modes[mfd._curr_mode];
            }
            break;
        case "EQ_COMMSLOGMFD":
            var cl = worldScripts.CommsLogMFD;
            if (cl && (cl._currMode || cl._currMode == 0)) {
                switch (cl._currMode) {
                    case 0: eq_mode = "Scroll back mode";
                        break;
                    case 1: eq_mode = "Scroll forward mode";
                        break;
                    case 2: eq_mode = "Scroll to prev launch";
                        break;
                    case 3: eq_mode = "Scroll to next launch";
                        break;
                    case 4: eq_mode = "View current";
                        break;
                    case 5: eq_mode = "View oldest";
                        break;
                    case 6: eq_mode = "Clear log mode";
                        break;
                    case 7: eq_mode = "Write comms to log";
                        break;
                    case 8:
                        if (worldScripts.CommsLogMFD._scrollMethod === 0) {
                            eq_mode = "Set scroll by message";
                        } else {
                            eq_mode = "Set scroll by line";
                        }
                        break;
                    default: eq_mode = "Scroll back mode";
                        break;
                }
            }
            break;
        case "EQ_TARGET_FILTERING_SYSTEM":
            if (_p.equipmentStatus("EQ_TARGET_FILTERING_SYSTEM") === "EQUIPMENT_OK") {
                switch (this._TFS._mode) {
                    case 0: eq_mode = "Hostile/outlaw";
                        break;
                    case 1: eq_mode = "Thargoid";
                        break;
                    case 2: eq_mode = "Police";
                        break;
                    case 3: eq_mode = "Neutral";
                        break;
                    case 4: eq_mode = "Cargo";
                        break;
                    case 5: eq_mode = "Asteroids";
                        break;
                }
            }
            break;
        case "EQ_WPH_ASC_UPGRADE":
            if (_p.equipmentStatus("EQ_WPH_ASC_UPGRADE") === "EQUIPMENT_OK") {
                eq_mode = "Clear current waypoint";
            }
            break;
        case "EQ_FUEL_TRANSFER":
            if (_p.equipmentStatus("EQ_FUEL_TRANSFER") === "EQUIPMENT_OK") {
                eq_mode = "Stop transfer";
            }
            break;
        case "EQ_BROADCASTCOMMSMFD":
            if (_p.equipmentStatus("EQ_BROADCASTCOMMSMFD") === "EQUIPMENT_OK") {
                eq_mode = "Select next option";
            }
            break;
        case "EQ_MARKET_INQUIRER_MFD":
            if (_p.equipmentStatus("EQ_MARKET_INQUIRER_MFD") == "EQUIPMENT_OK") {
                eq_mode = "View next commodity";
            }
            break;
        case "EQ_GCM_RANGE_FINDER_MFD":
            if (_p.equipmentStatus("EQ_GCM_RANGE_FINDER_MFD") === "EQUIPMENT_OK") {
                switch (worldScripts.GalCopBB_RangeFinder_MFD._mode) {
                    case 0: eq_mode = "Escape capsules";
                        break;
                    case 1: eq_mode = "Black boxes";
                        break;
                    case 2: eq_mode = "Asteroids";
                        break;
                    case 3: eq_mode = "Ships";
                        break;
                    case 4: eq_mode = "Comm relays";
                        break;
                    case 5: eq_mode = "Cargo pods";
                        break;
                    default: eq_mode = "Escape capsules";
                        break;
                }
            }
            break;
        case "EQ_BULK_CARGO_PROCESSOR":
            if (_p.equipmentStatus("EQ_BULK_CARGO_PROCESSOR") === "EQUIPMENT_OK") eq_mode = "Cycle processing type";
            break;
        case "EQ_FUEL_INJECTION_CRUISECONTROL":
            if (_p.equipmentStatus("EQ_FUEL_INJECTION_CRUISECONTROL") === "EQUIPMENT_OK") {
                if (worldScripts.FuelInjectionCruiseControl._autoEngage) {
                    eq_mode = "Turn off auto-engage";
                } else {
                    eq_mode = "Turn on auto-engage";
                }
            }
            break;
        case "EQ_SHIPS_LIBRARY":
            if (_p.equipmentStatus("EQ_SHIPS_LIBRARY") === "EQUIPMENT_OK") {
                eq_mode = expandDescription("[ships-library-mfd-mode" + worldScripts["Ships Library"].$mfdMode + "]");
            }
            break;
        case "EQ_MANIF_SCANNER":
            if (_p.equipmentStatus("EQ_MANIF_SCANNER") === "EQUIPMENT_OK") {
                if (worldScripts.ManifestScanner._scanMode == 0) {
                    eq_mode = "Set active scan mode";
                } else {
                    eq_mode = "Set manual scan mode";
                }
            }
            break;
        case "EQ_HEAT_SINK_CONTROL":
            if (_p.equipmentStatus("EQ_HEAT_SINK_CONTROL") === "EQUIPMENT_OK") {
                if (worldScripts.ShipConfiguration_HeatSink._mode == 0) {
                    eq_mode = "Set auto deploy mode";
                } else {
                    eq_mode = "Set manual deploy mode";
                }
            }
            break;
        case "EQ_SMUGGLING_INFLIGHT_STORAGE":
            if (_p.equipmentStatus("EQ_SMUGGLING_INFLIGHT_STORAGE") === "EQUIPMENT_OK") {
                eq_mode = "Cycle cargo to store";
            }
            break;
        case "EQ_CAMERA_DRONES":
            if (_p.equipmentStatus("EQ_CAMERA_DRONES") === "EQUIPMENT_OK") {
                eq_mode = "Select next camera";
            }
            break;
        case "EQ_WARRANT_SCANNER":
            var ws = worldScripts["BountySystem_WarrantScanner"];
            switch (ws._outputMode) {
                case 0: eq_mode = "MFD output";
                    break;
                case 1: eq_mode = "Console output";
            }
            break;
        case "EQ_HYPER_RADIO":
            eq_mode = "Reconnect";
            break;
        case "EQ_ORE_PROCESSOR":
            eq_mode = "Scan minerals";
            break;
        case "EQ_WPH_ASC_UPGRADE":
            eq_mode = "Delete selected";
            break;
        case "EQ_TELESCOPE":
            var ws = worldScripts["telescopeeq"];
            if (this._telescopeVersion >= 2) {
                if (this._telescopeVersion > 2.0) {
                    // cag's 2.0 update to Telescope puts the primeable equipment menu item values out of reach
                    // code in v2.1.4 makes the mode visible again.
                    var tm = [ 
                        [ "Nearest target" ],
                        [ "Rescan" ],
                        [ "Step forward in list" ],
                        [ "Step back in list" ],
                        [ "Steer:", "off", "nearest only", "nearest + step list"], 
                        [ "Lightballs:", "off", "nav only", "inc. ships", "large" ],
                        [ "Masslck ring:", "alert:off", "alert:on", "brighter" ],
                        [ "Sniper ring km:", "off", "5-25.6", "10-25.6", "15-25.6", "5-30", "10-30", "15-30"], //off=10-10
                        [ "Targets:", "20 and red alert", 50, 100, 200 ],
                        [ "Visual target:", "off", "weapons off", "no ring", "no station", "no question mark", "all" ],
                        [ "Visual target size:", 1, 2, 3, 4, 5, 6, 7, 8 ] 
                    ];
                    var selection = ws.$eq_MenuItem;
                    var subitem = (selection >= 4 ? ws.$eq_GetSubItem(selection) : 0);
                } else {
                    var tm = [["N/A"]];
                    var selection = 0;
                    var subitem = 0;
                }
            } else {
                var tm = [
                    [ "Nearest target" ],
                    [ "Rescan" ],
                    [ "Step forward in list" ],
                    [ "Step back in list" ],
                    [ "Lightballs:", "off", "nav only", "ships", "masslock borders", "bright masslock", "large" ],
                    [ "Sniper ring km:", "off", "5-25.6", "10-25.6", "15-25.6", "5-30", "10-30", "15-30"], //off=10-10
                    [ "Steer:", "off", "nearest only", "nearest + step list"],
                    [ "Targets:", "20 and red alert", 50, 100, 200 ],
                    [ "Visual target:", "off", "weapons off", "no ring", "no station", "no question mark", "all" ],
                    [ "Visual target size:", 1, 2, 3, 4, 5, 6, 7, 8 ]
                ];
                var selection = ws.$Telescopeeq_MenuItem;
                var subitem = (selection >= 4 ? ws.$Telescopeeq_GetSubItem(selection) : 0);
            }
            eq_mode = (selection >= 4 ? tm[selection][0] : "") + tm[selection][subitem];
            break;
        case "EQ_TOWBAR":
            if (_p.equipmentStatus("EQ_TOWBAR") === "EQUIPMENT_OK") {
                var ws = worldScripts["towbar"];
                switch (ws.$TowbarMiner) {
                    case 0: eq_mode = "Offline";
                        break;
                    case 1: eq_mode = "Cargo only";
                        break;
                    case 2: eq_mode = "Up to full";
                        break;
                    case 3: eq_mode = "Salvager";
                        break;
                    default: eq_mode = "Miner N/A";
                }
            }
            break;
        case "EQ_TSP_TARGET_BANKING_MODULE":
            var m = worldScripts[expandDescription("[tsplugins_script_sh]")].$tbmTargetMode;
            eq_mode = expandDescription("[tsplugins_title_mode" + m + "]");
            break;
        default: eq_mode = "N/A";
    }
    _p.setCustomHUDDial("VimanaX_EQMode", _padText(eq_mode, this._widths["VimanaX_EQMode"][this._widthLookup]));

    // check one MFD per 
    // make sure the HUD hasn't changed since the last cycle and reduced the number of MFDs
    if (this._checkMFDCycle > (_p.multiFunctionDisplays - 1)) this._checkMFDCycle = 0;
    this.$checkMFD(this._checkMFDCycle);
    this._checkMFDCycle = (this._checkMFDCycle + 1) % _p.multiFunctionDisplays;
}

/**************************************
 *                          right panel
 * ************************************/
//Player ship shields and hull test animation
//----------------------------------------------------------------------------------------
this.$animHull = function _vimanaXHUD_animHull() {
    var p = player.ship;
    if (!p || !p.isValid) return;
    if (!this._timer3Ping) { this._timer3Ping = true; this.$playSound(); }

    if (p.equipmentStatus("EQ_VIMANAX_SHIP_MODULE") === "EQUIPMENT_OK") {
        if (this._hullAnim[0]) {
            if (this._hullAnim[1] > 10) this._hullAnim[1] = 1;
            else this._hullAnim[1]++;
            if (this._hullAnim[1] <= 4) p.setCustomHUDDial("VimanaX_HullAnim", "vx_scan_" + this._hullAnim[1] + ".png");
            else p.setCustomHUDDial("VimanaX_HullAnim", "vx_blank.png");
        }
        var wtp = Math.round(p.aftShield / p.maxAftShield * 100);
        var wtt = Math.round(p.forwardShield / p.maxForwardShield * 100);
        if (wtp > 75) p.setCustomHUDDial("VimanaX_TT", "vx_tt100.png");
        else if (wtp > 50 && wtp < 76) p.setCustomHUDDial("VimanaX_TT", "vx_tt75.png");
        else if (wtp > 25 && wtp < 51) p.setCustomHUDDial("VimanaX_TT", "vx_tt50.png");
        else if (wtp > 1 && wtp < 26) p.setCustomHUDDial("VimanaX_TT", "vx_tt25.png");
        else p.setCustomHUDDial("VimanaX_TT", "vx_blank.png");

        if (wtt > 75) p.setCustomHUDDial("VimanaX_TP", "vx_tp100.png");
        else if (wtt > 50 && wtt < 76) p.setCustomHUDDial("VimanaX_TP", "vx_tp75.png");
        else if (wtt > 25 && wtt < 51) p.setCustomHUDDial("VimanaX_TP", "vx_tp50.png");
        else if (wtt > 1 && wtt < 26) p.setCustomHUDDial("VimanaX_TP", "vx_tp25.png");
        else p.setCustomHUDDial("VimanaX_TP", "vx_blank.png");
    } else {
        p.setCustomHUDDial("VimanaX_HullAnim", "vx_blank.png");
        p.setCustomHUDDial("VimanaX_TT", "vx_blank.png");
        p.setCustomHUDDial("VimanaX_TP", "vx_blank.png");
        if (p.equipmentStatus("EQ_VIMANAX_SHIP_MODULE") === "EQUIPMENT_UNAVAILABLE") {
            this._animTimer.stop();
            delete this._animTimer;
        }
    }
}

//----------------------------------------------------------------------------------------
this.$equipmentStatus = function _vimanaXHUD_equipmentStatus() {  //check equip             
    var that = _vimanaXHUD_equipmentStatus;
    var _padText = (that._padText = that._padText || this.$padText);
    var _staticText = (that._staticText = that._staticText || this._staticText);
    var _widths = (that._widths = that._widths || this._widths);
    var _widthLookup = (that._widthLookup = that._widthLookup || this._widthLookup);
    var _p = (that._p = that._p || player.ship);

    _p.setCustomHUDDial("VimanaX_Rh1", "");
    _p.setCustomHUDDial("VimanaX_Rh2", "");
    var i = 10;
    while (i--) {
        _p.setCustomHUDDial("VimanaX_R" + i, "");
    }
    if (_p.equipmentStatus("EQ_VIMANAX_SHIP_MODULE") === "EQUIPMENT_OK") {
        _p.setCustomHUDDial("VimanaX_PSName", _padText(_p.displayName, _widths["VimanaX_PSName"][_widthLookup]));
        //if (this._hullAnim[0]) var m = "vx_" + this._hullAnim[0] + ".png";
        //else var m = "vx_blank.png";
        _p.setCustomHUDDial("VimanaX_PShip", this._hullAnim[0]); // , m);

        if (this._eqDamaged.length) {
            /***********************
             *         equip damaged
             * *********************/
            var pd = Math.round((this._eqDamaged.length / _p.equipment.length) * 1000) / 10;
            _p.setCustomHUDDial("VimanaX_Rh1", _staticText.shipDamaged);
            _p.setCustomHUDDial("VimanaX_Rh2", this._eqDamaged.length + " (" + pd + "%) system(s) broken");
            _p.setCustomHUDDial("VimanaX_R0", _staticText.checkList);

            if (this._SRS && this._SRS.$controllerVersion && missionVariables.repairCounter > 0) {
                if (this._SRS.$selfRepairsSystemStatus === "Stand-by")
                    this._SRS.checkEquipment();
            }
        } else {
            /***********************
             *         no damage
             * *********************/
            _p.setCustomHUDDial("VimanaX_Rh1", "");
            _p.setCustomHUDDial("VimanaX_Rh2", "");

            if (this._lastUsed[16] > 0) {
                _p.setCustomHUDDial("VimanaX_R8", "All equipment & systems");
                _p.setCustomHUDDial("VimanaX_R9", "online and operational");
            } else {
                _p.setCustomHUDDial("VimanaX_R9", " No additional equipment!");
            }
        }
    } else {
        var tx = _staticText.unavailable;
        _p.setCustomHUDDial("VimanaX_R1", tx);
        if (_p.equipmentStatus("EQ_VIMANAX_SHIP_MODULE") === "EQUIPMENT_DAMAGED") tx = _staticText.moduleDamaged;
        else tx = _staticText.moduleNotInstalled;
        _p.setCustomHUDDial("VimanaX_R2", tx);
        _p.setCustomHUDDial("VimanaX_PShip", "vx_blank.png");
    }
}

/**************************************
 *                            left panel
 * ************************************/
//----------------------------------------------------------------------------------------
this.$setLPanel = function _vimanaXHUD_setLPanel() {
    var p = player.ship;
    if (p.target && p.target.isValid && !p.target.isWormhole) {
        var i = 10;
        while (i--) {
            p.setCustomHUDDial("VimanaX_L" + i, "");
        }
        if (p.equipmentStatus("EQ_VIMANAX_TARGET_MODULE") === "EQUIPMENT_OK") {
            this.$targetInfo();
        } else {
            p.setCustomHUDDial("VimanaX_PTarget", "vx_blank.png");
            p.setCustomHUDDial("VimanaX_Lh", "");
            var tx = "";
            p.setCustomHUDDial("VimanaX_L3", this._staticText.unavailable); 
            if (p.equipmentStatus("EQ_VIMANAX_TARGET_MODULE") === "EQUIPMENT_DAMAGED") tx = this._staticText.moduleDamaged;
            else tx = this._staticText.moduleNotInstalled;
            p.setCustomHUDDial("VimanaX_L4", tx); 
        }
    } else {                                 //travel info
        if (this._lastUsed[12] == 1) {
            this._lastUsed[12] = 0;
            this._lastUsed[13] = "";
            p.setCustomHUDDial("VimanaX_LPTitle", this._staticText.travelHeader);
            p.setCustomHUDDial("VimanaX_PTarget", "vx_globe.png");
            p.setCustomHUDDial("VimanaX_CEnergy", "");
            p.setCustomHUDDial("VimanaX_CSpeed", "");
            p.setCustomHUDDial("VimanaX_CMissile", "");

            if (p.equipmentStatus("EQ_VIMANAX_TRAVEL_MODULE") === "EQUIPMENT_OK") {
                this.$travelInfo();
            } else {
                this.$jumpDistIndicator();
                p.setCustomHUDDial("VimanaX_PTarget", "vx_blank.png");
                p.setCustomHUDDial("VimanaX_Lh", "");
                var tx = "";
                p.setCustomHUDDial("VimanaX_L3", this._staticText.unavailable);
                if (p.equipmentStatus("EQ_VIMANAX_TRAVEL_MODULE") === "EQUIPMENT_DAMAGED") tx = this._staticText.moduleDamaged;
                else tx = this._staticText.moduleNotInstalled;
                p.setCustomHUDDial("VimanaX_L4", tx);
            }
        }
    }
}

//----------------------------------------------------------------------------------------
this.$targetInfo = function _vimanaXHUD_targetInfo() {
    var that = _vimanaXHUD_targetInfo;
    var _padText = (that._padText = that._padText || this.$padText);
    var _cbtMFD = (that._cbtMFD = that._cbtMFD || this._combatMFD);
    var _ms = (that._ms = that._ms || this._MS);
    var _wsi = (that._wsi = that._wsi || this._wsi);
    var _player = (that._player = that._player || player);
    var _p = (that._p = that._p || player.ship);

    var tdata = [];
    var col1 = 5;
    var max = this._widths["VimanaX_L0"][this._widthLookup];
    var hmax = this._widths["VimanaX_Lh"][this._widthLookup];
    if (this._widthLookup == 1) col1 = 6; //{ max = 13.35; col1 = 6; hmax = 11.86; }

    var i = 10;
    while (i--) {
        tdata[i] = "";
    }
    this._lastUsed[12] = 1;
    tdata[0] = _p.target.displayName;
    var tgt = _p.target;

    if (tgt.dataKey == "telescopemarker") {
        tdata[1] = "Additional info not available";
        tdata[2] = "(Out of range)";
        var itn = tdata[0].indexOf("km ");
        if (itn > -1 && itn < 10) tdata[0] = tdata[0].substr(itn + 3);
        if (this._lastUsed[13] != tdata[0]) { //load target model only for telescope 
            this._lastUsed[13] = tdata[0];
            var model = _wsi.$getShipImage(tgt);
            _p.setCustomHUDDial("VimanaX_PTarget", model);
        }
    } else if ((tgt.isBoulder || tgt.isRock) && !tgt.isPiloted) {
        tdata[1] = _padText("SPEED:", col1) + _cbtMFD.$Data["combatTSpeed"] + "m/s";
        tdata[2] = _padText("BOUNTY:", col1) + tgt.bounty + "€";
    } else if (tgt.isMissile) {
        tdata[1] = _padText("SPEED:", col1) + _cbtMFD.$Data["combatTSpeed"] + "m/s";
        tdata[2] = _padText("ENERGY:", col1) + Math.round(tgt.energy);
        tdata[4] = _padText("TRAVELLED:", col1) + tgt.distanceTravelled.toFixed(0) + " m";
    } else if (tgt.hasRole("escape-capsule")) {
        tdata[1] = _padText("SPEED:", col1) + _cbtMFD.$Data["combatTSpeed"] + "m/s";
        tdata[2] = _padText("BOUNTY:", col1) + tgt.bounty + "€";
    } else if ((tgt.scanClass == "CLASS_BUOY" || (tgt.scanClass == "CLASS_STATION" && !tgt.isStation)) && !tgt.isPiloted) {
        if (tgt.name) tdata[0] = tgt.name;
        else if (tgt.beaconLabel) tdata[0] = tgt.beaconLabel;
        else if (tgt.beaconCode) tdata[0] = tgt.beaconCode;
        else tdata[0] = "Unidentified";
        tdata[2] = _padText("ENERGY:", col1) + Math.round(tgt.energy);
        tdata[3] = _padText("RADIUS:", col1) + Math.round(tgt.collisionRadius) + " m";
    } else if (tgt.isStation) {
        if (tgt.maxSpeed == 0) {
            tdata[3] = _padText("RADIUS:", col1) + Math.round(tgt.collisionRadius) + " m";
        } else {
            tdata[3] = _padText("SPEED:", col1) + _cbtMFD.$Data["combatTSpeed"] + "m/s";
        }
        tdata[4] = _padText("ENERGY:", col1) + Math.round(tgt.energy);
        tdata[6] = _padText("DEFENDERS:", col1) + tgt.dockedPolice;
        if (tgt.requiresDockingClearance) {
            tdata[1] = _padText("DOCK:", col1) + "REQUEST";
            switch (_player.dockingClearanceStatus) {
                case "DOCKING_CLEARANCE_STATUS_REQUESTED":
                    tdata[1] = _padText("DOCK:", col1) + "HOLD";
                    break;
                case "DOCKING_CLEARANCE_STATUS_GRANTED":
                    tdata[1] = _padText("DOCK:", col1) + "GRANTED";
                    break;
                case "DOCKING_CLEARANCE_STATUS_TIMING_OUT":
                    tdata[1] = _padText("DOCK:", col1) + "EXPIRING";
            }
        } else {
            tdata[1] = _padText("DOCK:", col1) + "FREE";
        }
    } else if (tgt.isDerelict) {
        tdata[2] = _padText("ENERGY:", col1) + Math.round(tgt.energy);
        tdata[4] = _padText("CARGO:", col1) + tgt.cargoSpaceUsed + "/" + tgt.cargoSpaceCapacity + "t";
    } else if (tgt.isShip && (tgt.isPiloted || tgt.isThargoid)) {
        tdata[1] = _padText("SPEED:", col1) + _cbtMFD.$Data["combatTSpeed"] + "m/s";
        tdata[2] = _padText("ENERGY:", col1) + Math.round(tgt.energy);
        // use combatMFD to get weapon type, so we don't get more information than it provides
        tdata[5] = _padText("WEAPON:", col1) + _padText(_cbtMFD.$Data["combatTLaser"].replace("Laser: ", ""), (max - col1));
        tdata[6] = _padText("RANGE:", col1) + (tdata[5].indexOf("Unknown") >= 0 ? "??" : (tgt.weaponRange / 1000).toFixed(1) + "km");
        // this reveals information the player doesn't have any right to know
        /*var mc = 0;
        var hmc = 0;
        var msc = "";
        i = tgt.missiles.length;
        while (i--) {
            let mst = tgt.missiles[i].equipmentKey;
            if (mst == "EQ_MISSILE" || mst == "EQ_ARMOURY_STANDARD_MISSILE") mc++;
            else hmc++;
        }

        if (hmc > 0 && mc > 0) msc = hmc + "h/" + mc + "s";
        else if (hmc > 0) msc = hmc + "h";
        else if (mc > 0) msc = mc + "s";
        else msc = "0";*/
        tdata[4] = _padText("MISSILE:", col1) + _cbtMFD.$Data["combatTMissile"];
        // only show the used cargo space if the manifest scanner has done a scan
        // capacity is related to ship specs, and is therefore OK to show
        var cp = tgt.cargoSpaceCapacity;
        if (_ms && cp > 0) {
            var d = _ms.$findShipScan(tgt);
            if (d !== "") {
                tdata[7] = _padText("CARGO:", col1) + tgt.cargoSpaceUsed + "/" + cp + "t";
            } else {
                tdata[7] = _padText("CARGO:", col1) + "??/" + cp + "t";
            }
        } else {
            tdata[7] = _padText("CARGO:", col1) + (cp > 0 ? "??" : "--") + "/" + cp + "t";
        }
        tdata[9] = _padText("BOUNTY:", col1) + tgt.bounty + "€";
        if (_player.alertCondition == 3) {
            _p.setCustomHUDDial("VimanaX_CEnergy", "E: " + Math.round(tgt.energy));
            _p.setCustomHUDDial("VimanaX_CSpeed", "V: " + _cbtMFD.$Data["combatTSpeed"] + "m/s");
            _p.setCustomHUDDial("VimanaX_CMissile", "M: " + _cbtMFD.$Data["combatTMissile"]);
        }
    } else if (tgt.isCargo) {
        tdata[0] = tgt.name;
        tdata[1] = tgt.shipUniqueName;
        if (tdata[1].indexOf("Gold") > -1 || tdata[1].indexOf("Platinum") > -1) var unit = "kg";
        else if (tdata[1].indexOf("Gem-Stones") > -1) var unit = "g";
        else var unit = "t";
        tdata[2] = _padText("AMOUNT:", col1) + tgt.commodityAmount + unit;
        tdata[3] = _padText("SPEED:", col1) + _cbtMFD.$Data["combatTSpeed"] + "m/s";
    }
    //--------------
    _p.setCustomHUDDial("VimanaX_Lh", _padText(tdata[0], hmax));
    _p.setCustomHUDDial("VimanaX_L0", "");
    i = 9
    while (i--) {
        _p.setCustomHUDDial("VimanaX_L" + (i + 1), tdata[i + 1]);
    }
}

//----------------------------------------------------------------------------------------
this.$travelInfo = function _vimanaXHUD_travelInfo() {
    var that = _vimanaXHUD_travelInfo;
    var _padText = (that._padText = that._padText || this.$padText);
    var p = player.ship;
    var dest = "Destination not set";

    this._reqFuel = 0;
    var ddist = "";
    var nlabel = "";

    var col1 = 7;
    var col2 = 1.8;
    var col3 = 6.2;
    var max = this._widths["VimanaX_L0"][this._widthLookup];
    var hmax = this._widths["VimanaX_Lh"][this._widthLookup];
    if (this._widthLookup == 1) { col1 = 9.0; col2 = 2.1; col3 = 7.3; }

    var i = 7;
    while (i--) {
        p.setCustomHUDDial("VimanaX_L" + (i + 3), "");
    }
    if (system.isInterstellarSpace) {
        dest = "Interstellar Space!";
        ddist = "Route calculation unavailable";
        nlabel = "";
    } else if (system.ID != p.targetSystem) {
        var fullRoute = system.info.routeToSystem(System.infoForSystem(galaxyNumber, p.targetSystem), p.routeMode);
        var tsys = System.infoForSystem(galaxyNumber, p.targetSystem);
        if (!tsys.hasOwnProperty("concealment") || tsys.concealment < 200) {
            dest = _padText(tsys.name, col1);
            if (!tsys.hasOwnProperty("concealment") || tsys.concealment < 100) {
                dest += this._ecos[tsys.economy] + this._govs[tsys.government] + (tsys.techlevel + 1);
            } else {
                dest += "? ? ?";
            }
        } else {
            dest = _padText("(Unknown)", col1) + "? ? ?";
        }
        if (fullRoute) {
            let dday = Math.floor(fullRoute.time / 24);
            let dhour = Math.floor(fullRoute.time % 24);
            let dmin = Math.floor(fullRoute.time % 60);
            let tx = Math.floor(fullRoute.distance * 10) / 10;
            let hp = fullRoute.route.length - 1;
            ddist = tx.toFixed(1).toString() + "ly, " + dday + "d:" + dhour + "h:" + dmin + "m, " + hp + " jmp";
            if (defaultFont.measureString(ddist) > hmax) {
                ddist = tx.toFixed(1).toString() + "ly, " + fullRoute.time.toFixed(1) + "h, " + hp + " jmp";
            }
            if (fullRoute.route.length > 0) {
                if (fullRoute.route.length > 8) var nxr = 8;
                else var nxr = fullRoute.route.length;
                if (p.routeMode === "OPTIMIZED_BY_NONE" && fullRoute.route.length > 2) {
                    p.setCustomHUDDial("VimanaX_L4", "Unknown route!");
                } else {
                    for (i = 1; i < nxr; i++) {
                        let a = i + 2;
                        let b = System.infoForSystem(galaxyNumber, fullRoute.route[i]);
                        let c = system.info.routeToSystem(System.infoForSystem(galaxyNumber, fullRoute.route[i]), p.routeMode);
                        let tx = Math.floor(c.distance * 10) / 10;
                        if (i == 1) this._reqFuel = tx;
                        let d = _padText(tx.toFixed(1).toString(), col2, true) + "ly  ";
                        if (!b.hasOwnProperty("concealment") || b.concealment < 200) {
                            d += _padText(b.name, col3);
                            if (!b.hasOwnProperty("concealment") || b.concealment < 100) {
                                d += this._ecos[b.economy] + this._govs[b.government] + (b.techlevel + 1);
                            } else {
                                d += "? ? ?";
                            }
                        } else {
                            d += _padText("(Unknown)", col3) + "? ? ?";
                        }
                        p.setCustomHUDDial("VimanaX_L" + a, d);
                    }
                }
                nlabel = this._staticText.nextHops;
            }
        }
    }
    p.setCustomHUDDial("VimanaX_Lh", dest);
    p.setCustomHUDDial("VimanaX_L0", ddist);
    p.setCustomHUDDial("VimanaX_L1", "");
    p.setCustomHUDDial("VimanaX_L2", nlabel);
}

//----------------------------------------------------------------------------------------
// used when travel mod hasn't been purchased or isn't available
this.$jumpDistIndicator = function _vimanaXHUD_jumpDistIndicator() {
    var p = player.ship;
    this._reqFuel = 0;
    if (!p || !p.isValid) return;
    if (p.targetSystem == system.ID) return; // no target system set
    var fullRoute = system.info.routeToSystem(System.infoForSystem(galaxyNumber, p.targetSystem), p.routeMode);
    if (fullRoute && fullRoute.route.length > 1) {
        let c = system.info.routeToSystem(System.infoForSystem(galaxyNumber, fullRoute.route[1]), p.routeMode);
        let tx = Math.floor(c.distance * 10) / 10;
        this._reqFuel = tx;
    }
}

//----------------------------------------------------------------------------------------
this.$checkMaint = function _vimanaXHUD_checkMaint() {
    var p = player.ship;
    if (p.serviceLevel < 85) {
        this._maintenance = true;
    } else {
        this._maintenance = false;
        p.setCustomHUDDial("VimanaX_Service", "vx_blank.png");
    }
}

//-------------------------------------------------------------------------------------------------------------
// sets the witchspace destination labels to the next destination (to fix bug in 1.82 with the builtin dial that only shows the final destination)
this.$setDestination = function _vimanaXHUD_setDestination() {
	var p = player.ship;
	var planet = "(Unknown)";
    var extra = "";
    if (this._destination == system.ID) planet = "(Not set)";
	if (this._destination >= 0 && this._destination != system.ID) {
        var s = System.infoForSystem(galaxyNumber, this._destination);
        if (!s.hasOwnProperty("concealment") || s.concealment < 200) planet = s.name;
        if (!s.hasOwnProperty("concealment") || s.concealment < 100) {
            extra = " (" + this._ecos[s.economy] + this._govs[s.government] + (s.techlevel + 1) + ")";
            planet += extra;
        }
    }
	p.setCustomHUDDial("witchspace_destination", planet);
	this._holdTarget = p.targetSystem;
}

//-------------------------------------------------------------------------------------------------------------
this.$checkForNewDestination = function _vimanaXHUD_checkForNewDestination() {
	// check if our destination hasn't been set yet (-1) or if our targetSystem has changed, or we've just left the long/short range chart
	if (this._destination === -1 || this._holdTarget != player.ship.targetSystem || (this._mapScreen === "GUI_SCREEN_SHORT_RANGE_CHART" || this._mapScreen === "GUI_SCREEN_LONG_RANGE_CHART")) {
		this._destination = this.$playerTargetSystem();
		this.$setDestination();
	}
    if (player.ship.docked) this.$updateDockedHUDLabels();
}

//-------------------------------------------------------------------------------------------------------------
// returns the player's target system (1.80) or the next jump to their target system (1.82)
this.$playerTargetSystem = function _vimanaXHUD_playerTargetSystem() {
	var p = player.ship;
	if (p.hasOwnProperty("nextSystem")) return p.nextSystem;

	// need to check for the ANA when route checking - if no ANA it's just the targetSystem - no routing available
	var target = p.targetSystem;
	if (oolite.compareVersion("1.81") < 0 && p.hasEquipmentProviding("EQ_ADVANCED_NAVIGATIONAL_ARRAY") === true) {
		// in 1.81 or greater, the target system could be more than 7 ly away. It becomes, essentially, the final destination.
		// there could be multiple interim stop points between the current system and the target system.
		// the only way to get this info is to recreate a route using the same logic as entered on the ANA, and pick item 1
		// from the list. That should be the next destination in the list.
		if (target != this._lastSource) {
			var myRoute = System.infoForSystem(galaxyNumber, this._lastSource).routeToSystem(System.infoForSystem(galaxyNumber, target), p.routeMode);
			if (myRoute && myRoute.route.length > 1) {
				target = myRoute.route[1];
			}
		}
	}
	return target;
}

/***********************************
 *                    indicators
 ***********************************/
//----------------------------------------------------------------------------------------
this.$showIndicators = function _vimanaXHUD_showIndicators() {
    var that = _vimanaXHUD_showIndicators;
    var _padText = (that._padText = that._padText || this.$padText);
    var _widths = (that._widths = that._widths || this._widths);
    var _cbtMFD = (that._cbtMFD = that._cbtMFD || this._combatMFD);
    var _setGauge = (that._setGauge = that._setGauge || this.$setGauge);
    var _p = (that._p = that._p || player.ship);
    if (!_p || !_p.isValid) return;

    function calcSpeed(p, cbt) {
        if (p.speed > p.maxSpeed * p.injectorSpeedFactor || p.script._ficcEngaged) {
            return cbt.$Data["combatSpeed"];
        } else {
            return p.speed;
        }
    }

    var i = 0;
    var efl = 0 //extra fuel
    //var speed = Math.round(p.velocity.magnitude() / 10) * 10;
    var ctemp = Math.round(_p.temperature * 100);
    var fuel = (_p.fuel).toFixed(1);
    var td = -1;

    if (_p.target && _p.target.isValid && !_p.target.isWormhole) { //calculate & display distance to player target
        var trg = _p.target;
        if (_p.target.dataKey == "telescopemarker")
            if (this._TLS.$TelescopeList[this._TLS.$TelescopeListi - 1]) trg = this._TLS.$TelescopeList[this._TLS.$TelescopeListi - 1];
        if (trg.position) {
            td = trg.position.distanceTo(_p.position) - Math.round(trg.collisionRadius);
            if (td > 100000) td = Math.round(td / 1000);
            else td = Math.round(td / 10) / 100;
        }
    } else {
        var sec = "" + Math.floor(clock.seconds % 60); //display clock
        if (sec.length < 2) sec = "0" + sec;
        var min = "" + Math.floor(clock.minutes % 60);
        if (min.length < 2) min = "0" + min;
        _p.setCustomHUDDial("VimanaX_SClock", Math.floor(clock.hours % 24) + ":" + min + ":" + sec + " - " + clock.days);
    }
    // try to keep everything inside the element bounds
    var decimals = 2;
    var extra = "";
    if (td >= 1000000) {
        td = td / 1000000;
        decimals = 1;
        extra = "G";
    } else if (td >= 10000) {
        td = td / 1000;
        decimals = 1;
        extra = "M";
    } else if (td >= 1000) decimals = 0;
    else if (td >= 100) decimals = 1;
    _p.setCustomHUDDial("VimanaX_TDist", (td != -1 ? td.toFixed(decimals) + extra : "* * * * ") + this._spacer);
    //DuplexFuelTank.oxz
    if (_p.equipmentStatus("EQ_DUPLEX_FUEL_TANK_STATE_1") == "EQUIPMENT_OK") efl += 1;
    else if (_p.equipmentStatus("EQ_DUPLEX_FUEL_TANK_STATE_2") == "EQUIPMENT_OK") efl += 2;
    else if (_p.equipmentStatus("EQ_DUPLEX_FUEL_TANK_STATE_3") == "EQUIPMENT_OK") efl += 3;
    //ExtraFuelTanks
    if (_p.equipmentStatus("EQ_RESERVE_TANK") == "EQUIPMENT_OK") efl += 1;
    else if (_p.equipmentStatus("EQ_AUX_TANK") == "EQUIPMENT_OK") efl += 3;
    //Fuel_Tank
    if (_p.equipmentStatus("EQ_FUELTANK_MINE") == "EQUIPMENT_OK") {
        i = _p.missiles.length;
        while (i--) {
            if (_p.missiles[i].equipmentKey == "EQ_FUELTANK_MINE") efl += 3;
        }
    }

    // ASC dist
    var ascd_raw = _cbtMFD.$Data["combatSCTDist"];
    if (!ascd_raw) ascd_raw = "";
    if (this._lastUsed[19] != ascd_raw) {
        this._lastUsed[19] = ascd_raw;
        if (ascd_raw != "") {
            var ascd = parseInt(ascd_raw);
            // convert value back to m
            if (ascd_raw.indexOf("Mkm") > 0) ascd *= 1000000000;
            else if (ascd_raw.indexOf("km") > 0) ascd *= 1000;
            // work out scale for display
            var scale = "m";
            if (ascd >= 10000000000) { // Gm gigameters
                ascd /= 1000000000;
                scale = "Gm";
            } else if (ascd >= 10000000) {// Mm megameters
                ascd /= 1000000;
                scale = "Mm";
            } else if (ascd >= 1000) { // km kilometers
                ascd /= 1000;
                scale = "km";
            } 
            _p.setCustomHUDDial("VimanaX_ASCDist", ascd.toFixed(0) + scale);
        } else {
            _p.setCustomHUDDial("VimanaX_ASCDist", "");
        }
    }

    // altitude calculation
    if (system.isInterstellarSpace) {
        var alt = 99999;
        _setGauge("VimanaX_AltG", alt, 50000, "lpi");
        _p.setCustomHUDDial("VimanaX_Alt", "--");
        this._lastUsed[11] = alt;
    } else {
        // use combat MFD's value for alt
        var altRaw = _cbtMFD.$Data["combatAlt"].toString();
        var alt = parseInt(altRaw);
        if (isNaN(alt)) {
            alt = 99999;
        } else {
            if (altRaw.indexOf("Mkm") > 0) alt = 99999; // basically max dist
            else if (altRaw.indexOf("km") > 0) alt *= 1000 // convert to meters
        }
        // alt should now be in meters
        if (this._lastUsed[11] != alt) {
            var pre = "";
            if (alt < 1000) {
                pre = "0.";
                var a = alt;
            } else {
                var a = Math.round(alt / 1000);
            }
            _setGauge("VimanaX_AltG", alt, 50000, "lpi");
            if (a > 50000) {
                _p.setCustomHUDDial("VimanaX_Alt", "--");
            } else {
                var post = "";
                if (a >= 1000) {
                    a = a / 1000;
                    post = "k";
                }
                _p.setCustomHUDDial("VimanaX_Alt", pre + Math.round(a) + post);
            }
        }
        this._lastUsed[11] = alt;
    }

    if (this._lastUsed[0] != ctemp) {     //cabin temperature
        _p.setCustomHUDDial("VimanaX_CTemp", ctemp + "°");
        _setGauge("VimanaX_CTempG", ctemp, 100, "ln");
        this._lastUsed[0] = ctemp;
    }

    var spd = parseFloat(calcSpeed(_p, _cbtMFD)); //_p.speed; //_cbtMFD.$Data["combatSpeed"];
    if (this._lastUsed[1] != spd) {     //speed
        if (spd >= 100000) {
            _p.setCustomHUDDial("VimanaX_Speed", (spd / 1000).toFixed(0) + "k");
        } else {
            _p.setCustomHUDDial("VimanaX_Speed", parseFloat(spd).toFixed(0));
        }
        _p.setCustomHUDDial("VimanaX_Speed2", "V: " + parseFloat(spd).toFixed(0) + " m/s");
        if (spd > _p.maxSpeed) _setGauge("VimanaX_SpeedG", spd, _p.maxSpeed, "ln");
        else _setGauge("VimanaX_SpeedG", spd, _p.maxSpeed, "lp");
        this._lastUsed[1] = spd;
    }

    if (this._lastUsed[2] != fuel || this._lastUsed[3] != efl) { //fuel
        var ef = "";
        if (efl) ef = "+" + Math.round(efl);
        _p.setCustomHUDDial("VimanaX_Fuel", fuel + ef);
        _setGauge("VimanaX_FuelG", fuel, 7, "lp");
        this._lastUsed[3] = efl;
        this._lastUsed[2] = fuel;
    }
    if (this._lastUsed[15] != this._reqFuel) {     //required fuel 
        var a = Math.round(this._reqFuel / (7 / 15));
        _p.setCustomHUDDial("VimanaX_FuelR", "vx_fr" + a + ".png");
        this._lastUsed[15] = this._reqFuel;
    }

    if (this._lastUsed[4] != _p.cargoSpaceUsed || this._lastUsed[5] != _p.cargoSpaceCapacity) {     //cargo
        _p.setCustomHUDDial("VimanaX_Cargo", _p.cargoSpaceUsed + "/" + _p.cargoSpaceCapacity);
        this._lastUsed[5] = _p.cargoSpaceCapacity;
        if (_p.cargoSpaceCapacity == 0) _setGauge("VimanaX_CargoG", 1, 1, "ln");
        else _setGauge("VimanaX_CargoG", _p.cargoSpaceUsed, _p.cargoSpaceCapacity, "ln");
        this._lastUsed[4] = _p.cargoSpaceUsed;
    }

    if (this._lastUsed[6] != _p.energy) {        //energy
        _p.setCustomHUDDial("VimanaX_Energy", Math.round(_p.energy));
        _setGauge("VimanaX_EnergyG", _p.energy, _p.maxEnergy, "ppi");
        this._lastUsed[6] = _p.energy;
    }

    if (this._lastUsed[7] != _p.aftShield) {
        var wtp = Math.round(_p.aftShield / _p.maxAftShield * 100);
        _p.setCustomHUDDial("VimanaX_Ash", wtp + "%");
        _setGauge("VimanaX_AshG", _p.aftShield, _p.maxAftShield, "ppi");
        this._lastUsed[7] = _p.aftShield;
    }

    if (this._lastUsed[8] != _p.forwardShield) {
        var wtt = Math.round(_p.forwardShield / _p.maxForwardShield * 100);
        _p.setCustomHUDDial("VimanaX_Fsh", wtt + "%");
        _setGauge("VimanaX_FshG", _p.forwardShield, _p.maxForwardShield, "ppi");
        this._lastUsed[8] = _p.forwardShield;
    }

    var lsname = _p.currentWeapon.name;
    _p.setCustomHUDDial("VimanaX_LaserName", _padText(lsname, _widths["VimanaX_LaserName"][this._widthLookup], true));

    if (this._lastUsed[9] != _p.laserHeatLevel) {
        _p.setCustomHUDDial("VimanaX_LaserTemp", Math.round(_p.laserHeatLevel * 1190) + "°");
        _setGauge("VimanaX_LaserTempG", _p.laserHeatLevel, 0.85, "pn");
        this._lastUsed[9] = _p.laserHeatLevel;
    }

    if ((_p.equipmentStatus("EQ_IRONHIDE") == "EQUIPMENT_UNAVAILABLE" || _p.equipmentStatus("EQ_IRONHIDE") == "EQUIPMENT_UNKNOWN") && !this._SC_Armour) {
        _p.setCustomHUDDial("VimanaX_FArmour", "");
        _p.setCustomHUDDial("VimanaX_FArmourG", "vx_blank.png");
        _p.setCustomHUDDial("VimanaX_FArmourLabel", "");
        _p.setCustomHUDDial("VimanaX_AArmour", "");
        _p.setCustomHUDDial("VimanaX_AArmourG", "vx_blank.png");
        _p.setCustomHUDDial("VimanaX_AArmourLabel", "");
    }

    if (this._lastUsed[10] != missionVariables.ironHide_percentage) {
        _p.setCustomHUDDial("VimanaX_FArmour", missionVariables.ironHide_percentage.toFixed(0) + "%");
        _setGauge("VimanaX_FArmourG", missionVariables.ironHide_percentage, 100, "ppi");
        _p.setCustomHUDDial("VimanaX_FArmourLabel", "ARMOUR");
        _p.setCustomHUDDial("VimanaX_AArmour", "");
        _p.setCustomHUDDial("VimanaX_AArmourG", "vx_blank.png");
        _p.setCustomHUDDial("VimanaX_AArmourLabel", "");
        this._lastUsed[10] = missionVariables.ironHide_percentage;
    }

    if (this._SC_Armour) {
        var armourFront = 0;
        var armourAft = 0;
        var arm = worldScripts.ShipConfiguration_Armour;
        if (_p.script._armourFront >= 0) {
            armourFront = _p.script._armourFront;
            armourAft = _p.script._armourAft;
        } else {
            armourFront = arm._armourFront;
            armourAft = arm._armourAft;
        }
        if (this._lastUsed[17] != armourFront) {
            _p.setCustomHUDDial("VimanaX_FArmour", armourFront.toFixed(0) + "%");
            _setGauge("VimanaX_FArmourG", armourFront, 100, "ppi");
            _p.setCustomHUDDial("VimanaX_FArmourLabel", "F.ARM");
            this._lastUsed[17] = armourFront;
        }
        if (this._lastUsed[18] != armourAft) {
            _p.setCustomHUDDial("VimanaX_AArmour", armourAft.toFixed(0) + "%");
            _setGauge("VimanaX_AArmourG", armourAft, 100, "ppi");
            _p.setCustomHUDDial("VimanaX_AArmourLabel", "A.ARM");
            this._lastUsed[18] = armourAft;
        }
    }
}

//----------------------------------------------------------------------------------------
this.$setGauge = function _vimanaXHUD_setGauge(key, cur, max, pos) {
    //set gauge speed, ctemp, alt, shield, etc
    var a = max / 15;
    if (cur > max) cur = max;
    a = Math.round((cur / a));
    player.ship.setCustomHUDDial(key, "vx_" + a + "_" + pos + ".png");
}

/***********************************
 *                    F4 interface
 ***********************************/
//-------------------------------------------------------------------------------------------------------------
this.$initInterface = function _vimanaXHUD_initInterface(station) {
    station.setInterface(this.name, {
        title: "Vimana-X HUD Settings",
        category: "Ship Systems",
        summary: "Manages settings for some of the Vimana-X HUD components.",
        callback: this.$showPage.bind(this)
    });
}

//-------------------------------------------------------------------------------------------------------------
this.$showPage = function _vimanaXHUD_showPage() {
    var curChoices = {};
    var text = "";
    var col = 22;
    var counter = 0;

    text = "Select from the options below:";

    curChoices["00_00_ALERTS"] = {
        text: "Large alert popups on the main screen - " + (worldScripts.VimanaX_Alerts._disabled == false ? "Enabled" : "Disabled"),
        color: "greenColor",
        alignment: "LEFT",
        unselectable: true
    };
    if (worldScripts.VimanaX_Alerts._disabled == false) {
        curChoices["00_00_DISABLE_ALERTS"] = {
            text: "- Disable large alert popups",
            alignment: "LEFT"
        };
    } else {
        curChoices["00_00_ENABLE_ALERTS"] = {
            text: "- Enable large alert popups",
            alignment: "LEFT"
        };
    }
    curChoices["00_01_STYLE"] = {
        text: "Main screen UI style - " + this._style,
        color: "greenColor",
        alignment: "LEFT",
        unselectable: true
    };
    if (this._style == "dark") {
        curChoices["00_01_UILIGHT"] = {
            text: "- Change style to light",
            alignment: "LEFT"
        };
    } else {
        curChoices["00_01_UIDARK"] = {
            text: "- Change style to dark (helps manage glare)",
            alignment: "LEFT"
        };
    }
    curChoices["00_02_HEADER"] = {
        text: "Non-linear scanner - " + (this._nonLinear ? "Yes" : "No") + " / Scanner ultra-zoom - " + (this._ultraZoom ? "Yes" : "No"),
        color: "greenColor",
        alignment: "LEFT",
        unselectable: true
    };
    if (this._nonLinear == true) {
        curChoices["00_02_LINEAR"] = {
            text: "- Switch to linear scanner (ships can disappear from zoomed scanner)",
            alignment: "LEFT"
        }
    } else {
        curChoices["00_02_NONLINEAR"] = {
            text: "- Switch to non-linear scanner (ships are pushed outwards as zoom increases)",
            alignment: "LEFT"
        }
    }
    if (this._ultraZoom == true) {
        curChoices["00_03_NORMALZOOM"] = {
            text: "- Switch to normal zoom modes (1x/2x/3x/4x/5x)",
            alignment: "LEFT"
        }
    } else {
        curChoices["00_03_ULTRAZOOM"] = {
            text: "- Switch to ultra zoom modes (1x/2x/4x/8x/16x)",
            alignment: "LEFT"
        }
    }
    curChoices["00_99_OPTION"] = {
        text: "",
        unselectable: true
    };

    curChoices["01_00_HEADER"] = {
        text: "Special Slot 1 content",
        alignment: "LEFT",
        color: "greenColor",
        unselectable: true
    };
    curChoices["02_00_HEADER"] = {
        text: "Special Slot 2 content",
        alignment: "LEFT",
        color: "greenColor",
        unselectable: true
    };
    curChoices["01_00_OPTION"] = {
        text: this.$padText("- Nothing", col) + (this._setSlot1 == 0 ? " ** currently set" : ""),
        alignment: "LEFT"
    };
    curChoices["02_00_OPTION"] = {
        text: this.$padText("- Nothing", col) + (this._setSlot2 == 0 ? " ** currently set" : ""),
        alignment: "LEFT"
    };
    if (this._AMS) {
        counter += 1;
        curChoices["01_01_OPTION"] = {
            text: this.$padText("- Anti-Missile system (when installed)", col) + (this._setSlot1 == 1 ? " ** currently set" : ""),
            alignment: "LEFT"
        };
        curChoices["02_01_OPTION"] = {
            text: this.$padText("- Anti-Missile system (when installed)", col) + (this._setSlot2 == 1 ? " ** currently set" : ""),
            alignment: "LEFT"
        };
    }
    if (this._SRS) {
        counter += 1;
        curChoices["01_02_OPTION"] = {
            text: this.$padText("- Self-Repair system (when installed)", col) + (this._setSlot1 == 2 ? " ** currently set" : ""),
            alignment: "LEFT"
        };
        curChoices["02_02_OPTION"] = {
            text: this.$padText("- Self-Repair system (when installed)", col) + (this._setSlot2 == 2 ? " ** currently set" : ""),
            alignment: "LEFT"
        };
    }
    if (worldScripts.ShipConfiguration_HeatSink) {
        counter += 1;
        curChoices["01_05_OPTION"] = {
            text: this.$padText("- Heak sink control (when installed)", col) + (this._setSlot1 == 5 ? " ** currently set" : ""),
            alignment: "LEFT"
        };
        curChoices["02_05_OPTION"] = {
            text: this.$padText("- Heak sink control (when installed)", col) + (this._setSlot2 == 5 ? " ** currently set" : ""),
            alignment: "LEFT"
        };
    }
    if (worldScripts.oreProcessor) {
        counter += 1;
        curChoices["01_06_OPTION"] = {
            text: this.$padText("- Ore processor status (when installed)", col) + (this._setSlot1 == 6 ? " ** currently set" : ""),
            alignment: "LEFT"
        };
        curChoices["02_06_OPTION"] = {
            text: this.$padText("- Ore processor status (when installed)", col) + (this._setSlot2 == 6 ? " ** currently set" : ""),
            alignment: "LEFT"
        };
    }
    curChoices["01_03_OPTION"] = {
        text: this.$padText("- Rank (with # kills for next rank and since launch)", col) + (this._setSlot1 == 3 ? " ** currently set" : ""),
        alignment: "LEFT"
    };
    curChoices["02_03_OPTION"] = {
        text: this.$padText("- Rank (with # kills for next rank and since launch)", col) + (this._setSlot2 == 3 ? " ** currently set" : ""),
        alignment: "LEFT"
    };
    curChoices["01_04_OPTION"] = {
        text: this.$padText("- Legal status (with current bounty)", col) + (this._setSlot1 == 4 ? " ** currently set" : ""),
        alignment: "LEFT"
    };
    curChoices["02_04_OPTION"] = {
        text: this.$padText("- Legal status (with current bounty)", col) + (this._setSlot2 == 4 ? " ** currently set" : ""),
        alignment: "LEFT"
    };

    for (var i = 0; i < (5 - counter); i++) {
        curChoices["98_SPACER_" + i.toString()] = {
            text: "",
            unselectable: true
        }
    }

    curChoices["99_EXIT"] = "Exit";
    if (this._default == "") this._default = "99_EXIT";

    var opts = {
        screenID: "oolite-vimanaxhud-dockside-map",
        title: "Vimana-X HUD Configuration",
        allowInterrupt: true,
        exitScreen: "GUI_SCREEN_INTERFACES",
        initialChoicesKey: this._default,
        choices: curChoices,
        message: text
    };
    mission.runScreen(opts, this.$screenHandler, this);
}

//-------------------------------------------------------------------------------------------------------------
this.$screenHandler = function _vimanaXHUD_screenHandler(choice) {
    if (choice == null) return;

    this._default = choice;
    switch (choice) {
        case "00_00_DISABLE_ALERTS": worldScripts.VimanaX_Alerts._disabled = true; this._default = "00_00_ENABLE_ALERTS"; break;
        case "00_00_ENABLE_ALERTS": worldScripts.VimanaX_Alerts._disabled = false; this._default = "00_00_DISABLE_ALERTS"; break;
        case "00_01_UILIGHT": this._style = "light"; this._default = "00_01_UIDARK"; break;
        case "00_01_UIDARK": this._style = "dark"; this._default = "00_01_UILIGHT"; break;
        case "00_02_NONLINEAR": this._nonLinear = true; this._default = "00_02_LINEAR"; this.$updateHUDSelectorSettings(); break;
        case "00_02_LINEAR": this._nonLinear = false; this._default = "00_02_NONLINEAR"; this.$updateHUDSelectorSettings(); break;
        case "00_03_ULTRAZOOM": this._ultraZoom = true; this._default = "00_03_NORMALZOOM"; this.$updateHUDSelectorSettings(); break;
        case "00_03_NORMALZOOM": this._ultraZoom = false; this._default = "00_03_ULTRAZOOM"; this.$updateHUDSelectorSettings(); break;
        case "01_00_OPTION": this._setSlot1 = 0; this.$changeSettings(); break;
        case "01_01_OPTION": this._setSlot1 = 1; this.$changeSettings(); break;
        case "01_02_OPTION": this._setSlot1 = 2; this.$changeSettings(); break;
        case "01_03_OPTION": this._setSlot1 = 3; this.$changeSettings(); break;
        case "01_04_OPTION": this._setSlot1 = 4; this.$changeSettings(); break;
        case "01_05_OPTION": this._setSlot1 = 5; this.$changeSettings(); break;
        case "01_06_OPTION": this._setSlot1 = 6; this.$changeSettings(); break;
        case "02_00_OPTION": this._setSlot2 = 0; this.$changeSettings(); break;
        case "02_01_OPTION": this._setSlot2 = 1; this.$changeSettings(); break;
        case "02_02_OPTION": this._setSlot2 = 2; this.$changeSettings(); break;
        case "02_03_OPTION": this._setSlot2 = 3; this.$changeSettings(); break;
        case "02_04_OPTION": this._setSlot2 = 4; this.$changeSettings(); break;
        case "02_05_OPTION": this._setSlot2 = 5; this.$changeSettings(); break;
        case "02_06_OPTION": this._setSlot2 = 6; this.$changeSettings(); break;
    }

    if (choice != "99_EXIT") {
        this.$showPage();
    }
}

//----------------------------------------------------------------------------------------
this.$updateHUDSelectorSettings = function _vimanaXHUD_updateHUDSelectorSettings() {
    var h = worldScripts.hudselector;
    if (h) h.$HUDSelectorScanner = ((this._nonLinear ? 1 : 0) + (this._ultraZoom ? 2 : 0));
}

/***********************************
 *                    helpers
 ***********************************/
//----------------------------------------------------------------------------------------
this.$measureText = function _vimanaXHUD_measureText() {
    var test = defaultFont.measureString("0Z");
    var i = oolite.resourcePaths.length;
    while (i--) {
        // we're going to force the issue for OCRA Extended...
        if (oolite.resourcePaths[i].indexOf("OCRAExtended") >= 0) { test = 0.9; break; }
    }
    if (test > 0.864) this._widthLookup = 1;

    test = defaultFont.measureString("0");
    if (test > 0.5) {
        this._spacer = "";
    } else if (test > 0.45 && test <= 0.5) {
        this._spacer = " ";
    } else {
        this._spacer = "  ";
    }
}

//-------------------------------------------------------------------------------------------------------------
// appends space to currentText to the specified length in 'em'
this.$padText = function _vimanaXHUD_padText(currentText, desiredLength, leftSwitch, centreSwitch) {
    var that = _vimanaXHUD_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;
        }
    }
}

//-------------------------------------------------------------------------------------------------------------
// because there is no direct connection between equipment items and MFD ID's we're doing a translation here
this.$confirmMFDEquipment = function _vimanaXHUD_confirmMFDEquipment(mfdID) {
	var list = null;
	switch (mfdID) {
		case "combat_MFD": list = ["EQ_COMBATMFD"]; break;
		case "telescope": list = ["EQ_TELESCOPE"]; break;
		case "escortdeck": list = ["EQ_ESCORTDECK", "EQ_ESCORTDECKXL"]; break;
		case "CommsLogMFD": list = ["EQ_COMMSLOGMFD", "EQ_COMMSLOGMFD_PASSIVE"]; break;
		case "BroadcastCommsMFD": list = ["EQ_BROADCASTCOMMSMFD"]; break;
		case "trophy_mfd": list = ["EQ_TROPHY_MFD"]; break;
		case "navi_mfd": list = ["EQ_NAVIGATION_MFD"]; break;
        case "NavigationBeaconsMFD": list = ["EQ_NAVBEACONS_MFD"]; break;
		case "inquirer_mfd": list = ["EQ_MARKET_INQUIRER_MFD"]; break;
        case "HermitageMFD": list = null; if (!worldScripts.Hermitage_Main) return false; break; // no equip for this one
		case "manifest_mfd": list = ["EQ_MANIFEST_MFD"]; break;
		case "useful_MFD_general_info": list = null; if (!worldScripts.useful_MFDs) return false; break; // no equip for this one
        case "useful_MFD_market": list = null; if (!worldScripts.useful_MFDs) return false; break;
		case "Waypoint_Here_MFD": list = ["EQ_WPH_ASC_UPGRADE"]; break;
		case "DamageReportMFD": list = ["EQ_DAMAGE_REPORT_MFD", "EQ_DAMAGE_REPORT_MFD_PASSIVE"]; break;
		case "RangeFinderMFD": list = ["EQ_GCM_RANGE_FINDER_MFD"]; break;
		case "LaunchQueueMFD": list = null; break; // no equip for this one
		case "BountySystem_WarrantScanner": list = ["EQ_WARRANT_SCANNER"]; break;
        case "RandomStationNames": list = ["EQ_ALMANAC_UNIT_MFD"]; break;
        case "EQ_ADVANCED_SYSTEM_DATA_MFD": list = ["EQ_ADVANCED_SYSTEM_DATA_MFD"]; break;
        case "nm_primeable-mfd": list = null; if (!worldScripts.PrimeableEquipmentMFD) return false; break;
        case "SSLaneIndicator": list = ["EQ_SSLI_MFD"]; break;
        case "tsplugins_srs": list = ["EQ_TSP_SHORT_RANGE_SNAPSHOT"]; break;
        case "tsplugins_tmi": list = ["EQ_TSP_TARGET_MEMORY_INTERFACE"]; break;
        case "ships-library": list = ["EQ_SHIPS_LIBRARY"]; break;
	}
	if (list == null) return true;
	var p = player.ship;
    var i = list.length;
	while (i--) {
		if (p.equipmentStatus(list[i]) == "EQUIPMENT_OK") return true;
	}
	return false;
}

//-------------------------------------------------------------------------------------------------------------
this.$changeSettings = function _vimanaXHUD_changeSettings() {
    var list = ["", "AMS", "SRS", "RANK", "STATUS", "HEATSINK", "OREPROC"];
    if (this._setSlot1 >= 0) this._specialSlots[0] = list[this._setSlot1];
    if (this._setSlot2 >= 0) this._specialSlots[1] = list[this._setSlot2];
}

//-------------------------------------------------------------------------------------------------------------
this.$updateShipConfigHUD = function _vimanaXHUD_updateShipConfigHUD() {
    // tell ShipConfig to use our HUD on the F3 Equip Ship screen
    var sch = worldScripts.ShipConfiguration_F3HUDControl;
    var p = player.ship;
    if (sch && p.hud.indexOf(this.name) >= 0) {
        if (!sch._holdXHUD) sch._holdXHUD = sch._equipSpaceHUD;
        sch._equipSpaceHUD = this._dockedHUD;
    }
}

//-------------------------------------------------------------------------------------------------------------
this.$revertShipConfigHUD = function _vimanaXHUD_revertShipConfigHUD() {
    // tell ShipConfig to go back to it's former HUD on the F3 Equip Ship screen
    var sch = worldScripts.ShipConfiguration_F3HUDControl;
    var p = player.ship;
    if (sch && sch._holdXHUD) {
        sch._equipSpaceHUD = sch._holdXHUD;
        delete sch._holdXHUD;
    }
}

//-------------------------------------------------------------------------------------------------------------
this.$killsUntilNextRank = function _vimanaXHUD_killsUntilNextRank() {
    var ranks = [6400, 2560, 512, 128, 64, 32, 16, 8];
    var i = ranks.length;
    var score = player.score;
    while (i--) {
        if (ranks[i] > score) return (ranks[i] - score);
    }
    return 0;
}

//-------------------------------------------------------------------------------------------------------------
this.$playSound = function _vimanaXHUD_playSound() {
    var mySound = new SoundSource();
    mySound.sound = "[@click]";
    mySound.loop = false;
    mySound.play();
}

//-------------------------------------------------------------------------------------------------------------
this.$switchDockedColor = function() {
    player.ship.removeEquipment("EQ_VIMANAX_COLOR_NORMAL");
    player.ship.removeEquipment("EQ_VIMANAX_COLOR_AMBER");
    if (this.$checkForAmberMode() == true) {
        player.ship.awardEquipment("EQ_VIMANAX_COLOR_AMBER");
    } else {
        player.ship.awardEquipment("EQ_VIMANAX_COLOR_NORMAL");
    }
}

//-------------------------------------------------------------------------------------------------------------
this.$checkForAmberMode = function _vimanaXHUD_checkforAmberMode() {
    var xenonUI = false;
    if (worldScripts.Lib_GUI) {
        if (worldScripts.Lib_GUI.$cur == "XenonUI") xenonUI = true;
    } else {
        if (worldScripts.XenonUI) xenonUI = true;
    }
    if (!xenonUI) return false;
    return worldScripts.XenonUI._amber;
}

//-------------------------------------------------------------------------------------------------------------
this.$updateDockedHUDLabels = function() {
    var s = "";
    if (system.isInterstellarSpace) {
        s = "Interstellar space";
    } else {
        s = system.name + " (" + this._ecos[system.economy] + this._govs[system.government] + (system.techLevel + 1) + ")";
    }
    player.ship.setCustomHUDDial("current_system", s);
    player.ship.setCustomHUDDial("current_station", this.$padText(player.ship.dockedStation.displayName, 13.88, true));
}
