Back to Index Page generated: Nov 12, 2024, 11:02:03 PM

Expansion Dangerous HUD Blue Variant

Content

Warnings

  1. http://wiki.alioth.net/index.php/Dangerous%20HUD%20Blue%20Variant -> 404 Not Found
  2. Information URL mismatch between OXP Manifest and Expansion Manager string length at character position 0

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description This is a HUD in the style of Elite Dangerous, featuring an blue theme for both the HUD and for the GUI, cockpit views (fighter, hauler or glass only), glass effect, monitor effect for aft view, new sounds effects (ECM, hyperjumps, low energy, missile warning), custom made warnings signs, HUD animations including a pulsating scanner. Based on phkb's Xenon HUD. Tested with vanilla Oolite as well as with BGS (Backgroundset) and Xenon UI OXPs, all of which work fine with the blue color scheme. This is a HUD in the style of Elite Dangerous, featuring an blue theme for both the HUD and for the GUI, cockpit views (fighter, hauler or glass only), glass effect, monitor effect for aft view, new sounds effects (ECM, hyperjumps, low energy, missile warning), custom made warnings signs, HUD animations including a pulsating scanner. Based on phkb's Xenon HUD. Tested with vanilla Oolite as well as with BGS (Backgroundset) and Xenon UI OXPs, all of which work fine with the blue color scheme.
Identifier gsagostinho.DangerousHUD.BlueVariant gsagostinho.DangerousHUD.BlueVariant
Title Dangerous HUD Blue Variant Dangerous HUD Blue Variant
Category HUDs HUDs
Author gsagostinho gsagostinho
Version 2.0.2 2.0.2
Tags Balance=green, HUD, HUDs, hud, huds Balance=green, HUD, HUDs, hud, huds
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
Conflict Expansions
Information URL n/a
Download URL https://wiki.alioth.net/img_auth.php/7/72/Gsagostinho.DangerousHUD.BlueVariant.oxz n/a
License CC BY-NC-SA 4.0 CC BY-NC-SA 4.0
File Size n/a
Upload date 1610873335

Documentation

README.txt

Dangerous HUD (Blue Variant)
==============================

Version: 2.0.2
Required Oolite Version: 1.87
Author: Gilberto Agostinho (gsagostinho)
Credits: based on phkb's Xenon HUD
License: CC-BY-NC-SA 3.0

About
=====

This is a HUD in the style of Elite Dangerous, featuring an blue theme for both the HUD and for the GUI, cockpit views, glass effect, monitor effect for aft view, new sounds effects (ECM, hyperjumps, low energy, missile warning), custom made warnings signs, HUD animations including a pulsating scanner. Based on phkb's Xenon HUD.

The Dangerous HUD has three layouts: fighter cockpit view, hauler cockpit view and glass only view. To switch between them, first prime the "Dangerous HUD Mode Selector" then press the activation key. The HUD also has a minimal mode, which makes the crosshair and gauges nearly transparent when not in red or red/yellow alert.

Tested with vanilla Oolite as well as with BGS (Backgroundset) and Xenon UI OXPs, all of which work fine with the blue colour scheme. Be warned that this HUD is more CPU intensive than your standard HUD, so a weak machine may not run it very well.

If you also use the Market Observer OXP, I suggest the following alteration to make it look good with the new blue GUI: add the following parameter "color = (230,230,230);" (without quotes) to the "Average", "Diff", "%Diff" and "Purchases" legends. For instance, the "Average" legend will look like this after the alteration:

        {
            text    = "Average:";
            x       = -145;
            y       = 184;
            height  = 16;
            width   = 15;
            color   = (230,230,230); // add this!
        },

Finally, if you also happen to play Elite Dangerous at the same time as Oolite, you perhaps would like to take a look at mine Dangerous Keyconfig OXP which remaps Oolite's keyboard controls in a similar way as Elite Dangerous, so that one does not go crazy getting used to two different keyboard layouts for the same functions.

Version history
===============

08/12/2018 - version 2.0.2: fixes a bug which kept the HUD sounds playing after autodocking.
24/10/2018 - version 2.0.1: fixes a bug in which the cockpit background was disappearing when in red alert and minimal mode.
23/07/2018 - version 2.0: simplified crosshairs (wepons off, weapons on, minimal mode and docking mode).
                          simplified layout, removed clutter around crosshair. 
                          much improved scanner, with better animation and improved size.
                          mass lock circle indicator is now visible in all cockpit modes. 
                          new torus drive sound.
                          when using the Manual Witchjump Alignment OXP, the system target colour will now match the Dangerous HUD colour (thanks phkb!). 
                          when the player uses an escape pod the cockpit is not shown any longer in the escape pod docking animation after the ejection (thanks phkb!).
                          if the player dies and if they are using the Ship Repurchase OXP, then the cockpit is not shown any longer in the docking animation after the crash (thanks phkb!).
                          added white and purple variants.
19/07/2018 - version 1.11: cockpit lighting changes intensity when toggling weapons in minimal mode.
                           enabled minimal mode by default (i.e. crosshairs only in red alert or when weapons are on, else they fade out).
18/07/2018 - version 1.10: cockpit lighting changes colour when in red alert or if HUD is damaged (using Breakable HUD/IFF Scanner OXP).
23/02/2018 - version 1.9: merging improvements made by phkb on his Xenon HUD (version 2.0.2).
                          the hue of the cockpit now matches the colour variant.
                          fixing the 'TypeError: this.playerBoughtNewShip is not a function' which would affect some users.
13/12/2017 - version 1.8: merging improvements made by phkb on his Xenon HUD (version 1.5.11).
29/11/2017 - version 1.7: merging improvements made by phkb on his Xenon HUD (version 1.5.10).
                          new fuel leak warning message.
                          small improvements to the missile warning.
                          improvements to the position of the warnings on hauler and glass cockpits.
                          when in minimal mode, toggling weapons now changes the HUD back to the default view.
20/08/2017 - version 1.6.1: fixes a small error due to a typo.
19/08/2017 - version 1.6: performance improvements (many thanks to cag and phkb for all the help!).
                          improvements to the minimal crosshair mode: when crosshairs are set to be visible only in red/yellow alert, the gauges are now visible though very transparent.
                          fixed a bug which caused JS errors when escape pod was launched.
                          HUD now compatible with Breakable HUD/IFF Scanner OXP (thanks to phkb).
17/08/2017 - version 1.5: merging improvements made by phkb on his Xenon HUD (version 1.5.5), including improved HUDSelector integration and performance improvements.
14/08/2017 - Version 1.4: merging improvements made by phkb on his Xenon HUD (version 1.5.4).
                          added hauler cockpit mode.
                          flipped glass on side and aft (cockpit) views so that the glass dirt doesn't match when switching views.
18/07/2017 - Version 1.3: fixed a small error in the script.js, using a variable which was not defined.
                          optimized the script by switching back to local variables.
                          improved scanner pulsation.
17/07/2017 - Version 1.2: new pink variant.
                          slight modification to the green variation's hue.
                          darker scanner's background.
                          added glass only mode (i.e. no cockpit).
                          fixed wrong dates in version history.
                          target reticle now has the same colours as the HUD.
10/07/2017 - Version 1.1: added new sound for missile warning.
                          text on the message display is now also blue.
                          fixed small bug with ECM noise sound being heard while docked.
                          shipyard screen now also uses the same colour scheme as the other screens.
                          new mass lock indicator.
                          new green and blue variants.
07/07/2017 - Version 1.0: initial release.

Equipment

Name Visible Cost [deci-credits] Tech-Level
Critical Warning no 0 1+
Critical Warning Noisy 1 no 0 1+
Critical Warning Noisy 2 no 0 1+
DangerousHUD Centre Element Controller no 0 1+
DangerousHUD Centre Element Controller (minimal view) no 0 1+
DangerousHUD Clock Position 1 no 0 1+
DangerousHUD Clock Position 2 no 0 1+
DangerousHUD Clock Position 3 no 0 1+
DangerousHUD Docking Centre Element Controller no 0 1+
Fuel Leak Warning no 0 1+
DangerousHUD Missile Warning no 0 1+
Dangerous HUD Mode Selector no 0 1+
DangerousHUD Aft View no 0 1+
DangerousHUD Foward View no 0 1+
DangerousHUD Foward View minimal mode no 0 1+
DangerousHUD Port View no 0 1+
DangerousHUD Starboard View no 0 1+
Mass lock indicator no 0 1+
Mass lock lamp indicator no 0 1+
Scanner Frame 1 no 0 1+
Scanner Frame 2 no 0 1+
Scanner Frame 3 no 0 1+
Scanner Frame 4 no 0 1+
Scanner Frame 5 no 0 1+
Scanner Frame 6 no 0 1+
Scanner Frame 7 no 0 1+
Scanner Frame 8 no 0 1+
Shields Offline Warning no 0 1+

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
Config/script.js
"use strict";
this.name        = "DangerousHUD";
this.author      = "gsagostinho, based on work by phkb";
this.copyright   = "2018 phkb, 2018 gsagostinho";
this.description = "Controls HUD selector compatibility and inflight GUI screen changes";
this.licence     = "CC BY-NC-SA 4.0";

