Back to Index Page generated: May 19, 2025, 12:03:06 PM

Expansion Vimana-X HUD

Content

Warnings

  1. Required Expansions mismatch between OXP Manifest and Expansion Manager at character position 0060 (DIGIT ZERO vs LATIN SMALL LETTER N)
  2. Unresolved dependency reference to oolite.oxp.Wildeblood.ActiveCrosshairs:0
  3. No version in dependency reference to oolite.oxp.Norby.CombatMFD:null
  4. No version in dependency reference to oolite.oxp.phkb.WireframeShipImages:null
  5. No version in dependency reference to oolite.oxp.Wildeblood.alerting_crosshairs:null
  6. No version in dependency reference to oolite.oxp.Wildeblood.LaserificCrosshairs:null
  7. No version in dependency reference to oolite.oxp.Wildeblood.ShieldtasticCrosshairs:null
  8. No version in dependency reference to oolite.oxp.Wildeblood.ActiveCrosshairs:null
  9. Conflict Expansions mismatch between OXP Manifest and Expansion Manager at character position 0075 (DIGIT ZERO vs LATIN SMALL LETTER N)

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description A system-wide tweak, refinement and rework of the Vimana HUD. A system-wide tweak, refinement and rework of the Vimana HUD.
Identifier oolite.oxp.phkb.VimanaX_HUD oolite.oxp.phkb.VimanaX_HUD
Title Vimana-X HUD Vimana-X HUD
Category HUD HUD
Author Gnievmir, phkb Gnievmir, phkb
Version 1.25 1.25
Tags
Required Oolite Version
Maximum Oolite Version
Required Expansions
  • oolite.oxp.Norby.CombatMFD:0
  • oolite.oxp.phkb.WireframeShipImages:0
  • oolite.oxp.Norby.CombatMFD:
  • oolite.oxp.phkb.WireframeShipImages:
  • Optional Expansions
  • oolite.oxp.Norby.HUDSelector:1.18
  • oolite.oxp.Thargoid.RepairBots:2.14
  • oolite.oxp.CommonSenseOTB.ShieldEqualizer+Capacitors:1.3
  • oolite.oxp.Lone_Wolf.ShieldCyclerNext:2.1
  • oolite.oxp.CommonSenseOTB.SniperLock:1.0
  • oolite.oxp.EricWalch.MissileAnalyser:1.2
  • oolite.oxp.hoqllnq.missile-beep:1.3
  • oolite.oxp.phkb.LMSS:2.1
  • oolite.oxp.Thargoid.IronHide:2.00
  • oolite.oxp.Wildeblood.AutoCrosshairs:1.1.1
  • oolite.oxp.Norby.HUDSelector:1.18
  • oolite.oxp.Thargoid.RepairBots:2.14
  • oolite.oxp.CommonSenseOTB.ShieldEqualizer+Capacitors:1.3
  • oolite.oxp.Lone_Wolf.ShieldCyclerNext:2.1
  • oolite.oxp.CommonSenseOTB.SniperLock:1.0
  • oolite.oxp.EricWalch.MissileAnalyser:1.2
  • oolite.oxp.hoqllnq.missile-beep:1.3
  • oolite.oxp.phkb.LMSS:2.1
  • oolite.oxp.Thargoid.IronHide:2.00
  • oolite.oxp.Wildeblood.AutoCrosshairs:1.1.1
  • Conflict Expansions
  • oolite.oxp.Wildeblood.alerting_crosshairs:0
  • oolite.oxp.Wildeblood.LaserificCrosshairs:0
  • oolite.oxp.Wildeblood.ShieldtasticCrosshairs:0
  • oolite.oxp.Wildeblood.ActiveCrosshairs:0
  • oolite.oxp.Wildeblood.alerting_crosshairs:
  • oolite.oxp.Wildeblood.LaserificCrosshairs:
  • oolite.oxp.Wildeblood.ShieldtasticCrosshairs:
  • oolite.oxp.Wildeblood.ActiveCrosshairs:
  • Information URL https://wiki.alioth.net/index.php/Vimana-X_HUD n/a
    Download URL https://wiki.alioth.net/img_auth.php/8/80/VimanaX_HUD_1.25.oxz n/a
    License CC BY-SA 4.0 CC BY-SA 4.0
    File Size n/a
    Upload date 1747150443

    Documentation

    Also read http://wiki.alioth.net/index.php/Vimana-X%20HUD

    Readme_Vimana_2.07.txt

    VimanaHUD OXP
    -------------
    v2.07, by Gnievmir
    
    Vimana HUD is a full featured Heads Up Display, overlaying a complex dashboard over the external optical feed shown in your viewscreen.
    
    It has analogic/digital gauges for Speed, Fuel, Altitude, Cargo, Cabin Temperature, Forward and Aft Shield Strength, Energy, Armour and Laser Temperature; icons describing existence and readiness of Fuel Injectors, Fuel Scoops, Energy Unit (EEU or NEU), ECM, LMSS, Repair System, Shield Capacitors and Shield Equalizer or Shield Cycler. 
    
    It describes the primed equipment and the next primeable equipment in the cycle, the weapon mounted in the current view direction, and the available capacity for Anti-Missile System darts and Repair System charges.
    
    There are custom crosshairs for each alert condition, and visual alerts, warnign and critical levels, for energy, cabin temperature, shield strength, and altitude.
    
    There are two versions of the in-flight HUD, one with 6 MFDs and other with 12 MFDs, though the lower 2 MFD slots in the 12-slots version should only be used on widescreen monitors. There is a docked HUD that shows information on the screen borders, leaving the centre free for the station interfaces.
    
    The expansion modules, available on Ship Outfitting (F3) screen, show information that usually would be shown on MFDs.
    
    Equipments
    ----------
    
    - Travel Module, available at TL 6 for 1,000 ₢
    
    Shows multiple witchspace destinations, with distance/fuel consumption, travel time and number of jumps.
    
    
    - Ship Module, available at TL 6 for 1,500 ₢
    
    Shows damage status of ship's equipment.
    
    
    - Target Module, available at TL 6 for 2,500 ₢
    
    Displays information on current target.
    
    
    - TFSystem, available at TL 7 for 3,100 ₢
    
    Target Filtering System, allows selection of targets by class: hostile/outlaw, police, thargoid, neutral, cargo, asteroids, etc.
    
    
    - Vimana Beam Laserm available at TL 9 for 15,000 ₢
    
    A low heat beam laser with low energy footprint, range of 25km. Alternative to Military Laser.
    
    
    License
    -------
    
    Creative Commons Attribution Non-Comercial Share-Alike 4.0 (https://creativecommons.org/licenses/by-nc-sa/4.0/)
    
    Version History
    ---------------
    v2.07 (by Dybal)
    
    * Fixes display of Repair System status.
    
    v2.06 (by Dybal)
    
    * Moves overriding of ship characteristics to VimanaShipOverrides OXP.
    * Fixes Repair System worldScript name.
    * Makes HUD compatible with HUD Selector.
    * Updates compatibility with Repair Bots 2.14, Shield Equalizer and Capacitors v1.6+, SniperLock Plus.
    * Changes Repair Bots, Shield Equalizer and Capacitos, SniperLock, Missile Analyser, Missile Beep, LMSS, Iron Hide and Auto Crosshairs from required to optional.
    * Makes it compatible with Shield Cycler Next v2.0+.
    * Adds a 12-MFDs version.
    * Makes it incompatible with Active Crosshairs OXP (it overrides the HUD's crosshairs).
    * Adds central dot to crosshairs.
    * Sets crosshairs before launch.
    * Adds docked version of the HUD, displaying info on the screen borders and leaving the screen centre free for Station Interfaces.
    * Keeps the Compass target when an ident or missile target is acquired.
    * Uses beacon label, if defined, for Compass target display
    * Doesn't display shield low warning in Torus Drive (for HardWay OXP users).
    
    v2.05
    
    * Initial version published by Gnievmir on http://bb.oolite.space/viewtopic.php?p=268089
    
    

    readme.txt

    Vimana-X HUD
    ============
    By Gnievmir and phkb
    
    Overview
    ========
    Gnievmir's original Vimana HUD has earned a lot of praise for the stylish layout of the graphical dials and other UI bells and whistles. However, I always struggled to choose it for a number of reasons:
    - It seemed to be designed with a single font in mind. Using a different font leads to a lot of text overrunning the graphical bounds of the UI, or not aligning correctly.
    - It also seemed to be designed with a very specific group of OXP's in mind. If those OXP's are missing then parts of the UI were effectively useless.
    - When viewing any of the F5-F8 pages during flight, or when going to the F2 screen after pausing, the HUD would overlap parts of the screen, making some things difficult to read.
    - The Ship info and Target info panels are useful, but only a limited number of ships would be shown as an image.
    - The "Mode" information for certain primable OXP equipment items was limited in what it would show.
    - The jump distance indicator on the fuel gauge would only show after the Travel Module was purchased.
    - An "uber" laser was included in the original Vimana HUD, as well as a targeting equipment item. Both were better suited to separate OXP's.
    
    So, I embarked on a tweaking session, which turned into a design/layout session, which turned into a much bigger update than I was expecting. However, I feel the result is worth it. Here's a complete breakdown of everything I did:
    
    1. I divided the UI up into two, with only the scanner and core dials and gauges showing whenever a non-viewscreen view is selected.
    2. I repositioned some components to allow for some greater flexibility with other items. I repositioned the injectors icon, the fuel scoop icon, and the fuel warning icon to be inside the speed, cargo and fuel gauges respectively, which allowed me to move the shield capacitors icon, shield cycler icon and EEU icons to the left side of the UI. This then allowed enough room to add an additional gauge which is used for aft armour (at present, this is only used by Ship Configuration, but if other OXP's deploy aft shields it can be configured to use that as well).
    3. I darkened the background of the UI substantially, making it less transparent, and therefore better able to cope with high-glare environments. But in case anyone was particularly attached to the "light" version, it can still be used as an option (selectable from an F4 interface screen).
    4. I reworked much of the text alignment code to ensure all the displays would work well with every font available. So columns will line up, text will be centred where required, and text items will not go beyond the bounds of the UI (mostly!).
    5. I looked at how it works with other OXP's and tried to expand the possibilities and remove the locked-in feeling with some of the UI elements. In particular, the Anti-missile system and the Self-Repair system, which had their own lines on the UI. I switched this for a customisable system to allow for future OXP integrations, and added a couple of extra options to select from. There is now a F4 interface page, "Vimana-X HUD Settings" where the different options can be selected.
    6. I expanded the "MODE" display for primable equipment, finding as many OXP's as I could that make use of this feature and adding the appropriate text.
    7. I added alert icons inside each of the items that can cause alerts (altitude, cabin temp, energy, shields), and a missile warning icon in the combat HUD, to complement the larger warnings that appear at the top of the screen. If you find the top screen icons too intrusive, they can be turned off via the interfaces page, leaving just the smaller alert icons on the HUD. Also, I removed the text from the alert images, leaving them as images, and added text to the HUD, so that the warnings will appear in whatever font the player has chosen to use.
    8. I added a bunch (600+!) of extra ship images from a variety of sources, so chances are a ship image will display in the left panel in the majority of cases. I also redid the existing images, because I couldn't reproduce the style of the original. What I've used is the wireframe version of all the ships, which carries a nice blueprint/schematic style to the ships. If I've left out your favourite ships, just let me know and I'll include them in a future release.
    9. I changed the way the "scan" component works. In the original HUD, different parts of your ship would be highlighted individually, as if a "scan" was taking place. However, given the number of new ship images I was adding, it would be a mammoth task to divide each one up into four to keep that system. So I implemented a new "scan" that will work for whatever ship is displayed.
    10. I changed the colour of the jump distance indicator in the fuel gauge, to make it stand out more. 
    11. I changed the source of the targeted ship's weapon, taking it from Combat MFD's data, so that it matches what you see in that MFD, but also so that some information isn't revealed before the player has any right to know.
    12. I added an icon for the naval energy unit, to make it distinct from the normal one.
    13. To aid with startup timeout issues, I made the various timers start in sequence, and play a small sound when they turn on, to indicate the systems are starting up.
    14. I added a 10-MFD version of the HUD, as well as reducing the size of the lower left and right MFD's on the 12-MFD version, to prevent them from overlapping the UI on a 16:9 display. If you use the 12-MFD HUD, and your screen dimensions cause the lower left and right MFD's to overlap the UI, and it doesn't make your eyes twitch, then everything is fine! But if you find small details like that really annoying, and you really need all the MFD's you can get, I'd recommend the 10-MFD version. I won't judge.
    15. I turned on the non-linear scanner and ultra zoom options on the HUD. Plus added options to change these settings on the F4 interface page.
    16. The Alt gauge will now reset when entering interstellar space.
    17. Only equipment that is visible on the F5 page will be shown on any damaged equipment list.
    18. Lots of small bug fixes, code tweaks and performance improvements.
    19. I removed the targeting equipment item and the "uber" laser. It's now just a HUD. If you really want to keep those items, you should keep the original Vimana HUD OXP installed. There should be no conflicts between the HUDs.
    
    If you have previously used the Vimana HUD, and purchased the Target, Travel and Ship modules for it, you will have those modules added automatically when you install this HUD. 
    
    License
    =======
    Creative Commons Attribution Non-Commercial Share-Alike 4.0 (https://creativecommons.org/licenses/by-nc-sa/4.0/)
    
    Version History
    ===============
    1.25
    - Switched the custom name to be right aligned, rather than left aligned.
    
    1.24
    - When a target entity has a custom name, it will now be put on a separate line, below the ship class name.
    
    1.23
    - Refuelling stations now show energy and collision radius when targeted.
    - Equipment damaged or repaired in dock will now longer generate an error.
    
    1.22
    - Fixed bug that was causing the travel info to be calculated and displayed over and over.
    - Fixed issue with globe image.
    
    1.21 
    - Added rgba_background to message_gui element.
    - Added individual images for all asteroids, boulders, fragments and splinters.
    - Split off the ship images into a separate OXP (Wireframe Ship Images) to make it easier for other OXP authors to leverage the images, and so this OXP doesn't need to be updated as much.
    - Re-enabled ship scan and shield graphics (forgot to turn them on again after testing!)
    
    1.20
    - Performance improvements.
    - Added image for Sidewinder NG
    - Added more Thargoid/Tharglet images, and improved identification for various Thargoid Warships and Robot Fighters.
    - Added/tweaked images for Thargoid vessels in TCAT 2.0.
    - Added some missing Feudal States images.
    - Added image for Cobra Mk IX.
    - Added image for Sidewinder NG.
    - Max normal speed now always shown correctly on speed dial.
    
    1.19
    - Added images for Revolutionary AstroFarms and Revolutionary Logistics.
    
    1.18
    - Added image for Fruit Bat and Flying Fox.
    - Added missing Rock Hermit disambiguation link for Pirate Coves.
    - Carriers that are ships will now have their speed displayed in the left panel when targeted, instead of their collision radius.
    
    1.17
    - Added images from Lave Academy.
    - Added images from Coluber Racers.
    - Added image from STE.
    - Improved detection of Xenon UI amber mode on startup.
    - Improved protection against missing data from Extra Rock Hermits.
    
    1.16
    - Added images for Extra Rock Hermits.
    
    1.15
    - Added images for Jump Gates.
    - Added images for Nuit Vampires.
    - Added images for Isis Interstellar.
    
    1.14
    - Fixed for NaN showing in space compass distance when Manual Witchspace Alignment target is selected.
    - Clock on docked HUD is now right-aligned to the game window no matter what font is used.
    - Some code refactoring.
    
    1.13
    - Small tweak to the compass target distance display, so "km" remains the scale up to 9999km before switching.
    
    1.12
    - Fixed issue with missile warning system not working reliably,
    - Added primable equipment info for Ejection Damper (from GalCop Missions OXP).
    - Tweaked the distance to target element, so large values should fit into the UI bounds better.
    - Space compass target distance made to stay within bounds.
    - Speed value will now stay within bounds.
    - Added disambiguation for Kiota Habitat Stations (could be 2 ring, 4 ring or 4 ring variant).
    - Added code to read Telescope V2 mode (only available with Telescope v2.1.4).
    
    1.11
    - Added some missing station image lookups.
    - Rotated some station images for consistency.
    - Tweaked the compass image for less graininess.
    - Further improvements to the MFD background clearing process.
    - Added extra system info to witchspace destination label when docked.
    - Added station name and current system name and info to docked HUD.
    - Missile data in the target information panel now only shows what type of missile the target has launched.
    - Used cargo space of the target is now only visible if Manifest Scanner has scanned ship.
    - Added missing Sidewinder image, now distinct from Sidewinder Escort.
    - Added disambiguation keys for ships named "Sidewinder Scout Ships" (which could be Sidewinders or Sidewinder Escorts).
    
    1.10
    - Better protection against undefined results when targeting ships.
    
    1.9
    - Fixed issue with docked HUD not showing hyperspace destination unless a system map concealment OXP was active and systems had been revealed.
    - Added docked HUD amber mode, which is auto-selected if XenonUI is active and has it's amber mode turned on.
    - Fixed a number of errors with ship images (missing files, mis-named files and incorrect lookups).
    
    1.8
    - Added ship images for Sniper Gun ships.
    - Added ship images for Riredi OXP ships.
    - Added ship speed to combat crosshairs.
    
    1.7
    - Fixed issue where route information was not showing in left side panel unless a system map concealment OXP was active and systems had been revealed.
    - Switched gauges for Alt, Energy, Front/Aft Shield, and Front/Aft Armour to have biggest dial segment for the smallest (and most critical) value.
    - Fixed issue where Ironhide armour percentage could have excessive decimal points.
    - Made flashing warning labels stay on screen for longer for better readability.
    - Fixed issue preventing Shield Cycler icons from appearing.
    - Removed incompatibility settings with Shield Cycler.
    - Switched alerting function calculation of altitude to use Combat MFD's calculation, rather than doing it again.
    - Linked up colour of the Manual Witchspace Alignment jump beacon to match UI colours.
    - Some code refactoring.
    
    1.6
    - Fixed issue with target speed values showing as "undefined".
    - More improvements to the MFD background clearing process.
    - Fixed spelling error for Vampire Mk6 image.
    - Fixed spelling error for Boomslang MkIII image.
    - Fixed spelling error for Raptor Defense Interceptor image.
    - Corrected station identification for Solo's Alt Stations.
    - Fixed JS error when targeting a system that cannot be reached.
    - Small tweak to the character width of the speed value, so it doesn't overflow the UI when speed is high and using wide fonts.
    
    1.5
    - Added fuel leak warning.
    - Cleaned up issue where MFD background images were not being removed when the MFD slot was cleared, in some cases.
    - Fixed a couple of issues where JS errors would occur when the player ship was destroyed.
    - Fixed issues where the witchspace destination would read "(Unknown)" when no destination had been set.
    - Moved storage of missile monitoring array to somewhere where it shouldn't be overwritten or lost.
    - Bug fixes.
    
    1.4
    - Target info for escape pods now just shows speed and bounty.
    - Fixed issue where not all cargo containers were getting an image in the target info.
    - Made the background of MFD's a bit darker when in "dark" mode.
    - Changed the colour of the MFD's to green to match the rest of the UI.
    - Switched to CombatMFD's target speed value, for consistency between that MFD and the target info displayed here.
    - Switched to CombatMFD's altitude calculation, as there's no need to calculate the same number twice.
    - Borrowed missile tracking system from XenonHUD for improved performance.
    - Resized most of the image files to save Oolite time resizing them after starting.
    - Made the HUD work properly without HUD Selector installed.
    - Better integration with HUD Selector, particularly the number of MFD's shown as available.
    - Added options to sell each of the mods.
    - Witchspace destination and the travel mod now honour the concealment property on systems.
    - Added more ship images.
    - Code cleanup and refactoring.
    
    1.3
    - Added ship images for the Accipiter, Boomslang Mk3 and Mk4, Constore buoys, Copperhead Yari, Escortdeck ships including the S8, Farstar Murderer, Far Arm ships, Firefly, King Cobra MkI, Metal alloys, Morrigan, Mosquito, Outrider, S9 Firefly, Shuriken, Shrike, Swift, Scimitar, Stingray, Scorpius, Tembo, Tepiu, Wyvern, Snark, YAH billboard, Montana05's resource pack items, plus a couple of items I missed from Armoury.
    
    1.2
    - Stopped auto-awarding all mods to player, regardless of whether they'd purchased the Vimana HUD equivalents.
    - Fixed a bug with checking route distance when no route set.
    - Tweaks to the Heat sink special slot output. Will now display "0 avail" when no heat sinks are left, rather than a blank.
    
    1.1
    - Adjusted the F4 options page to better handle all options being visible.
    - Added options for setting Ultra Zoom and Non-Linear scanner to the options page.
    - Added joystick sensitivity indicator to the HUD.
    - Added ship images for the FdL Lightspeeder, Stormbrewer, Kracken, Draven ships, Armory items, Phantom, Spectre, SKS Plasma Mk1, Heavy Metal ships, ADCK Bulk Haulers, Saiph Interceptor, Rigel Tactical Bomber, Star Destroyer, Star Destroyer Shuttle, Tie Fighter and Tie Interceptor.
    - Some code refactoring.
    
    1.0
    - Initial release
    

    Equipment

    Name Visible Cost [deci-credits] Tech-Level
    VimanaX Color Amber no 1 1+
    VimanaX Color Normal no 1 1+
    VimanaX Font Narrow no 1 1+
    VimanaX Font Normal no 1 1+
    Sell Vimana-X HUD Ship Mod yes 750 6+
    Sell Vimana-X HUD Target Mod yes 1000 6+
    Sell Vimana-X HUD Travel Mod yes 500 6+
    Vimana-X HUD Ship Mod yes 15000 6+
    Vimana-X HUD Target Mod yes 25000 6+
    Vimana-X HUD Travel Mod yes 10000 6+

    Ships

    This expansion declares no ships. This may be related to warnings.

    Models

    This expansion declares no models. This may be related to warnings.

    Scripts

    Path
    Scripts/VimanaX_Alerts.js
    "use strict";
    this.name = "VimanaX_Alerts";
    this.author = "Gnievmir, phkb";
    this.license = "CC-BY-NC-SA 3.0";
    
    this._alertTimer = null;		//store pointer to graphical info timer
    this._lastAlert = [];
    this._disabled = false;
    this._seq = 0;
    this._flip = false;
    this._combatMFD = null;
    this._resetCounter = 0;
    this._warningOn = false;
    
    this._alerts = [
        ["vx_clean.png", "", "", ""],                                   //0 -no alert
        ["vx_d_missile.png", "DANGER!", "INCOMING MISSILE", ""],        //1 
        ["vx_d_altitude.png", "DANGER!", "ALTITUDE", "TOO LOW"],        //2
        ["vx_d_temp.png", "DANGER!", "TEMPERATURE", "CRITICAL LEVEL"],  //3
        ["vx_d_energy.png", "DANGER!", "ENERGY", "CRITICAL LEVEL"],     //4 
        ["vx_d_shield.png", "DANGER!", "SHIELD", "CRITICAL LEVEL"],     //5 
        ["vx_w_energy.png", "WARNING!", "ENERGY", "LOW LEVEL"],         //6
        ["vx_w_shield.png", "WARNING!", "SHIELD", "LOW LEVEL"],         //7
        ["vx_w_temp.png", "WARNING!", "TEMPERATURE", "TOO HIGH"],       //8 
        ["vx_w_fuelleak.png", "WARNING!", "FUEL LEAK", "DETECTED"]       //9
    ];
    
    this._operationalFunctionNames = [ // list of functions to enable/disable at HUDSelector callback
        "shipAttackedWithMissile",
        "shipWillLaunchFromStation",
        "shipWillDockWithStation",
        "shipDied"
    ];
    
    //----------------------------------------------------------------------------------------
    this.shipAttackedWithMissile = function (missile, whom) {
        var p = player.ship;
        p._incomingMiss = true;
        if (this._lastAlert[0] != 1) this._lastAlert[0] = -1;
        this.$display(1);
    	if (p) p._missiles.push(missile);
    }
    
    //----------------------------------------------------------------------------------------
    this.shipExitedWitchspace = function() {
    	if (player.ship._missiles) {
    		player.ship._missiles.length = 0;
    	} else {
    		player.ship._missiles = [];
    	}
    }
    
    //----------------------------------------------------------------------------------------
    this.shipWillLaunchFromStation = function () {
        this._seq = 0;
        this.shipExitedWitchspace(); // make sure the missiles array is reset and present
        if (!this._alertTimer) this._alertTimer = new Timer(this, this.$alerts.bind(this), 0, 0.5);
        this.$resetAlerts();
    }
    
    //----------------------------------------------------------------------------------------
    this.shipWillDockWithStation = function () {
        var p = player.ship;
        if (!p || !p.isValid) return;
       
        if (this._alertTimer) {
            this._alertTimer.stop();
            delete this._alertTimer;
        }
        p.setCustomHUDDial("VimanaX_Alert", this._alerts[0][0]);
        p.setCustomHUDDial("VimanaX_AlertText1_Red", "");
        p.setCustomHUDDial("VimanaX_AlertText2_Red", "");
        p.setCustomHUDDial("VimanaX_AlertText3_Red", "");
        p.setCustomHUDDial("VimanaX_AlertText1_Orange", "");
        p.setCustomHUDDial("VimanaX_AlertText2_Orange", "");
        p.setCustomHUDDial("VimanaX_AlertText3_Orange", "");
        p._missiles.length = 0;    
    }
    
    //----------------------------------------------------------------------------------------
    this.shipDied = function (whom, why) {
        this.shipWillDockWithStation();
    }
    
    //----------------------------------------------------------------------------------------
    this.$resetAlerts = function () {
        for (let i = 1; i < 5; i++) {
            this._lastAlert[i] = 100000;
        }
        this._lastAlert[5] = 0;
        this._lastAlert[6] = 0;
        player.ship._incomingMiss = false;
        /*this._incomingMiss = false;
    	// reset the missile monitoring array
        var p = player.ship;
    	if (p._missiles) p._missiles = [];
    	p._missiles.length = 0;*/
    }
    
    //----------------------------------------------------------------------------------------
    this.$alerts = function _vimanaXAlerts_alerts() {
        var that = _vimanaXAlerts_alerts;
        var _p = (that._p = that._p || player.ship);
        var _cbtMFD = (that._cbtMFD = that._cbtMFD || this._combatMFD);
        var _incMissiles = (that._incMissiles = that._incMissiles || this.$checkForIncomingMissiles);
        if (!_p || !_p.isValid) return;
        
        var ano = 0;
        //check incoming missile
        _incMissiles();
    
        // use combat MFD's value for alt
        var altRaw = _cbtMFD.$Data["combatAlt"].toString();
        var alt = parseInt(altRaw);
        if (isNaN(alt)) {
            alt = 999999;
        } else {
            if (altRaw.indexOf("Mkm") > 0) alt = 999999; // basically max dist
            else if (altRaw.indexOf("km") > 0) alt *= 1000 // convert to meters
        }
    
        if (_p.energy < _p.maxEnergy / 3 && _p.energy < this._lastAlert[1]) {
            ano = 4;
            this._lastAlert[1] = _p.energy;
        } else if (_p.forwardShield < _p.maxForwardShield * 0.2 && _p.forwardShield < this._lastAlert[2]) {
            ano = 5;
            this._lastAlert[2] = _p.forwardShield;
        } else if (_p.aftShield < _p.maxAftShield * 0.2 && _p.aftShield < this._lastAlert[3]) {
            ano = 5;
            this._lastAlert[3] = _p.aftShield;
        } else if (alt < 10000 && alt < this._lastAlert[4]) {
            ano = 2;
            this._lastAlert[4] = alt;
        } else if (_p.temperature > 0.7 && _p.temperature > this._lastAlert[5]) {
            ano = 3;
            this._lastAlert[5] = _p.temperature;
        } else if (_p.energy < _p.maxEnergy / 2 && _p.energy < this._lastAlert[1]) {
            ano = 6;
            this._lastAlert[1] = _p.energy;
        } else if (!_p.torusEngaged && _p.forwardShield < _p.maxForwardShield / 2 && _p.forwardShield < this._lastAlert[2]) {
            ano = 7;
            this._lastAlert[2] = _p.forwardShield;
        } else if (!_p.torusEngaged && _p.aftShield < _p.maxAftShield / 2 && _p.aftShield < this._lastAlert[3]) {
            ano = 7;
            this._lastAlert[3] = _p.aftShield;
        } else if (_p.temperature > 0.5 && _p.temperature > this._lastAlert[5]) {
            ano = 8;
            this._lastAlert[5] = _p.temperature;
        } else if (_p.fuelLeakRate > 0 && _p.fuel > 0) {
            ano = 9;
        }
        this.$display(ano);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // performs a scan of the missile array to see if any are still tracking the player
    this.$checkForIncomingMissiles = function _vimanaXAlerts_checkForIncomingMissiles() {
    	var p = player.ship;
    	// do we have any missiles in the queue?
    	if (p._missiles.length === 0) {
    		p._incomingMiss = false;
    		return;
    	}
    	// are they in range and valid?
        p._incomingMiss = false; // reset it here, so it can be set if a valid missile is found
    	var ml = p._missiles.length;
    	while (ml--) {
    		var m = p._missiles[ml];
    		if (m.isValid && m.isInSpace && m.position.distanceTo(p) < p.scannerRange) {
    			p._incomingMiss = true;
    			break;
    		}
    	}
    }
    
    //----------------------------------------------------------------------------------------
    this.$display = function _vimanaXAlerts_display(a) {
        if (a == 0 && a == this._lastAlert[0]) {
            this._resetCounter = (this._resetCounter + 1) % 4;
            // if we're getting here on every pulse, and a warning message is on, better remove it.
            if (this._resetCounter > 2 && this._warningOn == true) this.$removeAlertDisplay();
            this.$resetAlerts();
            return;
        }
        this._resetCounter = 0;
        var p = player.ship;
        if (a > 0) { //alerts
            this._seq = (this._seq + 1) % 3;
            if (this._seq < 2) {
                this._flip = false;
                if (this._disabled == false) { // we're just disabling the display of the alert, not any of the calcs
                    p.setCustomHUDDial("VimanaX_Alert", this._alerts[a][0]);
                    if (this._alerts[a][0].indexOf("_d_") >= 0) {
                        p.setCustomHUDDial("VimanaX_AlertText1_Red", this._alerts[a][1]);
                        p.setCustomHUDDial("VimanaX_AlertText2_Red", this._alerts[a][2]);
                        p.setCustomHUDDial("VimanaX_AlertText3_Red", this._alerts[a][3]);
                        p.setCustomHUDDial("VimanaX_AlertText1_Orange", "");
                        p.setCustomHUDDial("VimanaX_AlertText2_Orange", "");
                        p.setCustomHUDDial("VimanaX_AlertText3_Orange", "");
                    } else {
                        p.setCustomHUDDial("VimanaX_AlertText1_Red", "");
                        p.setCustomHUDDial("VimanaX_AlertText2_Red", "");
                        p.setCustomHUDDial("VimanaX_AlertText3_Red", "");
                        p.setCustomHUDDial("VimanaX_AlertText1_Orange", this._alerts[a][1]);
                        p.setCustomHUDDial("VimanaX_AlertText2_Orange", this._alerts[a][2]);
                        p.setCustomHUDDial("VimanaX_AlertText3_Orange", this._alerts[a][3]);
                    }
                    this._warningOn = true;
                }
            } else {
                this.$removeAlertDisplay();
            }
        } else {
            if (this._flip) this.$removeAlertDisplay();
            this._flip = !this._flip;
        }
        this._lastAlert[0] = a;
    }
    
    //----------------------------------------------------------------------------------------
    this.$removeAlertDisplay = function _vimanaXAlerts_removeAlertDisplay() {
        var p = player.ship;
        p.setCustomHUDDial("VimanaX_Alert", this._alerts[0][0]);
        p.setCustomHUDDial("VimanaX_AlertText1_Red", this._alerts[0][1]);
        p.setCustomHUDDial("VimanaX_AlertText2_Red", this._alerts[0][2]);
        p.setCustomHUDDial("VimanaX_AlertText3_Red", this._alerts[0][3]);
        p.setCustomHUDDial("VimanaX_AlertText1_Orange", this._alerts[0][1]);
        p.setCustomHUDDial("VimanaX_AlertText2_Orange", this._alerts[0][2]);
        p.setCustomHUDDial("VimanaX_AlertText3_Orange", this._alerts[0][3]);
        this._warningOn = false;
    }
    
    //----------------------------------------------------------------------------------------
    this.$disableAlerts = function _vimanaXAlerts_disableAlerts() {
        if (this._alertTimer && this._alertTimer.isRunning) this._alertTimer.stop();
        var ws = worldScripts.VimanaX_Alerts;
        var funcNames = this._operationalFunctionNames;
        var i = funcNames.length;
        while (i--)
            if (ws[funcNames[i]]) {
                ws["$save_" + funcNames[i]] = ws[funcNames[i]];
                delete ws[funcNames[i]];
            }
    }
    
    //----------------------------------------------------------------------------------------
    this.$enableAlerts = function _vimanaXAlerts_enableAlerts() {
        var ws = worldScripts.VimanaX_Alerts;
        var funcNames = this._operationalFunctionNames;
        var i = funcNames.length;
        while (i--)
        if (!ws[funcNames[i]]) {
            ws[funcNames[i]] = ws["$save_" + funcNames[i]];
        }
    }
    Scripts/VimanaX_Conditions.js
    "use strict";
    this.name = "VimanaXConditions";
    this.author = "phkb";
    this.copyright = "2023 phkb";
    this.description = "Condition script for equipment.";
    this.licence = "CC BY-NC-SA 4.0";
    
    //-------------------------------------------------------------------------------------------------------------
    this.allowAwardEquipment = function (equipment, ship, context) {
        if (context === "scripted") return true;
        return false;
    }
    
    Scripts/VimanaX_HUD.js
    "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;
        var subhead = "";
    
        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.hasRole("RSsatellite")) && !tgt.isPiloted) {
            if (tgt.name) {
                tdata[0] = tgt.name;
                if (tgt.displayName) tdata[0] = tgt.displayName;
            } else if (tgt.beaconLabel) tdata[0] = tgt.beaconLabel;
            else if (tgt.beaconCode) tdata[0] = tgt.beaconCode;
            else tdata[0] = "Unidentified";
            if (tdata[0].indexOf(":") > 0) {
                subhead = tdata[0].split(": ")[1];
                tdata[0] = tdata[0].split(": ")[0];
            }
            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.displayName.indexOf(":") > 0) {
                tdata[0] = tgt.shipClassName;
                subhead = tgt.displayName.replace(tgt.shipClassName + ": ", "");
            }
            if (tgt.maxSpeed == 0) {
                tdata[4] = _padText("RADIUS:", col1) + Math.round(tgt.collisionRadius) + " m";
            } else {
                tdata[4] = _padText("SPEED:", col1) + _cbtMFD.$Data["combatTSpeed"] + "m/s";
            }
            tdata[5] = _padText("ENERGY:", col1) + Math.round(tgt.energy);
            tdata[7] = _padText("DEFENDERS:", col1) + tgt.dockedPolice;
            if (tgt.requiresDockingClearance) {
                tdata[2] = _padText("DOCK:", col1) + "REQUEST";
                switch (_player.dockingClearanceStatus) {
                    case "DOCKING_CLEARANCE_STATUS_REQUESTED":
                        tdata[2] = _padText("DOCK:", col1) + "HOLD";
                        break;
                    case "DOCKING_CLEARANCE_STATUS_GRANTED":
                        tdata[2] = _padText("DOCK:", col1) + "GRANTED";
                        break;
                    case "DOCKING_CLEARANCE_STATUS_TIMING_OUT":
                        tdata[2] = _padText("DOCK:", col1) + "EXPIRING";
                }
            } else {
                tdata[2] = _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)) {
            if (tgt.displayName.indexOf(":") > 0) {
                tdata[0] = tgt.shipClassName;
                subhead = tgt.displayName.replace(tgt.shipClassName + ": ", "");
            }
            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));
        if (subhead != "") _p.setCustomHUDDial("VimanaX_L0", _padText(subhead, max, true));
        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));
    }