this._dockingCrosshairs = "DangerousHUD_crosshairs_docking.png";
this._holdFilter = 0;                    // hold spot for the sunGlareFilter value for the ship
this._destination = -1;                    // current witchspace destination
this._lastSource = -1;                    // used to establish the start point for destination system calculations
this._glareFilterInstalled = false;        // flag to indicate whether the glare filter OXP is installed
this._glareClarifiedInstalled = false;    // flag to indicate whether the glare clarifier OXP is installed
this._glareTimer = null;                // timer used to check when the glare filter is turned on
this._doChecks = false;                    // flag to indicated that the glare filter has been turned on and therefore checks need to me made
this._defaultGlareFilter = 0.4;            // default glare filter value provided by this OXP
this._hudVanisherInstalled = false;        // flag to indicate whether the HUD Vanisher OXP is installed
this._mode = "";                        // HUD mode, either blank for cockpit view, "_hauler" for hauler cockpit or "_glass" for glass only mode
this._minimal = false;                        // HUD minimal mode
this._viewForward = true;                     // HUD forward view status
this._crosshairMode = 1;                // Crosshair mode: 0 = normal, 1 = off in green/yellow, on in red, 2 = off in green, on in red/yellow
this._dockTimer = null;                    // timer used when docking to determine if the player has exceeded the alotted time
this._ironHideArmour = false;            // flag to indicate that IronHide armour is installed
this._shipConfigArmour = false;            // flag to indicate that Ship Configuration armour is installed
this._holdTarget = 0;
this._jumpCountdownStarted = false;        // flag used to monitor when a jump countdown has started
this._mapScreenChangeTimer = null;
this._mapScreen = "";
this._disableDockingHUD = false;
this._disableMissileWarning = false;
this._removePrimableEquip = false;
this._trueValues = ["yes", "1", 1, "true", true];
this._damaged = false;
this._crosshairList = [];
this._escapePodActivated = false;

//-------------------------------------------------------------------------------------------------------------
// functions used for animations

this.$scannerAnimationFrame1 = function() {
    player.ship.awardEquipment("EQ_SCANNER_FRAME_1");
}
this.$scannerAnimationFrame2 = function() {
    var p = player.ship;
    p.removeEquipment("EQ_SCANNER_FRAME_1");
    p.awardEquipment("EQ_SCANNER_FRAME_2");
}
this.$scannerAnimationFrame3 = function() {
    var p = player.ship;
    p.removeEquipment("EQ_SCANNER_FRAME_2");
    p.awardEquipment("EQ_SCANNER_FRAME_3");
}
this.$scannerAnimationFrame4 = function() {
    var p = player.ship;
    p.removeEquipment("EQ_SCANNER_FRAME_3");
    p.awardEquipment("EQ_SCANNER_FRAME_4");
}
this.$scannerAnimationFrame5 = function() {
    var p = player.ship;
    p.removeEquipment("EQ_SCANNER_FRAME_4");
    p.awardEquipment("EQ_SCANNER_FRAME_5");
}
this.$scannerAnimationFrame6 = function() {
    var p = player.ship;
    p.removeEquipment("EQ_SCANNER_FRAME_5");
    p.awardEquipment("EQ_SCANNER_FRAME_6");
}
this.$scannerAnimationFrame7 = function() {
    var p = player.ship;
    p.removeEquipment("EQ_SCANNER_FRAME_6");
    p.awardEquipment("EQ_SCANNER_FRAME_7");
}
this.$scannerAnimationFrame8 = function() {
    var p = player.ship;
    p.removeEquipment("EQ_SCANNER_FRAME_7");
    p.awardEquipment("EQ_SCANNER_FRAME_8");
}
this.$scannerAnimationEnd = function() {
    player.ship.removeEquipment("EQ_SCANNER_FRAME_8");
}
this.$criticalWarningReset = function() {
    var p = player.ship;
    p.removeEquipment("EQ_CRITICAL_WARNING");
    p.removeEquipment("EQ_CRITICAL_WARNING_NOISY_1");
    p.removeEquipment("EQ_CRITICAL_WARNING_NOISY_2");
}
this.$criticalWarning = function() {
    var p = player.ship;
    p.removeEquipment("EQ_CRITICAL_WARNING_NOISY_2");
    p.awardEquipment("EQ_CRITICAL_WARNING");
}
this.$criticalWarningNoisy1 = function() {
    var p = player.ship;
    p.removeEquipment("EQ_CRITICAL_WARNING");
    p.awardEquipment("EQ_CRITICAL_WARNING_NOISY_1");
}
this.$criticalWarningNoisy2 = function() {
    var p = player.ship;
    p.removeEquipment("EQ_CRITICAL_WARNING_NOISY_1");
    p.awardEquipment("EQ_CRITICAL_WARNING_NOISY_2");
}

//-------------------------------------------------------------------------------------------------------------
// stop all sounds

this.$stopAllSounds = function() {
    var ps = player.ship.script;
    if (ps._criticalEnergySound.isPlaying) ps._criticalEnergySound.stop();
    if (ps._ECMsound.isPlaying) ps._ECMsound.stop();
    if (ps._missileWarningSound.isPlaying) ps._missileWarningSound.stop();
    if (ps._jumpSound.isPlaying) ps._jumpSound.stop();
    if (ps._TorusSoundStart.isPlaying) ps._TorusSoundStart.stop();
    if (ps._TorusSound.isPlaying) ps._TorusSound.stop();
    if (ps._TorusSoundEnd.isPlaying) ps._TorusSoundEnd.stop();
}

//-------------------------------------------------------------------------------------------------------------
// mass lock indicator

this.$massLockChecker = function() {

    var p = player.ship;
    if (player.alertCondition > 1 || player.alertMassLocked === true) {
        // we're keeping track of the mass lock state via a flag, so we don't have to keep updating the HUD with the same value each second.
        if (p.script._massLockOn === false) {
            p.awardEquipment("EQ_MASS_LOCK");
            p.script._massLockOn = true;
        };
        if (p.viewDirection === "VIEW_FORWARD") {
            p.awardEquipment("EQ_MASS_LOCK_LAMP");
        } else {
            p.removeEquipment("EQ_MASS_LOCK_LAMP");
        };
    } else {
        if (p.script._massLockOn === true) {
            p.removeEquipment("EQ_MASS_LOCK");
            p.removeEquipment("EQ_MASS_LOCK_LAMP");
            p.script._massLockOn = false;
        };
    };
    
}

//-------------------------------------------------------------------------------------------------------------

// configuration settings for use in Lib_Config
this._DangerousHUDConfig = {Name:this.name, Alias: "DangerousHUD", Display:"Config", Alive:"_DangerousHUDConfig", 
    Bool:{
        B0:{Name:"_disableDockingHUD", Def:false, Desc:"Disable docking HUD"},
        B1:{Name:"_disableMissileWarning", Def:false, Desc:"Disable missile warning"},
        B2:{Name:"_removePrimableEquip", Def:false, Desc:"Removes primable equipment"},
        Info:"0 - Disables the docking HUD, so the main HUD stays active for docking.\n1 - Disables the missile warning element.\n2 - Removes HUD Mode selector primable equipment."},
    SInt:{
        S0:{Name:"_crosshairMode", Def:0, Min:0, Max:2, Desc:"HUD Crosshairs mode"},
        Info:"0 - Setting 0 = On in all conditions, 1 = On in Red condition only, 2 = On in Red/Yellow condtions"}
};

//-------------------------------------------------------------------------------------------------------------
// Allows OXP lasers to use a different crosshair png file
// usage: lcobject is an object containing two properties:
//        laser:         the name of the equipment key of the laser
//        filename:    the filename of the crosshairs file to use
this.$customCrosshairs = function(lcobject) {
    if (!lcobject.laser || lcobject.laser === "") {
        throw "Invalid laser equipment object specified. Make sure the passed object has a 'laser:\"EQ_WEAPON_MYLASER\"' specified.";
    }
    if (!lcobject.filename || lcobject.filename === "") {
        throw "Invalid crosshair filename specified. Make sure the passed object has a 'filename:\"specific_crosshairs.png\"' specified. See readme.txt file for possible filenames.";
    }
	var ps = player.ship.script;
	if (!ps._crosshairList) ps._crosshairList = [];
	var ch = ps._crosshairList;
	// look for an existing entry and update the filename if found
	for (var i = 0; i < ch.length; i++) {
		if (ch[i].laser === lcobject.laser) {
			ch[i].filename = lcobject.filename;
			return;
		}
	}
	// if not found, just add the object to the array
	ch.push(lcobject);
	// just in case the player ship script gets replaced...
	var m_ch = this._crosshairList;
	// look for an existing entry and update the filename if found
	for (var i = 0; i < m_ch.length; i++) {
		if (m_ch[i].laser === lcobject.laser) {
			m_ch[i].filename = lcobject.filename;
			return;
		}
	}
	// if not found, just add the object to the array
	m_ch.push(lcobject);
}

//=============================================================================================================
// adding compatibility to Breakable HUD/IFF Scanner OXP

this.equipmentDamaged = function(equipKey) {
	if (equipKey === "EQ_BREAKABLE_HUD_IFF_SCANNER") {
		this._damaged = true;
	}
}

this.equipmentRepaired = function(equipKey) {
	if (equipKey === "EQ_BREAKABLE_HUD_IFF_SCANNER") {
		this._damaged = false;
	}
}

//=============================================================================================================
// ship interfaces

//-------------------------------------------------------------------------------------------------------------
// for compatibility with HUD selector
this.startUp = function () {

    var p = player.ship;
    var ps = p.script;
    var w = worldScripts;
    var h = w.hudselector;
    
    p.hud =  this.name + this._mode + ".plist";

    if(h) h.$HUDSelectorAddHUD("DangerousHUD", this.name);

    ps._currentCrosshairs = "";
    ps._missiles = [];
    ps._lastCheck = true;
    ps._missileWarning = false;
    ps._missileWarningChanged = false;
    ps._fuelLeakWarning = false;
    ps._playerIsDocking = false;
    // ps._previousCrosshairs = null;
    ps._criticalWarningAnimationTimer = null; // these below are a bunch of timers used for the animations
    ps.$criticalWarningReset = this.$criticalWarningReset;
    ps.$criticalWarning = this.$criticalWarning;
    ps.$criticalWarningNoisy1 = this.$criticalWarningNoisy1;
    ps.$criticalWarningNoisy2 = this.$criticalWarningNoisy2;
    ps.$selectCrosshairs = this.$selectCrosshairs;
    ps.$timeTick = this.$timeTick;
    ps.$scannerAnimation = this.$scannerAnimation;
    ps.$checkForIncomingMissiles = this.$checkForIncomingMissiles;
    ps.$massLockChecker = this.$massLockChecker;
    
    ps._scannerAnimationTimerA = null;
    ps._scannerAnimationTimerB = null;
    ps._scannerAnimationTimerC = null;
    ps._scannerAnimationTimerD = null;
    ps._scannerAnimationTimerE = null;
    ps._scannerAnimationTimerF = null;
    ps._scannerAnimationTimerG = null;
    ps._scannerAnimationTimerH = null;
    ps.$scannerAnimationFrame1 = this.$scannerAnimationFrame1;
    ps.$scannerAnimationFrame2 = this.$scannerAnimationFrame2;
    ps.$scannerAnimationFrame3 = this.$scannerAnimationFrame3;
    ps.$scannerAnimationFrame4 = this.$scannerAnimationFrame4;
    ps.$scannerAnimationFrame5 = this.$scannerAnimationFrame5;
    ps.$scannerAnimationFrame6 = this.$scannerAnimationFrame6;
    ps.$scannerAnimationFrame7 = this.$scannerAnimationFrame7;
    ps.$scannerAnimationFrame8 = this.$scannerAnimationFrame8;
    ps.$scannerAnimationEnd = this.$scannerAnimationEnd;

    this.$customCrosshairs({laser:"EQ_WEAPON_NONE", filename:"DangerousHUD_crosshairs_none.png"});
    this.$customCrosshairs({laser:"EQ_WEAPON_PULSE_LASER", filename:"DangerousHUD_crosshairs_weapon.png"});
    this.$customCrosshairs({laser:"EQ_WEAPON_BEAM_LASER", filename:"DangerousHUD_crosshairs_weapon.png"});
    this.$customCrosshairs({laser:"EQ_WEAPON_MINING_LASER", filename:"DangerousHUD_crosshairs_weapon.png"});
    this.$customCrosshairs({laser:"EQ_WEAPON_MILITARY_LASER", filename:"DangerousHUD_crosshairs_weapon.png"});
    
    // New Sounds
    ps._criticalEnergySound = new SoundSource;
    ps._criticalEnergySound.loop = false;
    ps._criticalEnergySoundFiles = ["criticalEnergy1.ogg", "criticalEnergy2.ogg", "criticalEnergy3.ogg", "criticalEnergy4.ogg"]

    ps._jumpSound = new SoundSource;
    ps._jumpSound.loop = false;

    ps._missileWarningSound = new SoundSource;
    ps._missileWarningSound.loop = true;
    ps._missileWarningSound.sound = "missileWarning.ogg";

    ps._ECMsound = new SoundSource;
    ps._ECMsound.loop = false;
    ps._ECMsound.sound = "ECMnoise.ogg";
    
    ps._TorusSoundStart = new SoundSource;
    ps._TorusSoundStart.loop = false;
    ps._TorusSoundStart.sound = "torusStart.ogg";
    
    ps._TorusSound = new SoundSource;
    ps._TorusSound.loop = true;
    ps._TorusSound.sound = "torus.ogg";
    
    ps._TorusSoundEnd = new SoundSource;
    ps._TorusSoundEnd.loop = false;
    ps._TorusSoundEnd.sound = "torusEnd.ogg";
    
	// this caters for the case where HUD selector is not installed
	// the theory is that, without HUD selector, you can't have more than 1 HUD installed
	// so if we get to this point we can assume that DangerousHUD has the ball
	// and we can monkey patch breakable HUD without too many concerns
	if (w.Breakable_HUD_IFF_Scanner && !h) {
		var biff = w.Breakable_HUD_IFF_Scanner;
		biff._prev_bis_updatescanner = biff.bis_updatescanner;
		biff.bis_updatescanner = w.DangerousHUD.$new_bis_updatescanner;
	}
	if (p.equipmentStatus("EQ_BREAKABLE_HUD_IFF_SCANNER") === "EQUIPMENT_DAMAGED") this._damaged = true;
    
}

//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function() {
	var p = player.ship;
    if (this.playerBoughtNewShip) this.playerBoughtNewShip(p, 0);
    if (worldScripts.GlareClarifier) {
        this._glareClarifiedInstalled = true;
        this._glareFilterInstalled = false;
    }
    if (worldScripts["HUD Vanisher"]) this._hudVanisherInstalled = true;
    
    // restore HUD mode from mission variables
    if (missionVariables.DANGEROUSHUD_Mode) this._mode = missionVariables.DANGEROUSHUD_Mode;
    
    // restore the crosshair mode from mission variables
    if (missionVariables.DANGEROUSHUD_CrosshairMode) this._crosshairMode = parseInt(missionVariables.DANGEROUSHUD_CrosshairMode);
    this._lastSource = system.ID;
    this.$setCurrentSystem();
    this._minimal = false;

    // make sure hudselector has the correct scanner settings
    var h = worldScripts.hudselector;
    if (h && p.hud.indexOf(this.name) > 0) {
        var typ = 0;
		if (p.scannerNonLinear === true) typ += 1;
		if (p.scannerUltraZoom === true) typ += 2;
        if (h.$HUDSelectorScanner === null || h.$HUDSelectorScanner != typ) h.$HUDSelectorSetScanner(typ);
    }

    // read flags from saved game
    if (missionVariables.DANGEROUSHUD_DisableDockHUD) this._disableDockingHUD = (this._trueValues.indexOf(missionVariables.DANGEROUSHUD_DisableDockHUD) >= 0 ? true : false);
    if (missionVariables.DANGEROUSHUD_DisableMissWarn) this._disableMissileWarning = (this._trueValues.indexOf(missionVariables.DANGEROUSHUD_DisableMissWarn) >= 0 ? true : false);
    if (missionVariables.DANGEROUSHUD_RemoveEquip) this._removePrimableEquip = (this._trueValues.indexOf(missionVariables.DANGEROUSHUD_RemoveEquip) >= 0 ? true : false);
    // remove old flag, if it's still there
    if (missionVariables.DANGEROUSHUD_DisableMassLock) delete missionVariables.DANGEROUSHUD_DisableMassLock;
    
    // register our settings, if Lib_Config is present
    if (worldScripts.Lib_Config) worldScripts.Lib_Config._registerSet(this._DangerousHUDConfig);
}

//-------------------------------------------------------------------------------------------------------------
this.playerWillSaveGame = function() {
    missionVariables.DANGEROUSHUD_CrosshairMode = this._crosshairMode;
    missionVariables.DANGEROUSHUD_DisableDockHUD = this._disableDockingHUD;
    missionVariables.DANGEROUSHUD_DisableMissWarn = this._disableMissileWarning;
    missionVariables.DANGEROUSHUD_Mode = this._mode;
}

//-------------------------------------------------------------------------------------------------------------
this.guiScreenChanged = function(to, from) {

    var p = player.ship;
    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 (p.status === "STATUS_IN_FLIGHT") {
        // when in flight, switch to the alt hud if the player selects anything other that the main screen
        if (guiScreen === "GUI_SCREEN_MAIN") {
			if (this._damaged === false) {
				p.hud = this.name + this._mode + ".plist";
				if (p.script._playerIsDocking === true) p.crosshairs = "crosshairs_docking.plist";
			} else {
				p.hud = this.name + this._mode + "_damaged.plist";
			}
        } else {
            // the alt hud moves the speed, energy and shield bars to the bottom left, with all the other gauges
            // to keep them from getting in the way of the Dangerous HUD backgrounds
            p.hud = this.name + "_alt.plist";
        }
    }

}

//-------------------------------------------------------------------------------------------------------------
this.shipWillLaunchFromStation = function(station) {

    var p = player.ship;
    var ps = p.script;
    // reset the missile monitoring array
	if (!ps._missiles) ps._missiles = [];
	ps._massLockOn = false;
    ps._missileWarning = false;
    ps._missileWarningChanged = false;
    ps._fuelLeakWarning = false;

	if (!ps.$selectCrosshairs) ps.$selectCrosshairs = this.$selectCrosshairs;
	if (!ps.$timeTick) ps.$timeTick = this.$timeTick;
	if (!ps.$checkForIncomingMissiles) ps.$checkForIncomingMissiles = this.$checkForIncomingMissiles;

	// oolite 1.85 has a new event to handle the change in weapons online status, so this code only applies to earlier versions
	if (oolite.compareVersion("1.85") > 0) {
		ps._checkForWeaponsOnline = true;
	} else {
		ps._checkForWeaponsOnline = false;
	}
    ps._disableMissileWarning = this._disableMissileWarning;

    if (this._glareClarifiedInstalled === false && worldScripts["glare filter"] && p.equipmentStatus("EQ_GLARE_FILTER") === "EQUIPMENT_OK") {
        this._glareFilterInstalled = true;
        // force the default glare filter level to be the maximum
        worldScripts["glare filter"].filterPointer = 2;
    }
    
    // add the viewmode selector and centre equipment items regardless of whether this is the current HUD or not.
    // that way, if HUD selector changes to/from this HUD mid-flight, the right equipment is already installed and the HUD should work as normal
    if (this._removePrimableEquip === false) {
        p.awardEquipment("EQ_DANGEROUSHUD_VIEWMODE");
    } else {
        p.removeEquipment("EQ_DANGEROUSHUD_VIEWMODE");
    }
    this.$displayCrosshairs();
    
    // because there's no way of centring items, we'll move the centred position of the clock based on the width of the font
    var test = defaultFont.measureString("000");
    if (test >= 1.7) {
        p.awardEquipment("EQ_DANGEROUSHUD_CLOCK_1")
    } else if (test > 1.4 && test < 1.7) {
        p.awardEquipment("EQ_DANGEROUSHUD_CLOCK_2");
    } else {
        p.awardEquipment("EQ_DANGEROUSHUD_CLOCK_3");
    }
    
    // default view after launching == forward
    this._viewForward = true;
    
    // resetting scanner, shield warning and variables after every launch
    p.removeEquipment("EQ_SCANNER_FRAME_1");
    p.removeEquipment("EQ_SCANNER_FRAME_2");
    p.removeEquipment("EQ_SCANNER_FRAME_3");
    p.removeEquipment("EQ_SCANNER_FRAME_4");
    p.removeEquipment("EQ_SCANNER_FRAME_5");
    p.removeEquipment("EQ_SCANNER_FRAME_6");
    p.removeEquipment("EQ_SCANNER_FRAME_7");
    p.removeEquipment("EQ_SCANNER_FRAME_8");
    p.removeEquipment("EQ_SHIELDS_OFFLINE");
    ps._criticalWarningValue = 0;
    ps._shieldsWarningOn = false;
    ps._massLockOn = false;
    ps.$massLockChecker();
    
	if (this._damaged === false) {
		p.hud = this.name + this._mode + ".plist";
	} else {
		p.hud = this.name + this._mode + "_damaged.plist";
	}

    if (this._glareClarifiedInstalled === false) {
        // make a note of the player's ship filter value
        this._holdFilter = p.sunGlareFilter;
        // only set the filter if the ship's filter level is less than 50%.
        if (this._holdFilter < this._defaultGlareFilter) {
            p.sunGlareFilter = this._defaultGlareFilter;
        }
    };

    // preset the crosshairs
    ps._currentCrosshairs = this.$selectCrosshairs(p.viewDirection);
    this.$setCrosshairs();

    // set up the glare filter check timer
    if (this._glareFilterInstalled) {
        // if the glare filter is installed, start a timer to monitor when it's turned on
        this._glareTimer = new Timer(this, this.$checkGlareFilter, 5, 5);
    }

    this._lastSource = system.ID;
    ps._playerIsDocking = false;
    
    if (!ps._timeTickTimer || ps._timeTickTimer.isRunning === false) 
        ps._timeTickTimer = new Timer(p.script, ps.$timeTick, 0, 0.25);

    if (!ps._scannerAnimationTimer || ps._scannerAnimationTimer.isRunning === false) 
        ps._scannerAnimationTimer = new Timer(p.script, ps.$scannerAnimation, 0, 4.0);
    
    if (p.equipmentStatus("EQ_IRONHIDE") === "EQUIPMENT_OK") this._ironHideArmour = true;
	  var sc = worldScripts.ShipConfiguration_Core;
	  if (sc) {
		    var a = sc._armour;
		    if (a && a.length > 0) {
			      for (var i = 0; i <= a.length; i++) {
				       if (a[i] && p.equipmentStatus(a[i]) === "EQUIPMENT_OK") {this._shipConfigArmour = true; break;}
			      }
		    }
	  }
    // force an update to the HUD so initial armour value can be displayed
    this.shipTakingDamage(0, null, "");
    
	// tell manual witchspace alignment which color to use for the nav frame
	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 = 1; // 0 = blue, 1 = orange, 2 = green, 3 = pink
		}
	}

}

//-------------------------------------------------------------------------------------------------------------
this.shipDockedWithStation = function(station) {

    var p = player.ship;
    
    // if docked with a escape pod the HUD must be reset
    if (this._escapePodActivated === true) {
        p.hud = this.name + this._mode + ".plist";
        this._escapePodActivated = false;
    }

    // remove the Dangerous HUD equipment item, if found
  	var remove = ["EQ_DANGEROUSHUD_CLOCK_1",
  	              "EQ_DANGEROUSHUD_CLOCK_2",
  	              "EQ_DANGEROUSHUD_CLOCK_3",
  	              "EQ_DANGEROUSHUD_MISSILEWARNING",
  	              "EQ_DANGEROUSHUD_LEAKWARNING"];
  	for (var i = 0; i < remove.length; i++) p.removeEquipment(remove[i]);
    
    this.$setCurrentSystem();

	  if (this._glareClarifiedInstalled === false) {
		    if (this._holdFilter < this._defaultGlareFilter) {
		      	// restore the filter level to the stored value, just in case the player switches HUD while docked.
		      	p.sunGlareFilter = this._holdFilter;
		    }
    }

    this.$stopTimers();
    
    this.$stopAllSounds();
    
}

//-------------------------------------------------------------------------------------------------------------
this.shipWillDockWithStation = function(station) {

    var p = player.ship;
    
    p.removeEquipment("EQ_DANGEROUSHUD_CENTRE");
    p.removeEquipment("EQ_DANGEROUSHUD_CENTRE_MINIMAL");
    // reset the missile monitoring array
    p.script._missiles.length = 0;

    if (this._escapePodActivated === false) {
        p.hud = this.name + this._mode + ".plist";
    } else {
        p.hud = "DangerousHUD_escape_pod.plist";
    }

    this.$stopTimers();
    
    this.$stopAllSounds();
    
}

//-------------------------------------------------------------------------------------------------------------
this.playerStartedJumpCountdown = function(type, seconds) {

    var ps = player.ship.script;
    this._jumpCountdownStarted = true;
    if (type === "standard") {
        if (!ps._jumpSound.isPlaying) {
            ps._jumpSound.sound = "standardJump.ogg";
            ps._jumpSound.play();
        };
    } else {
        if (!ps._jumpSound.isPlaying) {
            ps._jumpSound.sound = "galacticJump.ogg";
            ps._jumpSound.play();
        };
    };
    
}

//-------------------------------------------------------------------------------------------------------------
this.playerCancelledJumpCountdown = function() {
    this._jumpCountdownStarted = false;
    var ps = player.ship.script;
    if (ps._jumpSound.isPlaying) ps._jumpSound.stop();
}

//-------------------------------------------------------------------------------------------------------------
this.playerJumpFailed = function(reason) {
    this._jumpCountdownStarted = false;
}

//-------------------------------------------------------------------------------------------------------------
this.shipDied = function(whom, why) {
    this.$stopTimers();
    this.$stopAllSounds();
}

//-------------------------------------------------------------------------------------------------------------
this.shipTakingDamage = function(amount, whom, type) {

    var p = player.ship;
	var ps = p.script;
	if (!p || !ps) return;

    // work out how much armour is left in front and aft positions
    var armourFront = 0;
    var armourAft = 0;

    // ironhide only keeps one value for armour, so we'll put that value into both positions
    if (this._ironHideArmour === true) {
        armourFront = missionVariables.ironHide_percentage;
        armourAft = armourFront;
    }
	// ship config has independant front and aft armour values, so we can use those directly
	if (this._shipConfigArmour === true) {
		var arm = worldScripts.ShipConfiguration_Armour;
		if (ps._armourFront) {
			armourFront = ps._armourFront;
			armourAft = ps._armourAft;
		} else {
			armourFront = arm._armourFront;
			armourAft = arm._armourAft;
		}
	}

    // set the custom dials to the values
    // if no armour is installed, these values will be zero, effectively turning off the hud elements
    p.setCustomHUDDial("armour_forward", armourFront / 100);
    p.setCustomHUDDial("armour_aft", armourAft / 100);
    
}

//-------------------------------------------------------------------------------------------------------------
this.shipAttackedWithMissile = function(missile, whom) {
    if (this._disableMissileWarning === true) return; // don't add missiles if the indicator is disabled
    // add the missile to our array for checking
	var ps = player.ship.script;
	if (ps) ps._missiles.push(missile);
}

//--------------------------------------------------------------------------------------------------------------
this.alertConditionChanged = function(newCondition, oldCondition) {
    // only update the crosshairs when the condition is something other than docked (0)
    if (newCondition > 0) this.$displayCrosshairs();
}

//--------------------------------------------------------------------------------------------------------------
this.viewDirectionChanged = function(viewString) {

    var p = player.ship;
    var ps = p.script;

    // no need to do this if the hud vanisher is installed
    if (this._hudVanisherInstalled === false) {
        if (viewString === "VIEW_CUSTOM") {
            p.hudHidden = true;
        } else {
            p.hudHidden = false;
        }
    }
    // if view not forward then no cockpit image
    if (viewString === "VIEW_FORWARD") {
        this._viewForward = true;
        this.$massLockChecker(); // checking if mass lock indicator should be turned on immediately (as otherwise it is checked only every 250ms)
        if (this._minimal === false) {
            p.awardEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD");
            p.removeEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD_MINIMAL");
        } else{
            p.removeEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD");
            p.awardEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD_MINIMAL");
        };
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_AFT");
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_PORT");
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_STARBOARD");
    } else if (viewString === "VIEW_AFT") {
        this._viewForward = false;
        this.$massLockChecker();
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD");
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD_MINIMAL");
        p.awardEquipment("EQ_DANGEROUSHUD_VIEW_AFT");
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_PORT");
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_STARBOARD");
    } else if (viewString === "VIEW_PORT") {
        this._viewForward = false;
        this.$massLockChecker();
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD");
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD_MINIMAL");
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_AFT");
        p.awardEquipment("EQ_DANGEROUSHUD_VIEW_PORT");
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_STARBOARD");
    } else if (viewString === "VIEW_STARBOARD") {
        this._viewForward = false;
        this.$massLockChecker();
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD");
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD_MINIMAL");
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_AFT");
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_PORT");
        p.awardEquipment("EQ_DANGEROUSHUD_VIEW_STARBOARD");
    } else {
        this._viewForward = false;
        p.removeEquipment("EQ_MASS_LOCK");
        p.removeEquipment("EQ_MASS_LOCK_LAMP");
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD");
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD_MINIMAL");
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_AFT");
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_PORT");
        p.removeEquipment("EQ_DANGEROUSHUD_VIEW_STARBOARD");
    };
    
    ps._currentCrosshairs = this.$selectCrosshairs(viewString);
    p.setCustomHUDDial("crosshairs", ps._currentCrosshairs);
    
}

//-------------------------------------------------------------------------------------------------------------
this.shipExitedWitchspace = function() {
    if (player.ship.script._missiles) {
		player.ship.script._missiles.length = 0;
	} else {
		player.ship.script._missiles = [];
	}
    if (system.ID != -1) this._lastSource = system.ID;

    this._jumpCountdownStarted = false;
    this.guiScreenChanged("", "");
    
    this._destination = this.$playerTargetSystem();
    this.$setDestination();
    this.$setCurrentSystem();

    if (this._dockTimer && this._dockTimer.isRunning) this._dockTimer.stop();
}

//-------------------------------------------------------------------------------------------------------------
this.playerBoughtNewShip = function(ship, price) {
    if (!this.$hudSelector && player.ship.hud === "hud.plist") {
        player.ship.hud = this.name + this._mode + ".plist";
    }
}

//-------------------------------------------------------------------------------------------------------------
this.playerRequestedDockingClearance = function(message) {

    if (this._disableDockingHUD === false) {
        var p = player.ship;
        var ps = p.script;
        if (message === "DOCKING_CLEARANCE_GRANTED" || message === "DOCKING_CLEARANCE_EXTENDED" || message === "DOCKING_CLEARANCE_DENIED_TRAFFIC_INBOUND" || message === "DOCKING_CLEARANCE_DENIED_TRAFFIC_OUTBOUND") {
            ps._playerIsDocking = true;
            // ps._previousCrosshairs = p.crosshairs;
            p.removeEquipment("EQ_DANGEROUSHUD_CENTRE");
            p.removeEquipment("EQ_DANGEROUSHUD_CENTRE_MINIMAL");
            p.awardEquipment("EQ_DANGEROUSHUD_DOCKING");
            p.crosshairs = "crosshairs_docking.plist";
            if (message === "DOCKING_CLEARANCE_GRANTED" || message === "DOCKING_CLEARANCE_EXTENDED") {
                // start a timer so we can track when the clearance expires
                if (this._dockTimer && this._dockTimer.isRunning) this._dockTimer.stop();
                this._dockTimer = new Timer(this, this.$dockingExpired, 121, 0);
            }
        } else {
            ps._playerIsDocking = false;
            p.removeEquipment("EQ_DANGEROUSHUD_DOCKING");
            this.$displayCrosshairs();
            // p.crosshairs = ps._previousCrosshairs;
            if (this._dockTimer && this._dockTimer.isRunning) this._dockTimer.stop();
        }
    }
}

//-------------------------------------------------------------------------------------------------------------
this.playerDockingClearanceCancelled = function() {

    var p = player.ship;
    var ps = p.script;
    ps._playerIsDocking = false;
    p.removeEquipment("EQ_DANGEROUSHUD_DOCKING");
    this.$displayCrosshairs();
    // p.crosshairs = ps._previousCrosshairs;
    if (this._dockTimer && this._dockTimer.isRunning) this._dockTimer.stop();
    
}

//-------------------------------------------------------------------------------------------------------------
this.playerDockingClearanceExpired = function() {
	this.playerDockingClearanceCancelled();
}

//-------------------------------------------------------------------------------------------------------------
this.weaponsSystemsToggled = function(state) {
	var p = player.ship;
	var ps = p.script;
	if (ps) {
	    this.$displayCrosshairs();
		ps._currentCrosshairs = this.$selectCrosshairs(p.viewDirection);
		p.setCustomHUDDial("crosshairs", ps._currentCrosshairs);
	}
}

//=============================================================================================================
// helper functions

//-------------------------------------------------------------------------------------------------------------
// HUD selector callback to turn things on/off with the currently selected HUD
this.$HUDSelectorCallBack = function(off) {
    var w = worldScripts.DangerousHUD;
    if (off) { 
        w.$stopTimers();
        // do things to disable HUD like rename functions
        if (w.guiScreenChanged) {
            w.$save_guiScreenChanged = w.guiScreenChanged;
            delete w.guiScreenChanged;
        }
        if (w.shipWillLaunchFromStation) {
            w.$save_shipWillLaunchFromStation = w.shipWillLaunchFromStation;
            delete w.shipWillLaunchFromStation;
        }
        if (w.shipDockedWithStation) {
            w.$save_shipDockedWithStation = w.shipDockedWithStation;
            delete w.shipDockedWithStation;
        }
        if (w.shipWillDockWithStation) {
            w.$save_shipWillDockWithStation = w.shipWillDockWithStation;
            delete w.shipWillDockWithStation;
        }
        if (w.shipDied) {
            w.$save_shipDied = w.shipDied;
            delete w.shipDied;
        }
        if (w.shipTakingDamage) {
            w.$save_shipTakingDamage = w.shipTakingDamage;
            delete w.shipTakingDamage;
        }
        if (w.shipAttackedWithMissile) {
            w.$save_shipAttackedWithMissile = w.shipAttackedWithMissile;
            delete w.shipAttackedWithMissile;
        }
        if (w.alertConditionChanged) {
            w.$save_alertConditionChanged = w.alertConditionChanged;
            delete w.alertConditionChanged;
        }
        if (w.viewDirectionChanged) {
            w.$save_viewDirectionChanged = w.viewDirectionChanged;
            delete w.viewDirectionChanged;
        }
        if (w.shipExitedWitchspace) {
            w.$save_shipExitedWitchspace = w.shipExitedWitchspace;
            delete w.shipExitedWitchspace;
        }
        if (w.playerJumpFailed) {
            w.$save_playerJumpFailed = w.playerJumpFailed;
            delete w.playerJumpFailed;
        }
        if (w.playerStartedJumpCountdown) {
            w.$save_playerStartedJumpCountdown = w.playerStartedJumpCountdown;
            delete w.playerStartedJumpCountdown;
        }
        if (w.playerCancelledJumpCountdown) {
            w.$save_playerCancelledJumpCountdown = w.playerCancelledJumpCountdown;
            delete w.playerCancelledJumpCountdown;
        }
        if (w.playerBoughtNewShip) {
            w.$save_playerBoughtNewShip = w.playerBoughtNewShip;
            delete w.playerBoughtNewShip;
        }
        if (w.playerRequestedDockingClearance) {
            w.$save_playerRequestedDockingClearance = w.playerRequestedDockingClearance;
            delete w.playerRequestedDockingClearance;
        }
        if (w.playerDockingClearanceCancelled) {
            w.$save_playerDockingClearanceCancelled = w.playerDockingClearanceCancelled;
            delete w.playerDockingClearanceCancelled;
        }
		if (w.playerDockingClearanceExpired) {
			w.$save_playerDockingClearanceExpired = w.playerDockingClearanceExpired;
			delete w.playerDockingClearanceExpired;
		}
		if (w.weaponsSystemsToggled) {
			w.$save_weaponsSystemsToggled = w.weaponsSystemsToggled;
			delete w.weaponsSystemsToggled;
		}
		player.ship.removeEquipment("EQ_DANGEROUSHUD_VIEWMODE");
    } else { 
        // do things to activate HUD like restore disabled functions
        if (!w.guiScreenChanged) eval("w.guiScreenChanged = " + w.$save_guiScreenChanged);
        if (!w.shipWillLaunchFromStation) eval("w.shipWillLaunchFromStation = " + w.$save_shipWillLaunchFromStation);
        if (!w.shipDockedWithStation) eval("w.shipDockedWithStation = " + w.$save_shipDockedWithStation);
        if (!w.shipWillDockWithStation) eval("w.shipWillDockWithStation = " + w.$save_shipWillDockWithStation);
        if (!w.shipDied) eval("w.shipDied = " + w.$save_shipDied);
        if (!w.shipTakingDamage) eval("w.shipTakingDamage = " + w.$save_shipTakingDamage);
        if (!w.shipAttackedWithMissile) eval("w.shipAttackedWithMissile = " + w.$save_shipAttackedWithMissile);
        if (!w.alertConditionChanged) eval("w.alertConditionChanged = " + w.$save_alertConditionChanged);
        if (!w.viewDirectionChanged) eval("w.viewDirectionChanged = " + w.$save_viewDirectionChanged);
        if (!w.shipExitedWitchspace) eval("w.shipExitedWitchspace = " + w.$save_shipExitedWitchspace);
        if (!w.playerJumpFailed) eval("w.playerJumpFailed = " + w.$save_playerJumpFailed);
        if (!w.playerStartedJumpCountdown) eval("w.playerStartedJumpCountdown = " + w.$save_playerStartedJumpCountdown);
        if (!w.playerCancelledJumpCountdown) eval("w.playerCancelledJumpCountdown = " + w.$save_playerCancelledJumpCountdown);
        if (!w.playerBoughtNewShip) eval("w.playerBoughtNewShip = " + w.$save_playerBoughtNewShip);
        if (!w.playerRequestedDockingClearance) eval("w.playerRequestedDockingClearance = " + w.$save_playerRequestedDockingClearance);
        if (!w.playerDockingClearanceCancelled) eval("w.playerDockingClearanceCancelled = " + w.$save_playerDockingClearanceCancelled);
		if (!w.playerDockingClearanceExpired) eval("w.playerDockingClearanceExpired = " + w.$save_playerDockingClearanceExpired);
		if (!w.weaponsSystemsToggled) eval("w.weaponsSystemsToggled = " + w.$save_weaponsSystemsToggled);
        // force an update
        w.shipExitedWitchspace();
        w.shipWillLaunchFromStation();
		w.viewDirectionChanged(player.ship.viewDirection);
    }
}

//-------------------------------------------------------------------------------------------------------------
this.$checkForNewDestination = function $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();
    }
}

//-------------------------------------------------------------------------------------------------------------
// work out whether to show crosshair controls
this.$displayCrosshairs = function() {

    var p = player.ship;
    p.removeEquipment("EQ_DANGEROUSHUD_DOCKING");
	if (p.script) p.crosshairs = p.script._previousCrosshairs;
	p.crosshairs = null; // if (p.script) p.crosshairs = p.script._previousCrosshairs;

    switch (this._crosshairMode) {
        case 0: // on in all conditions
            p.awardEquipment("EQ_DANGEROUSHUD_CENTRE");
            p.removeEquipment("EQ_DANGEROUSHUD_CENTRE_MINIMAL");
            this._minimal = false;
            if (this._viewForward === true) {
                p.awardEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD");
                p.removeEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD_MINIMAL");
            }
            break;
        case 1: // on in combat red alert only (or when weapons are online)
            if ((p.alertCondition === 3 && player.alertHostiles) || (p.weaponsOnline === true)) {
                p.awardEquipment("EQ_DANGEROUSHUD_CENTRE");
                p.removeEquipment("EQ_DANGEROUSHUD_CENTRE_MINIMAL");
                this._minimal = false;
                if (this._viewForward === true) {
                    p.awardEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD");
                    p.removeEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD_MINIMAL");
                }
            } else {
                p.removeEquipment("EQ_DANGEROUSHUD_CENTRE");
                p.awardEquipment("EQ_DANGEROUSHUD_CENTRE_MINIMAL");
                this._minimal = true;
                if (this._viewForward === true) {
                    p.removeEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD");
                    p.awardEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD_MINIMAL");
                }
                p.crosshairs = "crosshairs_mini.plist";
            }
            break;
        case 2: // on in yellow and red only (or when weapons are online)
            if ((p.alertCondition >= 2) || (p.weaponsOnline === true)) {
                p.awardEquipment("EQ_DANGEROUSHUD_CENTRE");
                p.removeEquipment("EQ_DANGEROUSHUD_CENTRE_MINIMAL");
                this._minimal = false;
                if (this._viewForward === true) {
                    p.awardEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD");
                    p.removeEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD_MINIMAL");
                }
            } else {
                p.removeEquipment("EQ_DANGEROUSHUD_CENTRE");
                p.awardEquipment("EQ_DANGEROUSHUD_CENTRE_MINIMAL");
                this._minimal = true;
                if (this._viewForward === true) {
                    p.removeEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD");
                    p.awardEquipment("EQ_DANGEROUSHUD_VIEW_FORWARD_MINIMAL");
                }
                p.crosshairs = "crosshairs_mini.plist";
            }
            break;
    }
     
}

//-------------------------------------------------------------------------------------------------------------
// checks to see if the glare filter is ever turned on, and if so, monitors the glare filter level so it stays at the default level
this.$checkGlareFilter = function $checkForGlareFilter() {

    var w = worldScripts["glare filter"];
    var p = player.ship;
    
    // check to see if the filter ever gets turned on
    if (w.$filterOn) this._doChecks = true;
    // once it's been turned on, monitor the glare filter and reset it to the default
    if (this._doChecks) {
        // if the filter is on, but it's set to a low level, force it to the max level
        if (w.$filterPointer < 2) {
            w.$filterPointer = 2;
            w.$adjustFilter();
        }
        if (p.sunGlareFilter < this._defaultGlareFilter) p.sunGlareFilter = this._defaultGlareFilter;
    }
    // if the filter has been turned of, we can stop doing the checks
    if (!w.$fiterOn) this._doChecks = false;
    
}

//-------------------------------------------------------------------------------------------------------------
// sets the HUD dials to the current crosshair images
this.$setCrosshairs = function() {

    var p = player.ship;
    if (p.hud != this.name + "_alt.plist") {
        p.setCustomHUDDial("crosshairs", p.script._currentCrosshairs);
        p.setCustomHUDDial("crosshairsDocking", this._dockingCrosshairs);
    }
    
}

//-------------------------------------------------------------------------------------------------------------
// 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() {

    var p = player.ship;
    var planet = "";
    if (this._destination >= 0 && this._destination != system.ID) planet = System.systemNameForID(this._destination);
    p.setCustomHUDDial("witchspace_destination", planet);
    this._holdTarget = p.targetSystem;

}

//-------------------------------------------------------------------------------------------------------------
// sets the current location label
this.$setCurrentSystem = function() {

    var p = player.ship;
    var sys = "";
    if (system.ID === -1) {
        sys = "Interstellar space";
    } else {
        sys = system.name;
    }
    var stn = "";
    if (p.dockedStation) {
        stn = p.dockedStation.displayName;
        if (stn === "") stn = p.dockedStation.name;
    }
    p.setCustomHUDDial("current_system", sys);
    p.setCustomHUDDial("current_station", stn);

}

//-------------------------------------------------------------------------------------------------------------
// select the appropriate crosshairs based on the weapon in the selected view
this.$selectCrosshairs = function(view) {

    var w = worldScripts.DangerousHUD;
    var p = player.ship;
    if (p.weaponsOnline === false) return w.$weaponCrosshairs("EQ_WEAPON_NONE");

    var imageFile = "";
    switch (view) {
        case "VIEW_FORWARD":
            imageFile = w.$weaponCrosshairs(p.forwardWeapon.equipmentKey);
            break;
        case "VIEW_AFT":
            imageFile = w.$weaponCrosshairs(p.aftWeapon.equipmentKey);
            break;
        case "VIEW_PORT":
            imageFile = w.$weaponCrosshairs(p.portWeapon.equipmentKey);
            break;
        case "VIEW_STARBOARD":
            imageFile = w.$weaponCrosshairs(p.starboardWeapon.equipmentKey);
            break;
    }
    return imageFile;
}

//-------------------------------------------------------------------------------------------------------------
// select the correct crosshairs image based on the weapon
this.$weaponCrosshairs = function(weapon) {
	var ps = player.ship.script;
	var ch = ps._crosshairList;
	if (!ch) {
		// get a copy of the main list if the player ship script doesn't have it anymore
		ps._crosshairList = this._crosshairList.slice();
		ch = ps._crosshairList;
	}
	if (ch.length > 0) {
		for (var i = 0; i < ch.length; i++) {
			if (ch[i].laser === weapon) {
				return ch[i].filename;
			}
		}
	}
    return "DangerousHUD_crosshairs_weapon.png";
}

//-------------------------------------------------------------------------------------------------------------
// time tick (0.25s) used for animations
this.$timeTick = function $timeTick() {

    var p = this.ship;
    var ps = p.script;

	if (ps) {
	    // checking weapons online
        if (ps._checkForWeaponsOnline === true) {
			if (p.weaponsOnline != ps._lastCheck) {
				ps._lastCheck = p.weaponsOnline;
				ps._currentCrosshairs = this.$selectCrosshairs(p.viewDirection);
				p.setCustomHUDDial("crosshairs", ps._currentCrosshairs);
			}
		}
        // critical energy warning
        if (p.energy <= p.maxEnergy/4.0) {
            if (!ps._criticalEnergySound.isPlaying) {
                ps._criticalEnergySound.sound = ps._criticalEnergySoundFiles[Math.floor(Math.random() * ps._criticalEnergySoundFiles.length)];
                ps._criticalEnergySound.play();
            };
            var randomNumber = Math.random();
             if (randomNumber < 0.85 && (ps._criticalWarningValue === 0 || ps._criticalWarningValue === 2)) {
                ps._criticalWarningValue = 1;
                 ps.$criticalWarning();
            } else if (randomNumber >= 0.85 && (ps._criticalWarningValue === 0 || ps._criticalWarningValue === 1)) {
                ps._criticalWarningValue = 2;
                ps.$criticalWarningNoisy1();
                ps._criticalWarningAnimationTimer = new Timer(p.script, ps.$criticalWarningNoisy2, 0.12);
            };
        } else {
            if (ps._criticalWarningValue === 1 || ps._criticalWarningValue === 2) {
                ps._criticalWarningValue = 0;
                ps.$criticalWarningReset();
            };
        };

        // shield offline warning
        if (p.forwardShield < p.maxForwardShield/10.0 || p.aftShield < p.maxAftShield/10.0) {
            if (ps._shieldsWarningOn === false) {
                ps._shieldsWarningOn = true;
                p.awardEquipment("EQ_SHIELDS_OFFLINE");
            };
        } else {
            if (ps._shieldsWarningOn === true) {
                ps._shieldsWarningOn = false;
                p.removeEquipment("EQ_SHIELDS_OFFLINE");
            };
        };
        
        if (ps._disableMissileWarning === false) {
            this.$checkForIncomingMissiles();
            if (ps._missileWarning === true && ps._missileWarningChanged === true) {
                p.awardEquipment("EQ_DANGEROUSHUD_MISSILEWARNING");
                if (!ps._missileWarningSound.isPlaying) ps._missileWarningSound.play();
                ps._missileWarningChanged = false;
            };
            if (ps._missileWarning === false && ps._missileWarningChanged === true) {
                p.removeEquipment("EQ_DANGEROUSHUD_MISSILEWARNING");
                if (ps._missileWarningSound.isPlaying) ps._missileWarningSound.stop();
                ps._missileWarningChanged = false;
            };
        };
        
        if (p.torusEngaged === true) {
            if (!ps._TorusSound.isPlaying) {
                ps._TorusSoundStart.play();
                ps._TorusSound.play();
            };
        } else {
            if (ps._TorusSound.isPlaying) {
                ps._TorusSound.stop();
                ps._TorusSoundEnd.play();
            }
        };
        
	    if (p.fuelLeakRate > 0 && p.fuel > 0) {
            if (ps._fuelLeakWarning === false) {
                ps._fuelLeakWarning = true;
                p.awardEquipment("EQ_DANGEROUSHUD_LEAKWARNING");
            }
	    } else {
            if (ps._fuelLeakWarning === true) {
                ps._fuelLeakWarning = false;
                p.removeEquipment("EQ_DANGEROUSHUD_LEAKWARNING");
            }
	    }
        
        // mass lock indicator
        this.$massLockChecker();
    };
    
}

//-------------------------------------------------------------------------------------------------------------
// scanner animation
this.$scannerAnimation = function $scannerAnimation() {
    
    var ps = player.ship.script;
    
	if (ps) {
        ps.$scannerAnimationFrame1();
        ps._scannerAnimationTimerA = new Timer(ps, ps.$scannerAnimationFrame2, 0.1);
        ps._scannerAnimationTimerB = new Timer(ps, ps.$scannerAnimationFrame3, 0.2);
        ps._scannerAnimationTimerC = new Timer(ps, ps.$scannerAnimationFrame4, 0.3);
        ps._scannerAnimationTimerD = new Timer(ps, ps.$scannerAnimationFrame5, 0.4);
        ps._scannerAnimationTimerE = new Timer(ps, ps.$scannerAnimationFrame6, 0.5);
        ps._scannerAnimationTimerF = new Timer(ps, ps.$scannerAnimationFrame7, 0.6);
        ps._scannerAnimationTimerG = new Timer(ps, ps.$scannerAnimationFrame8, 0.7);
        ps._scannerAnimationTimerH = new Timer(ps, ps.$scannerAnimationEnd, 0.8);
    };

}

//-------------------------------------------------------------------------------------------------------------
// returns the player's target system (1.80) or the next jump to their target system (1.82)
this.$playerTargetSystem = function() {

    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), player.ship.routeMode);
            if (myRoute && myRoute.route.length > 1) {
                target = myRoute.route[1];
            }
        }
    }
    return target;
}

//-------------------------------------------------------------------------------------------------------------
// stops the dock timer
this.$stopTimers = function() {
	var p = player.ship;
	var ps = p.script;
    // stop the glare filter check timer if it's running
    if (this._glareTimer && this._glareTimer.isRunning) this._glareTimer.stop();
    // stop the dock timer check timer if it's running
    if (this._dockTimer && this._dockTimer.isRunning) this._dockTimer.stop();
    // stop the timer for the critical energy warning and sounds, as well as shield offline warning, if it's running
    if (ps && ps._timeTickTimer && ps._timeTickTimer.isRunning) ps._timeTickTimer.stop();    
    // stop the timer for the scanner animation if it's running
    if (ps && ps._scannerAnimationTimer && ps._scannerAnimationTimer.isRunning) ps._scannerAnimationTimer.stop();    
    
}

//-------------------------------------------------------------------------------------------------------------
// checks for an expired docking request
this.$dockingExpired = function $dockingExpired() {

    var p = player.ship;
    var ps = p.script;
    if (ps._playerIsDocking === true) {
        p.removeEquipment("EQ_DANGEROUSHUD_DOCKING");
        this.$displayCrosshairs();
        p.crosshairs = null; // p.crosshairs = ps._previousCrosshairs;
        ps._playerIsDocking = false;
    }

}

//-------------------------------------------------------------------------------------------------------------
// performs a scan of the missile array to see if any are still tracking the player
this.$checkForIncomingMissiles = function() {
    if (!this.ship || !this.ship.position) return;

    var found = false;
    var p = this.ship;
    var ps = p.script;
    if (ps._missiles.length === 0) {
        if (ps._missileWarning === true) ps._missileWarningChanged = true;
        ps._missileWarning = false;
        return;
    }
    
	// are they in range and valid?
	var ml = ps._missiles.length;
	for (var i = 0; i < ml; i++) {
		var m = ps._missiles[i];
		if (m.isValid && m.isInSpace && m.position.distanceTo(p) < p.scannerRange) {
			if (ps._missileWarning === false) ps._missileWarningChanged = true;
			ps._missileWarning = true;
			found = true;
			break;
		}
	}
	// has the flag state changed
	if (found === false && ps._missileWarning === true) {
		if (ps._missileWarning === true) ps._missileWarningChanged = true;
		ps._missileWarning = false;
		ps._missileWarningChanged = true;
	}
}

//-------------------------------------------------------------------------------------------------------------
// ship hit by ECM
this.shipHitByECM = function(pulsesRemaining)
{
    var p = player.ship;
    if (!p.script._ECMsound.isPlaying && !p.docked) p.script._ECMsound.play();
}

//-------------------------------------------------------------------------------------------------------------
// ship launched escape pod
this.shipLaunchedEscapePod = function(escapepod)
{
    this._escapePodActivated = true;
}

//-------------------------------------------------------------------------------------------------------------
// Adding compatibility to Breakable HUD/IFF Scanner
this.$new_bis_updatescanner = function() {	

    var p = player.ship;
	if (p.equipmentStatus("EQ_BREAKABLE_HUD_IFF_SCANNER") == "EQUIPMENT_OK") { // check to see if something has repaired the scanner on the fly e.g. Thargoid's Repair Bots OXP.
		this.bis_resetscanner();
		return;
	}
	if (Math.random() < 0.66) {
	   //player.ship.hudHidden = "True";
	   p.hud = "DangerousHUD" + worldScripts.DangerousHUD._mode + "_damaged.plist";
	} else {
		p.hud = "DangerousHUD" + worldScripts.DangerousHUD._mode + ".plist";
	}
    
}
Scripts/DangerousHUD_conditions.js
"use strict";
this.name        = "DangerousHUD_Equipment";
this.author      = "gsagostinho, based on work by phkb";
this.copyright   = "2015 phkb, 2017 gsagostinho";
this.description = "Condition script for Dangerous HUD equipment";
this.licence     = "CC BY-NC-SA 4.0";

this.allowAwardEquipment = function(equipment, ship, context) {
	if (context != "scripted") return false;
	return true;
}
Scripts/DangerousHUD_equip.js
"use strict";
this.name        = "DangerousHUD_Equipment";
this.author      = "gsagostinho, based on work by phkb";
this.copyright   = "2015 phkb, 2017 gsagostinho";
this.description = "Controls switching of Dangerous HUD to hi-contrast mode";
this.licence     = "CC BY-NC-SA 4.0";

//======================================================================================================================
// N key - used to turn cockpit mode on/off
this.activated = function() {

	var w = worldScripts.DangerousHUD;
	if (w._mode == "") {
		player.consoleMessage("Hauler cockpit mode activated");
		w._mode = "_hauler";
	} else if (w._mode == "_hauler") {
		player.consoleMessage("Glass only mode activated");
		w._mode = "_glass";
	} else {
		player.consoleMessage("Default cockpit mode activated");
		w._mode = "";
	}
	w.guiScreenChanged("", "");
	w = null;
	this.$playSound("mode"); // we'll use the same sound for mode and activate
	
}

//======================================================================================================================
// B key - used to cycle through the different crosshair modes
this.mode = function() {

	var w = worldScripts.DangerousHUD;
	w._crosshairMode += 1;
	if (w._crosshairMode == 3) w._crosshairMode = 0;
	switch (w._crosshairMode) {
		case 0:
			player.consoleMessage("Crosshairs on in all conditions");
			break;
		case 1:
			player.consoleMessage("Crosshairs on in condition red only");
			break;
		case 2:
			player.consoleMessage("Crosshairs on in condition yellow and red only");
			break;
	}
	w.$displayCrosshairs();
	w = null;
	this.$playSound("mode");
}

//-------------------------------------------------------------------------------------------------------------
// play sound effects
this.$playSound = function(soundtype) {
	var mySound = new SoundSource;

	switch (soundtype) {
		case "mode":
			mySound.sound = "[@click]";
			break;
		case "activate":
			mySound.sound = "[@beep]";
			break;
		case "stop":
			mySound.sound = "[@boop]";
			break;
	}
	mySound.loop = false;
	mySound.play();
}