Back to Index Page generated: Dec 20, 2024, 7:22:10 AM

Expansion Ship Configuration

Content

Warnings

  1. Required Expansions mismatch between OXP Manifest and Expansion Manager at character position 0066 (DIGIT ZERO vs LATIN SMALL LETTER N)
  2. No version in dependency reference to oolite.oxp.phkb.EquipmentStorage:null
  3. No version in dependency reference to oolite.oxp.CaptMurphy.BreakableTorusDrive:null
  4. No version in dependency reference to oolite.oxp.CaptMurphy.BreakableEnergyUnit:null
  5. No version in dependency reference to oolite.oxp.CaptMurphy.BreakableWitchDrive:null
  6. No version in dependency reference to oolite.oxp.CaptMurphy.BreakableShieldGenerators:null
  7. No version in dependency reference to oolite.oxp.CaptMurphy.BreakableEngines:null
  8. No version in dependency reference to oolite.oxp.redspear.equipment_by_ship_class:null
  9. No version in dependency reference to oolite.oxp.redspear.masslock_compensator:null
  10. No version in dependency reference to oolite.oxp.redspear.power_to_engines:null
  11. No version in dependency reference to oolite.oxp.stranger.HardWay:null
  12. Optional Expansions mismatch between OXP Manifest and Expansion Manager at character position 0075 (DIGIT ZERO vs LATIN SMALL LETTER N)
  13. 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 Gives all equipment space and weight, and allows ships to be configuration into different roles. Gives all equipment space and weight, and allows ships to be configuration into different roles.
Identifier oolite.oxp.phkb.ShipConfiguration oolite.oxp.phkb.ShipConfiguration
Title Ship Configuration Ship Configuration
Category Mechanics Mechanics
Author phkb phkb
Version 1.4.4 1.4.4
Tags
Required Oolite Version
Maximum Oolite Version
Required Expansions
  • oolite.oxp.phkb.EquipmentStorage:0
  • oolite.oxp.phkb.EquipmentStorage:
  • Optional Expansions
  • oolite.oxp.CaptMurphy.BreakableTorusDrive:0
  • oolite.oxp.CaptMurphy.BreakableTorusDrive:
  • Conflict Expansions
  • oolite.oxp.CaptMurphy.BreakableEnergyUnit:0
  • oolite.oxp.CaptMurphy.BreakableWitchDrive:0
  • oolite.oxp.CaptMurphy.BreakableShieldGenerators:0
  • oolite.oxp.CaptMurphy.BreakableEngines:0
  • oolite.oxp.redspear.equipment_by_ship_class:0
  • oolite.oxp.redspear.masslock_compensator:0
  • oolite.oxp.redspear.power_to_engines:0
  • oolite.oxp.stranger.HardWay:0
  • oolite.oxp.CaptMurphy.BreakableEnergyUnit:
  • oolite.oxp.CaptMurphy.BreakableWitchDrive:
  • oolite.oxp.CaptMurphy.BreakableShieldGenerators:
  • oolite.oxp.CaptMurphy.BreakableEngines:
  • oolite.oxp.redspear.equipment_by_ship_class:
  • oolite.oxp.redspear.masslock_compensator:
  • oolite.oxp.redspear.power_to_engines:
  • oolite.oxp.stranger.HardWay:
  • Information URL https://wiki.alioth.net/index.php/Ship_Configuration_OXP n/a
    Download URL https://wiki.alioth.net/img_auth.php/8/81/ShipConfiguration.oxz n/a
    License CC-BY-NC-SA 3.0 CC-BY-NC-SA 3.0
    File Size n/a
    Upload date 1708758408

    Documentation

    Also read http://wiki.alioth.net/index.php/Ship%20Configuration

    readme.txt

    Ship Configuration
    By Nick Rogers
    
    Thanks to Redspear, Norby, Devium, Venator Dha, Day, Ngalo, Astrobe, tsoj, DataPacRat and yangoip for their excellent suggestions and testing reports.
    Special thanks to Capt Murphy for his excellent set of Breakable equipment OXP's, the logic for some of which I have incorporated in this OXP.
    Also thanks go to Thargoid for his IronHide armour code, which I've borrowed code from, as well as CommonSenseOTB's Custom Shields.
    
    Overview
    ========
    This OXP aims to make the process of configuring your ship more deliberate. Instead of just adding more and more equipment without any implications, equipment will now use space, and the total weight of all equipment and cargo will have a bearing on performance. Decisions can now be made about how to best configure your ship for the role you want to play. If you want to configure your ship for trading, do you sacrifice engine performance or energy for cargo space? If you want to be a bounty hunter, what equipment do you swap out to make room for better shields, or do you change down to a beam laser to lighten the ship? Almost all equipment (including OXP equipment items) have space and weight considerations, and it is up to you to work out the best balance for the role you want to take.
    
    Heat also plays a more important role in gameplay. Firing your lasers continually will slowly heat up your ship, as will using your injectors, using the cloaking device, and being hit with a laser blast when your shields are down. Care needs to be taken so that your ship doesn't overheat. For instance, attempting to run away from an enemy ship on full injectors will heat up your ship to the point where you will begin to take damage.
    
    Important Note for New Players
    ==============================
    When you first load a saved game with this OXP installed, the calculated space for your installed equipment may require cargo space allocation. In this situation, any cargo in your hold may be removed. If the cargo needs to be removed to make way for equipment, it will be sold and the credits refunded to you.
    
    Equipment Space and Cargo Space
    ===============================
    Each ship has a standard amount of equipment space available to it, with a maximum of 40t in the largest ships. Once that space is filled, some cargo space can be re-allocated as equipment space. In ships with small cargo holds (less than 10t) all the cargo space can be reallocated as equipment space. For larger vessels, up to 75% of their cargo hold can be allocated, to a maximum of 40t. The process of allocating cargo space to equipment space is automatic - when you install a piece of equipment that exceeds the standard equipment space, cargo space will automatically be allocated. The following table provides details on how much equipment space is available:
    
                        Standard    Reallocated
                        Equipment   Cargo
    Ship type           Space       Space       Total
    -------------------------------------------------
    Adder               15t         2t          17t
    Anaconda            40t         40t         80t
    Asp Mark II         30t         0t          30t
    Boa                 30t         40t         70t
    Boa Class Cruiser   35t         40t         75t
    Cobra Mark I        15t         10t         25t
    Cobra Mark III+     20t         15t         35t
    Cobra Mark III*     20t         26t         46t
    Fer-de-Lance        20t         12t         32t
    Gecko               15t         3t          18t
    Krait               15t         2t          17t
    Mamba               15t         4t          19t
    Moray Star Boat     15t         7t          22t
    Moray Medical Boat* 15t         11t         26t
    Python              24t         40t         64t
    Orbital Shuttle     15t         22t         37t
    Sidewinder          15t         0t          15t
    Transporter         15t         12t         27t
    Worm                15t         5t          20t
    
    + Note: without cargo bay extension installed
    * Note: with cargo bay extension installed.
    
    The "Ship Comparison" OXP will display the equipment space and convertible cargo space values for most ships in the game.
    
    Ship Configuration Screen
    =========================
    To make changes to the configuration of your ship, go to the F3 Equip Ship screen and select the "Ship Configuration" item from the list.
    
    At the top of the screen are a number of values which will change as you make configuration choices via the menus:
    
    Cash                        This is your current credit balance
    Equipment space             The first number is the total amount of equipment space currently in use.
                                The amount in brackets is the total amount of equipment space currently available on the ship.
    Cargo space allocation      The first number is the amount of cargo space currently being partitioned for equipment use.
                                The amount in brackets is how much of the cargo hold can be partitioned for equipment use.
    Total equipment weight      This is the total weight of all installed equipment items plus cargo.
    Bus overload chance			This is the chance of encountering a bus overload situation with your current equipment loadout.
    
    Thrust                      This is the estimated maximum thrust your ship can achieve based on the current weight profile of your ship.
                                The number in brackets is the standard thrust value for this ship as declared by the manufacturer.
    Speed                       This is the estimated maximum speed your ship can achieve based on the current weight profile of your ship.
                                The number in brackets is the standard maximum speed value for this ship as declared by the manufacturer.
    Pitch                       This is the estimated maximum pitch value your ship can achieve based on the current weight profile of your ship.
                                The number in brackets is the standard pitch value for this ship as declared by the manufacturer.
    Roll                        This is the estimated maximum roll value your ship can achieve based on the current weight profile of your ship.
                                The number in brackets is the standard roll value for this ship as declared by the manufacturer.
    
    As you make changes to various parts of your ship the values at the top of the screen will change to reflect the estimated performance.
    
    The configuration of your ship is divided up into 13 main areas: Engines, Hyperdrive, Thrusters, Boosters, Energy, Shields (forward and aft), Fuel Injection, Heat Shields, Armour (forward and aft) and Electrical. The electrical system comprises of the main electrical bus, plus couplings for engines, hyperdrive, thrusters, boosters, energy banks, and forward and aft shields. Weapons are still installed via the F3 Equip Ship interfaces, but as you will see, your weapon choices will have a bearing on the performance of your ship.
    
    Items in the list colored orange can be installed.
    Items in the list colored green are the ones currently installed. The negative value in the "Cost" column indicates the refund you will receive when this item is swapped out for another.
    Items in the list colored red are the ones currently installed, but are damaged. You should get this item repaired as soon as possible. You will only get 50% of the cost of the item if you replace it.
    Items in the list colored light grey can be installed, but are above the class level of the electrical coupling currently installed for that subsystem. There would be a risk of bus overload by installing this item.
    Items in the list colored dark grey can be installed only when the electrical coupling for that subsystem is upgraded.
    
    Please note that you must have sufficient credit to purchase a new item before any refund for existing equipment can be applied. The purchase happens before the refund, so you need to have enough credit for the purchase.
    
    Note that some configurations are not possible at some stations. The techlevel for each configuration item is noted below.
    
    Engines
    -------
    Your engines control how fast your ship flies in normal space. Your level of thrust and maximum speed are dependant on your engines. When damaged, your thrust and speed will be reduced.
    
    Your engines are linked to the fuel injector system - if your engines are damaged, your fuel injectors will not function.
    
    There are 42 different classes of engine:
        Class 1A    -20% thrust, -7% speed below manufacturers specs, but only uses 1t of space, weighs 1t. (TL1)
        Class 1B    -30% thrust, -3% speed below manufacturers specs, but only uses 1t of space, weighs 1t. (TL1)
        Class 1C    -10% thrust, -10% speed below manufacturers specs, but only uses 1t of space, weighs 1t. (TL1)
        Class 1D    -20% thrust, -7% speed below manufacturers specs, but only uses 0.5t of space, weighs 1t. (TL3)
        Class 1E    -30% thrust, -3% speed below manufacturers specs, but only uses 0.5t of space, weighs 1t. (TL3)
        Class 1F    -10% thrust, -10% speed below manufacturers specs, but only uses 0.5t of space, weighs 1t. (TL3)
        Class 2A    Standard factory-fitted engines, achieves published levels of speed and thrust, uses 2t of space, weighs 2t. (TL1)
        Class 2B    -10% thrust, +4% speed over manufacturers specs, uses 2t of space, weighs 2t. (TL1)
        Class 2C    +10% thrust, -4% speed on manufacturers specs, uses 2t of space, weighs 2t. (TL1)
        Class 2D    Standard levels of speed and thrust, uses 1t of space, weighs 1.5t. (TL5)
        Class 2E    -10% thrust, +4% speed over manufacturers specs, uses 1t of space, weighs 1.5t. (TL5)
        Class 2F    +10% thrust, -4% speed on manufacturers specs, uses 1t of space, weighs 1.5t. (TL5)
        Class 3A    Standard levels of thrust, +7% speed over manufacturers specs, uses 3t of space, weighs 3t. (TL4)
        Class 3B    -10% thrust, +12% speed over manufacturers specs, uses 3t of space, weighs 3t. (TL4)
        Class 3C    +10% thrust, +3% speed over manufacturers specs, uses 3t of space, weighs 3t. (TL4)
        Class 3D    Standard levels of thrust, +7% speed over manufacturers specs, uses 1.5t of space, weighs 2t. (TL6)
        Class 3E    -10% thrust, +12% speed over manufacturers specs, uses 1.5t of space, weighs 2t. (TL6)
        Class 3F    +10% thrust, +3% speed over manufacturers specs, uses 1.5t of space, weighs 2t. (TL6)
        Class 4A    +20% thrust, +10% speed over manufacturers specs, uses 4t of space, weighs 3.5t. (TL5)
        Class 4B    +10% thrust, +15% speed over manufacturers specs, uses 4t of space, weighs 3.5t. (TL5)
        Class 4C    +30% thrust, +5% speed over manufacturers specs, uses 4t of space, weighs 3.5t. (TL5)
        Class 4D    +20% thrust, +10% speed over manufacturers specs, uses 2t of space, weighs 3t. (TL8)
        Class 4E    +10% thrust, +15% speed over manufacturers specs, uses 2t of space, weighs 3t. (TL8)
        Class 4F    +30% thrust, +5% speed over manufacturers specs, uses 2t of space, weighs 3t. (TL8)
        Class 5A    +20% thrust, +15% speed over manufacturers specs, uses 6t of space, weighs 4t. (TL6)
        Class 5B    +10% thrust, +20% speed over manufacturers specs, uses 6t of space, weighs 4t. (TL6)
        Class 5C    +30% thrust, +10% speed over manufacturers specs, uses 6t of space, weighs 4t. (TL6)
        Class 5D    +20% thrust, +15% speed over manufacturers specs, uses 3t of space, weighs 3.5t. (TL10)
        Class 5E    +10% thrust, +20% speed over manufacturers specs, uses 3t of space, weighs 3.5t. (TL10)
        Class 5F    +30% thrust, +10% speed over manufacturers specs, uses 3t of space, weighs 3.5t. (TL10)
        Class 6A    +40% thrust, +20% speed over manufacturers specs, uses 8t of space, weighs 5t. (TL7)
        Class 6B    +30% thrust, +25% speed over manufacturers specs, uses 8t of space, weighs 5t. (TL7)
        Class 6C    +50% thrust, +15% speed over manufacturers specs, uses 8t of space, weighs 5t. (TL7)
        Class 6D    +40% thrust, +20% speed over manufacturers specs, uses 4t of space, weighs 4t. (TL12)
        Class 6E    +30% thrust, +25% speed over manufacturers specs, uses 4t of space, weighs 4t. (TL12)
        Class 6F    +50% thrust, +15% speed over manufacturers specs, uses 4t of space, weighs 4t. (TL12)
        Class 7A    +40% thrust, +30% speed over manufacturers specs, uses 10t of space, weighs 6t. (TL9)
        Class 7B    +30% thrust, +35% speed over manufacturers specs, uses 10t of space, weighs 6t. (TL9)
        Class 7C    +50% thrust, +25% speed over manufacturers specs, uses 10t of space, weighs 6t. (TL9)
        Class 7D    +40% thrust, +30% speed over manufacturers specs, uses 5t of space, weighs 5t. (TL14)
        Class 7E    +30% thrust, +35% speed over manufacturers specs, uses 5t of space, weighs 5t. (TL14)
        Class 7F    +50% thrust, +25% speed over manufacturers specs, uses 5t of space, weighs 5t. (TL14)
    
    Engines of class D, E and F will also contribute to cabin heat.
    
    Hyperdrive
    ----------
    Hyperdrives control your ability to jump to other systems. When damaged the hyperdrive might start leaking fuel, or it may fail to engage, or if it does engage it might cause a mis-jump.
    
    There are 4 different classes of hyperdrive:
        Class 1    Takes only 1t of space, but takes 30 seconds to initiate a jump. (TL1)
        Class 2    Standard issue hyperdrive. Takes 2t of space, and takes 15 seconds to jump. (TL1)
        Class 3    Takes 5t of space, and takes 10 seconds to jump. (TL7)
        Class 4    Takes 8t of space, but only takes 5 seconds to jump. (TL13)
    
    Thrusters
    ---------
    Your thrusters control your manoeuvrability, how fast your ship can pitch and roll. When damaged, your pitch and roll rates will be reduced.
    
    There are 37 different classes of thrusters:
        Class 1     -5% pitch, -3% roll below manufacturers specs, but uses no space and only weighs 1t. (TL1)
        Class 2A    Standard factory-fitted thrusters, uses 1t of space, weighs 2t. (TL1)
        Class 2B    +2% pitch, -2% roll on manufacturers specs, uses 1t of space, weighs 2t. (TL1)
        Class 2C    -2% pitch, +2% roll on manufacturers specs, uses 1t of space, weighs 2t. (TL1)
        Class 2D    Standard factory-fitted thrusters, uses 0.5t of space, weighs 1t. (TL3)
        Class 2E    +2% pitch, -2% roll on manufacturers specs, uses 0.5t of space, weighs 1t. (TL3)
        Class 2F    -2% pitch, +2% roll on manufacturers specs, uses 0.5t of space, weighs 1t. (TL3)
        Class 3A    +5% pitch, +5% roll over manufacturers specs, uses 2t of space, weighs 3t. (TL5)
        Class 3B    +7% pitch, +3% roll over manufacturers specs, uses 2t of space, weighs 3t. (TL5)
        Class 3C    +3% pitch, +7% roll over manufacturers specs, uses 2t of space, weighs 3t. (TL5)
        Class 3D    +5% pitch, +5% roll over manufacturers specs, uses 1t of space, weighs 2t. (TL7)
        Class 3E    +7% pitch, +3% roll over manufacturers specs, uses 1t of space, weighs 2t. (TL7)
        Class 3F    +3% pitch, +7% roll over manufacturers specs, uses 1t of space, weighs 2t. (TL7)
        Class 4A    +8% pitch, +8% roll over manufacturers specs, uses 3t of space, weighs 3.5t. (TL7)
        Class 4B    +10% pitch, +6% roll over manufacturers specs, uses 3t of space, weighs 3.5t. (TL7)
        Class 4C    +6% pitch, +10% roll over manufacturers specs, uses 3t of space, weighs 3.5t. (TL7)
        Class 4D    +8% pitch, +8% roll over manufacturers specs, uses 1.5t of space, weighs 2.5t. (TL9)
        Class 4E    +10% pitch, +6% roll over manufacturers specs, uses 1.5t of space, weighs 2.5t. (TL9)
        Class 4F    +6% pitch, +10% roll over manufacturers specs, uses 1.5t of space, weighs 2.5t. (TL9)
        Class 5A    +12% pitch, +12% roll over manufacturers specs, uses 4t of space, weighs 4t. (TL8)
        Class 5B    +14% pitch, +10% roll over manufacturers specs, uses 4t of space, weighs 4t. (TL8)
        Class 5C    +10% pitch, +14% roll over manufacturers specs, uses 4t of space, weighs 4t. (TL8)
        Class 5D    +12% pitch, +12% roll over manufacturers specs, uses 2t of space, weighs 3t. (TL10)
        Class 5E    +14% pitch, +10% roll over manufacturers specs, uses 2t of space, weighs 3t. (TL10)
        Class 5F    +10% pitch, +14% roll over manufacturers specs, uses 2t of space, weighs 3t. (TL10)
        Class 6A    +18% pitch, +18% roll over manufacturers specs, uses 6t of space, weighs 4.5t. (TL9)
        Class 6B    +20% pitch, +16% roll over manufacturers specs, uses 6t of space, weighs 4.5t. (TL9)
        Class 6C    +16% pitch, +20% roll over manufacturers specs, uses 6t of space, weighs 4.5t. (TL9)
        Class 6D    +18% pitch, +18% roll over manufacturers specs, uses 3t of space, weighs 3.5t. (TL12)
        Class 6E    +20% pitch, +16% roll over manufacturers specs, uses 3t of space, weighs 3.5t. (TL12)
        Class 6F    +16% pitch, +20% roll over manufacturers specs, uses 3t of space, weighs 3.5t. (TL12)
        Class 7A    +24% pitch, +24% roll over manufacturers specs, uses 8t of space, weighs 5t. (TL11)
        Class 7B    +26% pitch, +22% roll over manufacturers specs, uses 8t of space, weighs 5t. (TL11)
        Class 7C    +22% pitch, +26% roll over manufacturers specs, uses 8t of space, weighs 5t. (TL11)
        Class 7D    +24% pitch, +24% roll over manufacturers specs, uses 4t of space, weighs 4t. (TL14)
        Class 7E    +26% pitch, +22% roll over manufacturers specs, uses 4t of space, weighs 4t. (TL14)
        Class 7F    +22% pitch, +26% roll over manufacturers specs, uses 4t of space, weighs 4t. (TL14)
    
    Thrusters of class D, E and F will also contribute to cabin heat.
    
    Boosters
    --------
    Boosters provide a performance increase to both your engines and thrusters. The downside is that you risk overheating your ship if you run over a certain percentage of your maximum speed. For instance, if you have Class 2 boosters installed, which build up heat from 93% of your throttle, then running your engines at more than 93% of their maximum speed will result in your cabin temperature rising. A warning tone will sound and a console message will be displayed when your reach this point during acceleration. When damaged any increase to engine or thruster performance will be lost.
    
    Boosters are only available from hi-tech worlds, and their cost is considerable.
    
    There are 7 different classes of boosters:
    	Class 1		+3% to speed, roll and pitch, uses 1t of space, heat buildup from 97% of throttle. (TL9)
    	Class 2		+6% to speed, roll and pitch, uses 2t of space, heat buildup from 93% of throttle. (TL10)
    	Class 3		+9% to speed, roll and pitch, uses 3t of space, heat buildup from 90% of throttle. (TL11)
    	Class 4		+12% to speed, roll and pitch, uses 4t of space, heat buildup from 87% of throttle. (TL12)
    	Class 5		+15% to speed, roll and pitch, uses 5t of space, heat buildup from 83% of throttle. (TL13)
    	Class 6		+18% to speed, roll and pitch, uses 6t of space, heat buildup from 80% of throttle. (TL14)
    	Class 7		+20% to speed, roll and pitch, uses 7t of space, heat buildup from 77% of throttle. (TL15)
    
    Energy
    ------
    Your ship uses energy to fire lasers, operate the ECM system, and powers a number of other systems on your ship. When your energy falls to zero and your ship is hit by an unshielded laser or missile, your ship will be destroyed. More energy means the ability to absorb more damage before destruction. If your energy banks are damaged, items like the naval energy unit and the extra energy unit (both of which control how fast your energy banks are recharged) will not function. When your energy banks are damaged they will begin to drain until you have only emergency reserves remaining. You should dock immediately for repairs.
    
    Because energy banks are just additional energy storage compartments, and there are few complications with the technology, they can be installed and repaired at any station.
    
    You can install up to 25 energy banks in your ship, if you have space. Standard class energy banks take up 1t of space per bank, and weight 1t per bank.
    
    Class "A" energy banks are available at TL13 stations or higher, for around double the cost of their standard class cousins. These energy banks utilise high-yield components to reduce the space required for each energy bank by half. That is, if a Class 9 energy bank uses 9t of space, a Class 9A energy bank will only use 4.5. The units will have the same weight, however.
    
    Also, cabin heat will be increased when using Class "A" energy banks.
    
    It is not possible to "mix-and-match" energy banks. You cannot have 1 set of class 4 energy banks, and another set of class 4A energy banks. They must all be of one type.
    
    The "Extra Energy Unit" equipment item increases the rate at which your energy banks recharge. It uses 3t of space.
    The "Naval Energy Unit" equipment item also increases the rate at which your energy banks recharge. It uses 5t of space.
    
    Shields (Forward and Aft)
    -------------------------
    Shields absorb energy from lasers and missiles. Without shields lasers and missiles can damage and cripple your ship. Stronger shields means you can deflect more attacks, but stronger shields take more space. If your shields are damaged, the shield booster or military shield enhancement will not function, and the benefits they supply (stronger shields that recharge faster) will be lost. If your shield is damaged, the energy will drain away until there is no shield strength at all.
    
    However, you may decide to forgo the protection shields provide and remove them entirely. THIS IS NOT RECOMMENDED! GalCop advises all pilots to install shields as part of their standard setup. If you have either of the shield boosting equipment items installed, you will not be able to remove your shields. If you decide to remove your shields it is highly recommended that some form of armour is installed to compensate.
    
    Apart from the option of removing your shields entirely, there are 5 different classes of shields:
        Class 1    Takes 64 points off the standard level of shields, but also reduces space to just 1t. (TL1)
        Class 2    Standard, factory-fitted shields, uses 2t of space. (TL1)
        Class 3    Adds 64 points to standard level of shields, uses 3t of space. (TL6)
        Class 4    Adds 128 points to standard level of shields, uses 4t of space. (TL9)
        Class 5    Adds 192 points to standard level of shields, uses 5t of space. (TL12)
    
    The "Shield Booster" equipment item adds 128 points to the shield strength. It uses 4t of space.
    The "Military Shield Enhancement" equipment item adds a further 128 points to the shields, and increases the rate at which they recharge. It uses 6t of space.
    
    Note that while the "Shield Booster" and "Military Shield Enhancement" have a cumulative effect (that is, if both are installed the total increase to the shields is 256 points), the various shield classes provide a single increase.
    
    Fuel Injection
    --------------
    Fuel injection systems dump unused Quirium fuel into your engines, giving you a massive boost in speed. If your engines are damaged any fuel injection system will not function.
    
    There are 4 different classes of fuel injection systems:
        Class 1    Burns 50% more fuel per second, and only provides half the speed boost of standard Class 2 injectors. Uses 0.5t of space. (TL5)
        Class 2    Achieves manufacturers declared specifications with regard to fuel burn rate and speed boost. Uses 1t of space. (TL11)
        Class 3    Burns 40% less fuel per second, and gives a 20% speed improvement over standard Class 2 injectors. Uses 2t of space. (TL12)
        Class 4    Burns 60% less fuel per second, and gives a 40% speed improvement over standard Class 2 injectors. But uses 4t of space. (TL13)
    
    Fuel Scoops
    -----------
    Fuel scoops give pilots a means of replenishing their fuel supply by scooping fuel gasses from the corona of the sun. Each fuel scoop contains an 'accumulator'. The fuel scoop accumulator is the storage area inside the scoop where gasses are held prior to being converted into fuel. The larger the accumulator, the faster fuel is scooped.
    
    There are 4 classes of fuel scoop available, each one having a different accumulator size:
        Class 1     0.10 ly accumulator. Weighs 2t. This is the standard type of fuel scoop. (TL6)
        Class 2     0.15 ly accumulator. Weigh6 4t. (TL7)
        Class 3     0.20 ly accumulator. Weighs 6t. (TL9)
        Class 4     0.25 ly accumulator. Weight 8t. (TL11)
    
    Heat Shields
    ------------
    Heat shielding protects your ship when flying close to the sun when skimming fuel. Without shielding your ship will heat up quickly and equipment and cargo can be damaged. Heat shielding will keep your ship cooler for longer, allowing you to easily skim fuel without needing to retreat to a safe distance too often. If your heat shield is damaged your ship will be unprotected from the heat of the sun.
    
    There are 4 different classes of heat shielding, none of which provide any protection from laser or missile attacks, but all of which add weight to your ship.
        Class 1    Adds 0.5 points to the ships base level of protection, but only adds 1t of weight. (TL3)
        Class 2    Adds 1.0 point to the ships base level of protection. This is the general standard level of heat shielding. Adds 3t of weight. (TL5)
        Class 3    Adds 1.5 points to the ships base level of protection. Adds 6t of weight. (TL8)
        Class 4    Adds 2.0 points to the ships base level of protection. Adds 9t of weight. (TL11)
        Class 5    Adds 2.5 points to the ships base level of protection. Adds 12t of weight. (TL12)
        Class 6    Adds 3.0 points to the ships base level of protection. Adds 16t of weight. (TL13)
    
    Note: If your ship comes equipped with manufacturer-fitted heat insulation above the industry standard level of 1.0, then installing additional heat shielding will effectively increase your total value. For instance, if your ship comes with a standard level of 3, and you install class 4 heat shields, your effective heat insulation rating is 5.
    
    Armour (Forward and Aft)
    ------------------------
    Adding armour to your ship can help protect the sensitive equipment contained within when your shields have fallen. Armour can be added to either the front or aft sections of your ship, and you can install different classes of armour in each section.
    
    In total, there are 7 classes of armour you can add to your ship, each with difference weight, strength and damage points.
        Class 1    Lightweight carbon-polymer coating. Armour strength of 100, damage point 85%. Weighs only 2t. (TL3)
        Class 2    Lightweight aluminium plating. Armour strength 125, damage point 80%. Weighs 7t. (TL5)
        Class 3    Polycarbonate casing. Armour strength 150, damage point 75%. Weighs 15t. (TL6)
        Class 4    Composite material. Armour strength 175, damage point 70%. Weighs 25t. (TL8)
        Class 5    Plasteel plating. Armour strength 200, damage point 60%. Weighs 40t. (TL9)
        Class 6    Durasteel plating. Armour strength 300, damage point 50%. Weighs 52t. (TL11)
        Class 7    Titanium plating. Armour strength 400, damage point 40%. Weighs 70t. (TL13)
    
    The strength of the armour defines how well the armour will stand up to attack. When lasers strike unshielded armour, the strength value defines how much of the armour will be depleted. Higher strength values will mean less armour is removed.
    
    The damage point of the armour is the point at which damage to internal components will potentially start to occur. A rating of 85% means that the armour can withstand 15% of damage with no chance that damage will be passed on to equipment. When damage falls below 85%, the chance that equipment will be damaged increases.
    
    Electrical
    ----------
    The electrical subsystem of your ship consists of a main electrical bus, onto which each secondary system connects via a coupling. There are 7 classes of main bus, and different classes of coupling for each secondary system.
    
    High class level electrical buses are expensive and weigh a considerable amount. Most ships come equipped with at least class 2 electrical buses as standard.
    
    Electrical bus items cannot be damaged. If inappropriate couplings and buses are used and bus overload occurs, damage is instead passed through to any equipment using the bus.
    
    Fuel injectors are powered through the main engine, the engine's power coupling applies to the fuel injectors.
    Heat shields are not powered, so do not require a coupling to the electrical system.
    
    There are 7 different classes of main electrical bus:
        Class 1    Can service class 1 couplings. No additional space requirements, and weighs only 1t. (TL1)
        Class 2    Can service up to class 2 couplings. No additional space requirements, weighs 4t. (TL1)
        Class 3    Can service up to class 3 couplings. Uses 2t of space, weighs 7t. (TL5)
        Class 4    Can service up to class 4 couplings. Uses 4t of space, weighs 12t. (TL7)
        Class 5    Can service up to class 5 couplings. Uses 6t of space, weighs 17t. (TL9)
        Class 6    Can service up to class 6 couplings. Uses 8t of space, weighs 23t. (TL11)
        Class 7    Can service up to class 7/8 couplings. Uses 10t of space, weighs 30t. (TL13)
    
    Engine Power Couplings:
        Class 1    Can service class 1 engines. Weighs 0.1t. (TL1)
        Class 2    Can service up to class 2 engines. Weighs 0.2t. (TL1)
        Class 3    Can service up to class 3 engines. Weighs 0.3t. (TL4)
        Class 4    Can service up to class 4 engines. Weighs 0.4t. (TL5)
        Class 5    Can service up to class 5 engines. Weighs 0.5t. (TL6)
        Class 6    Can service up to class 6 engines. Weighs 0.6t. (TL7)
        Class 7    Can service up to class 7 engines. Weighs 0.7t. (TL9)
    
    Hyperdrive Power Couplings:
        Class 1    Can service class 1 hyperdrives. Weighs 0.1t. (TL1)
        Class 2    Can service up to class 2 hyperdrives. Weighs 0.2t. (TL1)
        Class 3    Can service up to class 3 hyperdrives. Weighs 0.3t. (TL7)
        Class 4    Can service up to class 4 hyperdrives. Weighs 0.4t. (TL12)
    
    Thruster Power Couplings:
        Class 1    Can service class 1 thrusters. Weighs 0.1t. (TL1)
        Class 2    Can service up to class 2 thrusters. Weighs 0.2t. (TL1)
        Class 3    Can service up to class 3 thrusters. Weighs 0.3t. (TL5)
        Class 4    Can service up to class 4 thrusters. Weighs 0.4t. (TL7)
        Class 5    Can service up to class 5 thrusters. Weighs 0.5t. (TL8)
        Class 6    Can service up to class 6 thrusters. Weighs 0.6t. (TL9)
        Class 7    Can service up to class 7 thrusters. Weighs 0.7t. (TL11)
    
    Booster Power Couplings:
        Class 1    Can service class 1 boosters. Weighs 0.1t. (TL1)
        Class 2    Can service up to class 2 boosters. Weighs 0.2t. (TL1)
        Class 3    Can service up to class 3 boosters. Weighs 0.3t. (TL5)
        Class 4    Can service up to class 4 boosters. Weighs 0.4t. (TL7)
        Class 5    Can service up to class 5 boosters. Weighs 0.5t. (TL8)
        Class 6    Can service up to class 6 boosters. Weighs 0.6t. (TL9)
        Class 7    Can service up to class 7 boosters. Weighs 0.7t. (TL11)
    
    Energy Bank Power Couplings:
        Class 1    Can service up to class 4 energy banks. Weighs 0.1t. (TL1)
        Class 2    Can service up to class 7 energy banks. Weighs 0.2t. (TL1)
        Class 3    Can service up to class 10 energy banks. Weighs 0.3t. (TL1)
        Class 4    Can service up to class 13 energy banks. Weighs 0.4t. (TL1)
        Class 5    Can service up to class 16 energy banks. Weighs 0.5t. (TL1)
        Class 6    Can service up to class 19 energy banks. Weighs 0.6t. (TL1)
        Class 7    Can service up to class 22 energy banks. Weighs 0.7t. (TL1)
        Class 8    Can service up to class 25 energy banks. Weighs 0.8t. (TL1)
    
    Forward/Aft Shield Power Couplings:
        Class 1    Can service class 1 shields. Weighs 0.1t. (TL1)
        Class 2    Can service up to class 2 shields. Weighs 0.2t. (TL1)
        Class 3    Can service up to class 3 shields. Weighs 0.3t. (TL6)
        Class 4    Can service up to class 4 shields. Weighs 0.4t. (TL9)
        Class 5    Can service up to class 5 shields. Weighs 0.5t. (TL12)
    
    Bus Overload
    ------------
    You can install equipment at +1 class level over the level of the coupling, which in turn can be +1 class level over your main bus. However, running equipment over the coupling or bus class levels runs the risk of energy damage being passed through to equipment, even with full shield strength. If a bus overload occurs, damage can be passed on to *any* equipment item, not just the core systems.
    
    Equipment Space Extensions
    --------------------------
    In high-tech worlds you can purchase an equipment space extension that does not use cargo space. This involves some reconfiguration of existing equipment racks to allow the extension to be fitted. Only small-to-medium-sized ships can have these extensions fitted, and while more than one can be fitted, there is a maximum allowance of two extensions in any ship.
    
    The extensions come in the following sizes:
    	1t			Adds 3t of weight (TL11)
    	2t			Adds 5t of weight (TL12)
    	5t			Adds 10t of weight (TL13)
    
    Note: Because equipment extensions result in a more tightly arranged configuration of your equipment, there will be a noticable increase in cabin temperature when these items are installed.
    
    Selling Equipment
    =================
    An interface has been provided where all equipment that takes space or weight can be sold and removed from your ship. Only equipment items that do not have dependant items can be sold (eg. you can't sell the Extra Energy Unit if you have the Naval Energy Unit installed, you can't sell a passenger berth if you have a passenger inside it). Selling equipment can reduce the equipment space required as well as reducing weight profile of your ship. The sale price of equipment is 85% of the original price.
    
    Storing Equipment and Cargo
    ===========================
    As an alternative to selling the equipment, every main station has a self-storage facility into which your excess equipment can be transferred. If you choose to store equipment, an F4 interface screen, "Storage facility management", will be available that will show you all the equipment you have stored at this station or any other station. Equipment stored in the current station can be either sold or reinstalled. Equipment stored in other stations can be sold or transferred to the current station, after paying a transfer fee, but depending on the length of the trip and the number of dangerous systems the transfer ship must take to reach the current system, you may end up losing the equipment.
    
    Most cargo can also be stored in the facilities, and transferred between them. After selecting "Storage facility management", you will have an option to move cargo from your hold into the facility.
    
    Note: Storage facilities are only available at the main station in each system. If you dock at any other station the F4 interface screen will instead read "Storage facility information" and will provide details of what equipment and cargo you have in storage at the main station.
    
    Note: It is not possible to store upgrades to engines, thrusters, boosters, hyperdrive, shields, or any electrical equipment. Storage of these items is prohibited by station authorities due to safety considerations, as some untrained and unskilled pilots have taken it upon themselves to reinstall their equipment outside of station oversight with unfortunate results.
    
    Note: Slaves, firearms and narcotics cannot be stored in any facility, by GalCop law.
    
    Current Equipment List
    ======================
    This option lists all items installed in your ship that have either a space or weight requirement on your ship. The list is ordered with the largest items at the top, so you can always see what equipment is taking up the most space.
    
    Equipment Specifications
    ========================
    A new interface is now available on the F4 screen, entitled "View equipment specifications". This interface screen lists all possible equipment items available to the player, and the tech level, space and weight requirements of each item. Note, however, these items may or may not be available for purchase at your station, or indeed even in the system. These items are purely available somewhere in the galaxy, and the list explains what you can expect in terms of space and weight.
    
    The following table lists all the standard equipment and the space/weight requirements for each:
    
    Equipment Item               Space   Weight
    -------------------------------------------
    Standard Missile             0.0t    0.1t
    ECM-hardened Missile         0.0t    0.3t
    Quirium Cascade Mine         0.0t    0.2t
    Pulse Laser                  0.0t    1.0t
    Beam Laser                   0.0t    2.0t
    Mining Laser                 0.0t    1.5t
    Military Laser               0.0t    3.0t
    E.C.M. System                1.0t    1.0t
    Large Cargo Bay              0.0t    5.0t
    Fuel Scoops                  0.0t    2.0t
    Escape Pod                   0.0t    1.0t
    Extra Energy Unit            3.0t    3.0t
    Naval Energy Unit            5.0t    5.0t
    Docking Computer             1.0t    1.0t
    Galactic Hyperdrive          1.0t    1.0t
    Cloaking Device              1.0t    1.0t
    Advanced Space Compass       0.0t    1.0t
    Wormhole Scanner             0.0t    1.0t
    Shield Boosters              4.0t    4.0t
    Military Shield Enhancement  6.0t    6.0t
    
    Any standard equipment item not in this list will have zero space and weight requirements.
    
    Most OXP equipment has been categorised individually. If an item is not recognised by the system, it will assume a value of 1t of space, and 1t of weight. The spreadsheet file provided with the game package, "EquipmentSpecifications.ods" (OpenDocument format) contains a list of all known OXP equipment item keys and related space/weight requirements, as well as a list of all equipment keys that are considered to have no space/weight factor at all.
    
    Cabin Temperature and Heat Sinks
    ================================
    A number of different activities and events will now impact on cabin temperature. These are:
    	- Use of your hyperdrive
    	- Laser temperature
    	- Use of fuel injectors
    	- Use of cloaking device
    	- Laser hits on an unshielded hull
    	- Running your ship with an overloaded electrical bus
    	- Installing equipment extensions
    
    Each of these things on their own probably won't cook your ship, but if you combine two or three of them at the same time you can expect to see your cabin temperature reach dangerous levels quickly.
    
    Therefore care must be taken to (a) select appropriate lasers, engines and thrusters for the roles you want to perform, and (b) be careful how you use your lasers, fuel injectors and the cloaking device to avoid overheating your cabin and potentially causing catastrophic damage to your ship.
    
    Note: Entering hyperspace with high levels of heat increases your chance of having a misjump.
    
    To help with controlling cabin temperature, heat sinks can be purchased at all tech level 2 systems and above. You can purchase several heat sinks, but each one takes up 1t of cargo space, and adds 2t of weight.
    
    To deploy a heat sink, first prime the "Heat Sink Control" item by using the Shift-N key sequence, then press "N" to activate it. Up to approximately 40% of your cabin temperature can be jettisoned in this way, dependant on the size of your ship. For larger ships this value will be closer to 10%.
    
    You can also set the heat sink control to automatically deploy heat sinks whenever your cabin temperature reaches 75% of maximum. To do this, prime the "Heat Sink Control" and then select "B" to change the mode from "Manual control" to "Automatic control".
    
    Heat sinks can be damaged, and cannot be used when in a damaged state.
    
    Heat Shields also help with cabin heat. Higher levels of heat shield will slow the rate at which cabin temperature builds up.
    
    Heat sinks can be purchased at TL2 systems, for 30 Cr.
    
    3rd Party Interfaces
    ====================
    Purchase notification callbacks
    -------------------------------
    To have Ship Config callback a function when equipment is purchased, use this interface:
    
        var sc = worldScripts.ShipConfiguration_Core;
        if (sc) {
            sc.$addCallBack(this.MyFunctionName.bind(this));
        }
    
    In this example, the function "MyFunctionName" will be caused, with the context set to the functions' JS file.
    
    Ships
    -----
    Equipment Space and Power to Weight ratio:
    	Overriding the calculation of equipment space and the power to weight ratio for a particular ship can be done in two ways.
    
    	1. Via Javascript
    	To add an override for a particular ship type, add the code to a "startUp" script similar to the following:
    
    		var sc = worldScripts.ShipConfiguration_Core;
    		if (sc) {
    			sc._shipSpaceExceptions["Fer-de-Lance"] = [18];
    			sc._shipPowerToWeight["Fer-de-Lance"] = [1.5];
    		}
    
    
    	2. Via scriptInfo in shipdata.plist
    	To add an override directly in the shipdata.plist file, add the following lines to the "script_info" section:
    
    		"script_info" = {
    			"equipment_space" = 18; // how much default equipment space the ship has
    			"power_to_weight" = 1.5; // how powerful is the ship compared to its weight? default of 1, values of 2 or above will mean weight doesn't have as much effect
    		};
    
    	(You can change the "18" and "1.5" to whatever value is appropriate for the ship).
    
    Non-standard primary roles:
    	If your ship is only defined with a non-standard role (ie. your ship doesn't have one of the core roles attached to it when it is spawned), by default the ship will be given the standard, default level of equipment. However, you can still have the appropriate level of equipment for your ship by adding your ship role to the translation list in either of the following ways:
    
    	1. Via Javascript
    	To add a translation for your primary role, add this code to a "startUp" script similar to the following:
    
    		var sc = worldScripts.ShipConfiguration_Core;
    		if (sc) {
    			// make the primary role "my_ship_role" be equivalent to the core role "trader"
    			sc._NPCEquivalents["my_ship_role"] = "trader";
    		}
    
    	2. Via scriptInfo in shipdata.plist
    	To add an override directly in the shipdata.plist file, add the following lines to the "script_info" section:
    
    		"script_info" = {
    			// make the primary role "my_ship_role" be equivalent to the core role "trader"
    			"role_translation" = "my_ship_role|trader";
    		};
    
    
    Equipment
    ---------
    Overriding the definition of equipment space and weight for a particular piece of equipment can be done in two ways.
    
    1. Via Javascript
    Add the following code to a "startUp" script:
    
        var sc = worldScripts.ShipConfiguration_Core;
        if (sc) sc._equipmentMatrix["EQ_MY_EQUIPMENT_KEY"] = [2.0,2.0];
    
    The first value is space, the second is weight, both in tons.
    
    2. Via scriptInfo in equipment.plist
    To add an override directly in the equipment.plist file, add the following lines to the "script_info" section:
    
        "script_info" = {
            "equipment_space" = 2.0; // value in tons
            "equipment_weight" = 2.0; // value in tons
        };
    
    Setting both values to zero will mean the equipment is ignored by the system.
    
    Standard logic:
        Missiles take no space, but weigh at least 0.1t.
        Pylon mounted items take no space, but add weight.
        Equipment that uses cargo space won't use equipment space, but weight might not be 1:1. That is, a 5t cargo spot might weigh 8t.
        Weapons (lasers) generally take no space, but increasing power and/or range means more weight. Uber weapons (designed for capital ships) may actually use equipment or cargo space.
    
    Equipment Heat
    --------------
    It is possible to add a heat value into the heat calculation for when OXP equipment is in operation by using the "player.ship.script.thirdPartyHeat" property. The following script should be used as a template for OXP equipment scripts:
    
    	"use strict";
    	this.name        = "MyEquipmentOXP_ScriptName";
    	this.description = "Activation and control script for equipment with heat properties.";
    	this.licence     = "CC BY-NC-SA 3.0";
    
    	this._inOperation = false;  // the equipment may use a different method for determining when it is engaged or not.
    	this._heatAmount = 0.8;		// centralised value for heat exchange delta.
    								// 0.8 will make the cabin temp rise very slowly. lower numbers may not be visible on their own.
    								// ie if this is the only piece of equipment generating heat.
    								// higher numbers will make heat rise more quickly.
    
    	this.playerWillEnterWitchspace = function() {
    		// assuming the equipment will cease operation during a jump
    		if (this._inOperation == true) {
    			this._inOperation = false;
    			if (player.ship.script.thirdPartyHeat > 0) player.ship.script.thirdPartyHeat -= this._heatAmount;
    		}
    	}
    
    	this.equipmentDamaged = function(equipKey) {
    		if (equipKey == "EQ_MY_EQUIPMENT_KEY" && this._inOperation == true && player.ship.script.thirdPartyHeat > 0) {
    			this._inOperation = false;
    			if (player.ship.script.thirdPartyHeat > 0) player.ship.script.thirdPartyHeat -= this._heatAmount;
    		}
    	}
    
    	this.activated = function() {
    		// assuming the equipment is started and stopped by the "n" Activate key
    		if (this._InOperation == true) {
    			this._inOperation = false;
    			if (player.ship.script.thirdPartyHeat > 0) player.ship.script.thirdPartyHeat -= this._heatAmount;
    			return;
    		}
    		this._inOperation = true;
    		if (player.ship.script.thirdPartyHeat >= 0) player.ship.script.thirdPartyHeat += this._heatAmount;
    	}
    
    Also see the "shipconfig_witchdriveheat.js" file for another example of applying cabin heat.
    
    Special Note
    ============
    Parts of this OXP borrows heavily from Capt Murphy's set of "Breakable equipment" OXP's, specifically:
        Breakable Energy Unit
        Breakable Engines
        Breakable Shield Generators
        Breakable Witchdrive
    Most of the logic from those OXP's is incorporated in this OXP, and therefore those OXP's have been flagged as incompatible with this one. To use this OXP you must remove those OXP's from your AddOns folder, or via the in-game manager.
    
    Additionally, redspears "Masslock Compensators" and "Power to Engines" OXP's, as well as strangers "Hard Way" OXP, manipulate the speed of the ship at different times after launch, which interferes with the functionality of this OXP. They have been flagged as incompatible for the moment until a solution can be implemented.
    
    Requirements
    ============
    The Equipment Storage OXP is a requirement for this pack.
    
    License
    =======
    This OXP is released under the Creative Commons Attribution - Non-Commercial - Share Alike 3.0 license. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/
    
    Some code borrowed from Thargoids "IronHide Armour" OXP, and from CommonSenseOTB's "Custom Shields" OXP.
    
    Rocket image from http://simpleicon.com/rocket.html
    Thermometer image from http://simpleicon.com/temperature_3.html
    Chat image from http://simpleicon.com/chat-2.html.
    Grating image courtesy of Milosh Andrich (Iratemus@yahoo.com) from http://milosh--andrich.deviantart.com/art/Sci-fi-Texure-pack-05-335817650
    Heat sink deployed sound from "Big Door Closed" MP3, sourced from http://soundbible.com/1586-Big-Door-Closed.html Public Domain.
    Booster heat warning sound from "School Fire Alarm" MP3, sourced from http://soundbible.com/2022-School-Fire-Alarm.html Attribution 3.0
    
    Discussion
    ==========
    This OXP is discussed at this forum link: http://aegidian.org/bb/viewtopic.php?f=4&t=17842
    
    Version History
    ===============
    1.4.4
    - Small improvements to application of armour and booster variables to ship object.
    
    1.4.3
    - Fixed invalid JS function name.
    
    1.4.2
    - Added some additional items to the ignore equipment list.
    
    1.4.1
    - Fixed issue for ships of mass > 500000, where dumping heat sinks would increase cabin temp instead of reducing it.
    
    1.4.0
    - Added check for situation where the heat sync control mode becomes out of sync with the associate equipment item.
    - Added two missing flags from config options to save game, so they will be restored on game load.
    - Overridden default equipment items (Fuel Scoops, Heat Shields and Fuel Injectors), when added by other means, were not getting the additional Ship Configuration item at the same time.
    - Fix for code that calculates the weight of weapons when no predefined weight is set (Oolite 1.90 now required).
    - Moved core equipment overrides into defined plist.
    - Added interface to allow 3rd party functions to be called back when Ship Config equipment is purchased.
    - Bug fixes.
    
    1.3.8
    - Added ShipVersion equipment items to exclusion lists.
    - Fixed some issues where JS errors could occur if the player ship was destroyed.
    
    1.3.7
    - Corrected compatibility issue with Email system and armour repair items being recorded as equipment removals.
    
    1.3.6
    - Deploying the last heatsink was causing Oolite to crash.
    - Fixed issue where HUD was not being restored after viewing the Ship Configuration screen.
    
    1.3.5
    - Tweaks to the control of the F3 HUD for simpler integration with Xenon HUD (and any other HUD that might want to integrate with Ship Config).
    - Identified "Masslock Compensators" and "Power to Engines" OXP's as conflicting, and marked them in the manifest.
    
    1.3.4
    - Better use of new functions available in later versions of Oolite.
    
    1.3.3
    - Correction to cabin heat buildup calculation broken by update 1.3.2 :(
    
    1.3.2
    - Adjusted what happens to cabin heat in a nova system, to make it less deadly.
    - More fixes for improved compatibility with Coluber CH01 HUD.
    
    1.3.1
    - Fixed issue with the F3 HUD occasionally causing issues with Xenon UI and the Coluber CH01 HUD.
    - Tweaks to some equipment item names to prevent text overlapping on the F5 screen.
    
    1.3.0
    - Equipment storage system made into separate OXP, which is required by this one.
    
    1.2.8
    - Bug fixes.
    
    1.2.7
    - Ship energy is set to ship max energy whenever this value is updated.
    - Tweaks to info string for settings in Library Config, to prevent text truncation.
    - Updates to some zoom override values.
    - Improved script protection for when the player ejects.
    - Improved compatibility with Fuel Injection Cruise Control OXP.
    
    1.2.6
    - Starting the docking computer while a hyperspace countdown is active will now successfully disengage the heat buildup.
    - Cancelling and then restarting a jump countdown will now display the correct restart time value immediately when restarted.
    - Fixed issue with current page number on equipment specifications screen.
    - Fixed issue where selling equipment from storage was giving player a credit bonus in some circumstances.
    - Fixed issue with "%%" appearing in messages relating to transferred equipment being lost to pirates.
    - Fixed issue where selling equipment was not applying correct refund percentage.
    - Added missing "+heat" notice for Class 19A energy banks.
    - Location of stored equipment was not being displayed correctly after equipment transferred to local system.
    - Added flag to Library Config to control whether restrictions will be applied to NPC ships.
    
    1.2.5
    - Specialised HUD for the F3 screen will now only update the two custom HUD properties when the F3 screen is displayed.
    
    1.2.4
    - Equipment that cannot be sold at a station because of its equivalent tech level will now be displayed in the sell equipment list, but unselectable and with "Low TL" in the cost column.
    - Equipment that cannot be sold because other equipment depends on it will now be displayed in the sell equipment list, but unselectable and with "Required" in the cost column.
    - Fixed bug with assessing cargo space of unknown equipment items that take up cargo space.
    - More script protection for when the player ship is destroyed.
    - Code refactoring.
    
    1.2.3
    - Adjusted equipment space of Night Adder.
    
    1.2.1
    - Removed debug message when selling equipment.
    - Fixed HUD switching issue when using HUD Selector.
    
    1.2.0
    - Improved handling of player ship death scenarios.
    - Added extra equipment items to the ignore equipment list.
    - Added specialised HUD for the F3 screen to show equipment and cargo space remaining. Can be disabled via Library Config.
    - Updated EquipmentSpecifications.ods file with all current equipment keys specifically recognised.
    - Value for "Disable booster sound" setting now saved between sessions.
    
    1.1.3
    - Fixed transmit date on Storage Facility payment emails.
    - Bug fixes.
    
    1.1.2
    - Fixed issue with missing header text on Ship Configuration main menu.
    - Adjusted default equipment space for Fer-de-Lance.
    - Fixed some invalid ship reference errors during an escape pod sequence.
    - Extended the length of time cabin heat warning messages are displayed for.
    - Storing equipment for the first time at a station will now incur a deposit fee.
    - Fixed issue with cargo weight/space not being including in storage costs.
    - Fixed issue with incorrect/misleading labels on cargo storage menu items.
    - Code refactoring.
    
    1.1.1
    - Fixed bug that was preventing weapon in a starboard mount from being sold.
    
    1.1.0
    - Fixed bugs with incorrect amounts being refunded to the player when equipment is sold.
    - Fixed issue with incorrect refund amounts being displayed to the player on the "Sell Equipment" page.
    - Fixed issue where the ship size price factor was being incorrectly applied to fuel scoops, injectors and heat shields, and all other standard or OXP equipment items on the "Sell Equipment" page.
    - Equipment items can only be sold at stations where the can actually be bought as well.
    - Non-removable Ship Config equipment (eg Engines, Thrusters), when swapped for another unit, will only refund the price of that unit at the main station, to prevent exploitation.
    - Station equipment price factor was not being correctly applied to equipment buy/sell prices.
    - Better handling of player ship destruction.
    - Tweaks to weight values of engines, thrusters and electrical bus.
    - Corrected equipment space values for Adder and Krait in readme and on Wiki page.
    - Changed default equipment refund percentage back to 85%.
    
    1.0.0
    - Scripted equipment damage was being aggressively repaired by the armour.
    - Bus overload timer was being reset while running.
    
    0.9.2
    - New equipment items (ie. equipment purchased but not yet exposed to space travel) that are sold/exchanged will now be refunded at 100% of their cost, rather than the default 90%. This means you can swap items in and out to see the impact on ship stats, without having to take a loss on every exchange.
    - When setting a course to a target system, F7 screen will now display the new destination.
    - Equipment specification interface screen now includes TL required for purchasing equipment, and all equipment items are now being shown (not just the ones available in the current system). Also removed some unnecessary items from the list.
    
    0.9.1
    - Adjustment to Ore Processor equipment space requirements.
    - Added missing equipment items from Ore Processor OXP.
    - Added additional equipment items to the ignore list.
    - Code refactoring.
    
    0.9.0
    - Forward and aft armour can now be different classes.
    - Fixed issue with the armour equipment item not being removed when 100% damaged.
    - Purchasing other ship armour (eg IronHide) will now refund the cost of any existing Ship Config armour before removing it.
    - Improved code for processing expended heat sinks.
    - Added some additional OXP equipment items.
    - Bug fixes.
    
    0.8.2
    - Corrected minor issue with equipment.plist and fuel scoops.
    - Fixed issue with heat not being applied to NPC ships correctly. 
    - Consistency adjustments to equipment.plist.
    - Added "display_color" property to some equipment items (Oolite v1.85/86 only).
    - Bug fixes.
    
    0.8.1
    - Fixed issued with cargo not being able to be scooped.
    
    0.8.0
    - Added fuel scoop classes 1-4 to configuration menu.
    - Armour repairs now won't generate an "Equipment removed" email.
    - Code refactoring.
    - Bug fixes.
    
    0.7.2
    - Custom scripts will now be attached correctly when a new ship is purchased.
    
    0.7.1
    - Fixed faulty LMSS integration.
    
    0.7.0
    - Added ability to sell laser weapons from the "Sell Equipment" page.
    - Added ability to put laser weapons into storage.
    - Fixed script error that could occur when player ejects.
    - Tweaked the amount of heat dumped with a heat sink.
    - Fixed an issue with large player ships where heat could be added, rather than dumped, when a heat sink is deployed.
    
    0.6.7
    - Fixed issue where the core "EQ_HEAT_SHIELD" equipment item was not being added to the ship, meaning that any equipment item that required a heat shield was not able to be installed via the F3 screen (eg PlanetFall Landing Capability).
    - Adjusted the heat insulation factors for the heat shielding equipment.
    
    0.6.6
    - Updated method for determining player's next target system, to use new property "nextSystem" (when available in 1.85/6).
    - Bus overload chance will slowly decrease during flight the longer the player goes without being hit.
    - Tweaked what happens when a bus overload occurs, making it less likely that 3-5 items are damaged almost all at once.
    - Added ship roles from Keeper's YAH Haulers to NPC configuration.
    - Added ship roles from YAH to NPC configuration.
    - Added equipment from In-System Taxi OXP.
    - Fixed issue with equipment items that take up cargo space causing mis-calculations of the available cargo space.
    - Checking for an overloaded state now happens more frequently when docked, to cater for scenarios where equipment is added outside the equip ship screen (F3).
    - Code refactoring and bug fixes.
    
    0.6.5
    - Improvements to the heat sink deployment method.
    - Correction to issues with the timer for heat sink detonation control.
    
    0.6.4
    - Adjusted space/weight components of UPS Police Scanner and UPS Universal Scanner.
    - Fixed issue with core heat shield equipment not being added in the background whenever one of the new heat shield items is purchased.
    
    0.6.3
    - Removed some debug messages.
    - Removed all unnecessary debug-mode checks.
    - Added equipment items from "Vector" OXP.
    - Added equipment items from "Ring Racers" OXP.
    - Prevented sale of any equipment item that has a zero cost amount (as they are likely to be mission-OXP-related).
    
    0.6.2
    - Added logic for NPC's to turn off cloaking devices if their cabin temperature gets too high.
    - Added logic to check whether installing stored equipment has worked before removing it from the storage array.
    - Fixed incorrect monkey patching on shipDied and shipRemoved events.
    
    0.6.1
    - More equipment items can be transferred to storage, including things like MFD's and targeting enhancements.
    - Removed incorrect restriction for the military shield enhancement (it is not actually dependant on the standard shield boosters).
    - Added equipment space override for Asp Mark II Special.
    - Armour repair amounts are now in-line with the original cost of the item.
    - Fixed issue with equipment price in some OXP stations being ludicrously expensive.
    
    0.6.0
    - Added class "A" energy banks, that only take half the space of standard units, but also increase cabin heat.
    - Added class "D", "E" and "F" engines that only take half the space of class "A", "B" and "C" engines, but they also increase cabin heat.
    - Added class "D", "E" and "F" thrusters that only take half the space of class "A", "B" and "C" thrusters, but they also increase cabin heat.
    - Fixed Javascript error when escape pod is used.
    - If the Email System is present, adjusted method used to send emails when selling equipment.
    - Changed the equipment space setting for escape pods, as these would be built into the architecture of the ship, not in the equipment racks.
    - Added a tech level factor to equipment prices, so equipment should be cheaper in hi-tech systems, and more expensive in low-tech systems.
    - Adjusted the used equipment sale reduction from 15% to 10%.
    - Adjusted the heat build up from using hyperdrives to be variable based on the class level of hyperdrive.
    - Added conflicting status with Redspear's Equipment by Ship Class OXP.
    - Made compatible with Hyperspace Hanger OXP.
    - Shields, Shield Boosters and Military Shield Enhancement can now be damaged in any order.
    - Fixed issue with multiple passenger berths not being correctly reflected in weight calculations or display screens.
    - Fixed issue where damaged shields would continue to decharge even after repairing them.
    - Fixed issue where, if the Military Shield Enhancement and the Shield Boosters were damaged, you couldn't repair the former without repairing the latter, but time and credits would be deducted if you tried.
    - Fixed equipment naming convention issue.
    - Bug fixes.
    
    0.5.0
    - Added equipment space extensions to allow for more equipment without using cargo space, but with weight and cabin temp penalties.
    - Adjusted equipment space settings for fuel injectors.
    - Turned off some debug messages.
    - Toned down colour of storage facility background overlay image.
    - Fixed further compatibility issues with Ship Respray.
    - Fixed further compatibility issues with Combat Simulator.
    - Changed background overlay image during sell negotiations.
    
    0.4.4
    - The impact of damaged boosters was not being applied correctly. It wasn't making any difference if they were damaged.
    - Determination of player's hyperspace destination now considers the presence of the ANA.
    - Fixed error when not checking if a timer exists before trying to turn it off.
    - Adjusted weight/space settings for boosters.
    - Made compatible with "Hyperdrives" OXP.
    - Really really fixed the issue with the HUD disappearing after viewing the config screens.
    
    0.4.3
    - Was not correctly reading values in script_info from shipdata.
    
    0.4.2
    - Fixed spelling error in manifest.plist.
    
    0.4.1
    - Fixed small bug that could occur if the amount of used equipment space exactly equals the available space.
    - Removed debug message when purchasing a new ship.
    - Fixed issue with HUD not becoming visible again when launching while viewing the ship configuration screen..
    
    0.4.0
    - Adjusted heat shielding insulation strength for type 3 and 4 heat shields, making them more useful, particularly for sun-skimmers. Also added types 5 and 6 for additional heat shield options.
    - Fixed issue where the default level of heat insulation was being reset if heat shield equipment was not specifically installed on a ship.
    - Adjustments to manifest.plist.
    - Changed short range chart selection range to 7.5ly, rather than 15.
    - Better handling of interstellar space conditions.
    - Disabled ship configuration F3 item at police/navy stations (repairs are still possible at these stations, though).
    - Fixed issue with emails sent when selling equipment not displaying the correct refund amount.
    - F3 "Ship configuration" item now has a cost of 0 (zero).
    - Added the possibility of having a mis-jump when entering hyperspace with high heat levels.
    - Fixed issue with equipment overload state when returning from a combat simulation.
    
    0.3.0
    - Included the ability to store most equipment items in a local storage centre, and then retrieve that item at a later date. Also includes ability to sell equipment items directly from storage, or to transfer equipment items between storage facilities.
    - Cargo can also be stored in the main station storage facility, and transferred between facilities.
    - Included the ability to sell the cloaking device, or any equipment item that has an effective tech level >= 16, through a negotiation process.
    - Added warning sounds/notifications when ship temperature reaches critical levels.
    - Improved compatibility with the Single-Use witchdrive OXP.
    - Added a random element to the process of adding equipment to NPC's, so not all ships of the same role will have the same equipment.
    - Fixed issue where some column headings were not appearing correctly on the main Ship Config screen and the Electrical Bus sub-menu.
    - Fixed issue with invalid reference error when energy equipment is damaged.
    - Fixed issue with selling of passenger berths not working.
    - Removed the Breakable Torus Drive code and the incompatibility flag, moved OXP reference to "optional_oxps". If you like this feature you can install that OXP directly.
    - Removed the station equipmentPriceFactor from equipment price calculations, to avoid the loophole of buying equipment at the main station and selling it at a Rock Hermit for massive profits.
    - Fixed bug with armour damage-point calculations that was preventing any damage to equipment from taking place until armour was mostly gone.
    - Prevented smuggling compartments from being stored.
    - Added some additional role translations.
    - Changed "==" comparisons to "===" for performance improvements.
    - Equipment refund price set to 85% of original price.
    - Turned off free upgrades, turned on equipment installation time.
    - Added SniperLock equipment to ignore list.
    
    0.2.0
    - Added new equipment configuration item "Boosters" which give a boost to engines and thrusters (allowing your ship to reach higher speeds), but also generate cabin heat.
    - Now compatible with Ngalo's NShields and NPC Equipment Damage OXP's.
    - Fixed issue where buying a new ship was not resetting the stored equipment values on the configuration display.
    - Adjusted the weights of the electrical buses.
    - NPC fuel injectors now won't be upgraded if the auto-weapons routine didn't install them in the first place.
    - Added equipment items from Solar Harvester OXP and Single-Use Witchdrive OXP.
    - Improved the equipment space calculation, so that ships with more than 35t of cargo space will get at least 20t of equipment space, plus some extra.
    - Added means by which non-standard primary roles can be translated into core roles so that appropriate equipment is applied to each ship, rather than just the default equipment.
    - Added some additional equipment space exceptions.
    - Added some additional zoom factors for various ship types.
    - Turned off debug messages.
    - Adjustments to code design to allow for NPC equipment failure.
    - Bug fixes.
    
    0.1.3
    - Further adjustments to Separated Lasers and Sniper Gun space and weight amounts as supplied by Norby.
    - Added more NPC config possibilities.
    - Removed the "playerRescuedEscapePod" event, because it was unnecessary and it wasn't firing when I thought it would anyway.
    - Fixed spelling mistake on F3 screen description.
    - Added ability to allow third party OXP equipment to add their own heat delta value into the cabin heat calculation when in operation.
    - Added witchdrive jump heat buildup to heat calculations.
    
    0.1.2
    - Fixed issue with cabin temp when heat shield is damaged.
    - Adjusted "Separated Lasers" weight values.
    - Fixed issue with ships that have 0 cargo (eg Asp) attempting to be given EQ_EQUIPSPACE_0.
    - Fixed issue with "thrust" not being set along with "maxThrust".
    - Fixed issue with JS objects not being available when player ejects.
    
    0.1.1
    - Added some additional equipment items to the "No equipment space" list.
    - Added equipment items from Separated Lasers, Multiple Lasers, Sniper Gun, Trail Detector, Tionisla Reporter, Headlights, FarPlanets.
    - Configured the heat sink and the breakable torus drive entity to not get ship configuration.
    - Adding in missing JS file for the breakable torus drive.
    - Fixed issue with the cleanup routine for heatsinks causing a Javascript error.
    - Added missing ";" in shipdata.plist.
    - Code improvements.
    
    0.1.0
    - Fixed display issues on config screen where one header line was being overwritten.
    - Fixed NPC shield mechanics.
    - Added a flag to allow use of previous NPC config setup, based on role inclusion. To switch back to using role inclusion, set "this._useExclusions = false" in "shipconfig_npc.js".
    - Selling damaged equipment items will now only refund half the cost of the item.
    - Added bus overload chance to ship configuration screen.
    - Included fuel injector class level in bus overload calculation, as they use the engines electrical bus.
    - Added bus overload factor to temperature calculation.
    - Added additional energy bank options, now going up to 25 banks.
    - Rebalanced energy bank power couplings, reducing the number of classes to 8 (approx 3 banks per coupling level).
    - Updated space/weight definition for Missile Machine from Armoury.oxp to better reflect what this device is.
    - Tweaked TL availability for Class 4 Hyperdrives.
    
    0.0.13
    - Fixes to NPC equipment routines and heat sink parameter location for consistency with player and NPC ships.
    
    0.0.12
    - Config is now applied to all ships, including ones with "auto_weapons" set to false. Config can be switched off for a ship by adding a "no_config = 'yes'" to the script info for a ship.
    - Laser use, laser strikes, fuel injector use and cloaking device use will now heat up the cabin, which applies to NPC's as well. New equipment "Heat Sinks" allow for a percentage of cabin temperature to be dumped.
    - Added 7 classes of armour that will absorb damage before equipment. If IronHide armour or HardShips armour is installed, Ship Configuration armour items will not be available.
    - Added integration with Custom Shields and NPC Shields.
    - Fixed spelling mistake on "Equipment Specification" screen.
    - Adjusted space/weight requirements for gravity scanners and small and large dishes, from Telescope OXP, based on descriptions.
    - Moved most static text to descriptions.plist.
    - Fixed missing variable declaration in bus overload code.
    - Fixed issue on configuration screen where incorrect text was being displayed when no fuel injectors or heat shields were installed.
    - Removed all the "EQ_*_REPAIR" items from equipment.plist, as I figured out how to make the core repair items display properly.
    - Fixed issue with "getCargoCapacity" routine, which would return a "NaN" value for some ships.
    - Fixed issue with "Unknown escape code in string" errors appearing in log file.
    - Configured NPC equipment system, and created templates for most roles.
    - Further fixes to the issue where equipment items that take up cargo space were throwing out the available space calculations.
    - Updated screenID's to enable BGS background sounds.
    - Cleaned up sound function to avoid the need to check for BGS.
    - Updated check for "Allow Big GUI".
    - Toned down overlay images.
    - Code refactoring.
    
    0.0.11
    - Fixed Java script bug when dumping cargo.
    - Added police roles to NPC list.
    - Fixed spelling mistake for the heat shield when applying base equipment.
    - Fixed issue where equipment items that take cargo space were incorrectly adjusting the maximum cargo space available for equipment.
    - Added hyperdrive names, courtesy of Redspear.
    - Added passenger berth equipment item to matrix (although it isn't necessary now that the bugs above have been fixed).
    - Damaged core items now appear red on the Ship Configuration main menu.
    - Code refactoring and cleanup.
    
    0.0.10
    - Fixed issue with equipment space overload status showing with "0t" used cargo space.
    - Fixed issue where, after purchasing class 3 or above fuel injectors or heat shields, then saving and loading the game, class 2 items would also be installed.
    - Fixed issue where cargo space was being returned to the player after a save/load sequence.
    
    0.0.9
    - Added more plumbing for doing specific NPC role configurations.
    - Reworked the power to weight ratios to make larger ships harder to move, and smaller ships easier to move. So you can still put everything into an Anaconda, but you won't turn it into a Cobra.
    - Fixed issue with adding default equipment, where the calculation for the engine power coupling was in some situations returning invalid configurations.
    
    0.0.8
    - Fixed bug in $addEquipmentDataFromScriptInfo routine that was applying equipment weight value from script_info to equipment space and overwriting whatever had been entered for space.
    - Fixed issue where some Cobra Mark III models have a different mass.
    - Fixed issue with Ship Respray, where cargo space was disappearing when a respray was purchased.
    - Added current class levels to main menu items to make current installed items more visible.
    
    0.0.7
    - In an "overloaded" state, you can now switch between selling equipment and changing configuration in order to free up space.
    - Fixed issue with the installed equipment list, where player ships with no missiles defined was causing an error.
    - Fixed issue where you could install a much lower power coupling regardless of the equipment attached to it.
    - Adjusted layout of interface screen.
    - Adjusted position of "Ship Configuration" item on F3 screen so that fuel will come before it.
    - Adjusted the thruster percentages to give them more range.
    
    0.0.6
    - Fixed issue where NPC's were not getting adjustments applied, and where occasionally the wrong piece of kit was showing up on the player.
    - Changed minimum techlevel for doing configuration changes to 2, so you can't do config changes at Rock Hermits.
    - Fixed incorrect text on repair item for breakable torus drive.
    - Code refactoring.
    
    0.0.5
    - Added equipment items from "Laser Cannons".
    - Added better checking for unknown lasers.
    
    0.0.4
    - Really fixed the energy draining away issue.
    
    0.0.3
    - Disabled the "overheating engine" code as it wasn't working as intended.
    - Fixed issue (hopefully this time for sure!) where energy was being drained away.
    - Fixed issue (hopefully) with being able to purchase multiple items of the same type.
    - Adjusted engine upgrade speed values.
    - Fixed missing ";" in shipdata.plist.
    
    0.0.2
    - Price of upgrades now scaled to ship size (so an engine upgrade for a Boa costs more than an engine upgrade for a Transporter).
    - Changed layout of ship config screen to be more intuitive.
    - Added a flag to make all upgrades free during testing period.
    - Fixed issue (hopefully!) where energy was being drained away on launch.
    - Adjusted thrust and speed values for engine upgrades to be more noticeable.
    - When cargo is removed to make space for equipment, it will now be sold, rather than just removed.
    - Changed power-to-weight ratio for Transporters.
    - Changed shield upgrades to be in multiples of 64.
    - Changed Class 4 hyperdrive spin time to 5 seconds.
    - Moved salvaged equipment (from Anarchies OXP) into the ignore list, as these items are removed on purchase anyway.
    - IF BGS is in use, now using the BGS hull bang noise when damage occurs.
    - Added logic to cool engines down if you've run them in overload for a period of time.
    - Bug fixes.
    - Code refactoring.
    
    0.0.1
    - Initial Alpha release
    

    Equipment

    Name Visible Cost [deci-credits] Tech-Level
    Aft Shields Power Coupling Class 1 yes 5500 1+
    Aft Shields Power Coupling Class 2 yes 12500 1+
    Aft Shields Power Coupling Class 3 yes 22500 6+
    Aft Shields Power Coupling Class 4 yes 38500 9+
    Aft Shields Power Coupling Class 5 yes 53100 12+
    Aft Shields Class 1 yes 25000 1+
    Aft Shields Class 2 yes 55000 1+
    Aft Shields Class 3 yes 71000 6+
    Aft Shields Class 4 yes 125000 9+
    Aft Shields Class 5 yes 225000 12+
    Aft Armour Plating Class 1 yes 12000 3+
    Repair: Aft Armour Plating Class 1 no 600 2+
    Aft Armour Plating Class 2 yes 25000 5+
    Repair: Aft Armour Plating Class 2 no 1250 4+
    Aft Armour Plating Class 3 yes 41000 6+
    Repair: Aft Armour Plating Class 3 no 2050 5+
    Aft Armour Plating Class 4 yes 77000 8+
    Repair: Aft Armour Plating Class 4 no 3850 7+
    Aft Armour Plating Class 5 yes 156000 9+
    Repair: Aft Armour Plating Class 5 no 7800 8+
    Aft Armour Plating Class 6 yes 238000 11+
    Repair: Aft Armour Plating Class 6 no 11900 10+
    Aft Armour Plating Class 7 yes 538000 13+
    Repair: Aft Armour Plating Class 7 no 26900 12+
    Fwd Armour Plating Class 1 yes 12000 3+
    Repair: Forward Armour Plating Class 1 no 600 2+
    Fwd Armour Plating Class 2 yes 25000 5+
    Repair: Forward Armour Plating Class 2 no 1250 4+
    Fwd Armour Plating Class 3 yes 41000 6+
    Repair: Forward Armour Plating Class 3 no 2050 5+
    Fwd Armour Plating Class 4 yes 77000 8+
    Repair: Forward Armour Plating Class 4 no 3850 7+
    Fwd Armour Plating Class 5 yes 156000 9+
    Repair: Forward Armour Plating Class 5 no 7800 8+
    Fwd Armour Plating Class 6 yes 238000 11+
    Repair: Forward Armour Plating Class 6 no 11900 10+
    Fwd Armour Plating Class 7 yes 538000 13+
    Repair: Forward Armour Plating Class 7 no 26900 12+
    Armour Plating Class 1 no 12000 3+
    Armour Plating Class 2 no 25000 5+
    Armour Plating Class 3 no 41000 6+
    Armour Plating Class 4 no 77000 8+
    Armour Plating Class 5 no 156000 9+
    Armour Plating Class 6 no 238000 11+
    Armour Plating Class 7 no 538000 13+
    Boosters Power Coupling Class 1 yes 4000 1+
    Boosters Power Coupling Class 2 yes 16000 1+
    Boosters Power Coupling Class 3 yes 21000 4+
    Boosters Power Coupling Class 4 yes 28000 5+
    Boosters Power Coupling Class 5 yes 38000 6+
    Boosters Power Coupling Class 6 yes 42000 7+
    Boosters Power Coupling Class 7 yes 58000 9+
    Boosters Class 1 yes 55000 9+
    Boosters Class 2 yes 122000 10+
    Boosters Class 3 yes 197000 11+
    Boosters Class 4 yes 284000 12+
    Boosters Class 5 yes 386000 13+
    Boosters Class 6 yes 511000 14+
    Boosters Class 7 yes 727000 15+
    Main Electrical Bus Class 1 yes 15000 1+
    Main Electrical Bus Class 2 yes 48000 1+
    Main Electrical Bus Class 3 yes 152000 5+
    Main Electrical Bus Class 4 yes 325000 7+
    Main Electrical Bus Class 5 yes 563000 9+
    Main Electrical Bus Class 6 yes 894000 11+
    Main Electrical Bus Class 7 yes 1225000 13+
    Energy Bank Power Coupling Class 1 yes 3000 1+
    Energy Bank Power Coupling Class 2 yes 8000 1+
    Energy Bank Power Coupling Class 3 yes 14000 1+
    Energy Bank Power Coupling Class 4 yes 18000 1+
    Energy Bank Power Coupling Class 5 yes 23000 1+
    Energy Bank Power Coupling Class 6 yes 29000 1+
    Energy Bank Power Coupling Class 7 yes 35000 1+
    Energy Bank Power Coupling Class 8 yes 42000 1+
    Energy Banks Class 1 yes 5000 1+
    Energy Banks Class 10 yes 192220 1+
    Energy Banks Class 10A yes 384440 13+
    Energy Banks Class 11 yes 288330 1+
    Energy Banks Class 11A yes 576660 13+
    Energy Banks Class 12 yes 432490 1+
    Energy Banks Class 12A yes 864980 13+
    Energy Banks Class 13 yes 648740 1+
    Energy Banks Class 13A yes 1297480 13+
    Energy Banks Class 14 yes 973110 1+
    Energy Banks Class 14A yes 1946220 13+
    Energy Banks Class 15 yes 1459670 1+
    Energy Banks Class 15A yes 2919340 13+
    Energy Banks Class 16 yes 1751600 1+
    Energy Banks Class 16A yes 3503200 13+
    Energy Banks Class 17 yes 2101920 1+
    Energy Banks Class 17A yes 4203840 13+
    Energy Banks Class 18 yes 2522300 1+
    Energy Banks Class 18A yes 5044600 13+
    Energy Banks Class 19 yes 3026770 1+
    Energy Banks Class 19A yes 6053540 13+
    Energy Banks Class 1A yes 10000 13+
    Energy Banks Class 2 yes 7500 1+
    Energy Banks Class 20 yes 3632120 1+
    Energy Banks Class 20A yes 7264240 13+
    Energy Banks Class 21 yes 3995330 1+
    Energy Banks Class 21A yes 7990660 13+
    Energy Banks Class 22 yes 4394870 1+
    Energy Banks Class 22A yes 8789740 13+
    Energy Banks Class 23 yes 4834350 1+
    Energy Banks Class 23A yes 9668700 13+
    Energy Banks Class 24 yes 5317790 1+
    Energy Banks Class 24A yes 10635580 13+
    Energy Banks Class 25 yes 5849570 1+
    Energy Banks Class 25A yes 11699140 13+
    Energy Banks Class 2A yes 15000 13+
    Energy Banks Class 3 yes 11250 1+
    Energy Banks Class 3A yes 22500 13+
    Energy Banks Class 4 yes 16870 1+
    Energy Banks Class 4A yes 33740 13+
    Energy Banks Class 5 yes 25310 1+
    Energy Banks Class 5A yes 50620 13+
    Energy Banks Class 6 yes 37970 1+
    Energy Banks Class 6A yes 75940 13+
    Energy Banks Class 7 yes 56950 1+
    Energy Banks Class 7A yes 113900 13+
    Energy Banks Class 8 yes 85430 1+
    Energy Banks Class 8A yes 170860 13+
    Energy Banks Class 9 yes 128140 1+
    Energy Banks Class 9A yes 256280 13+
    Engine Power Coupling Class 1 yes 4000 1+
    Engine Power Coupling Class 2 yes 16000 1+
    Engine Power Coupling Class 3 yes 21000 4+
    Engine Power Coupling Class 4 yes 28000 5+
    Engine Power Coupling Class 5 yes 38000 6+
    Engine Power Coupling Class 6 yes 42000 7+
    Engine Power Coupling Class 7 yes 58000 9+
    Engine Class 1A yes 12000 1+
    Engine Class 1B yes 11500 1+
    Engine Class 1C yes 11700 1+
    Engine Class 1D yes 24000 3+
    Engine Class 1E yes 23000 3+
    Engine Class 1F yes 23400 3+
    Engine Class 2A yes 34000 1+
    Engine Class 2B yes 32000 1+
    Engine Class 2C yes 33000 1+
    Engine Class 2D yes 68000 5+
    Engine Class 2E yes 64000 5+
    Engine Class 2F yes 66000 5+
    Engine Class 3A yes 55500 4+
    Engine Class 3B yes 54500 4+
    Engine Class 3C yes 54300 4+
    Engine Class 3D yes 111000 4+
    Engine Class 3E yes 109000 4+
    Engine Class 3F yes 108600 4+
    Engine Class 4A yes 85000 5+
    Engine Class 4B yes 85200 5+
    Engine Class 4C yes 87800 5+
    Engine Class 4D yes 170000 8+
    Engine Class 4E yes 170400 8+
    Engine Class 4F yes 175600 8+
    Engine Class 5A yes 126000 6+
    Engine Class 5B yes 125000 6+
    Engine Class 5C yes 124000 6+
    Engine Class 5D yes 252000 10+
    Engine Class 5E yes 250000 10+
    Engine Class 5F yes 248000 10+
    Engine Class 6A yes 189000 7+
    Engine Class 6B yes 187000 7+
    Engine Class 6C yes 183000 7+
    Engine Class 6D yes 387000 12+
    Engine Class 6E yes 374000 12+
    Engine Class 6F yes 366000 12+
    Engine Class 7A yes 262000 9+
    Engine Class 7B yes 269000 9+
    Engine Class 7C yes 262000 9+
    Engine Class 7D yes 524000 14+
    Engine Class 7E yes 538000 14+
    Engine Class 7F yes 523000 14+
    EquipmentSpace1 no 1 1+
    EquipmentSpace10 no 1 1+
    EquipmentSpace11 no 1 1+
    EquipmentSpace12 no 1 1+
    EquipmentSpace13 no 1 1+
    EquipmentSpace14 no 1 1+
    EquipmentSpace15 no 1 1+
    EquipmentSpace16 no 1 1+
    EquipmentSpace17 no 1 1+
    EquipmentSpace18 no 1 1+
    EquipmentSpace19 no 1 1+
    EquipmentSpace2 no 1 1+
    EquipmentSpace20 no 1 1+
    EquipmentSpace21 no 1 1+
    EquipmentSpace22 no 1 1+
    EquipmentSpace23 no 1 1+
    EquipmentSpace24 no 1 1+
    EquipmentSpace25 no 1 1+
    EquipmentSpace26 no 1 1+
    EquipmentSpace27 no 1 1+
    EquipmentSpace28 no 1 1+
    EquipmentSpace29 no 1 1+
    EquipmentSpace3 no 1 1+
    EquipmentSpace30 no 1 1+
    EquipmentSpace31 no 1 1+
    EquipmentSpace32 no 1 1+
    EquipmentSpace33 no 1 1+
    EquipmentSpace34 no 1 1+
    EquipmentSpace35 no 1 1+
    EquipmentSpace36 no 1 1+
    EquipmentSpace37 no 1 1+
    EquipmentSpace38 no 1 1+
    EquipmentSpace39 no 1 1+
    EquipmentSpace4 no 1 1+
    EquipmentSpace40 no 1 1+
    EquipmentSpace5 no 1 1+
    EquipmentSpace6 no 1 1+
    EquipmentSpace7 no 1 1+
    EquipmentSpace8 no 1 1+
    EquipmentSpace9 no 1 1+
    1t Equipment Space Extension yes 20000 11+
    2t Equipment Space Extension yes 50000 12+
    5t Equipment Space Extension yes 100000 13+
    Fwd Shields Power Coupling Class 1 yes 5500 1+
    Fwd Shields Power Coupling Class 2 yes 12500 1+
    Fwd Shields Power Coupling Class 3 yes 22500 6+
    Fwd Shields Power Coupling Class 4 yes 38500 9+
    Fwd Shields Power Coupling Class 5 yes 53100 12+
    Fwd Shields Class 1 yes 25000 1+
    Fwd Shields Class 2 yes 55000 1+
    Fwd Shields Class 3 yes 71000 6+
    Fwd Shields Class 4 yes 125000 9+
    Fwd Shields Class 5 yes 225000 12+
    Witchdrive Fuel Injectors Class 1 yes 2000 5+
    Witchdrive Fuel Injectors Class 2 yes 6000 11+
    Witchdrive Fuel Injectors Class 3 yes 12500 12+
    Witchdrive Fuel Injectors Class 4 yes 35000 13+
    Fuel Scoops Class 1 yes 5250 6+
    Fuel Scoops Class 2 yes 6780 7+
    Fuel Scoops Class 3 yes 22000 9+
    Fuel Scoops Class 4 yes 42500 11+
    External Heat Shielding Class 1 yes 8000 3+
    External Heat Shielding Class 2 yes 15000 5+
    External Heat Shielding Class 3 yes 34000 8+
    External Heat Shielding Class 4 yes 52000 11+
    External Heat Shielding Class 5 yes 76000 12+
    External Heat Shielding Class 6 yes 89000 13+
    Heat Sink yes 300 2+
    Heat Sink Control yes 3200 2+
    Heat Sink Control yes 3200 2+
    Hyperdrive Power Coupling Class 1 yes 5000 1+
    Hyperdrive Power Coupling Class 2 yes 17500 1+
    Hyperdrive Power Coupling Class 3 yes 25000 7+
    Hyperdrive Power Coupling Class 4 yes 67000 12+
    AM18 Hyperdrive (Class 1) yes 15000 1+
    Prosset Hyperdrive (Class 2) yes 32000 1+
    CK40 V Ames Drive (Class 3) yes 56000 7+
    Titronix Intersun Hyperdrive (Class 4) yes 112000 13+
    Remove Aft Shields no 1000 1+
    Remove Forward Shields no 1000 1+
    Ship Configuration --> no 0 2+
    Thruster Power Coupling Class 1 yes 3500 1+
    Thruster Power Coupling Class 2 yes 10000 1+
    Thruster Power Coupling Class 3 yes 14000 5+
    Thruster Power Coupling Class 4 yes 21000 7+
    Thruster Power Coupling Class 5 yes 28000 8+
    Thruster Power Coupling Class 6 yes 34000 9+
    Thruster Power Coupling Class 7 yes 44000 11+
    Manoeuvring Thrusters Class 1 yes 5000 1+
    Manoeuvring Thrusters Class 2A yes 14000 1+
    Manoeuvring Thrusters Class 2B yes 15000 1+
    Manoeuvring Thrusters Class 2C yes 13000 1+
    Manoeuvring Thrusters Class 2D yes 28000 3+
    Manoeuvring Thrusters Class 2E yes 30000 3+
    Manoeuvring Thrusters Class 2F yes 26000 3+
    Manoeuvring Thrusters Class 3A yes 32000 5+
    Manoeuvring Thrusters Class 3B yes 31000 5+
    Manoeuvring Thrusters Class 3C yes 33000 5+
    Manoeuvring Thrusters Class 3D yes 64000 7+
    Manoeuvring Thrusters Class 3E yes 62000 7+
    Manoeuvring Thrusters Class 3F yes 66000 7+
    Manoeuvring Thrusters Class 4A yes 73000 7+
    Manoeuvring Thrusters Class 4B yes 74500 7+
    Manoeuvring Thrusters Class 4C yes 75800 7+
    Manoeuvring Thrusters Class 4D yes 146000 7+
    Manoeuvring Thrusters Class 4E yes 149000 9+
    Manoeuvring Thrusters Class 4F yes 151600 9+
    Manoeuvring Thrusters Class 5A yes 114000 8+
    Manoeuvring Thrusters Class 5B yes 111000 8+
    Manoeuvring Thrusters Class 5C yes 118000 8+
    Manoeuvring Thrusters Class 5D yes 226000 10+
    Manoeuvring Thrusters Class 5E yes 222000 10+
    Manoeuvring Thrusters Class 5F yes 236000 10+
    Manoeuvring Thrusters Class 6A yes 159000 9+
    Manoeuvring Thrusters Class 6B yes 159200 9+
    Manoeuvring Thrusters Class 6C yes 159300 9+
    Manoeuvring Thrusters Class 6D yes 318000 12+
    Manoeuvring Thrusters Class 6E yes 318400 12+
    Manoeuvring Thrusters Class 6F yes 318600 12+
    Manoeuvring Thrusters Class 7A yes 219000 11+
    Manoeuvring Thrusters Class 7B yes 219200 11+
    Manoeuvring Thrusters Class 7C yes 219300 11+
    Manoeuvring Thrusters Class 7D yes 438000 14+
    Manoeuvring Thrusters Class 7E yes 438400 14+
    Manoeuvring Thrusters Class 7F yes 438600 14+

    Ships

    Name
    Expended Heat Sink

    Models

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

    Scripts

    Path
    Scripts/sc_heatsink.js
    "use strict";
    this.name = "Heatsink Ship Script";
    this.author = "phkb";
    this.copyright = "2016 phkb";
    this.description = "Routines to automate heatsink destruction";
    this.licence = "CC BY-NC-SA 3.0";
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipSpawned = function() {
        this.ship.script._hsTimer = new Timer(this, this.ship.script.$cleanUpHeatSink.bind(this), 5, 0);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$cleanUpHeatSink = function $cleanUpHeatSink() {
    	this.ship.explode();
    }
    
    Scripts/shipconfig_armour.js
    "use strict";
    this.name = "ShipConfiguration_Armour";
    this.author = "phkb";
    this.copyright = "2016 phkb";
    this.description = "Routines for armour control";
    this.licence = "CC BY-NC-SA 3.0";
    
    // Code borrowed heavily from Thargoids "IronHide Armour" OXP and CSotB's "Custom Shields" OXP.
    
    this._debug = false;
    this._override = false; // flag to override the equipment damage routine.
    this._armourList = [];
    this._frontArmourList = [];
    this._aftArmourList = [];
    this._altArmour = null;
    this._holdArmour = {};
    this._simRunning = false;
    
    //-------------------------------------------------------------------------------------------------------------
    this.startUpComplete = function () {
    	if (worldScripts.ShipConfiguration_Core._disabled) {
    		delete this.playerWillSaveGame;
    		delete this.shipLaunchedFromStation;
    		delete this.shipTakingDamage;
    		delete this.equipmentDamaged;
    		delete this.equipmentRemoved;
    		delete this.equipmentAdded;
    		delete this.playerBoughtEquipment;
    		delete this.guiScreenWillChange;
    		delete this.startUpComplete;
    		return;
    	}
    
    	var ps = player.ship.script;
    	ps._frontDamagePoint = 0;
    	ps._frontArmourStrength = 0;
    	ps._armourFront = 0;
    	ps._aftDamagePoint = 0;
    	ps._aftArmourStrength = 0;
    	ps._armourAft = 0;
    
    	if (missionVariables.ShipConfig_ArmourFront) ps._armourFront = missionVariables.ShipConfig_ArmourFront;
    	if (missionVariables.ShipConfig_ArmourAft) ps._armourAft = missionVariables.ShipConfig_ArmourAft;
    	this.$grabLocalData();
    
    	if (worldScripts.ShipRespray) {
    		var sr = worldScripts.ShipRespray;
    		if (sr.$addPreSprayCall) {
    			sr.$addPreSprayCall(this.name, "$preResprayFunction");
    			sr.$addPostSprayCall(this.name, "$postResprayFunction");
    		}
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.playerWillSaveGame = function () {
    	missionVariables.ShipConfig_ArmourFront = player.ship.script._armourFront;
    	missionVariables.ShipConfig_ArmourAft = player.ship.script._armourAft;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipLaunchedFromStation = function (station) {
    	// get the damage percent for any armour we have in place
    	var p = player.ship;
    	var ps = p.script;
    	var sc = worldScripts.ShipConfiguration_Core;
    	if (sc.$simulatorRunning()) {
    		this._simRunning = true;
    		this.$preResprayFunction();
    	}
    
    	ps._frontArmourType = sc.$equipmentItemInUse("frontarmour", p);
    	if (ps._frontArmourType != "") {
    		var info = EquipmentInfo.infoForKey(ps._frontArmourType);
    		ps._frontDamagePoint = info.scriptInfo.damage_point;
    		ps._frontArmourStrength = info.scriptInfo.armour_strength;
    	} else {
    		ps._frontDamagePoint = 0;
    		ps._frontArmourStrength = 0;
    		ps._armourFront = 0;
    	}
    	ps._aftArmourType = sc.$equipmentItemInUse("aftarmour", p);
    	if (ps._aftArmourType != "") {
    		var info = EquipmentInfo.infoForKey(ps._aftArmourType);
    		ps._aftDamagePoint = info.scriptInfo.damage_point;
    		ps._aftArmourStrength = info.scriptInfo.armour_strength;
    	} else {
    		ps._aftDamagePoint = 0;
    		ps._aftArmourStrength = 0;
    		ps._armourAft = 0;
    	}
    	ps.$resetFlag = this.$resetFlag;
    	ps.$damageDirection = this.$damageDirection;
    	ps._frontDamageWarning = false;
    	ps._aftDamageWarning = false;
    	ps._shipDamage = false;
    
    	this.$updateBattleDamage();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipTakingDamage = function (amount, whom, type) {
    
    	// if whom isn't valid, don't do anything
    	if (!whom || whom.isValid === false) return;
    
    	var p = player.ship;
    	var ps = p.script;
    	if (!p || !ps) return;
    	
    	// start a timer to reset the shipDamage flag, so we can know what's damaged from here, and what's scripted from elsewhere
    	if (ps._checkTimer == null || ps._checkTimer.isRunning === false) {
    		if (!ps.$resetFlag) ps.$resetFlag = this.$resetFlag; // need to check this here for combat simulator
    		ps._checkTimer = new Timer(ps, ps.$resetFlag, 1, 0);
    	}
    
    	// don't go any further if we don't have ShipConfig armour installed
    	if (ps._frontArmourType === "" && ps._aftArmourType === "") return;
    
    	ps._shipDamage = true;
    
    	// record where the last damage came from. True = front, false = aft
    	ps._lastDamageDirection = ps.$damageDirection(player.ship, whom);
    	if (ps._lastDamageDirection === true) {
    		ps._lastDamageDirectionArmour = ps._armourFront;
    	} else {
    		ps._lastDamageDirectionArmour = ps._armourAft;
    	}
    	//if (this._debug) log(this.name, type + " " + amount + " hit from " + (this._lastDamageDirection === true ? "front" : "aft") + " " + whom);
    
    	if (amount && amount > 0 && type === "energy damage") { // if we have energy damage
    		var shield = 0;
    		if (ps._lastDamageDirection === true) {
    			shield = ps._frontArmourStrength * (ps._armourFront / 100);
    		} else {
    			shield = ps._aftArmourStrength * (ps._armourAft / 100);
    		}
    
    		//if (this._debug) log(this.name, "amount = " + amount + ", front = " + this._armourFront + ", aft = " + this._armourAft + ", shield = " + shield + ", energy = " + player.ship.energy + ", maxEnergy = " + player.ship.maxEnergy);
    		if (amount < shield && shield > 0) {
    			if ((p.energy + amount) < p.maxEnergy) {
    				p.energy += amount;
    				//if (this._debug) log(this.name, "armour absorbed hit - returning " + amount + " to energy " + player.ship.energy + ", " + amount + ", " + shield);
    			} else {
    				//if (this._debug) log(this.name, "armour absorbed hit - returning to energy to max " + player.ship.energy + ", " + amount + ", " + shield);
    				p.energy = p.maxEnergy;
    			}
    
    			if (ps._lastDamageDirection === true) {
    				ps._armourFront -= Math.floor(100 * (amount / ps._frontArmourStrength));
    				if (ps._armourFront < 100) {
    					player.consoleMessage("Forward armour down to " + ps._armourFront + "%");
    					//if (this._debug) log(this.name, "Forward armour down to " + this._armourFront + "%");
    					if (ps._armourFront < ps._frontDamagePoint && ps._frontDamageWarning === false) {
    						ps._frontDamageWarning = true;
    						player.consoleMessage("Damage point on forward armour reached! Equipment damage may occur!");
    						//if (this._debug) log(this.name, "Damage point on forward armour reached! Equipment damage may occur!");
    					}
    				}
    			} else {
    				ps._armourAft -= Math.floor(100 * (amount / ps._aftArmourStrength));
    				if (ps._armourAft < 100) {
    					player.consoleMessage("Aft armour down to " + ps._armourAft + "%");
    					//if (this._debug) log(this.name, "Aft armour down to " + this._armourAft + "%");
    					if (ps._armourAft < ps._aftDamagePoint && ps._aftDamageWarning === false) {
    						ps._aftDamageWarning = true;
    						player.consoleMessage("Damage point on aft armour reached! Equipment damage may occur!");
    						//if (this._debug) log(this.name, "Damage point on aft armour reached! Equipment damage may occur!");
    					}
    				}
    			}
    		} else {
    			if (shield > 0) p.energy += shield;
    			if (ps._lastDamageDirection === true) {
    				ps._armourFront = 0;
    			} else {
    				ps._armourAft = 0;
    			}
    		}
    	}
    	// check to see if the armour has been completely destroyed
    	if (ps._armourFront <= 0 && p.equipmentStatus(ps._frontArmourType) === "EQUIPMENT_OK") {
    		// if the armour is destroyed by damage
    		p.removeEquipment(ps._frontArmourType);
    		delete worldScripts.ShipConfiguration_Core._current["frontarmour"];
    		player.consoleMessage("Forward armour has been destroyed!", 6);
    	}
    	if (ps._armourAft <= 0 && p.equipmentStatus(ps._aftArmourType) === "EQUIPMENT_OK") {
    		// if the armour is destroyed by damage
    		p.removeEquipment(ps._aftArmourType);
    		delete worldScripts.ShipConfiguration_Core._current["aftarmour"];
    		player.consoleMessage("Aft armour has been destroyed!", 6);
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns true if hit is from the front, otherwise false
    // from CSotB's Custom Shields OXP
    this.$damageDirection = function (ship, whom) {
    
    	if (!ship || ship.isValid === false || !whom || whom.isValid === false) return true;
    
    	var shipSpeedCollisionRadiusAdjustment = (ship.maxSpeed / 350) * 8;
    	//added for shield collision issue caused by using solid models which are needed to work correctly in 1.76, applies to advanced and basic npcs also
    	if (ship.speed > ship.maxSpeed) {
    		var collisionRadiusAdjustment = (ship.speed / ship.maxSpeed) * shipSpeedCollisionRadiusAdjustment;
    	} else {
    		var collisionRadiusAdjustment = 0;
    	}
    
    	var impactRadiusFactor = ((3 * (1500 / (ship.position.distanceTo(whom)))) + 16);
    	var range = whom.position.distanceTo(ship) - (ship.collisionRadius + 1 + collisionRadiusAdjustment);
    	var dist = ship.collisionRadius + collisionRadiusAdjustment + impactRadiusFactor;
    	var impactLocation = whom.position.add(whom.vectorForward.multiply(range)); //determine possible forward weapon hit location
    	//too far from ship because of delay to hit from plasma weapon or off vector angle because of thargoid laser
    	if ((ship.position.distanceTo(impactLocation)) > dist) {
    		impactLocation = whom.position.add(whom.vectorForward.multiply(-(range))); //determine possible aft weapon hit location
    		//too far from ship because of delay to hit from plasma weapon or off vector angle because of thargoid laser
    		if ((ship.position.distanceTo(impactLocation)) > dist) {
    			impactLocation = whom.position.add(whom.vectorRight.multiply(range)); //determine possible starboard weapon hit location
    			//too far from ship because of delay to hit from plasma weapon or off vector angle because of thargoid laser
    			if ((ship.position.distanceTo(impactLocation)) > dist) {
    				impactLocation = whom.position.add(whom.vectorRight.multiply(-(range))); //determine possible port weapon hit location
    				//too far from ship because of delay to hit from plasma weapon or off vector angle because of thargoid laser
    				if ((ship.position.distanceTo(impactLocation)) > dist) {
    					var impactInterpolation = ((ship.collisionRadius + 1 + collisionRadiusAdjustment) / (ship.position.distanceTo(whom)));
    					impactLocation = Vector3D.interpolate(ship.position, whom.position, impactInterpolation); //interpolate weapon hit directly between ship and attacker as a fallback position
    				}
    			}
    		}
    	}
    	var impactdirection = impactLocation.subtract(ship.position).direction();
    	var impactangle = ship.heading.angleTo(impactdirection);
    
    	if (impactangle <= 1.57) {
    		return true;
    	} else {
    		return false;
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.equipmentDamaged = function (equipment) {
    	var p = player.ship;
    	var ps = p.script;
    	if (!p || !ps) return;
    	// as it doesn't make sense for the armour to be inoperable-damaged
    	if (this._armourList && this._armourList.indexOf(equipment) >= 0) {
    		player.ship.setEquipmentStatus(equipment, "EQUIPMENT_OK");
    		return;
    	}
    	// if we're specifically overriding the damage report routine, exit now
    	if (this._override === true) return;
    	// only continue if damage is coming from shipTakingDamage - if not, it's probably a scripted damage which we want to leave alone
    	if (ps._shipDamage === false) return;
    
    	var dp = 0;
    	if (ps._lastDamageDirection === true) {
    		ps._lastDamageDirectionArmour = ps._armourFront;
    		dp = ps._frontDamagePoint;
    		// how much armour do we have left? if there's less than the percentage set for each type of armour there's a chance the damage will stay
    		if (ps._lastDamageDirectionArmour === 0 && ps._armourFront > 95) ps._lastDamageDirectionArmour = 100;
    	} else {
    		ps._lastDamageDirectionArmour = ps._armourAft;
    		dp = ps._aftDamagePoint;
    		// how much armour do we have left? if there's less than the percentage set for each type of armour there's a chance the damage will stay
    		if (ps._lastDamageDirectionArmour === 0 && ps._armourAft > 95) ps._lastDamageDirectionArmour = 100;
    	}
    
    	//if (this._debug) log(this.name, "Equipment damaged: " + equipment);
    	if (ps._lastDamageDirectionArmour <= dp) {
    		// the more damaged the armour is, the more change there is of taking equipment damage
    		//var diff = (this._lastDamageDirectionArmour / (this._damagePoint + (100 - this._lastDamageDirection)));
    		var diff = (ps._lastDamageDirectionArmour / (dp + (dp - ps._lastDamageDirectionArmour)));
    		//if (this._debug) log(this.name, "Armour = " + this._lastDamageDirectionArmour + ", diff = " + diff);
    		// the less armour we have the greater the chance the damage will stay
    		if (Math.random() < diff) {
    			p.setEquipmentStatus(equipment, "EQUIPMENT_OK");
    			//if (this._debug) log(this.name, "Armour took hit instead - equipment repaired")
    		}
    	} else {
    		// if we still have armour above the damage point, equipment shouldn't get damaged
    		p.setEquipmentStatus(equipment, "EQUIPMENT_OK");
    		//if (this._debug) log(this.name, "Armour still OK - equipment repaired");
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.equipmentRemoved = function (equipment) {
    	if (this._frontArmourList && this._frontArmourList.indexOf(equipment) >= 0 && player.ship.isInSpace === false) {
    		var ps = player.ship.script;
    		ps._frontArmourType = "";
    		ps._armourFront = 0;
    		this.$updateManifest();
    	}
    	if (this._aftArmourList && this._aftArmourList.indexOf(equipment) >= 0 && player.ship.isInSpace === false) {
    		var ps = player.ship.script;
    		ps._aftArmourType = "";
    		ps._armourAft = 0;
    		this.$updateManifest();
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.equipmentAdded = function (equipment) {
    	if (this._frontArmourList && this._frontArmourList.indexOf(equipment) >= 0 && player.ship.isInSpace === false) {
    		var ps = player.ship.script;
    		ps._armourFront = 100;
    		ps._frontArmourType = equipment;
    	}
    	if (this._aftArmourList && this._aftArmourList.indexOf(equipment) >= 0 && player.ship.isInSpace === false) {
    		var ps = player.ship.script;
    		ps._armourAft = 100;
    		ps._aftArmourType = equipment;
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.playerBoughtEquipment = function (equipment) {
    	var p = player.ship;
    	var ps = p.script;
    	this.$grabLocalData();
    	// if the player installs some alternative armour, remove our one (if installed), so as to not double up
    	if (this._altArmour.indexOf(equipment) >= 0) {
    		if (ps._frontArmourType != "") {
    			// refund the cost 
    			var info = EquipmentInfo.infoForKey(ps._frontArmourType);
    			var dam = p.equipmentStatus(ps._frontArmourType);
    			var refund = (info.price / 10) * worldScripts.ShipConfiguration_Core._refundPct; //stn.equipmentPriceFactor;
    			if (dam === "EQUIPMENT_DAMAGED") refund *= 0.5;
    			player.credits += refund;
    
    			p.removeEquipment(ps._frontArmourType);
    		}
    		if (ps._aftArmourType != "") {
    			// refund the cost 
    			var info = EquipmentInfo.infoForKey(ps._aftArmourType);
    			var dam = p.equipmentStatus(ps._aftArmourType);
    			var refund = (info.price / 10) * worldScripts.ShipConfiguration_Core._refundPct; //stn.equipmentPriceFactor;
    			if (dam === "EQUIPMENT_DAMAGED") refund *= 0.5;
    			player.credits += refund;
    
    			p.removeEquipment(ps._aftArmourType);
    		}
    	}
    	// check for repair to armour
    	if (equipment.indexOf("_REPAIR") >= 0) {
    		// repair the armour
    		if (equipment.indexOf(ps._frontArmourType) >= 0 && ps._armourFront < 100) {
    			p.removeEquipment(equipment);
    			ps._armourFront = 100;
    		}
    		if (equipment.indexOf(ps._aftArmourType) >= 0 && ps._armourAft < 100) {
    			p.removeEquipment(equipment);
    			ps._armourAft = 100;
    		}
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.guiScreenWillChange = function (to, from) {
    	if (to === "GUI_SCREEN_MANIFEST") {
    		this.$updateManifest();
    	}
    	if (to === "GUI_SCREEN_STATUS" && this._simRunning === true) {
    		this._simRunning = false;
    		this.$postResprayFunction();
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$updateManifest = function $updateManifest() {
    	var ps = player.ship.script;
    	var eqtype_fr = worldScripts.ShipConfiguration_Core.$equipmentItemInUse("frontarmour", player.ship);
    	var eqtype_af = worldScripts.ShipConfiguration_Core.$equipmentItemInUse("aftarmour", player.ship);
    	if (player.ship.equipmentStatus(eqtype_fr) === "EQUIPMENT_OK" || player.ship.equipmentStatus(eqtype_af) === "EQUIPMENT_OK") {
    		var sep = ", ";
    		var front_type = "Class " + (this._frontArmourList.indexOf(eqtype_fr) + 1) + " Forward Armour";
    		var front_desc = " Strength: ";
    		var front_val = ps._armourFront + "%%";
    		if (eqtype_fr === "") {
    			front_type = "";
    			front_desc = "";
    			front_val = "";
    			sep = "";
    		}
    		var aft_type = "Class " + (this._aftArmourList.indexOf(eqtype_af) + 1) + " Aft Armour";
    		var aft_desc = " Strength: ";
    		var aft_val = ps._armourAft + "%%";
    		if (eqtype_af === "") {
    			aft_type = "";
    			aft_desc = "";
    			aft_val = "";
    			sep = "";
    		}
    		mission.setInstructions(expandDescription("[armour_manifest]", {
    			front_armour_type: front_type,
    			front_armour_desc: front_desc,
    			armour_front: front_val,
    			armour_sep: sep,
    			aft_armour_type: aft_type,
    			aft_armour_desc: aft_desc,
    			armour_aft: aft_val
    		}), this.name);
    	} else {
    		mission.setInstructions(null, this.name);
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$resetFlag = function $resetFlag() {
    	if (player.ship && player.ship.script) {
    		delete player.ship.script._checkTimer;
    		player.ship.script._shipDamage = false;
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // if "BattleDamage" is installed, we want to update the shipTakingDamage routine to take into consideration how much armour we have left
    // so we'll patch BattleDamage to add the extra logic
    this.$updateBattleDamage = function $updateBattleDamage() {
    	if (worldScripts["Battle Damage"]) {
    		var bd = worldScripts["Battle Damage"];
    		delete bd.shipTakingDamage;
    		//bd.$sc_shipTakingDamage = bg.shipTakingDamage;
    		bd.shipTakingDamage = this.$newBD_shipTakingDamage;
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // New "shipTakingDamage" routine for BattleDamage
    this.$newBD_shipTakingDamage = function $newBD_shipTakingDamage(amount, whom, type) {
    	if (amount === 0) return;
    	else if (missionVariables.BattleDamage_status === "DAMAGED") {
    		player.consoleMessage("Hull taking further damage.", 1);
    	} else {
    		var skip = false;
    		var ps = player.ship.script;
    		if (ps && ps._lastDamageDirectionArmour > 0) {
    			if (ps._lastDamageDirectionArmour < ps._damagePoint) {
    				// the less armour we have the greater the chance the damage will stay
    				if (Math.random() < (ps._lastDamageDirectionArmour / ps._damagePoint)) skip = true;
    			} else {
    				skip = true;
    			}
    		}
    		if (skip === false) {
    			player.ship.removeEquipment("EQ_HULL_REPAIR"); //remove 'repair' to allow 'repair' to be applied again. This should happen before any risk of damage to 'repair'
    			missionVariables.BattleDamage_status = "DAMAGED"; // set to damaged
    			player.consoleMessage("WARNING! HULL DAMAGE", 6);
    		}
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$preResprayFunction = function $preResprayFunction() {
    	this._holdArmour["front"] = player.ship.script._armourFront;
    	this._holdArmour["aft"] = player.ship.script._armourAft;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$postResprayFunction = function $postResprayFunction() {
    	player.ship.script._armourFront = this._holdArmour["front"];
    	player.ship.script._armourAft = this._holdArmour["aft"];
    	this._holdArmour = {};
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$grabLocalData = function $grabLocalData() {
    	var sc = worldScripts.ShipConfiguration_Core;
    	var ps = player.ship.script;
    	ps._frontArmourType = sc.$equipmentItemInUse("frontarmour", player.ship);
    	if (ps._frontArmourType != "") {
    		var info = EquipmentInfo.infoForKey(ps._frontArmourType);
    		ps._frontDamagePoint = info.scriptInfo.damage_point;
    		ps._frontArmourStrength = info.scriptInfo.armour_strength;
    	}
    	ps._aftArmourType = sc.$equipmentItemInUse("aftarmour", player.ship);
    	if (ps._aftArmourType != "") {
    		var info = EquipmentInfo.infoForKey(ps._aftArmourType);
    		ps._aftDamagePoint = info.scriptInfo.damage_point;
    		ps._aftArmourStrength = info.scriptInfo.armour_strength;
    	}
    
    	// grab a local reference to the armour arrays, so we don't have to keep two lists, but don't need to keep references to the other module
    	this._armourList = sc._armour;
    	this._frontArmourList = sc._frontarmour;
    	this._aftArmourList = sc._aftarmour;
    	this._altArmour = sc._altArmour;
    }
    Scripts/shipconfig_boosterheat.js
    "use strict";
    this.name = "ShipConfiguration_BoosterHeat";
    this.author = "phkb";
    this.copyright = "2016 phkb";
    this.description = "Process of adding cabin heat at certain throttle levels when boosters are installed";
    this.licence = "CC BY-NC-SA 3.0";
    
    this._boostHeatDelta = 0.93;
    this._fcbBoost = 0;
    
    //-------------------------------------------------------------------------------------------------------------
    this.startUpComplete = function () {
    	if (worldScripts.ShipConfiguration_Core._disabled) {
    		delete this.shipLaunchedFromStation;
    		delete this.shipWillDockWithStation;
    		delete this.shipDied;
    		delete this.startUpComplete;
    		return;
    	}
    	player.ship.script._boosterHeatEnabled = false;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipLaunchedFromStation = function (station) {
    	var p = player.ship;
    	if (p.script._boosterHeatPoint != 0) {
    		p.script._boosterHeatEnabled = false;
    		p.script._boosterHeatDelta = this._boostHeatDelta;
    		if (this._fcbBoost === 0) {
    			// set up our frame callback
    			this._fcbBoost = addFrameCallback(function (delta) {
    				if (delta === 0) return;
    				var p = player.ship;
    				var ps = p.script;
    				if (!ps) return; // probably player has died.
    				if (ps._boosterHeatPoint === 0) {
    					if (ps._boosterHeatEnabled === true) {
    						ps._boosterHeatEnabled = false;
    						ps.thirdPartyHeat -= ps._boosterHeatDelta;
    						if (ps.thirdPartyHeat < 0) ps.thirdPartyHeat = 0;
    					}
    					return;
    				}
    				// only apply the heat element if the ship speed is under the max speed value (ie not while injectors or torus drive are in use)
    				var disable = false;
    				if (p.speed <= p.maxSpeed) {
    					// what is the percentage of speed
    					if ((p.speed / p.maxSpeed) > ps._boosterHeatPoint) {
    						if (ps._boosterHeatEnabled === true) {
    							// just return if booster heat is already on
    							return;
    						} else {
    							// turn on booster heat
    							ps._boosterHeatEnabled = true;
    							ps.thirdPartyHeat += ps._boosterHeatDelta;
    							player.consoleMessage("Heat now being generated by boosters.", 2);
    							worldScripts.ShipConfiguration_Core.$playSound("booster_warning");
    						}
    					} else {
    						// disable if the ship is going less than the booster heat point
    						disable = true;
    					}
    				} else {
    					// disable booster heat if the ship is going faster than their max speed (injectors or torus)
    					disable = true;
    				}
    				if (disable === true) {
    					if (ps._boosterHeatEnabled === true) {
    						ps._boosterHeatEnabled = false;
    						ps.thirdPartyHeat -= ps._boosterHeatDelta;
    						if (ps.thirdPartyHeat < 0) ps.thirdPartyHeat = 0;
    					}
    				}
    			});
    		}
    	} else {
    		// in case the booster gets damaged while heat is enabled
    		if (p.script._boosterHeatEnabled === true) {
    			p.script._boosterHeatEnabled = false;
    			p.script.thirdPartyHeat -= p.script._boosterHeatDelta;
    		}
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipWillDockWithStation = function (station) {
    	this.$stopTimers();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipDied = function (whom, why) {
    	this.$stopTimers();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$stopTimers = function $stopTimers() {
    	if (this._fcbBoost != 0) {
    		if (isValidFrameCallback(this._fcbBoost)) removeFrameCallback(this._fcbBoost);
    		this._fcbBoost = 0;
    	}
    }
    Scripts/shipconfig_conditions.js
    "use strict";
    this.name = "ShipConfiguration_Conditions";
    this.author = "phkb";
    this.copyright = "2016 phkb";
    this.description = "Condition script for equipment.";
    this.license = "CC BY-NC-SA 3.0";
    
    //-------------------------------------------------------------------------------------------------------------
    this.allowAwardEquipment = function (equipment, ship, context) {
    
    	if (context === "scripted") return true;
    	if (context === "npc") return true;
    	if (equipment.indexOf("EQ_EQUIPSPACE") >= 0) return false;
    
    	// is this item damaged?
    	var p = player.ship;
    	if (p.equipmentStatus(equipment) === "EQUIPMENT_DAMAGED") {
    		// return true so that the "Repair" item is displayed.
    		return true;
    	}
    
    	if (equipment === "EQ_HEAT_SINK_CONTROL" || equipment === "EQ_HEAT_SINK_CONTROL_PASSIVE") return false;
    
    	var sc = worldScripts.ShipConfiguration_Core;
    
    	if (sc._disabled) return false;
    
    	if (equipment === "EQ_HEAT_SINK") {
    		if (sc._heatControl === false) {
    			return false;
    		} else {
    			return true;
    		}
    	}
    
    	if (equipment === "EQ_SHIPCONFIG" && sc._disabled === false) return true;
    
    	// check for damaged equipment items
    	if (equipment.indexOf("EQ_ARMOUR_FORWARD") >= 0 && equipment.indexOf("_REPAIR") >= 0) {
    		var result = false;
    		if (p.script._armourFront < 100) {
    			if (equipment === sc.$equipmentItemInUse("frontarmour", p) + "_REPAIR") result = true;
    		}
    		return result;
    	}
    	if (equipment.indexOf("EQ_ARMOUR_AFT") >= 0 && equipment.indexOf("_REPAIR") >= 0) {
    		var result = false;
    		if (p.script._armourAft < 100) {
    			if (equipment === sc.$equipmentItemInUse("aftarmour", p) + "_REPAIR") result = true;
    		}
    		return result;
    	}
    
    	if (equipment.indexOf("EQ_EXTENSION") >= 0) {
    		// small ships can't get 5t extension
    		var mss = sc.$getShipMass(ship);
    		if (EquipmentInfo.infoForKey(equipment).scriptInfo.equipment_extension >= 5 && mss < 50000) return false
    		// large ships can't get any
    		if (mss > 400000) return false
    		// maximum of 2 extensions can be installed at the same time
    		var count = this.$countExtensionsInShip(ship);
    		if (count === 2) return false;
    		return true;
    	}
    
    	if (context === "purchase") return false;
    
    	return true;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.updateEquipmentPrice = function (equipment, price) {
    	var sc = worldScripts.ShipConfiguration_Core;
    	var p = player.ship;
    	var newprice = price;
    	if (equipment.indexOf("EQ_ARMOUR_FORWARD") >= 0 && equipment.indexOf("_REPAIR") >= 0) {
    		var amt = p.script._armourFront;
    		// calculate percentage of damage
    		var cur = Math.floor((100 - amt) / 10);
    		// get the pricing factor for our ship
    		var priceFactor = sc.$equipmentPriceFactor(p.shipClassName, sc.$getShipMass(p));
    		// apply the price factor to the percentage of repair, to get a more realistic price
    		// otherwise, a repair bill could be way more expensive than a new installation.
    		cur = parseInt(cur * priceFactor);
    		if (cur > 9) cur = 9;
    		if (p.script._armourFront < 100 && cur === 0) cur = 1;
    		newprice = price * cur;
    	}
    	if (equipment.indexOf("EQ_ARMOUR_AFT") >= 0 && equipment.indexOf("_REPAIR") >= 0) {
    		var amt = p.script._armourAft;
    		// calculate percentage of damage
    		var cur = Math.floor((100 - amt) / 10);
    		// get the pricing factor for our ship
    		var priceFactor = sc.$equipmentPriceFactor(p.shipClassName, sc.$getShipMass(p));
    		// apply the price factor to the percentage of repair, to get a more realistic price
    		// otherwise, a repair bill could be way more expensive than a new installation.
    		cur = parseInt(cur * priceFactor);
    		if (cur > 9) cur = 9;
    		if (p.script._armourAft < 100 && cur === 0) cur = 1;
    		newprice = price * cur;
    	}
    	return newprice;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // counts the number of equipment extensions current installed
    this.$countExtensionsInShip = function $countExtensionsInShip(ship) {
    	var eq = ship.equipment;
    	var count = 0;
    	for (var i = 0; i < eq.length; i++) {
    		if (eq[i].equipmentKey.indexOf("EQ_EXTENSION") >= 0) count += 1;
    	}
    	return count;
    }
    Scripts/shipconfig_core.js
    "use strict";
    this.name = "ShipConfiguration_Core";
    this.author = "phkb";
    this.copyright = "2016 phkb";
    this.description = "Core routines for ShipConfiguration.";
    this.licence = "CC BY-NC-SA 3.0";
    
    /*
    	This OXP adds the concept of equipment space and weight: equipment space is limited, meaning you can't install everything at once, and having a lot of equipment installed will
    	change the performance stats of the ship.
    
    	Please read the "readme.txt" file - there's a lot of important info in there that's worth reading in order to make the most of this OXP.
    
    	Borrows code from Capt Murphy's Breakable Energy Unit OXP, Breakable Engines OXP, Breakable Shield Generators OXP, and Breakable Witchdrive OXP
    	Because of this, those OXP's are incompatible with this one, and the manifest has the incompatibilities flagged.
    
    	TODO:
    	- work out how to calculate and display ship heat profile (ie what units will generate heat with use and how much, and what units will increase cabin temp and how much)
    
    */
    
    this._disabled = false; // quick way to disable entire OXP
    this._debug = false; // turns on/off logging messages
    this._disableBoosterSound = false; // turns on/off the warning sound when boosters start generating heat
    this._disableF3HUD = false; // turns on/off the specialised F3 HUD (showing equipment & cargo space allocations)
    this._heatControl = true; // indicates that the heat transfer system is in use (ie laser temp adds to cabin temp, inclusion of heat sinks etc)
    this._installationTime = true; // flag that controls whether changing ship config also takes time
    this._freeUpgrades = false; // flag to make all upgrades free (yay!) for testing period only (boo!)
    this._refundPct = 0.85; // value between 0 and 1 that indicates how much refund you get on equipment sold. 0 = no refund, 1 = refund full original price
    this._weightFactor = 2; // increase to make ship weight have less weight (!) when doing adjustment calculations
    this._applyToNPC = true; // flag to indicate whether NPC ships will have same weight performance calculations applied to their ships
    this._shipModel = true; // flag to turn on player ship model on configuration screens.
    
    this._busOverloadLimit = 20; // at what point the electrical bus overloads (counter value trigger)
    this._shipRespray = false; // indicates that the Ship Respray OXP is installed
    this._resprayActive = false; // indicates that a respray is happening right now
    this._holdEquipSpace = "";
    this._torusSync = false; // indicates that the Synchronised Torus OXP is installed
    this._menuColor = "orangeColor"; // color of general menu items
    this._itemColor = "yellowColor"; // color of special menu items (eg exit menu items)
    this._installedColor = "greenColor"; // color of installed equipment items
    this._damagedColor = "redColor"; // color of damaged equipment items
    this._disabledColor = "darkGrayColor"; // color of disabled equipment items
    this._riskColor = "0.8 0.8 0.8 1"; // color of risky equipment items (items installed over the recommended power coupling/bus level)
    this._defaultHeatShieldHSFactor = 1.7; // default heat sink factor if no heat shield installed
    this._configScreen = false; // flag to indicate the config screen is active
    this._simulator = false; // holding variable to work out whether this launch/dock routine was part of a simulator run
    this._OXPHyperdrives = false; // indicates the Hyperdrives OXP is installed
    this._hyperHangar = false; // indicates the Hyperspace Hangar OXP is installed
    this._hyperHangarActive = false; // indicates that Hyperspace Hangar is active
    this._hyperHangarTimer = null; // timer to update hyperhangar's stored ship image
    
    this._current = {}; // dictionary of current list of installed options
    this._startUp = true; // flag to indicate startup procedures are underway
    this._initialSetup = false; // flag to indicate that initial equipment setup is necessary
    this._promptPlayer = false; // flag to indicate that the player needs to be prompted about equipment (overload)
    this._page = 0; // current page of the active display
    this._display = 0; // indicates which display is being shown
    this._source = ""; // source location string, set when various mission screens are shown and used by the choice handler to determine what screen to return to
    this._adding = false; // flag to indicate that the "equipmentAdded" routine is underway, in order to prevent endless loops
    this._removing = false; // flag to indicate that the "equipmentRemoved" routine is underway, in order to prevent endless loops
    this._damaging = false; // flag to indicate that the "equipmentDamaged" routine is underway, in order to prevent endless loops
    this._repairing = false; // flag to indicate that the "equipmentRepaired" routine is underway, in order to prevent endless loops
    this._sellEquipExitScreen = "GUI_SCREEN_STATUS"; // which screen sell equipment mission screen will exit to
    this._counter = 0; // counter used in the energy depletion routine
    this._busOverload = 0; // calculated value that indicates the players chance of receiving a bus overload
    this._busOverloadCounter = 0; // counter used in the bus overload routine. Counts number of times damage received, events triggered when
    this._busMessageCounter = 0; // counter used in the bus overload routine
    this._busOverloadResetTimer = null;
    this._busProcessing = false;
    this._energyRechargeRate_Stored = 0; // stored value of the energy recharge rate
    this._forwardShieldRechargeRate_Stored = 0; // stored value of the forward shield recharge rate
    this._aftRechargeRate_Stored = 0; // stored value of the aft shield recharge rate
    this._lastChoice = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""]; // players last selection on each mission screen
    this._trueValues = ["yes", "1", 1, "true", true];
    this._currEquip = [];
    this._callbacks = [];
    
    // configuration settings for use in Lib_Config
    this._scConfig = {
    	Name: this.name,
    	Alias: "Ship Configuration",
    	Display: "Config",
    	Alive: "_scConfig",
    	Bool: {
    		B0: {
    			Name: "_disableBoosterSound",
    			Def: false,
    			Desc: "Disable booster sound"
    		},
    		B1: {
    			Name: "_disableF3HUD",
    			Def: false,
    			Desc: "Disable special F3 HUD"
    		},
    		B2: {
    			Name: "_installationTime",
    			Def: true,
    			Desc: "Equipment install time"
    		},
    		B3: {
    			Name: "_freeUpgrades",
    			Def: false,
    			Desc: "Free upgrades"
    		},
    		B4: {
    			Name: "_applyToNPC",
    			Def: true,
    			Desc: "Apply to NPC ships"
    		},
    		Info: "0 - Disables the warning sound when boosters in use.\n1 - Disables specialised F3 HUD (displays equip space info)\n2 - Installing equipment uses game time.\n3 - All upgrades are free.\n4 - Indicates if NPC ships will have restrictions applied."
    	}
    };
    
    // for when the calculations need manual tweaking...
    this._shipSpaceExceptions = {
    	"Asp Mark II": 30, // ex-military design, so more equipment space available to make up for no cargo space.
    	"Asp Mark II Special": 35,
    	"Boa Class Cruiser": 35,
    	"Boa": 30,
    	"Cobra Mark III-XT": 23,
    	"Constrictor": 30,
    	"Fer-de-Lance": 20,
    	"GalCop Viper Interceptor": 25,
    	"GalCop Viper": 20,
    	"Night Adder": 20,
    	"Yasen-N 'Advanced'": 30,
    };
    
    // provides consistency for ship mass calculations
    // really only applies to ships that have multiple installation variations, where the mass value might return a slightly different number
    this._shipMassExceptions = {
    	"Cobra Mark III": 214737.6875,
    };
    
    // higher numbers mean equipment weight will have less impact on ship performance (better power to weight ratio)
    this._shipPowerToWeight = {
    	"Boa Class Cruiser": 0.8,
    	"Boa": 0.7,
    	"Cobra Mark III": 1.5,
    	"Constrictor": 8,
    	"Fer-de-Lance": 1.5,
    	"Mining Transporter": 3,
    	"Orbital Shuttle": 3,
    	"Pitviper Mark II": 1,
    	"Pitviper": 1,
    	"Transporter": 3,
    };
    
    // not in use atm
    this._shipHeatRateExceptions = {
    	"Boa": 0.97,
    	"Boa Class Cruiser": 0.94,
    };
    
    // default zoom is 3.6 - higher values mean smaller view, lower values mean bigger view
    // these values make ships look bigger or smaller, as appropriate
    this._zoomOverride = {
    	"Adder": 4.6,
    	"Anaconda": 2.3,
    	"Anaconda MMS": 2.3,
    	"Aphid": 3.2,
    	"Arafura": 3,
    	"Boa Class Cruiser": 2.5,
    	"Boa Class Cruiser MMS": 2.5,
    	"Boa": 2.5,
    	"Boa MMS": 2.5,
    	"Bug": 4.4,
    	"Chameleon": 3.3,
    	"Chopped Cobra": 3,
    	"Cobra Mark I": 4.6,
    	"Cobra Mark II-X": 4,
    	"Cobra Mark III": 3,
    	"Cobra Mark III MMS": 3,
    	"Cobra Mark III-XT": 3,
    	"Cobra Mark IV": 2.9,
    	"Cobra Mark IV MMS": 2.9,
    	"Cobra Rapier": 3,
    	"Copperhead Mk2": 3,
    	"Cruzer": 3,
    	"D.T.T. Atlas": 2.5,
    	"D.T.T. Cyclops": 2.5,
    	"D.T.T. Kraken": 2.8,
    	"D.T.T. MK-1": 3.4,
    	"D.T.T. Snake Charmer": 2.7,
    	"D.T.T. War Lance": 3.3,
    	"Fer-de-Lance": 3.3,
    	"Gecko": 4.2,
    	"Griffin Mk I": 3.3,
    	"Griff Boa Prototype": 2.5,
    	"Hognose": 4.3,
    	"Iguana": 3.2,
    	"Krait": 4.2,
    	"Lira": 1.9,
    	"Mamba Escort": 4.2,
    	"Mamba": 4.2,
    	"Miner Cobra Mark III": 3,
    	"Mining Transporter": 4.6,
    	"Monitor Mark II": 3,
    	"Monitor": 3,
    	"Moray Medical Boat": 4.2,
    	"Moray Star Boat": 4.2,
    	"Mussurana": 3,
    	"Night Adder": 4.2,
    	"Ophidian": 3,
    	"Orbital Shuttle": 4.6,
    	"Pitviper": 3.4,
    	"Pitviper (Vindicator)": 3.4,
    	"Pitviper (Buccaneer)": 3.4,
    	"Pitviper (Bountyhunter)": 3.4,
    	"Pitviper S.E. Beast": 3.4,
    	"Pitviper Mark II": 3,
    	"Python Class Cruiser": 2.5,
    	"Python ET Special": 2.6,
    	"Python ET Special MMS": 2.6,
    	"Python": 2.5,
    	"Python MMS": 2.5,
    	"Python SG": 2.5,
    	"Python SG-MMS": 2.5,
    	"Python BattleCruiser MMS": 2.5,
    	"Serpent Class Cruiser": 2.5,
    	"Sidewinder Scout Ship": 4.5,
    	"Sidewinder Special": 4.3,
    	"Skat": 3.4,
    	"Taxi Cab": 4.6,
    	"Tembo": 2.2,
    	"Transporter": 4.6,
    	"Worm": 4.6,
    	"Yasen-N": 3.2,
    	"Yasen-N 'Advanced' variant 1": 3.2,
    	"Yasen-N 'Advanced' variant 2": 3.2,
    	"Yasen-N 'Advanced' variant 3": 3.2,
    	"YellOo Cab": 4.4,
    };
    
    // dictionary of npc equivalent roles for translation purposes
    this._NPCEquivalents = {
    	"ftzpirate": "pirate",
    	"ftzhauler": "trader",
    	"jaguar_company_patrol": "hunter-medium",
    	"jaguar_company_ship_splinter": "hunter",
    	"jaguar_company_tug": "shuttle",
    	"jaguar_company_miner": "miner",
    	"bigTrader": "trader",
    	"trident": "shuttle",
    	"strelka": "trader",
    	"random_hits_big_boss_fighter": "pirate",
    	"random_hits_big_boss": "pirate-heavy-fighter",
    	"random_hits_patrol": "hunter-medium",
    	"random_hits_mining_hopper": "miner",
    	"blackmonk_gunship": "hunter-heavy",
    	"clipper-rescueship": "trader",
    	"dredgershuttle_up": "shuttle",
    	"dredgershuttle": "shuttle",
    	"wildShips_tanker": "trader",
    	"defense_ship": "police",
    	"ups_shuttle": "shuttle",
    	"ups-sun-police": "police",
    	"rrs-escort": "escort",
    	"anarchies_salvager_tugger": "scavenger",
    	"con-a-hauler": "trader",
    	"con-a-haulret": "trader",
    	"con-b-hauler": "trader",
    	"con-b-haulret": "trader",
    	"con-c-hauler": "trader",
    	"con-c-haulret": "trader",
    	"con-d-hauler": "trader",
    	"con-d-haulret": "trader",
    	"con-e-hauler": "trader",
    	"con-e-haulret": "trader",
    	"con-f-hauler": "trader",
    	"con-f-haulret": "trader",
    	"con-g-hauler": "trader",
    	"con-g-haulret": "trader",
    	"starsecurity": "escort",
    	"pi42security": "escort",
    	"tescoosecurity": "escort",
    	"mallwartsecurity": "escort",
    	"gmartsecurity": "escort",
    	"sainsboorysecurity": "escort",
    	"oodlessecurity": "escort",
    };
    
    /*
    	NPC configuration item definition:
    		{primaryRole:"", minSpace:X, maxSpace:Y, equipmentList:[]}
    				primaryRole     role to which this definition applies (eg "assassin-light")
    				minSpace		equipment space of ship must be greater than or equal to this value
    				maxSpace		equipment space of ship must be less than or equal to this value
    				equipmentlist   array of equipment areas with a number that indicates how far over default to go
    								can be a generic name or a specific equipment item
    								generic names: engines, thrusters, energy, frontshields, aftdhields, heatshields, fuelinjectors, fuelscoops
    								specific name example: EQ_ENGINE_TYPE3C, EQ_THRUSTERS_TYPE3B
    
    	eg 	{primaryRole:"assassin-light", minSpace:0, maxSpace:20, equipmentList:["engines:1", "thrusters:2", "energy:2", "EQ_HEAT_SHIELD_TYPE4"],
    		this would translate as:
    			for assassin-light roles, where the equipment space is between 0 and 20, put engines 1 over default, thrusters 2 over default, energy banks 2 over default, and give the ship type 4 heat shields.
    
    	ships not conforming to items in this list will receive default equipment
    	Please note: these values are open for discussion! Please let me know if you think some other settings would be more appropriate.
    */
    this._NPCConfig = [{
    		primaryRole: "assassin-light",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["EQ_ENGINE_TYPE3C", "EQ_THRUSTERS_TYPE3A", "EQ_ELEC_BUS_TYPE3", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:1"]
    	}, // Krait
    	{
    		primaryRole: "assassin-light",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_THRUSTERS_TYPE4A", "EQ_ELEC_BUS_TYPE4", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:2"]
    	}, // Cobra I, Moray Starboat
    	{
    		primaryRole: "assassin-light",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE5B", "EQ_THRUSTERS_TYPE5A", "EQ_ELEC_BUS_TYPE5", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:3"]
    	}, //
    	{
    		primaryRole: "assassin-medium",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["EQ_ENGINE_TYPE3C", "EQ_THRUSTERS_TYPE3A", "EQ_ELEC_BUS_TYPE3", "EQ_FUEL_INJECTION_TYPE2", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:1"]
    	}, //
    	{
    		primaryRole: "assassin-medium",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_THRUSTERS_TYPE4A", "EQ_ELEC_BUS_TYPE4", "EQ_FUEL_INJECTION_TYPE3", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:2"]
    	}, // Fer-de-Lance
    	{
    		primaryRole: "assassin-medium",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE5B", "EQ_THRUSTERS_TYPE5A", "EQ_ELEC_BUS_TYPE5", "EQ_FUEL_INJECTION_TYPE3", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:2"]
    	}, // Cobra III (no cargo extension)
    	{
    		primaryRole: "assassin-medium",
    		minSpace: 41,
    		maxSpace: 50,
    		equipmentList: ["EQ_ENGINE_TYPE6B", "EQ_THRUSTERS_TYPE6A", "EQ_ELEC_BUS_TYPE6", "EQ_FUEL_INJECTION_TYPE4", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:2"]
    	}, // Cobra III
    	{
    		primaryRole: "assassin-heavy",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_THRUSTERS_TYPE4A", "heatsinks:1"]
    	},
    	{
    		primaryRole: "assassin-heavy",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE5B", "EQ_THRUSTERS_TYPE5A", "energy:2", "EQ_ELEC_BUS_TYPE5", "EQ_FUEL_INJECTION_TYPE2", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:2"]
    	}, // Asp Mark II
    	{
    		primaryRole: "assassin-heavy",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE6B", "EQ_THRUSTERS_TYPE6A", "energy:2", "EQ_ELEC_BUS_TYPE6", "EQ_FUEL_INJECTION_TYPE3", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:3"]
    	}, //
    	{
    		primaryRole: "assassin-heavy",
    		minSpace: 41,
    		maxSpace: 60,
    		equipmentList: ["EQ_ENGINE_TYPE6B", "EQ_THRUSTERS_TYPE6A", "energy:4", "EQ_ELEC_BUS_TYPE6", "EQ_FUEL_INJECTION_TYPE4", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:4"]
    	}, //
    	{
    		primaryRole: "assassin-heavy",
    		minSpace: 61,
    		maxSpace: 80,
    		equipmentList: ["EQ_ENGINE_TYPE7B", "EQ_THRUSTERS_TYPE7A", "energy:4", "EQ_ELEC_BUS_TYPE7", "EQ_FUEL_INJECTION_TYPE4", "EQ_HEAT_SHIELD_TYPE4", "heatsinks:4"]
    	},
    	{
    		primaryRole: "hunter",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ELEC_BUS_TYPE3", "HEAT_SHIELD_TYPE4", "heatsinks:1"]
    	}, // gecko, krait, mamba, sidewinder
    	{
    		primaryRole: "hunter",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ELEC_BUS_TYPE3", "energy:1", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE4", "heatsinks:2"]
    	}, //
    	{
    		primaryRole: "hunter",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ELEC_BUS_TYPE3", "energy:2", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE4", "heatsinks:3"]
    	}, //
    	{
    		primaryRole: "hunter-medium",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ELEC_BUS_TYPE3", "energy:1", "HEAT_SHIELD_TYPE4", "heatsinks:1"]
    	}, //
    	{
    		primaryRole: "hunter-medium",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_ELEC_BUS_TYPE4", "energy:2", "HEAT_SHIELD_TYPE4", "heatsinks:2"]
    	}, // asp mark II, cobra I, fer-de-lance, moray starboat
    	{
    		primaryRole: "hunter-medium",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE5B", "EQ_ELEC_BUS_TYPE5", "energy:2", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE4", "heatsinks:3"]
    	}, // cobra III (std model)
    	{
    		primaryRole: "hunter-medium",
    		minSpace: 41,
    		maxSpace: 80,
    		equipmentList: ["EQ_ENGINE_TYPE6B", "EQ_ELEC_BUS_TYPE6", "energy:3", "frontshields:2", "aftshields:2", "HEAT_SHIELD_TYPE4", "heatsinks:3"]
    	}, // cobra III (+ extra cargo)
    	{
    		primaryRole: "hunter-heavy",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ELEC_BUS_TYPE3", "HEAT_SHIELD_TYPE4", "heatsinks:1"]
    	}, //
    	{
    		primaryRole: "hunter-heavy",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_ELEC_BUS_TYPE4", "HEAT_SHIELD_TYPE4", "heatsinks:2"]
    	}, // asp mark II, fer-de-lance
    	{
    		primaryRole: "hunter-heavy",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE5B", "EQ_ELEC_BUS_TYPE5", "energy:1", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE4", "heatsinks:3"]
    	}, // cobra III (std model)
    	{
    		primaryRole: "hunter-heavy",
    		minSpace: 41,
    		maxSpace: 50,
    		equipmentList: ["EQ_ENGINE_TYPE6B", "EQ_ELEC_BUS_TYPE6", "energy:1", "frontshields:2", "aftshields:2", "EQ_FUEL_INJECTION_TYPE4", "HEAT_SHIELD_TYPE4", "heatsinks:4"]
    	}, // cobra III (+ extra cargo)
    	{
    		primaryRole: "hunter-heavy",
    		minSpace: 51,
    		maxSpace: 80,
    		equipmentList: ["EQ_ENGINE_TYPE6B", "EQ_ELEC_BUS_TYPE6", "energy:2", "frontshields:2", "aftshields:2", "EQ_FUEL_INJECTION_TYPE4", "HEAT_SHIELD_TYPE4", "heatsinks:5"]
    	}, // cobra III (+ extra cargo)
    	{
    		primaryRole: "trader",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["energy:1", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE2", "heatsinks:1"]
    	}, // adder
    	{
    		primaryRole: "trader",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["energy:2", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE3", "heatsinks:2"]
    	}, // cobra I, fer-de-lance, moray star boat, moray medical boat
    	{
    		primaryRole: "trader",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["energy:3", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE3", "heatsinks:3"]
    	}, //
    	{
    		primaryRole: "trader",
    		minSpace: 41,
    		maxSpace: 50,
    		equipmentList: ["energy:3", "frontshields:2", "aftshields:2", "HEAT_SHIELD_TYPE3", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "heatsinks:4"]
    	}, //
    	{
    		primaryRole: "trader",
    		minSpace: 51,
    		maxSpace: 60,
    		equipmentList: ["energy:4", "frontshields:2", "aftshields:2", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE3", "EQ_ARMOUR_AFT_TYPE3", "heatsinks:5"]
    	}, //
    	{
    		primaryRole: "trader",
    		minSpace: 61,
    		maxSpace: 70,
    		equipmentList: ["energy:4", "frontshields:3", "aftshields:3", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE4", "EQ_ARMOUR_AFT_TYPE4", "heatsinks:6"]
    	}, // boa, python
    	{
    		primaryRole: "trader",
    		minSpace: 71,
    		maxSpace: 80,
    		equipmentList: ["energy:5", "frontshields:3", "aftshields:3", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE4", "EQ_ARMOUR_AFT_TYPE4", "heatsinks:7"]
    	}, // anaconda, boa cc
    	{
    		primaryRole: "trader-courier",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ELEC_BUS_TYPE3", "energy:1", "HEAT_SHIELD_TYPE2", "heatsinks:1"]
    	}, // adder
    	{
    		primaryRole: "trader-courier",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ELEC_BUS_TYPE3", "energy:2", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE3", "heatsinks:2"]
    	}, // asp mark II, fer-de-lance, moray starboat
    	{
    		primaryRole: "trader-courier",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_ELEC_BUS_TYPE4", "energy:2", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE3", "heatsinks:3"]
    	}, // cobra III (std model)
    	{
    		primaryRole: "trader-courier",
    		minSpace: 41,
    		maxSpace: 50,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_ELEC_BUS_TYPE4", "energy:3", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "heatsinks:3"]
    	}, // cobra III (+ extra cargo)
    	{
    		primaryRole: "trader-courier",
    		minSpace: 51,
    		maxSpace: 60,
    		equipmentList: ["EQ_ENGINE_TYPE5B", "EQ_ELEC_BUS_TYPE5", "energy:4", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE3", "EQ_ARMOUR_AFT_TYPE3", "heatsinks:4"]
    	}, //
    	{
    		primaryRole: "trader-courier",
    		minSpace: 61,
    		maxSpace: 70,
    		equipmentList: ["EQ_ENGINE_TYPE5B", "EQ_ELEC_BUS_TYPE5", "energy:4", "frontshields:2", "aftshields:2", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE4", "EQ_ARMOUR_AFT_TYPE4", "heatsinks:5"]
    	}, //
    	{
    		primaryRole: "trader-courier",
    		minSpace: 71,
    		maxSpace: 80,
    		equipmentList: ["EQ_ENGINE_TYPE6B", "EQ_ELEC_BUS_TYPE6", "energy:4", "frontshields:2", "aftshields:2", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE4", "EQ_ARMOUR_AFT_TYPE4", "heatsinks:6"]
    	}, // anaconda, boa cc
    	{
    		primaryRole: "trader-smuggler",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ELEC_BUS_TYPE3", "energy:1", "HEAT_SHIELD_TYPE2", "heatsinks:1"]
    	}, // adder,
    	{
    		primaryRole: "trader-smuggler",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ELEC_BUS_TYPE3", "energy:2", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE3", "heatsinks:2"]
    	}, // cobra I, fer-de-lance, moray starboat
    	{
    		primaryRole: "trader-smuggler",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_ELEC_BUS_TYPE4", "energy:2", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE3", "heatsinks:3"]
    	}, // cobra III (std model)
    	{
    		primaryRole: "trader-smuggler",
    		minSpace: 41,
    		maxSpace: 50,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_ELEC_BUS_TYPE4", "energy:3", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "heatsinks:3"]
    	}, // cobra III (+ extra cargo)
    	{
    		primaryRole: "trader-smuggler",
    		minSpace: 51,
    		maxSpace: 60,
    		equipmentList: ["EQ_ENGINE_TYPE5B", "EQ_ELEC_BUS_TYPE5", "energy:4", "frontshields:1", "aftshields:1", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE3", "EQ_ARMOUR_AFT_TYPE3", "heatsinks:4"]
    	}, //
    	{
    		primaryRole: "trader-smuggler",
    		minSpace: 61,
    		maxSpace: 70,
    		equipmentList: ["EQ_ENGINE_TYPE5B", "EQ_ELEC_BUS_TYPE5", "energy:4", "frontshields:2", "aftshields:2", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE4", "EQ_ARMOUR_AFT_TYPE4", "heatsinks:5"]
    	}, // python
    	{
    		primaryRole: "trader-smuggler",
    		minSpace: 71,
    		maxSpace: 80,
    		equipmentList: ["EQ_ENGINE_TYPE6B", "EQ_ELEC_BUS_TYPE6", "energy:4", "frontshields:2", "aftshields:2", "HEAT_SHIELD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE4", "EQ_ARMOUR_AFT_TYPE4", "heatsinks:6"]
    	}, //
    	{
    		primaryRole: "pirate",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "energy:1", "heatsinks:1"]
    	}, // adder, gecko, krait, mamba, sidewinder
    	{
    		primaryRole: "pirate",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "energy:2", "heatsinks:1"]
    	}, // cobra I, fer-de-lance, moray starboat
    	{
    		primaryRole: "pirate",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "energy:2", "heatsinks:2"]
    	}, // cobra III (std model)
    	{
    		primaryRole: "pirate",
    		minSpace: 41,
    		maxSpace: 50,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "energy:2", "heatsinks:2"]
    	}, // cobra III (+ extra cargo)
    	{
    		primaryRole: "pirate",
    		minSpace: 51,
    		maxSpace: 60,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "heatsinks:3"]
    	}, //
    	{
    		primaryRole: "pirate",
    		minSpace: 61,
    		maxSpace: 70,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "thrusters:2", "frontshields:1", "aftshields:1", "heatsinks:4"]
    	}, // python
    	{
    		primaryRole: "pirate",
    		minSpace: 71,
    		maxSpace: 80,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "energy:4", "thrusters:2", "frontshields:1", "aftshields:1", "heatsinks:4"]
    	}, //
    	{
    		primaryRole: "pirate-light-fighter",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "energy:1", "heatsinks:1"]
    	}, // adder, gecko, krait, mamba, sidewinder
    	{
    		primaryRole: "pirate-light-fighter",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "energy:2", "heatsinks:2"]
    	}, //
    	{
    		primaryRole: "pirate-light-fighter",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "heatsinks:2"]
    	}, //
    	{
    		primaryRole: "pirate-light-fighter",
    		minSpace: 41,
    		maxSpace: 50,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "energy:4", "heatsinks:3"]
    	}, //
    	{
    		primaryRole: "pirate-medium-fighter",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "energy:1", "heatsinks:1"]
    	}, // gecko
    	{
    		primaryRole: "pirate-medium-fighter",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "energy:2", "heatsinks:2"]
    	}, // asp mark II, cobra I, fer-de-lance, moray starboat
    	{
    		primaryRole: "pirate-medium-fighter",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "frontshields:1", "aftshields:1", "heatsinks:2"]
    	}, //
    	{
    		primaryRole: "pirate-medium-fighter",
    		minSpace: 41,
    		maxSpace: 50,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "energy:4", "frontshields:1", "aftshields:1", "heatsinks:3"]
    	}, //
    	{
    		primaryRole: "pirate-medium-fighter",
    		minSpace: 51,
    		maxSpace: 60,
    		equipmentList: ["EQ_ENGINE_TYPE5B", "energy:5", "frontshields:2", "aftshields:2", "heatsinks:3"]
    	}, //
    	{
    		primaryRole: "pirate-heavy-fighter",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "energy:1", "heatsinks:1"]
    	}, //
    	{
    		primaryRole: "pirate-heavy-fighter",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "energy:2", "heatsinks:2"]
    	}, // asp mark II, fer-de-lance,
    	{
    		primaryRole: "pirate-heavy-fighter",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "heatsinks:2"]
    	}, // cobra III (std model)
    	{
    		primaryRole: "pirate-heavy-fighter",
    		minSpace: 41,
    		maxSpace: 50,
    		equipmentList: ["EQ_ENGINE_TYPE5B", "energy:4", "frontshields:1", "aftshields:1", "heatsinks:2"]
    	}, // cobra III (+ extra cargo)
    	{
    		primaryRole: "pirate-heavy-fighter",
    		minSpace: 51,
    		maxSpace: 60,
    		equipmentList: ["EQ_ENGINE_TYPE5B", "energy:5", "frontshields:1", "aftshields:1", "heatsinks:3"]
    	}, //
    	{
    		primaryRole: "pirate-heavy-fighter",
    		minSpace: 61,
    		maxSpace: 70,
    		equipmentList: ["EQ_ENGINE_TYPE6B", "energy:6", "frontshields:2", "aftshields:2", "heatsinks:3"]
    	}, //
    	{
    		primaryRole: "pirate-heavy-fighter",
    		minSpace: 71,
    		maxSpace: 80,
    		equipmentList: ["EQ_ENGINE_TYPE6B", "energy:7", "frontshields:2", "aftshields:2", "heatsinks:4"]
    	}, //
    	{
    		primaryRole: "pirate-interceptor",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["EQ_ENGINE_TYPE4A", "heatsinks:1"]
    	}, //
    	{
    		primaryRole: "pirate-interceptor",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE5A", "heatsinks:1"]
    	}, // asp mark II, fer-de-lance, moray starboat
    	{
    		primaryRole: "pirate-interceptor",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE6A", "heatsinks:2"]
    	}, // cobra III (std model)
    	{
    		primaryRole: "pirate-interceptor",
    		minSpace: 41,
    		maxSpace: 80,
    		equipmentList: ["EQ_ENGINE_TYPE7A", "heatsinks:3"]
    	}, // cobra III (+ extra cargo)
    	{
    		primaryRole: "pirate-aegis-raider",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["EQ_ENGINE_TYPE3A", "heatsinks:1"]
    	}, //
    	{
    		primaryRole: "pirate-aegis-raider",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE4A", "heatsinks:1"]
    	}, // asp mark II, fer-de-lance
    	{
    		primaryRole: "pirate-aegis-raider",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "heatsinks:2"]
    	}, // cobra III (std model)
    	{
    		primaryRole: "pirate-aegis-raider",
    		minSpace: 41,
    		maxSpace: 80,
    		equipmentList: ["EQ_ENGINE_TYPE5A", "heatsinks:3"]
    	}, // cobra III (+ extra cargo)
    	{
    		primaryRole: "pirate-light-freighter",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "energy:1", "heatsinks:1"]
    	}, //
    	{
    		primaryRole: "pirate-light-freighter",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "energy:1", "heatsinks:1"]
    	}, // cobra I, moray starboat
    	{
    		primaryRole: "pirate-light-freighter",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "energy:2", "heatsinks:2"]
    	}, // cobra III (std model)
    	{
    		primaryRole: "pirate-light-freighter",
    		minSpace: 41,
    		maxSpace: 50,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "energy:2", "frontshields:1", "aftshields:1", "heatsinks:2"]
    	}, // cobra III (+ extra cargo)
    	{
    		primaryRole: "pirate-light-freighter",
    		minSpace: 51,
    		maxSpace: 60,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "frontshields:1", "aftshields:1", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "heatsinks:3"]
    	}, //
    	{
    		primaryRole: "pirate-light-freighter",
    		minSpace: 61,
    		maxSpace: 70,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "frontshields:2", "aftshields:2", "EQ_ARMOUR_FORWARD_TYPE3", "EQ_ARMOUR_AFT_TYPE3", "heatsinks:4"]
    	}, // python
    	{
    		primaryRole: "pirate-medium-freighter",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: []
    	}, // shouldn't get many ships in this bracket
    	{
    		primaryRole: "pirate-medium-freighter",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "energy:1", "heatsinks:2"]
    	}, //
    	{
    		primaryRole: "pirate-medium-freighter",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "energy:1", "heatsinks:2"]
    	}, // cobra III (std model)
    	{
    		primaryRole: "pirate-medium-freighter",
    		minSpace: 41,
    		maxSpace: 50,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "energy:2", "frontshields:1", "aftshields:1", "heatsinks:3"]
    	}, // cobra III (+ extra cargo)
    	{
    		primaryRole: "pirate-medium-freighter",
    		minSpace: 51,
    		maxSpace: 60,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "energy:2", "frontshields:1", "aftshields:1", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "heatsinks:4"]
    	}, //
    	{
    		primaryRole: "pirate-medium-freighter",
    		minSpace: 61,
    		maxSpace: 70,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "frontshields:2", "aftshields:2", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "heatsinks:5"]
    	}, // python
    	{
    		primaryRole: "pirate-medium-freighter",
    		minSpace: 71,
    		maxSpace: 80,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "frontshields:2", "aftshields:2", "EQ_ARMOUR_FORWARD_TYPE3", "EQ_ARMOUR_AFT_TYPE3", "heatsinks:6"]
    	}, // boa
    	{
    		primaryRole: "pirate-heavy-freighter",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: []
    	}, // shouldn't get many ships in these brackets
    	{
    		primaryRole: "pirate-heavy-freighter",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: []
    	}, //
    	{
    		primaryRole: "pirate-heavy-freighter",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "energy:1", "heatsinks:3"]
    	}, //
    	{
    		primaryRole: "pirate-heavy-freighter",
    		minSpace: 41,
    		maxSpace: 50,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "energy:2", "frontshields:1", "aftshields:1", "heatsinks:3"]
    	}, //
    	{
    		primaryRole: "pirate-heavy-freighter",
    		minSpace: 51,
    		maxSpace: 60,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "energy:2", "frontshields:2", "aftshields:2", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "heatsinks:4"]
    	}, //
    	{
    		primaryRole: "pirate-heavy-freighter",
    		minSpace: 61,
    		maxSpace: 70,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "frontshields:3", "aftshields:3", "EQ_ARMOUR_FORWARD_TYPE3", "EQ_ARMOUR_AFT_TYPE3", "heatsinks:5"]
    	}, // boa, python
    	{
    		primaryRole: "pirate-heavy-freighter",
    		minSpace: 71,
    		maxSpace: 80,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "energy:3", "frontshields:4", "aftshields:4", "EQ_ARMOUR_FORWARD_TYPE4", "EQ_ARMOUR_AFT_TYPE4", "heatsinks:6"]
    	}, // anaconda, boa cc
    	{
    		primaryRole: "escort",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["EQ_ENGINE_TYPE3B"]
    	},
    	{
    		primaryRole: "escort",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE3B"]
    	},
    	{
    		primaryRole: "escort",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE4B"]
    	},
    	{
    		primaryRole: "escort",
    		minSpace: 41,
    		maxSpace: 50,
    		equipmentList: ["EQ_ENGINE_TYPE4B"]
    	},
    	{
    		primaryRole: "escort",
    		minSpace: 51,
    		maxSpace: 60,
    		equipmentList: ["EQ_ENGINE_TYPE5B"]
    	},
    	{
    		primaryRole: "escort-medium",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["EQ_ENGINE_TYPE3B"]
    	},
    	{
    		primaryRole: "escort-medium",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "heatsinks:2"]
    	},
    	{
    		primaryRole: "escort-medium",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "heatsinks:2"]
    	},
    	{
    		primaryRole: "escort-medium",
    		minSpace: 41,
    		maxSpace: 50,
    		equipmentList: ["EQ_ENGINE_TYPE5B", "heatsinks:3"]
    	},
    	{
    		primaryRole: "escort-medium",
    		minSpace: 51,
    		maxSpace: 60,
    		equipmentList: ["EQ_ENGINE_TYPE5B", "heatsinks:3"]
    	},
    	{
    		primaryRole: "escort-medium",
    		minSpace: 61,
    		maxSpace: 70,
    		equipmentList: ["EQ_ENGINE_TYPE6B", "heatsinks:4"]
    	},
    	{
    		primaryRole: "escort-heavy",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["EQ_ENGINE_TYPE3B"]
    	},
    	{
    		primaryRole: "escort-heavy",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "heatsinks:2"]
    	},
    	{
    		primaryRole: "escort-heavy",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "heatsinks:2"]
    	},
    	{
    		primaryRole: "escort-heavy",
    		minSpace: 41,
    		maxSpace: 50,
    		equipmentList: ["EQ_ENGINE_TYPE5B", "heatsinks:3"]
    	},
    	{
    		primaryRole: "escort-heavy",
    		minSpace: 51,
    		maxSpace: 60,
    		equipmentList: ["EQ_ENGINE_TYPE5B", "heatsinks:3"]
    	},
    	{
    		primaryRole: "escort-heavy",
    		minSpace: 61,
    		maxSpace: 70,
    		equipmentList: ["EQ_ENGINE_TYPE6B", "heatsinks:4"]
    	},
    	{
    		primaryRole: "escort-heavy",
    		minSpace: 71,
    		maxSpace: 80,
    		equipmentList: ["EQ_ENGINE_TYPE6B", "heatsinks:4"]
    	},
    	{
    		primaryRole: "shuttle",
    		minSpace: 0,
    		maxSpace: 20,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "EQ_HEAT_SHIELD_TYPE3"]
    	},
    	{
    		primaryRole: "shuttle",
    		minSpace: 21,
    		maxSpace: 30,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "EQ_HEAT_SHIELD_TYPE3"]
    	},
    	{
    		primaryRole: "shuttle",
    		minSpace: 31,
    		maxSpace: 40,
    		equipmentList: ["EQ_ENGINE_TYPE3B", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_AFT_TYPE2", "EQ_HEAT_SHIELD_TYPE3"]
    	},
    	{
    		primaryRole: "shuttle",
    		minSpace: 41,
    		maxSpace: 80,
    		equipmentList: ["EQ_ENGINE_TYPE4B", "EQ_ARMOUR_FORWARD_TYPE3", "EQ_ARMOUR_AFT_TYPE3", "EQ_HEAT_SHIELD_TYPE3"]
    	},
    	{
    		primaryRole: "police",
    		minSpace: 0,
    		maxSpace: 80,
    		equipmentList: ["engines:2", "energy:1", "thrusters:2"]
    	},
    	{
    		primaryRole: "police-station-patrol",
    		minSpace: 0,
    		maxSpace: 80,
    		equipmentList: ["engines:2", "energy:1", "thrusters:2"]
    	},
    	{
    		primaryRole: "police-witchpoint-patrol",
    		minSpace: 0,
    		maxSpace: 80,
    		equipmentList: ["engines:3", "energy:2", "thrusters:3"]
    	},
    	{
    		primaryRole: "wingman",
    		minSpace: 0,
    		maxSpace: 80,
    		equipmentList: ["engines:2", "energy:1", "thrusters:2"]
    	},
    	{
    		primaryRole: "miner",
    		minSpace: 0,
    		maxSpace: 80,
    		equipmentList: ["EQ_ARMOUR_TYPE2"]
    	},
    	{
    		primaryRole: "scavenger",
    		minSpace: 0,
    		maxSpace: 80,
    		equipmentList: ["EQ_ARMOUR_TYPE2"]
    	},
    ];
    
    // these equipment items don't take up space or weight, or can just be ignored altogether
    this._ignoreEquip = ["EQ_FUEL", "EQ_SCANNER_SHOW_MISSILE_TARGET", "EQ_MULTI_TARGET", "EQ_ADVANCED_NAVIGATIONAL_ARRAY", "EQ_INTEGRATED_TARGETING_SYSTEM", "EQ_REVOVATION",
    	"EQ_TARGET_MEMORY", "EQ_SMUGGLING_PHASE_ADJUSTMENT", "EQ_SDC_HACK_CHIP", "EQ_IG_INSURANCE", "EQ_IG_LEGAL_HACK", "EQ_LMSS_ACTUATOR", "EQ_ESCORTCONTRACTS", "EQ_TEA_MAKER", "EQ_TEAPOT",
    	"EQ_RENOVATION", "EQ_COMMSLOGMFD", "EQ_COMMSLOGMFD_PASSIVE", "EQ_BROADCASTCOMMSMFD", "EQ_DAMAGE_REPORT_MFD", "EQ_DAMAGE_REPORT_MFD_PASSIVE", "EQ_COMBATMFD", "EQ_NAVIGATION_MFD",
    	"EQ_WEAPON_NONE", "EQ_APRIL_INVENTORY", "EQ_APRIL_TRANSFER", "EQ_APRIL_UNLOAD", "EQ_AMS_1", "EQ_AMS_2", "EQ_AMS_3", "EQ_AMS_4", "EQ_GLARE_FILTER", "EQ_GLARE_FILTER_REPLACE",
    	"EQ_RRS_FUEL", "EQ_AMS_5", "EQ_AMS_6", "EQ_AUTO_EJECT", "EQ_BOUNTY_INFORMER", "EQ_CARGOSPOTTER", "EQ_ELITE_RANK", "EQ_RESERVE_TANK_EMPTY", "EQ_AUX_TANK_EMPTY",
    	"EQ_WEAPON_GATLING_LASER_COOLER", "EQ_NDC_AUTODOCK", "EQ_OXPDevHelper", "EQ_HUDSELECTOR", "EQ_MARKET_INQUIRER_MFD", "EQ_TROPHY_MFD", "EQ_UPS_IDCLEANER", "EQ_UPS_PRIVATE_ESCORT",
    	"EQ_MULTIPASS", "EQ_MULTIPASSED_ID", "EQ_HARDWIRE_ORE_PROCESSOR", "EQ_SCANNER_SHOW_MISSILE_TARGET_SALVAGED", "EQ_MULTI_TARGET_SALVAGED", "EQ_ADVANCED_NAVIGATIONAL_ARRAY_SALVAGED",
    	"EQ_TARGETSELECTOR", "EQ_HULL_REPAIR", "EQ_SHIPS_CAT_1", "EQ_SHIPS_CAT_2", "EQ_SHIPS_CAT_3", "EQ_SHIPS_CAT_4", "EQ_SHIPS_CAT_5", "EQ_SHIPS_CAT_6", "EQ_SHIPS_CAT_7", "EQ_SHIPS_CAT_8",
    	"EQ_SHIPS_CAT_9", "EQ_TARGET_MEMORY_SALVAGED", "EQ_CTE_TRADERNET", "EQ_CTE_TRADERNET_RENEWAL", "EQ_CAMERA_DRONES", "EQ_HOLY_FUEL", "EQ_WPH_ASC_UPGRADE", "EQ_RRS_ANA",
    	"EQ_RRS_FLIGHTFORM", "EQ_RRS_FLIGHTFORM_DISCOUNT", "EQ_RRS_SERVICE", "EQ_RRS_ESCORT_TARGETING_SYSTEM", "EQ_RRS_ESCORT_TARGETING_SYSTEM_WAYSTATION",
    	"EQ_RRS_ESCORT_TARGETING_SYSTEM_DISCOUNT", "EQ_RRS_SCANNER_SHOW_MISSILE_TARGET", "EQ_RRS_SCANNER_SHOW_MISSILE_TARGET_DISCOUNT", "EQ_RRS_FULLEQUIP", "EQ_BREAKABLE_HUD_IFF_SCANNER",
    	"EQ_ESCORTDECK", "EQ_ESCORTDECKXL", "EQ_ESCORTDECK_adder", "EQ_ESCORTDECK_asp", "EQ_ESCORTDECK_gecko", "EQ_ESCORTDECK_sidewinder", "EQ_ESCORTDECK_viper", "EQ_ESCORTDECK_ophidian",
    	"EQ_ESCORTDECK_ghavial", "EQ_ESCORTDECK_wolf", "EQ_ESCORTDECK_arachnid", "EQ_ESCORTDECK_s8", "EQ_ESCORTDECK_sniper-wolf", "EQ_ESCORTDECK_sniper-arachnid", "EQ_ESCORTDECK_sniper-s8",
    	"EQ_HYPER_RADIO", "EQ_HYPER_RADIO_ADD", "EQ_HYPER_RADIO_PIRATE", "EQ_HIREDGUN_HIGH", "EQ_HIREDGUN_MID", "EQ_HIREDGUN_LOW", "EQ_ILS", "EQ_WEAPON_LASER_COOLER", "EQ_MANIFEST_MFD",
    	"EQ_RMB_CHAFF_MINE", "EQ_POLICE_SCANNER_UPGRADE", "EQ_Q-CHARGER_MESS", "EQ_REPAIRBOTS_RECHARGE", "EQ_SAFETYCATCH", "EQ_SAFETY_MINE", "EQ_SCANNER_ALERTING_ENHANCEMENT",
    	"EQ_SC_MANUAL_CONFIGURATOR_BASIC", "EQ_SC_MANUAL_CONFIGURATOR_STANDARD", "EQ_SC_MANUAL_CONFIGURATOR_ADVANCED", "EQ_SC_SC_REPAIR", "EQ_ENEMY_TARGETER_UPGRADE",
    	"EQ_TELESCOPE_REPAIR", "EQ_TELESCOPE_FULLREPAIR", "EQ_TELESCOPEEXT", "EQ_GRAVSCANNER_REPAIR", "EQ_GRAVSCANNER_FULLREPAIR", "EQ_GRAVSCANNER2_REPAIR", "EQ_GRAVSCANNER2_FULLREPAIR",
    	"EQ_SMALLDISH_REPAIR", "EQ_SMALLDISH_FULLREPAIR", "EQ_LARGEDISH_REPAIR", "EQ_LARGEDISH_FULLREPAIR", "EQ_TORUSTOSUN", "EQ_TRACKER", "EQ_TRACKERCAM_LINK", "EQ_TWS_GALACTICSATNAV",
    	"EQ_WELCOME_MAT", "EQ_SMUGGLING_COMPARTMENT_REPAIR_1", "EQ_SMUGGLING_COMPARTMENT_REPAIR_2", "EQ_SMUGGLING_COMPARTMENT_REPAIR_3", "EQ_SMUGGLING_COMPARTMENT_REPAIR_4",
    	"EQ_SMUGGLING_COMPARTMENT_REPAIR_5", "EQ_SMUGGLING_COMPARTMENT_REPAIR_6", "EQ_SMUGGLING_COMPARTMENT_REPAIR_7", "EQ_SMUGGLING_COMPARTMENT_REPAIR_8",
    	"EQ_SMUGGLING_COMPARTMENT_REPAIR_9", "EQ_SMUGGLING_COMPARTMENT_REPAIR_10", "EQ_SMUGGLING_COMPARTMENT_REPAIR_11", "EQ_SMUGGLING_COMPARTMENT_REPAIR_12",
    	"EQ_SMUGGLING_COMPARTMENT_REPAIR_13", "EQ_SMUGGLING_COMPARTMENT_REPAIR_14", "EQ_SMUGGLING_COMPARTMENT_REPAIR_15", "EQ_SMUGGLING_COMPARTMENT_REPAIR_16",
    	"EQ_SMUGGLING_COMPARTMENT_REPAIR_17", "EQ_SMUGGLING_COMPARTMENT_REPAIR_18", "EQ_SMUGGLING_COMPARTMENT_REPAIR_19", "EQ_SMUGGLING_COMPARTMENT_REPAIR_20", "EQ_FHUD_OOLITE",
    	"EQ_BREAKABLE_LIFE_SUPPORT_SYSTEM", "EQ_SHIPCONFIG", "EQ_FUEL_INJECTION", "EQ_HEAT_SHIELD", "EQ_RAILGUN_1_AMMUNITION", "EQ_RAILGUN_2_AMMUNITION", "EQ_XS_SELLPYLON_BASEDEQUIPMENT",
    	"EQ_RAILGUN_3_AMMUNITION", "EQ_RAILGUN_4_AMMUNITION", "EQ_COTBS_RESTORE", "EQ_GAL_DRIVE_MOD", "EQ_CATACLYSM_ALL_INCLUSIVE", "EQ_SALON_CONTROL", "EQ_SNIPER_SCOPE",
    	"EQ_SYSTEM_MARKET_WATCH", "EQ_AUTOECM", "EQ_FS_CLOAK_PLACEHOLDER", "EQ_FS_BOMB_PLACEHOLDER", "EQ_FS_INJECTION_PLACEHOLDER", "EQ_GALAXY_INFO", "EQ_LONG_RANGE_SCANNER_JUMP",
    	"EQ_RETICLE_TARGET_SENSITIVE", "EQ_SELL_ENERGY_GRID", "EQ_ECM_SALVAGED", "EQ_FUEL_SCOOPS_SALVAGED", "EQ_ESCAPE_POD_SALVAGED", "EQ_ENERGY_BOMB_SALVAGED", "EQ_ENERGY_UNIT_SALVAGED",
    	"EQ_NAVAL_ENERGY_UNIT_SALVAGED", "EQ_DOCK_COMP_SALVAGED", "EQ_GAL_DRIVE_SALVAGED", "EQ_FUEL_INJECTION_SALVAGED", "EQ_ADVANCED_COMPASS_SALVAGED", "EQ_SHIELD_BOOSTER_SALVAGED",
    	"EQ_NAVAL_SHIELD_BOOSTER_SALVAGED", "EQ_HEAT_SHIELD_SALVAGED", "EQ_WORMHOLE_SCANNER_SALVAGED", "EQ_OXPCONFIG_COLORS", "EQ_OXPCONFIG_M0", "EQ_OXPCONFIG_M1", "EQ_OXPCONFIG_M2",
    	"EQ_OXPCONFIG_M3", "EQ_OXPCONFIG_M4", "EQ_OXPCONFIG_M5", "EQ_OXPCONFIG_W0", "EQ_DTADAM", "EQ_DTADER", "EQ_DTAWEA", "EQ_CCL_OXPS_MINE", "EQ_CABAL_COMMON_SPECIALMARKETS",
    	"EQ_CABAL_COMMON_COMM", "EQ_MANIF_SCANNERX", "EQ_MC_DESCRAMBLER", "EQ_MURPH_THARGOID_DRIVE_TOFIT", "EQ_MURPH_THARGOID_DRIVE_QUOTE", "EQ_SHIP_RESPRAY", "EQ_SHIP_RESPRAY_180",
    	"EQ_HEAT_SINK_CONTROL", "EQ_HEAT_SINK_CONTROL_PASSIVE", "EQ_SYNC_TORUS", "EQ_AI_TRADING_ASSISTANT", "EQ_AUTO_CROSSHAIRS", "EQ_SELECTABLE_CROSSHAIRS", "EQ_TRAIL_DETECTOR",
    	"EQ_EREHWON_PHOTOCAMERA", "EQ_ENEMY_TARGETER_UPGRADE", "EQ_SNIPERLOCK", "EQ_VECTOR_PAD", "EQ_RINGRACER", "EQ_IN_SYSTEM_TAXI_LICENCE", "EQ_NS_MINING_SCANNER_UPGRADE",
    	"EQ_LUCKYCHARM", "EQ_PIRATE_FUEL", "EQ_FUEL_ALT1", "EQ_FUEL_ALT2", "EQ_FUEL_ALT3", "EQ_FUEL_ALT4", "EQ_FUEL_ALT5", "EQ_FUEL_ALT6", "EQ_SHIPS_LIBRARY", "EQ_ALMANAC_UNIT_MFD",
    	"EQ_VIMANA_TARGET_MODULE", "EQ_VIMANA_TRAVEL_MODULE", "EQ_VIMANA_SHIP_MODULE", "EQ_VIMANAX_TARGET_MODULE", "EQ_VIMANAX_TRAVEL_MODULE", "EQ_VIMANAX_SHIP_MODULE",
    	"EQ_SHIP_VERSION_10", "EQ_SHIP_VERSION_11", "EQ_SHIP_VERSION_12", "EQ_SHIP_VERSION_13", "EQ_SHIP_VERSION_14", 
    	"EQ_SHIP_VERSION_15", "EQ_SHIP_VERSION_16", "EQ_SHIP_VERSION_17", "EQ_SHIP_VERSION_18", "EQ_SHIP_VERSION_19", 
    	"EQ_SHIP_VERSION_20", "EQ_SHIP_VERSION_21", "EQ_SHIP_VERSION_22", "EQ_SHIP_VERSION_23", "EQ_SHIP_VERSION_24", 
    	"EQ_SHIP_VERSION_25", "EQ_SHIP_VERSION_26", "EQ_SHIP_VERSION_27", "EQ_SHIP_VERSION_28", "EQ_SHIP_VERSION_29", 
    	"EQ_SHIP_VERSION_30", "EQ_SHIP_VERSION_31", "EQ_SHIP_VERSION_32", "EQ_SHIP_VERSION_33", "EQ_SHIP_VERSION_34", 
    	"EQ_SHIP_VERSION_35", "EQ_SHIP_VERSION_36", "EQ_SHIP_VERSION_37", "EQ_SHIP_VERSION_38", "EQ_SHIP_VERSION_39", 
    	"EQ_SHIP_VERSION_40", "EQ_SHIP_VERSION_41", "EQ_SHIP_VERSION_42", "EQ_SHIP_VERSION_43", "EQ_SHIP_VERSION_44", 
    	"EQ_SHIP_VERSION_45", "EQ_SHIP_VERSION_46", "EQ_SHIP_VERSION_47", "EQ_SHIP_VERSION_48", "EQ_SHIP_VERSION_49", 
    	"EQ_SHIP_VERSION_50", "EQ_SHIP_VERSION_51", "EQ_SHIP_VERSION_52", "EQ_SHIP_VERSION_53", "EQ_SHIP_VERSION_54", 
    	"EQ_SHIP_VERSION_55", "EQ_SHIP_VERSION_56", "EQ_SHIP_VERSION_57", "EQ_SHIP_VERSION_58", "EQ_SHIP_VERSION_59", 
    	"EQ_SHIP_VERSION_60", "EQ_SHIP_VERSION_61", "EQ_SHIP_VERSION_62", "EQ_SHIP_VERSION_63", "EQ_SHIP_VERSION_64", 
    	"EQ_SHIP_VERSION_65", "EQ_SHIP_VERSION_66", "EQ_SHIP_VERSION_67", "EQ_SHIP_VERSION_68", "EQ_SHIP_VERSION_69", 
    	"EQ_SHIP_VERSION_70", "EQ_SHIP_VERSION_71", "EQ_SHIP_VERSION_72", "EQ_SHIP_VERSION_73", "EQ_SHIP_VERSION_74", 
    	"EQ_SHIP_VERSION_75", "EQ_SHIP_VERSION_76", "EQ_SHIP_VERSION_77", "EQ_SHIP_VERSION_78", "EQ_SHIP_VERSION_79", 
    	"EQ_SHIP_VERSION_80", "EQ_SHIP_VERSION_81", "EQ_SHIP_VERSION_82", "EQ_SHIP_VERSION_83", "EQ_SHIP_VERSION_84", 
    	"EQ_SHIP_VERSION_85", "EQ_SHIP_VERSION_86", "EQ_SHIP_VERSION_87", "EQ_SHIP_VERSION_88", "EQ_SHIP_VERSION_89", 
    	"EQ_SHIP_VERSION_90", "EQ_SHIP_VERSION_91", "EQ_SHIP_VERSION_92", "EQ_SHIP_VERSION_93", "EQ_SHIP_VERSION_94", 
    	"EQ_SHIP_VERSION_95", "EQ_SHIP_VERSION_96", "EQ_SHIP_VERSION_97", "EQ_SHIP_VERSION_98", "EQ_SHIP_VERSION_99", 
    	"EQ_SHIP_VERSION_100",
    	"EQ_SERVICE_LEVEL_75", "EQ_SERVICE_LEVEL_76", "EQ_SERVICE_LEVEL_77", "EQ_SERVICE_LEVEL_78", "EQ_SERVICE_LEVEL_79", 
    	"EQ_SERVICE_LEVEL_80", "EQ_SERVICE_LEVEL_81", "EQ_SERVICE_LEVEL_82", "EQ_SERVICE_LEVEL_83", "EQ_SERVICE_LEVEL_84", 
    	"EQ_SERVICE_LEVEL_85", "EQ_SERVICE_LEVEL_86", "EQ_SERVICE_LEVEL_87", "EQ_SERVICE_LEVEL_88", "EQ_SERVICE_LEVEL_89", 
    	"EQ_SERVICE_LEVEL_90", "EQ_SERVICE_LEVEL_91", "EQ_SERVICE_LEVEL_92", "EQ_SERVICE_LEVEL_93", "EQ_SERVICE_LEVEL_94", 
    	"EQ_SERVICE_LEVEL_95", "EQ_SERVICE_LEVEL_96", "EQ_SERVICE_LEVEL_97", "EQ_SERVICE_LEVEL_98", "EQ_SERVICE_LEVEL_99", 
    	"EQ_SERVICE_LEVEL_100"
    ];
    
    this._filler = ["EQ_EQUIPSPACE_1", "EQ_EQUIPSPACE_2", "EQ_EQUIPSPACE_3", "EQ_EQUIPSPACE_4", "EQ_EQUIPSPACE_5", "EQ_EQUIPSPACE_6", "EQ_EQUIPSPACE_7", "EQ_EQUIPSPACE_8",
    	"EQ_EQUIPSPACE_9", "EQ_EQUIPSPACE_10", "EQ_EQUIPSPACE_11", "EQ_EQUIPSPACE_12", "EQ_EQUIPSPACE_13", "EQ_EQUIPSPACE_14", "EQ_EQUIPSPACE_15", "EQ_EQUIPSPACE_16",
    	"EQ_EQUIPSPACE_17", "EQ_EQUIPSPACE_18", "EQ_EQUIPSPACE_19", "EQ_EQUIPSPACE_20", "EQ_EQUIPSPACE_21", "EQ_EQUIPSPACE_22", "EQ_EQUIPSPACE_23", "EQ_EQUIPSPACE_24",
    	"EQ_EQUIPSPACE_25", "EQ_EQUIPSPACE_26", "EQ_EQUIPSPACE_27", "EQ_EQUIPSPACE_28", "EQ_EQUIPSPACE_29", "EQ_EQUIPSPACE_30", "EQ_EQUIPSPACE_31", "EQ_EQUIPSPACE_32",
    	"EQ_EQUIPSPACE_33", "EQ_EQUIPSPACE_34", "EQ_EQUIPSPACE_35", "EQ_EQUIPSPACE_36", "EQ_EQUIPSPACE_37", "EQ_EQUIPSPACE_38", "EQ_EQUIPSPACE_39", "EQ_EQUIPSPACE_40"
    ];
    
    this._engines = ["EQ_ENGINE_TYPE1A", "EQ_ENGINE_TYPE1B", "EQ_ENGINE_TYPE1C", "EQ_ENGINE_TYPE1D", "EQ_ENGINE_TYPE1E", "EQ_ENGINE_TYPE1F",
    	"EQ_ENGINE_TYPE2A", "EQ_ENGINE_TYPE2B", "EQ_ENGINE_TYPE2C", "EQ_ENGINE_TYPE2D", "EQ_ENGINE_TYPE2E", "EQ_ENGINE_TYPE2F",
    	"EQ_ENGINE_TYPE3A", "EQ_ENGINE_TYPE3B", "EQ_ENGINE_TYPE3C", "EQ_ENGINE_TYPE3D", "EQ_ENGINE_TYPE3E", "EQ_ENGINE_TYPE3F",
    	"EQ_ENGINE_TYPE4A", "EQ_ENGINE_TYPE4B", "EQ_ENGINE_TYPE4C", "EQ_ENGINE_TYPE4D", "EQ_ENGINE_TYPE4E", "EQ_ENGINE_TYPE4F",
    	"EQ_ENGINE_TYPE5A", "EQ_ENGINE_TYPE5B", "EQ_ENGINE_TYPE5C", "EQ_ENGINE_TYPE5D", "EQ_ENGINE_TYPE5E", "EQ_ENGINE_TYPE5F",
    	"EQ_ENGINE_TYPE6A", "EQ_ENGINE_TYPE6B", "EQ_ENGINE_TYPE6C", "EQ_ENGINE_TYPE6D", "EQ_ENGINE_TYPE6E", "EQ_ENGINE_TYPE6F",
    	"EQ_ENGINE_TYPE7A", "EQ_ENGINE_TYPE7B", "EQ_ENGINE_TYPE7C", "EQ_ENGINE_TYPE7D", "EQ_ENGINE_TYPE7E", "EQ_ENGINE_TYPE7F"
    ];
    this._boosters = ["EQ_BOOSTERS_TYPE1", "EQ_BOOSTERS_TYPE2", "EQ_BOOSTERS_TYPE3", "EQ_BOOSTERS_TYPE4", "EQ_BOOSTERS_TYPE5", "EQ_BOOSTERS_TYPE6", "EQ_BOOSTERS_TYPE7"];
    this._hyperdrive = ["EQ_HYPERDRIVE_TYPE1", "EQ_HYPERDRIVE_TYPE2", "EQ_HYPERDRIVE_TYPE3", "EQ_HYPERDRIVE_TYPE4"];
    this._thrusters = ["EQ_THRUSTERS_TYPE1", "EQ_THRUSTERS_TYPE2A", "EQ_THRUSTERS_TYPE2B", "EQ_THRUSTERS_TYPE2C", "EQ_THRUSTERS_TYPE2D", "EQ_THRUSTERS_TYPE2E", "EQ_THRUSTERS_TYPE2F",
    	"EQ_THRUSTERS_TYPE3A", "EQ_THRUSTERS_TYPE3B", "EQ_THRUSTERS_TYPE3C", "EQ_THRUSTERS_TYPE3D", "EQ_THRUSTERS_TYPE3E", "EQ_THRUSTERS_TYPE3F",
    	"EQ_THRUSTERS_TYPE4A", "EQ_THRUSTERS_TYPE4B", "EQ_THRUSTERS_TYPE4C", "EQ_THRUSTERS_TYPE4D", "EQ_THRUSTERS_TYPE4E", "EQ_THRUSTERS_TYPE4F",
    	"EQ_THRUSTERS_TYPE5A", "EQ_THRUSTERS_TYPE5B", "EQ_THRUSTERS_TYPE5C", "EQ_THRUSTERS_TYPE5D", "EQ_THRUSTERS_TYPE5E", "EQ_THRUSTERS_TYPE5F",
    	"EQ_THRUSTERS_TYPE6A", "EQ_THRUSTERS_TYPE6B", "EQ_THRUSTERS_TYPE6C", "EQ_THRUSTERS_TYPE6D", "EQ_THRUSTERS_TYPE6E", "EQ_THRUSTERS_TYPE6F",
    	"EQ_THRUSTERS_TYPE7A", "EQ_THRUSTERS_TYPE7B", "EQ_THRUSTERS_TYPE7C", "EQ_THRUSTERS_TYPE7D", "EQ_THRUSTERS_TYPE7E", "EQ_THRUSTERS_TYPE7F"
    ];
    this._energy = ["EQ_ENERGYBANK_TYPE1", "EQ_ENERGYBANK_TYPE2", "EQ_ENERGYBANK_TYPE3", "EQ_ENERGYBANK_TYPE4", "EQ_ENERGYBANK_TYPE5", "EQ_ENERGYBANK_TYPE6",
    	"EQ_ENERGYBANK_TYPE7", "EQ_ENERGYBANK_TYPE8", "EQ_ENERGYBANK_TYPE9", "EQ_ENERGYBANK_TYPE10", "EQ_ENERGYBANK_TYPE11", "EQ_ENERGYBANK_TYPE12",
    	"EQ_ENERGYBANK_TYPE13", "EQ_ENERGYBANK_TYPE14", "EQ_ENERGYBANK_TYPE15", "EQ_ENERGYBANK_TYPE16", "EQ_ENERGYBANK_TYPE17", "EQ_ENERGYBANK_TYPE18",
    	"EQ_ENERGYBANK_TYPE19", "EQ_ENERGYBANK_TYPE20", "EQ_ENERGYBANK_TYPE21", "EQ_ENERGYBANK_TYPE22", "EQ_ENERGYBANK_TYPE23", "EQ_ENERGYBANK_TYPE24",
    	"EQ_ENERGYBANK_TYPE25",
    	"EQ_ENERGYBANK_TYPE1A", "EQ_ENERGYBANK_TYPE2A", "EQ_ENERGYBANK_TYPE3A", "EQ_ENERGYBANK_TYPE4A", "EQ_ENERGYBANK_TYPE5A", "EQ_ENERGYBANK_TYPE6A",
    	"EQ_ENERGYBANK_TYPE7A", "EQ_ENERGYBANK_TYPE8A", "EQ_ENERGYBANK_TYPE9A", "EQ_ENERGYBANK_TYPE10A", "EQ_ENERGYBANK_TYPE11A", "EQ_ENERGYBANK_TYPE12A",
    	"EQ_ENERGYBANK_TYPE13A", "EQ_ENERGYBANK_TYPE14A", "EQ_ENERGYBANK_TYPE15A", "EQ_ENERGYBANK_TYPE16A", "EQ_ENERGYBANK_TYPE17A", "EQ_ENERGYBANK_TYPE18A",
    	"EQ_ENERGYBANK_TYPE19A", "EQ_ENERGYBANK_TYPE20A", "EQ_ENERGYBANK_TYPE21A", "EQ_ENERGYBANK_TYPE22A", "EQ_ENERGYBANK_TYPE23A", "EQ_ENERGYBANK_TYPE24A",
    	"EQ_ENERGYBANK_TYPE25A"
    ];
    this._frontshields = ["EQ_NO_FORWARD_SHIELD", "EQ_FORWARD_SHIELD_TYPE1", "EQ_FORWARD_SHIELD_TYPE2", "EQ_FORWARD_SHIELD_TYPE3", "EQ_FORWARD_SHIELD_TYPE4", "EQ_FORWARD_SHIELD_TYPE5"];
    this._aftshields = ["EQ_NO_AFT_SHIELD", "EQ_AFT_SHIELD_TYPE1", "EQ_AFT_SHIELD_TYPE2", "EQ_AFT_SHIELD_TYPE3", "EQ_AFT_SHIELD_TYPE4", "EQ_AFT_SHIELD_TYPE5"];
    this._heatshields = ["EQ_HEAT_SHIELD_TYPE1", "EQ_HEAT_SHIELD_TYPE2", "EQ_HEAT_SHIELD_TYPE3", "EQ_HEAT_SHIELD_TYPE4", "EQ_HEAT_SHIELD_TYPE5", "EQ_HEAT_SHIELD_TYPE6"];
    this._fuelinjectors = ["EQ_FUEL_INJECTION_TYPE1", "EQ_FUEL_INJECTION_TYPE2", "EQ_FUEL_INJECTION_TYPE3", "EQ_FUEL_INJECTION_TYPE4"];
    this._fuelscoops = ["EQ_FUEL_SCOOPS_TYPE1", "EQ_FUEL_SCOOPS_TYPE2", "EQ_FUEL_SCOOPS_TYPE3", "EQ_FUEL_SCOOPS_TYPE4"];
    this._armour = [];
    this._frontarmour = ["EQ_ARMOUR_FORWARD_TYPE1", "EQ_ARMOUR_FORWARD_TYPE2", "EQ_ARMOUR_FORWARD_TYPE3", "EQ_ARMOUR_FORWARD_TYPE4", "EQ_ARMOUR_FORWARD_TYPE5",
    	"EQ_ARMOUR_FORWARD_TYPE6", "EQ_ARMOUR_FORWARD_TYPE7"
    ];
    this._aftarmour = ["EQ_ARMOUR_AFT_TYPE1", "EQ_ARMOUR_AFT_TYPE2", "EQ_ARMOUR_AFT_TYPE3", "EQ_ARMOUR_AFT_TYPE4", "EQ_ARMOUR_AFT_TYPE5", "EQ_ARMOUR_AFT_TYPE6",
    	"EQ_ARMOUR_AFT_TYPE7"
    ];
    this._electricalbus = ["EQ_ELEC_BUS_TYPE1", "EQ_ELEC_BUS_TYPE2", "EQ_ELEC_BUS_TYPE3", "EQ_ELEC_BUS_TYPE4", "EQ_ELEC_BUS_TYPE5", "EQ_ELEC_BUS_TYPE6", "EQ_ELEC_BUS_TYPE7"];
    this._hdCoupling = ["EQ_HYPERDRIVE_COUPLING_TYPE1", "EQ_HYPERDRIVE_COUPLING_TYPE2", "EQ_HYPERDRIVE_COUPLING_TYPE3", "EQ_HYPERDRIVE_COUPLING_TYPE4"];
    this._enCoupling = ["EQ_ENGINE_COUPLING_TYPE1", "EQ_ENGINE_COUPLING_TYPE2", "EQ_ENGINE_COUPLING_TYPE3", "EQ_ENGINE_COUPLING_TYPE4", "EQ_ENGINE_COUPLING_TYPE5",
    	"EQ_ENGINE_COUPLING_TYPE6", "EQ_ENGINE_COUPLING_TYPE7"
    ];
    this._bsCoupling = ["EQ_BOOSTERS_COUPLING_TYPE1", "EQ_BOOSTERS_COUPLING_TYPE2", "EQ_BOOSTERS_COUPLING_TYPE3", "EQ_BOOSTERS_COUPLING_TYPE4", "EQ_BOOSTERS_COUPLING_TYPE5",
    	"EQ_BOOSTERS_COUPLING_TYPE6", "EQ_BOOSTERS_COUPLING_TYPE7"
    ];
    this._ebCoupling = ["EQ_ENERGYBANK_COUPLING_TYPE1", "EQ_ENERGYBANK_COUPLING_TYPE2", "EQ_ENERGYBANK_COUPLING_TYPE3", "EQ_ENERGYBANK_COUPLING_TYPE4", "EQ_ENERGYBANK_COUPLING_TYPE5",
    	"EQ_ENERGYBANK_COUPLING_TYPE6", "EQ_ENERGYBANK_COUPLING_TYPE7", "EQ_ENERGYBANK_COUPLING_TYPE8"
    ];
    this._thCoupling = ["EQ_THRUSTERS_COUPLING_TYPE1", "EQ_THRUSTERS_COUPLING_TYPE2", "EQ_THRUSTERS_COUPLING_TYPE3", "EQ_THRUSTERS_COUPLING_TYPE4", "EQ_THRUSTERS_COUPLING_TYPE5",
    	"EQ_THRUSTERS_COUPLING_TYPE6", "EQ_THRUSTERS_COUPLING_TYPE7"
    ];
    this._fsCoupling = ["EQ_FORWARD_SHIELD_COUPLING_TYPE1", "EQ_FORWARD_SHIELD_COUPLING_TYPE2", "EQ_FORWARD_SHIELD_COUPLING_TYPE3", "EQ_FORWARD_SHIELD_COUPLING_TYPE4",
    	"EQ_FORWARD_SHIELD_COUPLING_TYPE5"
    ];
    this._asCoupling = ["EQ_AFT_SHIELD_COUPLING_TYPE1", "EQ_AFT_SHIELD_COUPLING_TYPE2", "EQ_AFT_SHIELD_COUPLING_TYPE3", "EQ_AFT_SHIELD_COUPLING_TYPE4", "EQ_AFT_SHIELD_COUPLING_TYPE5"];
    // these items will have a ship-size based price factor applied to their purchase price
    this._priceFactor = [].concat(this._engines).concat(this._boosters).concat(this._hyperdrive).concat(this._thrusters)
    	.concat(this._energy).concat(this._frontshields).concat(this._aftshields).concat(this._frontarmour).concat(this._aftarmour)
    	.concat(this._electricalbus).concat(this._hdCoupling).concat(this._enCoupling).concat(this._bsCoupling).concat(this._ebCoupling)
    	.concat(this._thCoupling).concat(this._fsCoupling).concat(this._asCoupling);
    
    this._equipCouplingBus = {
    	"EQ_THRUSTERS_TYPE1": "EQ_THRUSTERS_COUPLING_TYPE1",
    	"EQ_THRUSTERS_TYPE2A": "EQ_THRUSTERS_COUPLING_TYPE2",
    	"EQ_THRUSTERS_TYPE2B": "EQ_THRUSTERS_COUPLING_TYPE2",
    	"EQ_THRUSTERS_TYPE2C": "EQ_THRUSTERS_COUPLING_TYPE2",
    	"EQ_THRUSTERS_TYPE2D": "EQ_THRUSTERS_COUPLING_TYPE2",
    	"EQ_THRUSTERS_TYPE2E": "EQ_THRUSTERS_COUPLING_TYPE2",
    	"EQ_THRUSTERS_TYPE2F": "EQ_THRUSTERS_COUPLING_TYPE2",
    	"EQ_THRUSTERS_TYPE3A": "EQ_THRUSTERS_COUPLING_TYPE3",
    	"EQ_THRUSTERS_TYPE3B": "EQ_THRUSTERS_COUPLING_TYPE3",
    	"EQ_THRUSTERS_TYPE3C": "EQ_THRUSTERS_COUPLING_TYPE3",
    	"EQ_THRUSTERS_TYPE3D": "EQ_THRUSTERS_COUPLING_TYPE3",
    	"EQ_THRUSTERS_TYPE3E": "EQ_THRUSTERS_COUPLING_TYPE3",
    	"EQ_THRUSTERS_TYPE3F": "EQ_THRUSTERS_COUPLING_TYPE3",
    	"EQ_THRUSTERS_TYPE4A": "EQ_THRUSTERS_COUPLING_TYPE4",
    	"EQ_THRUSTERS_TYPE4B": "EQ_THRUSTERS_COUPLING_TYPE4",
    	"EQ_THRUSTERS_TYPE4C": "EQ_THRUSTERS_COUPLING_TYPE4",
    	"EQ_THRUSTERS_TYPE4D": "EQ_THRUSTERS_COUPLING_TYPE4",
    	"EQ_THRUSTERS_TYPE4E": "EQ_THRUSTERS_COUPLING_TYPE4",
    	"EQ_THRUSTERS_TYPE4F": "EQ_THRUSTERS_COUPLING_TYPE4",
    	"EQ_THRUSTERS_TYPE5A": "EQ_THRUSTERS_COUPLING_TYPE5",
    	"EQ_THRUSTERS_TYPE5B": "EQ_THRUSTERS_COUPLING_TYPE5",
    	"EQ_THRUSTERS_TYPE5C": "EQ_THRUSTERS_COUPLING_TYPE5",
    	"EQ_THRUSTERS_TYPE5D": "EQ_THRUSTERS_COUPLING_TYPE5",
    	"EQ_THRUSTERS_TYPE5E": "EQ_THRUSTERS_COUPLING_TYPE5",
    	"EQ_THRUSTERS_TYPE5F": "EQ_THRUSTERS_COUPLING_TYPE5",
    	"EQ_THRUSTERS_TYPE6A": "EQ_THRUSTERS_COUPLING_TYPE6",
    	"EQ_THRUSTERS_TYPE6B": "EQ_THRUSTERS_COUPLING_TYPE6",
    	"EQ_THRUSTERS_TYPE6C": "EQ_THRUSTERS_COUPLING_TYPE6",
    	"EQ_THRUSTERS_TYPE6D": "EQ_THRUSTERS_COUPLING_TYPE6",
    	"EQ_THRUSTERS_TYPE6E": "EQ_THRUSTERS_COUPLING_TYPE6",
    	"EQ_THRUSTERS_TYPE6F": "EQ_THRUSTERS_COUPLING_TYPE6",
    	"EQ_THRUSTERS_TYPE7A": "EQ_THRUSTERS_COUPLING_TYPE7",
    	"EQ_THRUSTERS_TYPE7B": "EQ_THRUSTERS_COUPLING_TYPE7",
    	"EQ_THRUSTERS_TYPE7C": "EQ_THRUSTERS_COUPLING_TYPE7",
    	"EQ_THRUSTERS_TYPE7D": "EQ_THRUSTERS_COUPLING_TYPE7",
    	"EQ_THRUSTERS_TYPE7E": "EQ_THRUSTERS_COUPLING_TYPE7",
    	"EQ_THRUSTERS_TYPE7F": "EQ_THRUSTERS_COUPLING_TYPE7",
    	"EQ_ENERGYBANK_TYPE1": "EQ_ENERGYBANK_COUPLING_TYPE1",
    	"EQ_ENERGYBANK_TYPE2": "EQ_ENERGYBANK_COUPLING_TYPE1",
    	"EQ_ENERGYBANK_TYPE3": "EQ_ENERGYBANK_COUPLING_TYPE1",
    	"EQ_ENERGYBANK_TYPE4": "EQ_ENERGYBANK_COUPLING_TYPE1",
    	"EQ_ENERGYBANK_TYPE5": "EQ_ENERGYBANK_COUPLING_TYPE2",
    	"EQ_ENERGYBANK_TYPE6": "EQ_ENERGYBANK_COUPLING_TYPE2",
    	"EQ_ENERGYBANK_TYPE7": "EQ_ENERGYBANK_COUPLING_TYPE2",
    	"EQ_ENERGYBANK_TYPE8": "EQ_ENERGYBANK_COUPLING_TYPE3",
    	"EQ_ENERGYBANK_TYPE9": "EQ_ENERGYBANK_COUPLING_TYPE3",
    	"EQ_ENERGYBANK_TYPE10": "EQ_ENERGYBANK_COUPLING_TYPE3",
    	"EQ_ENERGYBANK_TYPE11": "EQ_ENERGYBANK_COUPLING_TYPE4",
    	"EQ_ENERGYBANK_TYPE12": "EQ_ENERGYBANK_COUPLING_TYPE4",
    	"EQ_ENERGYBANK_TYPE13": "EQ_ENERGYBANK_COUPLING_TYPE4",
    	"EQ_ENERGYBANK_TYPE14": "EQ_ENERGYBANK_COUPLING_TYPE5",
    	"EQ_ENERGYBANK_TYPE15": "EQ_ENERGYBANK_COUPLING_TYPE5",
    	"EQ_ENERGYBANK_TYPE16": "EQ_ENERGYBANK_COUPLING_TYPE5",
    	"EQ_ENERGYBANK_TYPE17": "EQ_ENERGYBANK_COUPLING_TYPE6",
    	"EQ_ENERGYBANK_TYPE18": "EQ_ENERGYBANK_COUPLING_TYPE6",
    	"EQ_ENERGYBANK_TYPE19": "EQ_ENERGYBANK_COUPLING_TYPE6",
    	"EQ_ENERGYBANK_TYPE20": "EQ_ENERGYBANK_COUPLING_TYPE7",
    	"EQ_ENERGYBANK_TYPE21": "EQ_ENERGYBANK_COUPLING_TYPE7",
    	"EQ_ENERGYBANK_TYPE22": "EQ_ENERGYBANK_COUPLING_TYPE7",
    	"EQ_ENERGYBANK_TYPE23": "EQ_ENERGYBANK_COUPLING_TYPE8",
    	"EQ_ENERGYBANK_TYPE24": "EQ_ENERGYBANK_COUPLING_TYPE8",
    	"EQ_ENERGYBANK_TYPE25": "EQ_ENERGYBANK_COUPLING_TYPE8",
    	"EQ_ENERGYBANK_TYPE1A": "EQ_ENERGYBANK_COUPLING_TYPE1",
    	"EQ_ENERGYBANK_TYPE2A": "EQ_ENERGYBANK_COUPLING_TYPE1",
    	"EQ_ENERGYBANK_TYPE3A": "EQ_ENERGYBANK_COUPLING_TYPE1",
    	"EQ_ENERGYBANK_TYPE4A": "EQ_ENERGYBANK_COUPLING_TYPE1",
    	"EQ_ENERGYBANK_TYPE5A": "EQ_ENERGYBANK_COUPLING_TYPE2",
    	"EQ_ENERGYBANK_TYPE6A": "EQ_ENERGYBANK_COUPLING_TYPE2",
    	"EQ_ENERGYBANK_TYPE7A": "EQ_ENERGYBANK_COUPLING_TYPE2",
    	"EQ_ENERGYBANK_TYPE8A": "EQ_ENERGYBANK_COUPLING_TYPE3",
    	"EQ_ENERGYBANK_TYPE9A": "EQ_ENERGYBANK_COUPLING_TYPE3",
    	"EQ_ENERGYBANK_TYPE10A": "EQ_ENERGYBANK_COUPLING_TYPE3",
    	"EQ_ENERGYBANK_TYPE11A": "EQ_ENERGYBANK_COUPLING_TYPE4",
    	"EQ_ENERGYBANK_TYPE12A": "EQ_ENERGYBANK_COUPLING_TYPE4",
    	"EQ_ENERGYBANK_TYPE13A": "EQ_ENERGYBANK_COUPLING_TYPE4",
    	"EQ_ENERGYBANK_TYPE14A": "EQ_ENERGYBANK_COUPLING_TYPE5",
    	"EQ_ENERGYBANK_TYPE15A": "EQ_ENERGYBANK_COUPLING_TYPE5",
    	"EQ_ENERGYBANK_TYPE16A": "EQ_ENERGYBANK_COUPLING_TYPE5",
    	"EQ_ENERGYBANK_TYPE17A": "EQ_ENERGYBANK_COUPLING_TYPE6",
    	"EQ_ENERGYBANK_TYPE18A": "EQ_ENERGYBANK_COUPLING_TYPE6",
    	"EQ_ENERGYBANK_TYPE19A": "EQ_ENERGYBANK_COUPLING_TYPE6",
    	"EQ_ENERGYBANK_TYPE20A": "EQ_ENERGYBANK_COUPLING_TYPE7",
    	"EQ_ENERGYBANK_TYPE21A": "EQ_ENERGYBANK_COUPLING_TYPE7",
    	"EQ_ENERGYBANK_TYPE22A": "EQ_ENERGYBANK_COUPLING_TYPE7",
    	"EQ_ENERGYBANK_TYPE23A": "EQ_ENERGYBANK_COUPLING_TYPE8",
    	"EQ_ENERGYBANK_TYPE24A": "EQ_ENERGYBANK_COUPLING_TYPE8",
    	"EQ_ENERGYBANK_TYPE25A": "EQ_ENERGYBANK_COUPLING_TYPE8",
    };
    this._extensions = ["EQ_EXTENSION_1", "EQ_EXTENSION_2", "EQ_EXTENSION_5"];
    this._equipHeatList = {
    	"EQ_ENERGYBANK_TYPE1A": 0.004,
    	"EQ_ENERGYBANK_TYPE2A": 0.008,
    	"EQ_ENERGYBANK_TYPE3A": 0.012,
    	"EQ_ENERGYBANK_TYPE4A": 0.016,
    	"EQ_ENERGYBANK_TYPE5A": 0.02,
    	"EQ_ENERGYBANK_TYPE6A": 0.024,
    	"EQ_ENERGYBANK_TYPE7A": 0.028,
    	"EQ_ENERGYBANK_TYPE8A": 0.032,
    	"EQ_ENERGYBANK_TYPE9A": 0.036,
    	"EQ_ENERGYBANK_TYPE10A": 0.04,
    	"EQ_ENERGYBANK_TYPE11A": 0.044,
    	"EQ_ENERGYBANK_TYPE12A": 0.048,
    	"EQ_ENERGYBANK_TYPE13A": 0.052,
    	"EQ_ENERGYBANK_TYPE14A": 0.056,
    	"EQ_ENERGYBANK_TYPE15A": 0.06,
    	"EQ_ENERGYBANK_TYPE16A": 0.064,
    	"EQ_ENERGYBANK_TYPE17A": 0.068,
    	"EQ_ENERGYBANK_TYPE18A": 0.072,
    	"EQ_ENERGYBANK_TYPE19A": 0.076,
    	"EQ_ENERGYBANK_TYPE20A": 0.08,
    	"EQ_ENERGYBANK_TYPE21A": 0.084,
    	"EQ_ENERGYBANK_TYPE22A": 0.088,
    	"EQ_ENERGYBANK_TYPE23A": 0.092,
    	"EQ_ENERGYBANK_TYPE24A": 0.096,
    	"EQ_ENERGYBANK_TYPE25A": 0.1,
    	"EQ_ENGINE_TYPE1D": 0.02,
    	"EQ_ENGINE_TYPE1E": 0.02,
    	"EQ_ENGINE_TYPE1F": 0.02,
    	"EQ_ENGINE_TYPE2D": 0.04,
    	"EQ_ENGINE_TYPE2E": 0.04,
    	"EQ_ENGINE_TYPE2F": 0.04,
    	"EQ_ENGINE_TYPE3D": 0.06,
    	"EQ_ENGINE_TYPE3E": 0.06,
    	"EQ_ENGINE_TYPE3F": 0.06,
    	"EQ_ENGINE_TYPE4D": 0.08,
    	"EQ_ENGINE_TYPE4E": 0.08,
    	"EQ_ENGINE_TYPE4F": 0.08,
    	"EQ_ENGINE_TYPE5D": 0.1,
    	"EQ_ENGINE_TYPE5E": 0.1,
    	"EQ_ENGINE_TYPE5F": 0.1,
    	"EQ_ENGINE_TYPE6D": 0.12,
    	"EQ_ENGINE_TYPE6E": 0.12,
    	"EQ_ENGINE_TYPE6F": 0.12,
    	"EQ_ENGINE_TYPE7D": 0.14,
    	"EQ_ENGINE_TYPE7E": 0.14,
    	"EQ_ENGINE_TYPE7F": 0.14,
    	"EQ_THRUSTERS_TYPE2D": 0.0266,
    	"EQ_THRUSTERS_TYPE2E": 0.0266,
    	"EQ_THRUSTERS_TYPE2F": 0.0266,
    	"EQ_THRUSTERS_TYPE3D": 0.04,
    	"EQ_THRUSTERS_TYPE3E": 0.04,
    	"EQ_THRUSTERS_TYPE3F": 0.04,
    	"EQ_THRUSTERS_TYPE4D": 0.0533,
    	"EQ_THRUSTERS_TYPE4E": 0.0533,
    	"EQ_THRUSTERS_TYPE4F": 0.0533,
    	"EQ_THRUSTERS_TYPE5D": 0.0666,
    	"EQ_THRUSTERS_TYPE5E": 0.0666,
    	"EQ_THRUSTERS_TYPE5F": 0.0666,
    	"EQ_THRUSTERS_TYPE6D": 0.08,
    	"EQ_THRUSTERS_TYPE6E": 0.08,
    	"EQ_THRUSTERS_TYPE6F": 0.08,
    	"EQ_THRUSTERS_TYPE7D": 0.0933,
    	"EQ_THRUSTERS_TYPE7E": 0.0933,
    	"EQ_THRUSTERS_TYPE7F": 0.0933,
    };
    
    // this items will be suppressed on the "Sell Equipment" screen
    this._noSell = ["EQ_BREAKABLE_TORUSDRIVE", "EQ_BREAKABLE_HUD_IFF_SCANNER"];
    // array of rare equipment items that will require negotiation if they are sold
    this._sellNegotiate = [];
    
    // if any of these are installed, ship config won't allow its own armour to be installed
    this._altArmour = ["EQ_IRONHIDE", "EQ_HARDNOSE", "EQ_VERYHARDNOSE", "EQ_VERYVERYHARDNOSE", "EQ_HARDARMOUR_III", "EQ_HARDARMOUR_V", "EQ_HARDARMOUR_X"];
    
    this._shieldEquipment = ["EQ_SHIELD_BOOSTER", "EQ_NAVAL_SHIELD_BOOSTER", "EQ_NAVAL_GRID", "EQ_ENERGY_GRID"];
    
    // matrix consists of: equipment key, then space required (t), weight of item (t)
    // eg: "EQ_EQUIPMENTITEM":[space,weight]
    // items not on this list (and not in ignore list) will default to 1t space, 1t weight
    this._equipmentMatrix = {
    	"EQ_MISSILE": [0, 0.1],
    	"EQ_HARDENED_MISSILE": [0, 0.3],
    	"EQ_QC_MINE": [0, 0.2],
    	"EQ_WEAPON_PULSE_LASER": [0, 1],
    	"EQ_WEAPON_BEAM_LASER": [0, 2],
    	"EQ_WEAPON_MINING_LASER": [0, 1.5],
    	"EQ_WEAPON_MILITARY_LASER": [0, 3],
    	"EQ_PASSENGER_BERTH": [0, 5],
    	"EQ_CARGO_BAY": [0, 5],
    	"EQ_ECM": [1, 1],
    	"EQ_FUEL_SCOOPS": [0, 0],
    	"EQ_ESCAPE_POD": [0, 1],
    	"EQ_ENERGY_UNIT": [3, 3],
    	"EQ_NAVAL_ENERGY_UNIT": [5, 5],
    	"EQ_DOCK_COMP": [1, 1],
    	"EQ_GAL_DRIVE": [1, 1],
    	"EQ_CLOAKING_DEVICE": [1, 1],
    	"EQ_ADVANCED_COMPASS": [1, 1],
    	"EQ_WORMHOLE_SCANNER": [1, 1],
    	"EQ_SHIELD_BOOSTER": [4, 4],
    	"EQ_NAVAL_SHIELD_BOOSTER": [6, 6],
    	"EQ_MILITARY_SCANNER_FILTER": [4, 4],
    	"EQ_MILITARY_JAMMER": [4, 4],
    
    	"EQ_HYPERDRIVE_TYPE1": [1, 1],
    	"EQ_HYPERDRIVE_TYPE2": [2, 2],
    	"EQ_HYPERDRIVE_TYPE3": [5, 5],
    	"EQ_HYPERDRIVE_TYPE4": [8, 8],
    	"EQ_ENGINE_TYPE1A": [1, 1],
    	"EQ_ENGINE_TYPE1B": [1, 1],
    	"EQ_ENGINE_TYPE1C": [1, 1],
    	"EQ_ENGINE_TYPE1D": [0.5, 1],
    	"EQ_ENGINE_TYPE1E": [0.5, 1],
    	"EQ_ENGINE_TYPE1F": [0.5, 1],
    	"EQ_ENGINE_TYPE2A": [2, 2],
    	"EQ_ENGINE_TYPE2B": [2, 2],
    	"EQ_ENGINE_TYPE2C": [2, 2],
    	"EQ_ENGINE_TYPE2D": [1, 1.5],
    	"EQ_ENGINE_TYPE2E": [1, 1.5],
    	"EQ_ENGINE_TYPE2F": [1, 1.5],
    	"EQ_ENGINE_TYPE3A": [3, 3],
    	"EQ_ENGINE_TYPE3B": [3, 3],
    	"EQ_ENGINE_TYPE3C": [3, 3],
    	"EQ_ENGINE_TYPE3D": [1.5, 2],
    	"EQ_ENGINE_TYPE3E": [1.5, 2],
    	"EQ_ENGINE_TYPE3F": [1.5, 2],
    	"EQ_ENGINE_TYPE4A": [4, 3.5],
    	"EQ_ENGINE_TYPE4B": [4, 3.5],
    	"EQ_ENGINE_TYPE4C": [4, 3.5],
    	"EQ_ENGINE_TYPE4D": [2, 3],
    	"EQ_ENGINE_TYPE4E": [2, 3],
    	"EQ_ENGINE_TYPE4F": [2, 3],
    	"EQ_ENGINE_TYPE5A": [6, 4],
    	"EQ_ENGINE_TYPE5B": [6, 4],
    	"EQ_ENGINE_TYPE5C": [6, 4],
    	"EQ_ENGINE_TYPE5D": [3, 3.5],
    	"EQ_ENGINE_TYPE5E": [3, 3.5],
    	"EQ_ENGINE_TYPE5F": [3, 3.5],
    	"EQ_ENGINE_TYPE6A": [8, 5],
    	"EQ_ENGINE_TYPE6B": [8, 5],
    	"EQ_ENGINE_TYPE6C": [8, 5],
    	"EQ_ENGINE_TYPE6D": [4, 4],
    	"EQ_ENGINE_TYPE6E": [4, 4],
    	"EQ_ENGINE_TYPE6F": [4, 4],
    	"EQ_ENGINE_TYPE7A": [10, 6],
    	"EQ_ENGINE_TYPE7B": [10, 6],
    	"EQ_ENGINE_TYPE7C": [10, 6],
    	"EQ_ENGINE_TYPE7D": [5, 5],
    	"EQ_ENGINE_TYPE7E": [5, 5],
    	"EQ_ENGINE_TYPE7F": [5, 5],
    	"EQ_THRUSTERS_TYPE1": [0, 1],
    	"EQ_THRUSTERS_TYPE2A": [1, 2],
    	"EQ_THRUSTERS_TYPE2B": [1, 2],
    	"EQ_THRUSTERS_TYPE2C": [1, 2],
    	"EQ_THRUSTERS_TYPE2D": [0.5, 1],
    	"EQ_THRUSTERS_TYPE2E": [0.5, 1],
    	"EQ_THRUSTERS_TYPE2F": [0.5, 1],
    	"EQ_THRUSTERS_TYPE3A": [2, 3],
    	"EQ_THRUSTERS_TYPE3B": [2, 3],
    	"EQ_THRUSTERS_TYPE3C": [2, 3],
    	"EQ_THRUSTERS_TYPE3D": [1, 2],
    	"EQ_THRUSTERS_TYPE3E": [1, 2],
    	"EQ_THRUSTERS_TYPE3F": [1, 2],
    	"EQ_THRUSTERS_TYPE4A": [3, 3.5],
    	"EQ_THRUSTERS_TYPE4B": [3, 3.5],
    	"EQ_THRUSTERS_TYPE4C": [3, 3.5],
    	"EQ_THRUSTERS_TYPE4D": [1.5, 2.5],
    	"EQ_THRUSTERS_TYPE4E": [1.5, 2.5],
    	"EQ_THRUSTERS_TYPE4F": [1.5, 2.5],
    	"EQ_THRUSTERS_TYPE5A": [4, 4],
    	"EQ_THRUSTERS_TYPE5B": [4, 4],
    	"EQ_THRUSTERS_TYPE5C": [4, 4],
    	"EQ_THRUSTERS_TYPE5D": [2, 3],
    	"EQ_THRUSTERS_TYPE5E": [2, 3],
    	"EQ_THRUSTERS_TYPE5F": [2, 3],
    	"EQ_THRUSTERS_TYPE6A": [6, 4.5],
    	"EQ_THRUSTERS_TYPE6B": [6, 4.5],
    	"EQ_THRUSTERS_TYPE6C": [6, 4.5],
    	"EQ_THRUSTERS_TYPE6D": [3, 3.5],
    	"EQ_THRUSTERS_TYPE6E": [3, 3.5],
    	"EQ_THRUSTERS_TYPE6F": [3, 3.5],
    	"EQ_THRUSTERS_TYPE7A": [8, 5],
    	"EQ_THRUSTERS_TYPE7B": [8, 5],
    	"EQ_THRUSTERS_TYPE7C": [8, 5],
    	"EQ_THRUSTERS_TYPE7D": [4, 4],
    	"EQ_THRUSTERS_TYPE7E": [4, 4],
    	"EQ_THRUSTERS_TYPE7F": [4, 4],
    	"EQ_BOOSTERS_TYPE1": [1, 1],
    	"EQ_BOOSTERS_TYPE2": [1.5, 1.5],
    	"EQ_BOOSTERS_TYPE3": [2, 2],
    	"EQ_BOOSTERS_TYPE4": [2.5, 2.5],
    	"EQ_BOOSTERS_TYPE5": [3, 3],
    	"EQ_BOOSTERS_TYPE6": [3.5, 3.5],
    	"EQ_BOOSTERS_TYPE7": [4, 4],
    	"EQ_ENERGYBANK_TYPE1": [1, 1],
    	"EQ_ENERGYBANK_TYPE2": [2, 2],
    	"EQ_ENERGYBANK_TYPE3": [3, 3],
    	"EQ_ENERGYBANK_TYPE4": [4, 4],
    	"EQ_ENERGYBANK_TYPE5": [5, 5],
    	"EQ_ENERGYBANK_TYPE6": [6, 6],
    	"EQ_ENERGYBANK_TYPE7": [7, 7],
    	"EQ_ENERGYBANK_TYPE8": [8, 8],
    	"EQ_ENERGYBANK_TYPE9": [9, 9],
    	"EQ_ENERGYBANK_TYPE10": [10, 10],
    	"EQ_ENERGYBANK_TYPE11": [11, 11],
    	"EQ_ENERGYBANK_TYPE12": [12, 12],
    	"EQ_ENERGYBANK_TYPE13": [13, 13],
    	"EQ_ENERGYBANK_TYPE14": [14, 14],
    	"EQ_ENERGYBANK_TYPE15": [15, 15],
    	"EQ_ENERGYBANK_TYPE16": [16, 16],
    	"EQ_ENERGYBANK_TYPE17": [17, 17],
    	"EQ_ENERGYBANK_TYPE18": [18, 18],
    	"EQ_ENERGYBANK_TYPE19": [19, 19],
    	"EQ_ENERGYBANK_TYPE20": [20, 20],
    	"EQ_ENERGYBANK_TYPE21": [21, 21],
    	"EQ_ENERGYBANK_TYPE22": [22, 22],
    	"EQ_ENERGYBANK_TYPE23": [23, 23],
    	"EQ_ENERGYBANK_TYPE24": [24, 24],
    	"EQ_ENERGYBANK_TYPE25": [25, 25],
    	"EQ_ENERGYBANK_TYPE1A": [0.5, 1],
    	"EQ_ENERGYBANK_TYPE2A": [1, 2],
    	"EQ_ENERGYBANK_TYPE3A": [1.5, 3],
    	"EQ_ENERGYBANK_TYPE4A": [2, 4],
    	"EQ_ENERGYBANK_TYPE5A": [2.5, 5],
    	"EQ_ENERGYBANK_TYPE6A": [3, 6],
    	"EQ_ENERGYBANK_TYPE7A": [3.5, 7],
    	"EQ_ENERGYBANK_TYPE8A": [4, 8],
    	"EQ_ENERGYBANK_TYPE9A": [4.5, 9],
    	"EQ_ENERGYBANK_TYPE10A": [5, 10],
    	"EQ_ENERGYBANK_TYPE11A": [5.5, 11],
    	"EQ_ENERGYBANK_TYPE12A": [6, 12],
    	"EQ_ENERGYBANK_TYPE13A": [6.5, 13],
    	"EQ_ENERGYBANK_TYPE14A": [7, 14],
    	"EQ_ENERGYBANK_TYPE15A": [7.5, 15],
    	"EQ_ENERGYBANK_TYPE16A": [8, 16],
    	"EQ_ENERGYBANK_TYPE17A": [8.5, 17],
    	"EQ_ENERGYBANK_TYPE18A": [9, 18],
    	"EQ_ENERGYBANK_TYPE19A": [9.5, 19],
    	"EQ_ENERGYBANK_TYPE20A": [10, 20],
    	"EQ_ENERGYBANK_TYPE21A": [10.5, 21],
    	"EQ_ENERGYBANK_TYPE22A": [11, 22],
    	"EQ_ENERGYBANK_TYPE23A": [11.5, 23],
    	"EQ_ENERGYBANK_TYPE24A": [12, 24],
    	"EQ_ENERGYBANK_TYPE25A": [12.5, 25],
    	"EQ_NO_FORWARD_SHIELD": [0, 0],
    	"EQ_FORWARD_SHIELD_TYPE1": [1, 1],
    	"EQ_FORWARD_SHIELD_TYPE2": [2, 2],
    	"EQ_FORWARD_SHIELD_TYPE3": [3, 3],
    	"EQ_FORWARD_SHIELD_TYPE4": [4, 4],
    	"EQ_FORWARD_SHIELD_TYPE5": [5, 5],
    	"EQ_NO_AFT_SHIELD": [0, 0],
    	"EQ_AFT_SHIELD_TYPE1": [1, 1],
    	"EQ_AFT_SHIELD_TYPE2": [2, 2],
    	"EQ_AFT_SHIELD_TYPE3": [3, 3],
    	"EQ_AFT_SHIELD_TYPE4": [4, 4],
    	"EQ_AFT_SHIELD_TYPE5": [5, 5],
    	"EQ_HEAT_SHIELD_TYPE1": [0, 1],
    	"EQ_HEAT_SHIELD_TYPE2": [0, 3],
    	"EQ_HEAT_SHIELD_TYPE3": [0, 6],
    	"EQ_HEAT_SHIELD_TYPE4": [0, 9],
    	"EQ_HEAT_SHIELD_TYPE5": [0, 12],
    	"EQ_HEAT_SHIELD_TYPE6": [0, 16],
    	"EQ_FUEL_INJECTION_TYPE1": [0.5, 1],
    	"EQ_FUEL_INJECTION_TYPE2": [1, 2],
    	"EQ_FUEL_INJECTION_TYPE3": [2, 3],
    	"EQ_FUEL_INJECTION_TYPE4": [4, 5],
    	"EQ_FUEL_SCOOPS_TYPE1": [0, 2],
    	"EQ_FUEL_SCOOPS_TYPE2": [0, 4],
    	"EQ_FUEL_SCOOPS_TYPE3": [0, 6],
    	"EQ_FUEL_SCOOPS_TYPE4": [0, 8],
    	"EQ_ARMOUR_TYPE1": [0, 0], // obsolete
    	"EQ_ARMOUR_TYPE2": [0, 0], // obsolete
    	"EQ_ARMOUR_TYPE3": [0, 0], // obsolete
    	"EQ_ARMOUR_TYPE4": [0, 0], // obsolete
    	"EQ_ARMOUR_TYPE5": [0, 0], // obsolete
    	"EQ_ARMOUR_TYPE6": [0, 0], // obsolete
    	"EQ_ARMOUR_TYPE7": [0, 0], // obsolete
    	"EQ_ARMOUR_FORWARD_TYPE1": [0, 2],
    	"EQ_ARMOUR_FORWARD_TYPE2": [0, 7],
    	"EQ_ARMOUR_FORWARD_TYPE3": [0, 15],
    	"EQ_ARMOUR_FORWARD_TYPE4": [0, 25],
    	"EQ_ARMOUR_FORWARD_TYPE5": [0, 40],
    	"EQ_ARMOUR_FORWARD_TYPE6": [0, 52],
    	"EQ_ARMOUR_FORWARD_TYPE7": [0, 70],
    	"EQ_ARMOUR_AFT_TYPE1": [0, 2],
    	"EQ_ARMOUR_AFT_TYPE2": [0, 7],
    	"EQ_ARMOUR_AFT_TYPE3": [0, 15],
    	"EQ_ARMOUR_AFT_TYPE4": [0, 25],
    	"EQ_ARMOUR_AFT_TYPE5": [0, 40],
    	"EQ_ARMOUR_AFT_TYPE6": [0, 52],
    	"EQ_ARMOUR_AFT_TYPE7": [0, 70],
    	"EQ_ELEC_BUS_TYPE1": [0, 1],
    	"EQ_ELEC_BUS_TYPE2": [0, 4],
    	"EQ_ELEC_BUS_TYPE3": [2, 7],
    	"EQ_ELEC_BUS_TYPE4": [4, 12],
    	"EQ_ELEC_BUS_TYPE5": [6, 17],
    	"EQ_ELEC_BUS_TYPE6": [8, 23],
    	"EQ_ELEC_BUS_TYPE7": [10, 30],
    	"EQ_HYPERDRIVE_COUPLING_TYPE1": [0, 0.1],
    	"EQ_HYPERDRIVE_COUPLING_TYPE2": [0, 0.2],
    	"EQ_HYPERDRIVE_COUPLING_TYPE3": [0, 0.3],
    	"EQ_HYPERDRIVE_COUPLING_TYPE4": [0, 0.4],
    	"EQ_ENGINE_COUPLING_TYPE1": [0, 0.1],
    	"EQ_ENGINE_COUPLING_TYPE2": [0, 0.2],
    	"EQ_ENGINE_COUPLING_TYPE3": [0, 0.3],
    	"EQ_ENGINE_COUPLING_TYPE4": [0, 0.4],
    	"EQ_ENGINE_COUPLING_TYPE5": [0, 0.5],
    	"EQ_ENGINE_COUPLING_TYPE6": [0, 0.6],
    	"EQ_ENGINE_COUPLING_TYPE7": [0, 0.7],
    	"EQ_BOOSTERS_COUPLING_TYPE1": [0, 0.1],
    	"EQ_BOOSTERS_COUPLING_TYPE2": [0, 0.2],
    	"EQ_BOOSTERS_COUPLING_TYPE3": [0, 0.3],
    	"EQ_BOOSTERS_COUPLING_TYPE4": [0, 0.4],
    	"EQ_BOOSTERS_COUPLING_TYPE5": [0, 0.5],
    	"EQ_BOOSTERS_COUPLING_TYPE6": [0, 0.6],
    	"EQ_BOOSTERS_COUPLING_TYPE7": [0, 0.7],
    	"EQ_ENERGYBANK_COUPLING_TYPE1": [0, 0.1],
    	"EQ_ENERGYBANK_COUPLING_TYPE2": [0, 0.2],
    	"EQ_ENERGYBANK_COUPLING_TYPE3": [0, 0.3],
    	"EQ_ENERGYBANK_COUPLING_TYPE4": [0, 0.4],
    	"EQ_ENERGYBANK_COUPLING_TYPE5": [0, 0.5],
    	"EQ_ENERGYBANK_COUPLING_TYPE6": [0, 0.6],
    	"EQ_ENERGYBANK_COUPLING_TYPE7": [0, 0.7],
    	"EQ_ENERGYBANK_COUPLING_TYPE8": [0, 0.8],
    	"EQ_THRUSTERS_COUPLING_TYPE1": [0, 0.1],
    	"EQ_THRUSTERS_COUPLING_TYPE2": [0, 0.2],
    	"EQ_THRUSTERS_COUPLING_TYPE3": [0, 0.3],
    	"EQ_THRUSTERS_COUPLING_TYPE4": [0, 0.4],
    	"EQ_THRUSTERS_COUPLING_TYPE5": [0, 0.5],
    	"EQ_THRUSTERS_COUPLING_TYPE6": [0, 0.6],
    	"EQ_THRUSTERS_COUPLING_TYPE7": [0, 0.7],
    	"EQ_FORWARD_SHIELD_COUPLING_TYPE1": [0, 0.1],
    	"EQ_FORWARD_SHIELD_COUPLING_TYPE2": [0, 0.2],
    	"EQ_FORWARD_SHIELD_COUPLING_TYPE3": [0, 0.3],
    	"EQ_FORWARD_SHIELD_COUPLING_TYPE4": [0, 0.4],
    	"EQ_FORWARD_SHIELD_COUPLING_TYPE5": [0, 0.5],
    	"EQ_AFT_SHIELD_COUPLING_TYPE1": [0, 0.1],
    	"EQ_AFT_SHIELD_COUPLING_TYPE2": [0, 0.2],
    	"EQ_AFT_SHIELD_COUPLING_TYPE3": [0, 0.3],
    	"EQ_AFT_SHIELD_COUPLING_TYPE4": [0, 0.4],
    	"EQ_AFT_SHIELD_COUPLING_TYPE5": [0, 0.5],
    
    	"EQ_ADDITIONAL_AFT_ARMOUR": [0, 3],
    	"EQ_ADDITIONAL_CORE_HULL": [0, 5],
    	"EQ_ADDITIONAL_FRONT_ARMOUR": [0, 3],
    	"EQ_ADV_NAV_COMP": [1, 1],
    	"EQ_AFT_SHIELD_CAPACITOR": [2, 2],
    	"EQ_AMS": [0, 3],
    	"EQ_ANTISAPPER": [3, 3],
    	"EQ_APRIL": [0, 2],
    	"EQ_APRIL_EXPANSION": [0, 2],
    	"EQ_APRIL_NPC_MISSILE": [0, 2],
    	"EQ_AQUATICS_1_GUARDIAN": [3, 3],
    	"EQ_AQUATICS_1_JAMMER_MINE": [0, 0.1],
    	"EQ_AQUATICS_1_TRIDENT_MISSILE": [0, 0.2],
    	"EQ_AQUATICS_CLOAK": [1, 1],
    	"EQ_AQUATICS_GUARDIAN": [2, 2],
    	"EQ_AQUATICS_JAMMER_MINE": [0, 0.1],
    	"EQ_AQUATICS_TRIDENT_MISSILE": [0, 0.2],
    	"EQ_ARMOURY_BUGBOMB_MINE": [0, 0.3],
    	"EQ_ARMOURY_BUZZBOMB_MINE": [0, 0.2],
    	"EQ_ARMOURY_CUTPURSE_MISSILE": [0, 0.2],
    	"EQ_ARMOURY_DECOY_MINE": [0, 0.5],
    	"EQ_ARMOURY_DISPLACER_MISSILE": [0, 0.3],
    	"EQ_ARMOURY_FIELD_MISSILE": [0, 0.3],
    	"EQ_ARMOURY_HARD_MISSILE": [0, 0.2],
    	"EQ_ARMOURY_INTERDICTOR_MINE": [0, 0.2],
    	"EQ_ARMOURY_KICKER_MISSILE": [0, 0.2],
    	"EQ_ARMOURY_MISSILEMACHINE_MINE": [0, 2],
    	"EQ_ARMOURY_SCREAMER_MINE": [0, 0.3],
    	"EQ_ARMOURY_STANDARD_MISSILE": [0, 0.1],
    	"EQ_ARMOURY_STUNBOMB_MINE": [0, 0.2],
    	"EQ_ARMOURY_TRACKER_MISSILE": [0, 0.5],
    	"EQ_ARMOURY_UNIBOMB_MINE": [0, 0.3],
    	"EQ_ATDRONE_LAUNCHER_MINE": [0, 0.2],
    	"EQ_AUTO_SKIMMER": [1, 1],
    	"EQ_AUX_TANK": [3, 3],
    	"EQ_BEACONLAUNCHER_MINE": [0, 0.1],
    	"EQ_BEACON_DEVICE": [0.5, 0.5],
    	"EQ_BEACON_MISSILE": [0, 0.1],
    	"EQ_BEERCOOLER": [0.1, 0.1],
    	"EQ_BIGSHCAP": [12, 12],
    	"EQ_BIGSHCAP2": [14, 14],
    	"EQ_BREAKABLE_TORUSDRIVE": [1, 1],
    	"EQ_CARGO_SCANNER": [1, 1],
    	"EQ_CARGO_SHEPHERD_MINE": [0.5, 0.5],
    	"EQ_CDRONE_LAUNCHER_MINE": [0, 0.2],
    	"EQ_CRIPPLED_CLOAKING": [1, 1],
    	"EQ_CT_CONVERT": [3, 3],
    	"EQ_CT_DRONE_1": [2, 2],
    	"EQ_CT_DRONE_2": [2, 2],
    	"EQ_CT_DRONE_3": [2, 2],
    	"EQ_CT_DRONE_4": [2, 2],
    	"EQ_CT_MINE": [0, 0.3],
    	"EQ_DREDGER_SALVAGE_MISSILE": [0, 0.2],
    	"EQ_DUMMY1": [0, 1],
    	"EQ_DUMMY10": [0, 10],
    	"EQ_DUMMY100": [0, 100],
    	"EQ_DUMMY5": [0, 5],
    	"EQ_DUMMY50": [0, 50],
    	"EQ_ECD_MINE": [0, 0.3],
    	"EQ_EEG": [1, 1],
    	"EQ_EEU": [3, 3],
    	"EQ_ELECTRONICS_BOX": [1, 3],
    	"EQ_ENERGY_BOMB": [0, 0.2],
    	"EQ_ENERGY_GRID": [3, 3],
    	"EQ_EQUIPMENT_BOX": [2, 5],
    	"EQ_ERB": [1, 1],
    	"EQ_ESG": [3, 3],
    	"EQ_FEUDAL_FLARE_MINE": [0, 0.1],
    	"EQ_FORWARD_SHIELD_CAPACITOR": [2, 2],
    	"EQ_FTL_TORUS": [3, 3],
    	"EQ_FTL_TORUS2": [3, 3],
    	"EQ_FUELTANK_MINE": [3, 3],
    	"EQ_GAL_DRIVE_MINE": [0, 0.1],
    	"EQ_GRAVSCANNER": [2, 4],
    	"EQ_GRAVSCANNER2": [3, 6],
    	"EQ_HARDARMOUR_III": [0, 5],
    	"EQ_HARDARMOUR_V": [0, 8],
    	"EQ_HARDARMOUR_X": [0, 10],
    	"EQ_HARDNOSE": [0, 1],
    	"EQ_HARDSHIELD_1": [2, 4],
    	"EQ_HARDSHIELD_10": [11, 22],
    	"EQ_HARDSHIELD_2": [3, 6],
    	"EQ_HARDSHIELD_3": [4, 8],
    	"EQ_HARDSHIELD_4": [5, 10],
    	"EQ_HARDSHIELD_5": [6, 12],
    	"EQ_HARDSHIELD_6": [7, 14],
    	"EQ_HARDSHIELD_7": [8, 16],
    	"EQ_HARDSHIELD_8": [9, 18],
    	"EQ_HARDSHIELD_9": [10, 20],
    	"EQ_HRACK_1_MISSILE": [0, 0.2],
    	"EQ_HRACK_2_MISSILE": [0, 0.3],
    	"EQ_HRACK_3_MISSILE": [0, 0.4],
    	"EQ_HTCAT": [2, 2],
    	"EQ_Headlights": [0, 0.3],
    	"EQ_INJECTOR_BOX": [2, 2],
    	"EQ_IRACK_1_MISSILE": [0, 0.2],
    	"EQ_IRACK_2_MISSILE": [0, 0.3],
    	"EQ_IRACK_3_MISSILE": [0, 0.4],
    	"EQ_IRONHIDE": [0, 5], // will need script to adjust for mil version
    	"EQ_I_MISSILE": [0, 0.3],
    	"EQ_KDRONE_LAUNCHER_MINE": [0, 0.3],
    	"EQ_LARGEDISH": [3, 10],
    	"EQ_LASERBOOSTER": [1, 1],
    	"EQ_LASERREDUCTOR": [1, 1],
    	"EQ_LASER_COOLER": [5, 5],
    	"EQ_LASER_COUPLER": [0, 2],
    	"EQ_LASER_STABILISER": [0, 2],
    	"EQ_LBOOST_BEAM_AFT": [0, 2],
    	"EQ_LBOOST_BEAM_FWD": [0, 2],
    	"EQ_LBOOST_BEAM_PORT": [0, 2],
    	"EQ_LBOOST_BEAM_STAR": [0, 2],
    	"EQ_LBOOST_MILITARY_AFT": [0, 3],
    	"EQ_LBOOST_MILITARY_FWD": [0, 3],
    	"EQ_LBOOST_MILITARY_PORT": [0, 3],
    	"EQ_LBOOST_MILITARY_STAR": [0, 3],
    	"EQ_LBOOST_MINING_AFT": [0, 1.5],
    	"EQ_LBOOST_MINING_FWD": [0, 1.5],
    	"EQ_LBOOST_MINING_PORT": [0, 1.5],
    	"EQ_LBOOST_MINING_STAR": [0, 1.5],
    	"EQ_LBOOST_PULSE_AFT": [0, 1],
    	"EQ_LBOOST_PULSE_FWD": [0, 1],
    	"EQ_LBOOST_PULSE_PORT": [0, 1],
    	"EQ_LBOOST_PULSE_STAR": [0, 1],
    	"EQ_LIFE_BOX": [3, 3],
    	"EQ_LMSS_ACTIVATOR": [0, 1],
    	"EQ_LMSS_AFT": [0, 1],
    	"EQ_LMSS_FRONT": [0, 1],
    	"EQ_LMSS_PORT": [0, 1],
    	"EQ_LMSS_STARBOARD": [0, 1],
    	"EQ_LONG_RANGE_SCANNER": [2, 2],
    	"EQ_MANIF_SCANNER": [1, 1],
    	"EQ_MICRO_G_TORUS": [2, 2],
    	"EQ_MICRO_G_TORUS2": [2, 2],
    	"EQ_MILITARYTARGETTINGSYSTEM": [1, 1],
    	"EQ_MIL_INJECTION": [3, 3],
    	"EQ_MISJUMP_ANALYSER": [1, 1],
    	"EQ_MISSILE_ANALYSER": [1, 1],
    	"EQ_MURPH_THARGOID_DRIVE": [1, 1],
    	"EQ_NAVAL_GRID": [5, 5],
    	"EQ_NEXUS_BASIC_MISSILE": [0, 0.3],
    	"EQ_NEXUS_BUG_MISSILE": [0, 0.4],
    	"EQ_NEXUS_BUG_R_MISSILE": [0, 0.4],
    	"EQ_NEXUS_PREMIUM_MISSILE": [0, 0.4],
    	"EQ_NEXUS_ULTIMATE_MISSILE": [0, 0.5],
    	"EQ_NRACK_1_MISSILE": [0, 0.2],
    	"EQ_NRACK_2_MISSILE": [0, 0.3],
    	"EQ_NRACK_3_MISSILE": [0, 0.4],
    	"EQ_OCZ_CORONALHARVESTER": [2, 0],
    	"EQ_ORE_PROCESSOR": [0, 5],
    	"EQ_ORE_SCANNER": [1, 2],
    	"EQ_HARDWIRE_ORE_PROCESSOR": [0, 0.1],
    	"EQ_PHASE_SCANNER": [2, 2],
    	"EQ_PLANETFALL": [0, 5],
    	"EQ_PROBE_LAUNCHER_MINE": [0, 0.2],
    	"EQ_Q-CHARGER": [2, 2],
    	"EQ_QTHI_AuxEnergyGenerator": [0, 4],
    	"EQ_QTHI_AuxEnergyGeneratorHT": [0, 4],
    	"EQ_QTHI_AuxEnergyGeneratorHv": [0, 6],
    	"EQ_QTHI_AuxEnergyGeneratorLt": [2, 2],
    	"EQ_RAILGUN_1": [0, 1],
    	"EQ_RAILGUN_2": [0, 1.5],
    	"EQ_RAILGUN_3": [0, 2],
    	"EQ_RAILGUN_4": [0, 2.5],
    	"EQ_REG": [1, 1],
    	"EQ_REPAIRBOTS_CONTROLLER": [2, 2],
    	"EQ_REPAIRBOTS_MINE": [0, 0.1],
    	"EQ_RESCUE_MISSILE": [0, 2],
    	"EQ_RESERVE_TANK": [1, 1],
    	"EQ_RETROROCKETS": [0, 3],
    	"EQ_RMB_CASCADE_MISSILE": [0, 0.3],
    	"EQ_RMB_CHAFF_LAUNCHER": [0, 0.3],
    	"EQ_RMB_DEFENCE_MINE": [0, 0.4],
    	"EQ_RMB_DISTRESS_MINE": [0, 0.2],
    	"EQ_RMB_FRAG_MINE": [0, 0.3],
    	"EQ_RMB_FRAG_MISSILE": [0, 0.3],
    	"EQ_RMB_INTERCEPT_MISSILE": [0, 0.2],
    	"EQ_RMB_LAW_MISSILE": [0, 0.3],
    	"EQ_RMB_OVERRIDE_MISSILE": [0, 0.3],
    	"EQ_RMB_REMOTE_MINE": [0, 0.5],
    	"EQ_RMB_THARGOID_MISSILE": [0, 0.4],
    	"EQ_ROCKHERMIT_SCANNER": [1, 1],
    	"EQ_RRS_ASC": [1, 1],
    	"EQ_RRS_DOCK_COMP": [1, 1],
    	"EQ_RRS_HEAT_SHIELD": [0, 3],
    	"EQ_RRS_SCOOPS": [0, 2],
    	"EQ_RRS_SOLAR_MINE": [0, 2],
    	"EQ_SAPPERMODE": [0, 1],
    	"EQ_SAPPERNULLIFIER": [5, 5],
    	"EQ_SC_SHIELD_CYCLER_ADVANCED": [3, 3],
    	"EQ_SC_SHIELD_CYCLER_BASIC": [1, 1],
    	"EQ_SC_SHIELD_CYCLER_STANDARD": [2, 2],
    	"EQ_SHIELD_BOX": [5, 5],
    	"EQ_SHIELD_EQUALIZER": [2, 2],
    	"EQ_SHIPMINER": [1, 1],
    	"EQ_SHIPMINERASSISTANT": [0.5, 0.5],
    	"EQ_SMALLDISH": [1, 5],
    	"EQ_SMUGGLING_COMPARTMENT_1": [0, 1],
    	"EQ_SMUGGLING_COMPARTMENT_10": [0, 5],
    	"EQ_SMUGGLING_COMPARTMENT_11": [0, 6],
    	"EQ_SMUGGLING_COMPARTMENT_12": [0, 6],
    	"EQ_SMUGGLING_COMPARTMENT_13": [0, 7],
    	"EQ_SMUGGLING_COMPARTMENT_14": [0, 7],
    	"EQ_SMUGGLING_COMPARTMENT_15": [0, 8],
    	"EQ_SMUGGLING_COMPARTMENT_16": [0, 8],
    	"EQ_SMUGGLING_COMPARTMENT_17": [0, 9],
    	"EQ_SMUGGLING_COMPARTMENT_18": [0, 9],
    	"EQ_SMUGGLING_COMPARTMENT_19": [0, 10],
    	"EQ_SMUGGLING_COMPARTMENT_2": [0, 1],
    	"EQ_SMUGGLING_COMPARTMENT_20": [0, 10],
    	"EQ_SMUGGLING_COMPARTMENT_3": [0, 2],
    	"EQ_SMUGGLING_COMPARTMENT_4": [0, 2],
    	"EQ_SMUGGLING_COMPARTMENT_5": [0, 3],
    	"EQ_SMUGGLING_COMPARTMENT_6": [0, 3],
    	"EQ_SMUGGLING_COMPARTMENT_7": [0, 4],
    	"EQ_SMUGGLING_COMPARTMENT_8": [0, 4],
    	"EQ_SMUGGLING_COMPARTMENT_9": [0, 5],
    	"EQ_SRACK_1_MISSILE": [0, 0.2],
    	"EQ_SRACK_2_MISSILE": [0, 0.3],
    	"EQ_SRACK_3_MISSILE": [0, 0.4],
    	"EQ_SUWITCHDRIVE": [2, 2],
    	"EQ_SUWITCHDRIVESPARECOILS": [1, 1],
    	"EQ_TELESCOPE": [1, 1],
    	"EQ_TOWBAR": [1, 1],
    	"EQ_TOWBARINJ": [0.5, 0.5],
    	"EQ_TOWBARREPAIRBOT": [0.5, 0.5],
    	"EQ_TOWBARSTAB_MINE": [0, 0.1],
    	"EQ_TRACKERCAM_MINE": [0, 0.2],
    	"EQ_TUGDRONE_MISSILE": [0, 0.3],
    	"EQ_UPS_POLICE_SCANNER": [0.3, 0.3],
    	"EQ_UPS_UNIVERSAL_SCANNER": [0.5, 0.5],
    	"EQ_VACUUM_PUMP": [0, 1],
    	"EQ_VERYHARDNOSE": [0, 3],
    	"EQ_VERYVERYHARDNOSE": [0, 5],
    	"EQ_WARHEAD_MINE": [0, 0.2],
    	"EQ_WEAPON_ANDERSON_LASER": [0, 3],
    	"EQ_WEAPON_ASSAULT_LASER": [0, 2],
    	"EQ_WEAPON_BEAM_LASER_2": [0, 4],
    	"EQ_WEAPON_BEAM_LASER_3": [0, 6],
    	"EQ_WEAPON_BEAM_LASER_4": [0, 8],
    	"EQ_WEAPON_BEAM_LASER_5": [0, 10],
    	"EQ_WEAPON_BLAST_LASER": [0, 1.5],
    	"EQ_WEAPON_BURST_LASER": [0, 2],
    	"EQ_WEAPON_CANNON_1": [0, 0.5],
    	"EQ_WEAPON_CANNON_10": [0, 3],
    	"EQ_WEAPON_CANNON_10_2": [0, 6],
    	"EQ_WEAPON_CANNON_10_3": [0, 9],
    	"EQ_WEAPON_CANNON_10_4": [0, 12],
    	"EQ_WEAPON_CANNON_10_5": [0, 15],
    	"EQ_WEAPON_CANNON_11": [1, 8],
    	"EQ_WEAPON_CANNON_11_2": [2, 16],
    	"EQ_WEAPON_CANNON_11_3": [3, 24],
    	"EQ_WEAPON_CANNON_11_4": [4, 32],
    	"EQ_WEAPON_CANNON_11_5": [5, 40],
    	"EQ_WEAPON_CANNON_12": [2, 10],
    	"EQ_WEAPON_CANNON_13": [2, 12],
    	"EQ_WEAPON_CANNON_14": [3, 15],
    	"EQ_WEAPON_CANNON_15": [3, 20],
    	"EQ_WEAPON_CANNON_16": [3, 15],
    	"EQ_WEAPON_CANNON_17": [5, 30],
    	"EQ_WEAPON_CANNON_18": [8, 40],
    	"EQ_WEAPON_CANNON_2": [0, 2],
    	"EQ_WEAPON_CANNON_2_2": [0, 4],
    	"EQ_WEAPON_CANNON_2_3": [0, 6],
    	"EQ_WEAPON_CANNON_2_4": [0, 8],
    	"EQ_WEAPON_CANNON_2_5": [0, 10],
    	"EQ_WEAPON_CANNON_3": [0, 3],
    	"EQ_WEAPON_CANNON_4": [0, 4],
    	"EQ_WEAPON_CANNON_4_2": [0, 8],
    	"EQ_WEAPON_CANNON_4_3": [0, 12],
    	"EQ_WEAPON_CANNON_4_4": [0, 16],
    	"EQ_WEAPON_CANNON_4_5": [0, 20],
    	"EQ_WEAPON_CANNON_5": [0, 6],
    	"EQ_WEAPON_CANNON_6": [0, 3],
    	"EQ_WEAPON_CANNON_7": [0, 3],
    	"EQ_WEAPON_CANNON_7_2": [0, 6],
    	"EQ_WEAPON_CANNON_7_3": [0, 9],
    	"EQ_WEAPON_CANNON_7_4": [0, 12],
    	"EQ_WEAPON_CANNON_7_5": [0, 15],
    	"EQ_WEAPON_CANNON_8": [0, 5],
    	"EQ_WEAPON_CANNON_9": [1, 6],
    	"EQ_WEAPON_CANNON_EA": [0, 5],
    	"EQ_WEAPON_CANNON_EA_2": [0, 10],
    	"EQ_WEAPON_CANNON_EA_3": [0, 15],
    	"EQ_WEAPON_CANNON_EA_4": [0, 20],
    	"EQ_WEAPON_CANNON_EA_5": [0, 25],
    	"EQ_WEAPON_CANNON_ECO": [0, 1],
    	"EQ_WEAPON_CANNON_ECO_2": [0, 2],
    	"EQ_WEAPON_CANNON_ECO_3": [0, 3],
    	"EQ_WEAPON_CANNON_ECO_4": [0, 4],
    	"EQ_WEAPON_CANNON_ECO_5": [0, 5],
    	"EQ_WEAPON_CANNON_HEAVY_SAPPER": [0, 5],
    	"EQ_WEAPON_CANNON_HEAVY_SNIPER_GUN": [0, 5],
    	"EQ_WEAPON_CANNON_HEAVY_SNIPER_GUN_2": [0, 10],
    	"EQ_WEAPON_CANNON_HEAVY_SNIPER_GUN_3": [0, 15],
    	"EQ_WEAPON_CANNON_HEAVY_SNIPER_GUN_4": [0, 20],
    	"EQ_WEAPON_CANNON_HEAVY_SNIPER_GUN_5": [0, 25],
    	"EQ_WEAPON_CANNON_SAPPER": [0, 3],
    	"EQ_WEAPON_CANNON_SNIPER_GUN": [0, 3],
    	"EQ_WEAPON_CANNON_SNIPER_GUN_2": [0, 6],
    	"EQ_WEAPON_CANNON_SNIPER_GUN_3": [0, 9],
    	"EQ_WEAPON_CANNON_SNIPER_GUN_4": [0, 12],
    	"EQ_WEAPON_CANNON_SNIPER_GUN_5": [0, 15],
    	"EQ_WEAPON_DEXM_LASER": [0, 3],
    	"EQ_WEAPON_DUAL_LASER": [0, 2],
    	"EQ_WEAPON_EBEAM_LASER": [0, 2],
    	"EQ_WEAPON_ECO_LASER": [0, 1],
    	"EQ_WEAPON_ECO_LASER_2": [0, 2],
    	"EQ_WEAPON_ECO_LASER_3": [0, 3],
    	"EQ_WEAPON_ECO_LASER_4": [0, 4],
    	"EQ_WEAPON_ECO_LASER_5": [0, 5],
    	"EQ_WEAPON_ECO_REACTOR": [0, 2],
    	"EQ_WEAPON_ECO_REACTOR_2": [0, 4],
    	"EQ_WEAPON_ECO_REACTOR_3": [0, 6],
    	"EQ_WEAPON_ECO_REACTOR_4": [0, 8],
    	"EQ_WEAPON_ECO_REACTOR_5": [0, 10],
    	"EQ_WEAPON_EMILITARY_LASER": [0, 3],
    	"EQ_WEAPON_EPULSE_LASER": [0, 1],
    	"EQ_WEAPON_FRONTIER_LASER": [0, 2],
    	"EQ_WEAPON_GATLING_LASER_1": [0, 1],
    	"EQ_WEAPON_GATLING_LASER_2": [0, 1.5],
    	"EQ_WEAPON_GATLING_LASER_3": [0, 2],
    	"EQ_WEAPON_GATLING_LASER_4": [0, 2.5],
    	"EQ_WEAPON_GATLING_LASER_5": [0, 3],
    	"EQ_WEAPON_HIRAD_LASER": [0, 2],
    	"EQ_WEAPON_HVARISCAN_LASER": [0, 1.5],
    	"EQ_WEAPON_JKMINING_LASER": [0, 1.5],
    	"EQ_WEAPON_LUCAS_LASER": [0, 2.5],
    	"EQ_WEAPON_MILITARY_LASER_2": [0, 6],
    	"EQ_WEAPON_MILITARY_LASER_3": [0, 9],
    	"EQ_WEAPON_MILITARY_LASER_4": [0, 12],
    	"EQ_WEAPON_MILITARY_LASER_5": [0, 15],
    	"EQ_WEAPON_PULSE_LASER_2": [0, 2],
    	"EQ_WEAPON_PULSE_LASER_3": [0, 3],
    	"EQ_WEAPON_PULSE_LASER_4": [0, 4],
    	"EQ_WEAPON_PULSE_LASER_5": [0, 5],
    	"EQ_WEAPON_QVC_LASER": [0, 3],
    	"EQ_WEAPON_RIMMERACE_LASER": [0, 3],
    	"EQ_WEAPON_STAR_LASER": [0, 2],
    	"EQ_WEAPON_VARISCAN_LASER": [0, 1.5],
    	"EQ_WEAPON_WILLIAMS_LASER": [0, 2],
    	"EQ_WEAPON_ZEUSCORP_LASER": [0, 2.5],
    	"EQ_XS_SWORD_MISSILE": [0, 0.1],
    	"EQ_X_SWORD_A_MISSILE": [0, 0.1],
    	"EQ_X_SWORD_MISSILE": [0, 0.1],
    	"EQ_AM18_HYPERDRIVE": [0.5, 0.5],
    	"EQ_HZ_HYPERDRIVE": [0.8, 0.8],
    	"EQ_TURBULEN_HYPEDRIVE": [1, 1],
    	"EQ_PROSSET_HYPERDRIVE": [2, 2],
    	"EQ_AMES_HYPERDRIVE": [2.5, 2.5],
    	"EQ_TITRONIX_HYPERDRIVE": [3, 3],
    	"EQ_IRRIKAN_HYPERDRIVE": [4, 4],
    	"EQ_CARGO_TARGETER": [0.5, 0.5],
    	"EQ_VECTOR_SPACELANE": [0.2, 0.2],
    	"EQ_VECTOR_FUNA_MISSILE": [0, 0.2],
    	"EQ_VECTOR_FUNB_MISSILE": [0, 0.3],
    	"EQ_VECTOR_FUNC_MISSILE": [0, 0.4],
    	"EQ_VECTOR_AREIDIS_SCANNER": [1.5, 1.5],
    	"EQ_VECTOR_EMP_MINE": [0, 1.5],
    	"EQ_VECTOR_SCOOPS": [0, 1],
    	"EQ_TARGET_AUTOLOCK": [0, 0],
    };
    
    //-------------------------------------------------------------------------------------------------------------
    this.$addCallback = function $addCallback(obj) {
    	this._callbacks.push(obj);
    }
    
    //=============================================================================================================
    // system functions
    
    //-------------------------------------------------------------------------------------------------------------
    this.startUp = function () {
    	if (this._disabled === true) {
    		delete this.equipmentAdded;
    		delete this.equipmentRemoved;
    		delete this.playerBoughtEquipment;
    		delete this.missionScreenOpportunity;
    		delete this.missionScreenEnded;
    		delete this.equipmentDamaged;
    		delete this.equipmentRepaired;
    		delete this.playerBoughtNewShip;
    		delete this.guiScreenChanged;
    		delete this.guiScreenWillChange;
    		delete this.shipDockedWithStation;
    		delete this.shipWillLaunchFromStation;
    		delete this.shipLaunchedFromStation;
    		delete this.playerStartedJumpCountdown;
    		delete this.playerStartedAutoPilot;
    		delete this.shipDied;
    		delete this.shipTakingDamage;
    		delete this.shipSpawned;
    		delete this.shipFiredMissile;
    		delete this.shipScoopedOther;
    		delete this.playerRescuedEscapePod;
    		delete this.startUpComplete;
    		delete this.startUp;
    		return;
    	}
    
    	this._armour = [].concat(this._frontarmour).concat(this._aftarmour);
    
    	var p = player.ship;
    	var oldarmour = ["EQ_ARMOUR_TYPE1", "EQ_ARMOUR_TYPE2", "EQ_ARMOUR_TYPE3", "EQ_ARMOUR_TYPE4", "EQ_ARMOUR_TYPE5", "EQ_ARMOUR_TYPE6", "EQ_ARMOUR_TYPE7"];
    	for (var i = 0; i < oldarmour.length; i++) {
    		if (player.ship.equipmentStatus(oldarmour[i]) === "EQUIPMENT_OK") {
    			p.awardEquipment("EQ_ARMOUR_FORWARD_TYPE" + (i + 1));
    			p.awardEquipment("EQ_ARMOUR_AFT_TYPE" + (i + 1));
    			p.removeEquipment(oldarmour[i]);
    		}
    	}
    
    	// look for any equipment items that have a weight/space value set in script info
    	this.$addEquipmentDataFromScriptInfo();
    	// look for any ships that have an equipment space or power to weight ratio set in script info
    	this.$addShipDataFromScriptInfo();
    	// add essential equipment to the "no sell" list - do it programmatically, rather than hardcoding equipment keys,
    	// so if we ever expand the list they'll get added automatically
    	this.$populateNoSellList();
    
    	if (worldScripts.ShipRespray) this._shipRespray = true;
    	if (worldScripts.Synchronised_Torus) this._torusSync = true;
    
    	// if the station dock control is installed, add a callback to tell it to check for launched ships
    	if (worldScripts.StationDockControl && worldScripts.StationDockControl._disable == false) {
    		this.$addCallback(worldScripts.StationDockControl.$checkForLaunchedShips.bind(worldScripts.StationDockControl));
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.startUpComplete = function () {
    	// register our settings, if Lib_Config is present
    	if (worldScripts.Lib_Config) worldScripts.Lib_Config._registerSet(this._scConfig);
    
    	if (worldScripts.EmailSystem) {
    		var ga = worldScripts.GalCopAdminServices;
    		for (var i = 1; i <= 7; i++) {
    			ga._maint_repair_equip.push("EQ_ARMOUR_FORWARD_TYPE" + i + "_REPAIR");
    			ga._maint_repair_equip.push("EQ_ARMOUR_AFT_TYPE" + i + "_REPAIR");
    		}
    	}
    
    	var hy = worldScripts.Hyperdrives;
    	if (hy) this._OXPHyperdrives = true;
    
    	// remove the main config equip item from any new purchase emails
    	var w = worldScripts.GalCopAdminServices;
    	if (w) w._purchase_ignore_equip.push("EQ_SHIPCONFIG");
    
    	if (worldScripts.NPC_Equipment_Damage) {
    		var npcEq = worldScripts.NPC_Equipment_Damage
    		// add in our equipmentdamaged processing event to the NPC damaged handler array
    		npcEq.NPC_equipmentDamagedHandlers.push(this.$equipmentDamaged_Event);
    	}
    
    	var p = player.ship;
    	// add base equipment items if this is the first time
    	this._initialSetup = this.$installBaseEquipment(p);
    	// check that there is space for all equipment
    	// if not, we need to remove something, so load up the sell equipment screen
    	this._promptPlayer = !this.$addEquipmentSpaceItem(p);
    
    	// set up the interface screen, if required
    	this.$initInterface(p.dockedStation);
    	this._startUp = false;
    
    	this.$setUpScriptConfig();
    
    	if (this._OXPHyperdrives === true) {
    		// make sure we remove any SC hyperdrives if the player has installed the Hyperdrives OXP
    		for (var i = 0; i < this._hyperdrive.length; i++) {
    			p.removeEquipment(this._hyperdrive[i]);
    		}
    		for (var i = 0; i < this._hdCoupling.length; i++) {
    			p.removeEquipment(this._hdCoupling[i]);
    		}
    	}
    
    	// tap into shipresprays pre/post function calls
    	if (this._shipRespray) {
    		var sr = worldScripts.ShipRespray;
    		if (sr.$addPreSprayCall) {
    			sr.$addPreSprayCall(this.name, "$preResprayFunction");
    			sr.$addPostSprayCall(this.name, "$postResprayFunction");
    		}
    	}
    
    	// monkey patch combat sim so we can do some pre-launch work done
    	if (worldScripts["Combat Simulator"]) {
    		worldScripts["Combat Simulator"]._startFight = this.$combatSim_startFight;
    	}
    
    	// check to see if hyperspace hangar is installed
    	if (worldScripts.HyperspaceHangar) this._hyperHangar = true;
    
    	// load up or repopulate the current equipment list (so we know what's brand new and what's used)
    	if (missionVariables.ShipConfiguration_CurrentEquip) {
    		this._currEquip = JSON.parse(missionVariables.ShipConfiguration_CurrentEquip);
    		delete missionVariables.ShipConfiguration_CurrentEquip;
    	} else {
    		this._currEquip = [];
    		var eq = player.ship.equipment;
    		for (var i = 0; i < eq.length; i++) {
    			this._currEquip.push(eq[i].equipmentKey);
    		}
    	}
    	if (missionVariables.ShipConfiguration_BoosterSound) this._disableBoosterSound = (this._trueValues.indexOf(missionVariables.ShipConfiguration_BoosterSound) >= 0 ? true : false);
    	if (missionVariables.ShipConfiguration_DisableF3HUD) this._disableF3HUD = (this._trueValues.indexOf(missionVariables.ShipConfiguration_DisableF3HUD) >= 0 ? true : false);
    	if (missionVariables.ShipConfiguration_ApplyToNPC) this._applyToNPC = (this._trueValues.indexOf(missionVariables.ShipConfiguration_ApplyToNPC) >= 0 ? true : false);
    	if (missionVariables.ShipConfiguration_FreeUpgrades) this._freeUpgrades = (this._trueValues.indexOf(missionVariables.ShipConfiguration_FreeUpgrades) >= 0 ? true : false);
    	if (missionVariables.ShipConfiguration_InstallationTime) this._installationTime = (this._trueValues.indexOf(missionVariables.ShipConfiguration_InstallationTime) >= 0 ? true : false);
    	
    	// upgraded features in v1.84
    	if (0 < oolite.compareVersion("1.84")) {
    		delete this.shipDumpedCargo;
    	} else {
    		delete this.shipSpawned;
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.playerWillSaveGame = function () {
    	missionVariables.ShipConfiguration_CurrentEquip = JSON.stringify(this._currEquip);
    	missionVariables.ShipConfiguration_BoosterSound = this._disableBoosterSound;
    	missionVariables.ShipConfiguration_DisableF3HUD = this._disableF3HUD;
    	missionVariables.ShipConfiguration_ApplyToNPC = this._applyToNPC;
    	missionVariables.ShipConfiguration_FreeUpgrades = this._freeUpgrades;
    	missionVariables.ShipConfiguration_InstallationTime = this._installationTime;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipDockedWithStation = function (station) {
    	this.$stopTimers();
    	this.$initInterface(station);
    
    	// re-load the current equipment list so we know what's used
    	this._currEquip.length = 0;
    	var eq = player.ship.equipment;
    	for (var i = 0; i < eq.length; i++) {
    		this._currEquip.push(eq[i].equipmentKey);
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipDied = function (whom, why) {
    	this.$stopTimers();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.missionScreenOpportunity = function () {
    	// looks like we need to ask the player to remove some equipment
    	if (this._promptPlayer === true) {
    		this._promptPlayer = false;
    		this._page = 0;
    		this.$sellEquipment();
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.equipmentDamaged = function (equipmentKey) {
    	// we're attaching the equipmentDamaged_Event to the script object of the player, so NPC Equipment failure can be implemented more simply.
    	if (player.ship && player.ship.script) {
    		// check to see if we've been set up yet
    		if (!player.ship.script.$equipmentDamaged_Event) this.$setUpScriptConfig();
    		if (player.ship.script.$equipmentDamaged_Event) player.ship.script.$equipmentDamaged_Event(equipmentKey);
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.equipmentRepaired = function (equipmentKey) {
    
    	if (this._repairing === true) return;
    	if (this._damaging === true) return;
    
    	this._repairing = true;
    
    	// look for cases where equipment was repaired in flight
    	var p = player.ship;
    
    	if (equipmentKey === "EQ_HEAT_SINK") {
    		if (p.equipmentStatus("EQ_HEAT_SINK_CONTROL") != "EQUIPMENT_OK") {
    			if (worldScripts.ShipConfiguration_HeatSink.controlMode === 0) {
    				p.awardEquipment("EQ_HEAT_SINK_CONTROL");
    			} else {
    				p.awardEquipment("EQ_HEAT_SINK_CONTROL_PASSIVE");
    			}
    		}
    		this._repairing = false;
    		return;
    	}
    
    	/*if (p.docked === false) {
    		// can't repair shield boosters until shields are fixed
    		if ((equipmentKey === "EQ_NAVAL_SHIELD_BOOSTER" || equipmentKey === "EQ_SHIELD_BOOSTER" || equipmentKey === "EQ_NAVAL_GRID" || equipmentKey === "EQ_ENERGY_GRID")
    			&& (p.equipmentStatus(this.$equipmentItemInUse("frontshields", p)) != "EQUIPMENT_OK" || p.equipmentStatus(this.$equipmentItemInUse("aftshields", p)) != "EQUIPMENT_OK")) {
    			this._damaging = true;
    			p.setEquipmentStatus(equipmentKey, "EQUIPMENT_DAMAGED");
    			this._damaging = false;
    			equipmentKey = "";
    		}
    		// can't repair extra energy units until main unit is bank online
    		if ((equipmentKey === "EQ_ENERGY_UNIT" || equipmentKey === "EQ_NAVAL_ENERGY_UNIT" || equipmentKey === "EQ_NAVAL_GRID" || equipmentKey === "EQ_ENERGY_GRID")
    			&& p.equipmentStatus(this.$equipmentItemInUse("energy", p)) != "EQUIPMENT_OK") {
    			this._damaging = true;
    			p.setEquipmentStatus(equipmentKey, "EQUIPMENT_DAMAGED");
    			this._damaging = false;
    			equipmentKey = "";
    		}
    	} */
    	if (this._engines.indexOf(equipmentKey) >= 0) {
    		p.maxSpeed = this.$calculatedValue("speed", p);
    		p.maxThrust = this.$calculatedValue("thrust", p);
    		p.thrust = p.maxThrust;
    	}
    	if (this._thrusters.indexOf(equipmentKey) >= 0) {
    		p.maxPitch = this.$calculatedValue("pitch", p);
    		p.maxRoll = this.$calculatedValue("roll", p);
    	}
    	if (this._boosters.indexOf(equipmentKey) >= 0) {
    		var boostEq = EquipmentInfo.infoForKey(equipmentKey);
    		p.script._boosterHeatPoint = boostEq.scriptInfo.heat_buildup;
    		p.maxSpeed = this.$calculatedValue("speed", p);
    		p.maxThrust = this.$calculatedValue("thrust", p);
    		p.thrust = p.maxThrust;
    		p.maxPitch = this.$calculatedValue("pitch", p);
    		p.maxRoll = this.$calculatedValue("roll", p);
    		p.maxYaw = this.$calculatedValue("yaw", p);
    	}
    	if (this._energy.indexOf(equipmentKey) >= 0) {
    		p.energyRechargeRate = p.script._energyRechargeRate_Stored;
    		p.script._energyRechargeRate_Stored = 0;
    	}
    	if (this._frontshields.indexOf(equipmentKey) >= 0) {
    		p.forwardShieldRechargeRate = p.script._forwardShieldRechargeRate_Stored;
    		p.script._forwardShieldRechargeRate_Stored = 0;
    		this.$enableShieldOXPs();
    	}
    	if (this._aftshields.indexOf(equipmentKey) >= 0) {
    		p.aftShieldRechargeRate = p.script._aftshieldsRechargeRate_Stored;
    		p.script._aftshieldsRechargeRate_Stored = 0;
    		this.$enableShieldOXPs();
    	}
    	if (this._heatshields.indexOf(equipmentKey) >= 0) {
    		p.awardEquipment("EQ_HEAT_SHIELD");
    		var info = EquipmentInfo.infoForKey(equipmentKey);
    		var shipspec = Ship.shipDataForKey(p.dataKey);
    		var shipdef = 1;
    		if (typeof shipspec["heat_insulation"] != "undefined") shipdef = parseFloat(shipspec["heat_insulation"]);
    		p.heatInsulation = shipdef + parseFloat(info.scriptInfo.oolite_heat_insulation_strength);
    	}
    	if (equipmentKey === "EQ_HEAT_SHIELD") {
    		p.setEquipmentStatus(this.$equipmentItemInUse("heatshields", p), "EQUIPMENT_OK");
    		var info = EquipmentInfo.infoForKey(equipmentKey);
    		p.heatInsulation += info.scriptInfo.oolite_heat_insulation_strength;
    	}
    	if (this._fuelinjectors.indexOf(equipmentKey) >= 0) {
    		// can't repair injectors until main engines are repaired
    		if (p.equipmentStatus(this.$equipmentItemInUse("engines", p)) != "EQUIPMENT_OK") {
    			this._damaging = true;
    			p.setEquipmentStatus(equipmentKey, "EQUIPMENT_DAMAGED");
    			this._damaging = false;
    			this._repairing = false;
    			return;
    		}
    		p.setEquipmentStatus("EQ_FUEL_INJECTION", "EQUIPMENT_OK");
    	}
    	// special case for when an OXP repairs the fuel injectors directly
    	if (equipmentKey === "EQ_FUEL_INJECTION") {
    		p.setEquipmentStatus(this.$equipmentItemInUse("fuelinjectors", p), "EQUIPMENT_OK");
    	}
    	if (this._fuelscoops.indexOf(equipmentKey) >= 0) {
    		p.setEquipmentStatus("EQ_FUEL_SCOOPS", "EQUIPMENT_OK");
    	}
    	// special case for when an OXP repairs the fuel scoops directly
    	if (equipmentKey === "EQ_FUEL_SCOOPS") {
    		p.setEquipmentStatus(this.$equipmentItemInUse("fuelscoops", p), "EQUIPMENT_OK");
    	}
    
    	this._repairing = false;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.playerBoughtNewShip = function (ship, price) {
    	//log(this.name, "playerBoughtNewShip - " + ship);
    	if (this._resprayActive === true) return;
    	if (this._simulator === true) return;
    	this.$setUpScriptConfig();
    	this._current = {};
    	this._startUp = true;
    	var result = this.$installBaseEquipment(ship);
    	this._startUp = false;
    	this.equipmentAdded("");
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.playerBoughtEquipment = function (equipmentKey) {
    	if (equipmentKey === "EQ_HEAT_SINK") {
    		if (player.ship.equipmentStatus("EQ_HEAT_SINK_CONTROL") != "EQUIPMENT_OK") {
    			worldScripts.ShipConfiguration_HeatSink.controlMode = 0;
    			player.ship.awardEquipment("EQ_HEAT_SINK_CONTROL");
    		}
    	}
    
    	this._sellEquipExitScreen === "GUI_SCREEN_EQUIP_SHIP";
    
    	if (equipmentKey === "EQ_SHIPCONFIG") {
    		player.ship.removeEquipment(equipmentKey);
    		this._lastChoice = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""];
    		this._source = "";
    		this._display = 0;
    		this._page = 0;
    		this.$shipConfig();
    		return;
    	}
    	// armour repair handled in it's own script
    	if (equipmentKey.indexOf("_REPAIR") >= 0) return;
    
    	if (this._promptPlayer === true) {
    		this.missionScreenOpportunity();
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.equipmentAdded = function (equipmentKey) {
    
    	//if (this._simulator === true) return;
    
    	// make sure we don't end up in a perpetual loop
    	if (this._startUp === true) return;
    	if (this._removing === true) return;
    	if (this._adding === true) return;
    
    	// ignore any of the filler items
    	if (this._filler.indexOf(equipmentKey) >= 0) return;
    
    	// ignore any removal equipment items
    	if (equipmentKey.indexOf("REMOVE") > 0 || equipmentKey.indexOf("REMOVAL") > 0 || equipmentKey.indexOf("REFUND") > 0 ||
    		equipmentKey.indexOf("_DAMAGED") > 0 || equipmentKey.indexOf("_REPAIR") > 0) return;
    	if (this._ignoreEquip.indexOf(equipmentKey) >= 0) return;
    
    	this._adding = true;
    
    	var p = player.ship;
    
    	// special cases for the equipment items we're overriding. If another OXP ever adds these items, we need to also add our specialised item
    	if (equipmentKey === "EQ_FUEL_INJECTION" && p.alertCondition === 0) {
    		p.awardEquipment("EQ_FUEL_INJECTION_TYPE2");
    		this._adding = false;
    		return;
    	}
    	if (equipmentKey === "EQ_HEAT_SHIELD" && p.alertCondition === 0) {
    		p.awardEquipment("EQ_HEAT_SHIELD_TYPE2");
    		this._adding = false;
    		return;
    	}
    	if (equipmentKey === "EQ_FUEL_SCOOPS" && p.alertCondition === 0) {
    		p.awardEquipment("EQ_FUEL_SCOOPS_TYPE1");
    		this._adding = false;
    		return;
    	}
    
    	// ignore anything that's not visible
    	if (equipmentKey != "" && equipmentKey != "EQ_NO_FORWARD_SHIELD" && equipmentKey != "EQ_NO_AFT_SHIELD") {
    		var eqinfo = EquipmentInfo.infoForKey(equipmentKey);
    		if (eqinfo && eqinfo.isVisible === false) return;
    		if (!eqinfo && this._debug) log(this.name, "!!ERROR: No equipmentInfo for equipment key " + equipmentKey);
    	}
    	var stn = p.dockedStation;
    	var equipSpace = this.$equipmentSpaceTotal(p);
    	var cargoSpace = this.$cargoSpaceAvailable(p);
    
    	// if we're installing one of the replacement items, make a note of it so we can remove it
    	var original = "";
    	var state = "";
    	var originalSpace = 0;
    	var applyPF = true;
    
    	if (this._electricalbus.indexOf(equipmentKey) >= 0) {
    		var check = "";
    		for (var i = 0; i < this._electricalbus.length; i++) {
    			if (this._electricalbus[i] != equipmentKey) {
    				check = p.equipmentStatus(this._electricalbus[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._electricalbus[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    
    	if (this._hyperdrive.indexOf(equipmentKey) >= 0) {
    		var check = "";
    		for (var i = 0; i < this._hyperdrive.length; i++) {
    			if (this._hyperdrive[i] != equipmentKey) {
    				check = p.equipmentStatus(this._hyperdrive[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._hyperdrive[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    	if (this._hdCoupling.indexOf(equipmentKey) >= 0) {
    		var check = "";
    		for (var i = 0; i < this._hdCoupling.length; i++) {
    			if (this._hdCoupling[i] != equipmentKey) {
    				check = p.equipmentStatus(this._hdCoupling[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._hdCoupling[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    	if (this._engines.indexOf(equipmentKey) >= 0) {
    		var check = "";
    		for (var i = 0; i < this._engines.length; i++) {
    			if (this._engines[i] != equipmentKey) {
    				check = p.equipmentStatus(this._engines[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._engines[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    	if (this._enCoupling.indexOf(equipmentKey) >= 0) {
    		var check = "";
    		for (var i = 0; i < this._enCoupling.length; i++) {
    			if (this._enCoupling[i] != equipmentKey) {
    				check = p.equipmentStatus(this._enCoupling[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._enCoupling[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    	if (this._thrusters.indexOf(equipmentKey) >= 0) {
    		var check = "";
    		for (var i = 0; i < this._thrusters.length; i++) {
    			if (this._thrusters[i] != equipmentKey) {
    				check = p.equipmentStatus(this._thrusters[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._thrusters[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    	if (this._thCoupling.indexOf(equipmentKey) >= 0) {
    		var check = "";
    		for (var i = 0; i < this._thCoupling.length; i++) {
    			if (this._thCoupling[i] != equipmentKey) {
    				check = p.equipmentStatus(this._thCoupling[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._thCoupling[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    	if (this._boosters.indexOf(equipmentKey) >= 0) {
    		var check = "";
    		for (var i = 0; i < this._boosters.length; i++) {
    			if (this._boosters[i] != equipmentKey) {
    				check = p.equipmentStatus(this._boosters[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._boosters[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    	if (this._bsCoupling.indexOf(equipmentKey) >= 0) {
    		var check = "";
    		for (var i = 0; i < this._bsCoupling.length; i++) {
    			if (this._bsCoupling[i] != equipmentKey) {
    				check = p.equipmentStatus(this._bsCoupling[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._bsCoupling[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    	if (this._energy.indexOf(equipmentKey) >= 0) {
    		var check = "";
    		for (var i = 0; i < this._energy.length; i++) {
    			if (this._energy[i] != equipmentKey) {
    				check = p.equipmentStatus(this._energy[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._energy[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    	if (this._ebCoupling.indexOf(equipmentKey) >= 0) {
    		var check = "";
    		for (var i = 0; i < this._ebCoupling.length; i++) {
    			if (this._ebCoupling[i] != equipmentKey) {
    				check = p.equipmentStatus(this._ebCoupling[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._ebCoupling[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    	if (this._frontshields.indexOf(equipmentKey) >= 0) {
    		var check = "";
    		for (var i = 0; i < this._frontshields.length; i++) {
    			if (this._frontshields[i] != equipmentKey) {
    				check = p.equipmentStatus(this._frontshields[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._frontshields[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    	if (this._fsCoupling.indexOf(equipmentKey) >= 0) {
    		var check = "";
    		for (var i = 0; i < this._fsCoupling.length; i++) {
    			if (this._fsCoupling[i] != equipmentKey) {
    				check = p.equipmentStatus(this._fsCoupling[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._fsCoupling[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    	if (this._aftshields.indexOf(equipmentKey) >= 0) {
    		var check = "";
    		for (var i = 0; i < this._aftshields.length; i++) {
    			if (this._aftshields[i] != equipmentKey) {
    				check = p.equipmentStatus(this._aftshields[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._aftshields[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    	if (this._asCoupling.indexOf(equipmentKey) >= 0) {
    		var check = "";
    		for (var i = 0; i < this._asCoupling.length; i++) {
    			if (this._asCoupling[i] != equipmentKey) {
    				check = p.equipmentStatus(this._asCoupling[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._asCoupling[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    	if (this._heatshields.indexOf(equipmentKey) >= 0) {
    		applyPF = false;
    		p.awardEquipment("EQ_HEAT_SHIELD");
    		var check = "";
    		for (var i = 0; i < this._heatshields.length; i++) {
    			if (this._heatshields[i] != equipmentKey) {
    				check = p.equipmentStatus(this._heatshields[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._heatshields[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    	if (this._fuelinjectors.indexOf(equipmentKey) >= 0) {
    		applyPF = false;
    		p.awardEquipment("EQ_FUEL_INJECTION");
    		var check = "";
    		for (var i = 0; i < this._fuelinjectors.length; i++) {
    			if (this._fuelinjectors[i] != equipmentKey) {
    				check = p.equipmentStatus(this._fuelinjectors[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._fuelinjectors[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    	if (this._fuelscoops.indexOf(equipmentKey) >= 0) {
    		applyPF = false;
    		p.awardEquipment("EQ_FUEL_SCOOPS");
    		var check = "";
    		for (var i = 0; i < this._fuelscoops.length; i++) {
    			if (this._fuelscoops[i] != equipmentKey) {
    				check = p.equipmentStatus(this._fuelscoops[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._fuelscoops[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    	if (this._frontarmour.indexOf(equipmentKey) >= 0) {
    		var check = "";
    		for (var i = 0; i < this._frontarmour.length; i++) {
    			if (this._frontarmour[i] != equipmentKey) {
    				check = p.equipmentStatus(this._frontarmour[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._frontarmour[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    	if (this._aftarmour.indexOf(equipmentKey) >= 0) {
    		var check = "";
    		for (var i = 0; i < this._aftarmour.length; i++) {
    			if (this._aftarmour[i] != equipmentKey) {
    				check = p.equipmentStatus(this._aftarmour[i]);
    				if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    					original = this._aftarmour[i];
    					originalSpace = this._equipmentMatrix[original][0];
    					state = check;
    				}
    			}
    		}
    	}
    
    	// remove and refund old equipment
    	if (original != "") {
    		// is this new or used? idx === -1 means new, otherwise any number >= 0 means used
    		var idx = this._currEquip.indexOf(original);
    		if (idx >= 0) this._currEquip.splice(idx, 1);
    
    		if (this._freeUpgrades === false) {
    			var oldinfo = EquipmentInfo.infoForKey(original);
    			var priceFactor = this.$equipmentPriceFactor(p.shipClassName, this.$getShipMass(p));
    			if (applyPF === false) priceFactor = 1;
    			if (state === "EQUIPMENT_OK") {
    				player.credits += ((oldinfo.price / 10) * priceFactor) * (idx >= 0 ? this._refundPct : 1) * (stn.equivalentTechLevel >= oldinfo.techLevel ? stn.equipmentPriceFactor : 1);
    			} else {
    				// only refund half if it's damaged
    				player.credits += ((oldinfo.price / 10) * priceFactor) * 0.5 * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1);
    			}
    		}
    		if (this._debug) log(this.name, "Removing " + original);
    		p.removeEquipment(original);
    	}
    
    	this.$checkForOverload();
    
    	/*var used = this.$calcEquipmentSpace(p);
    	if (used > equipSpace) {
    		// allocate cargo space to equipment space
    		var diff = parseInt(used - equipSpace);
    		if (diff > cargoSpace) {
    			// we don't have space for this
    			// switch into "overloaded" mode so the player can choose what item to remove
    			this._initialSetup = true;
    			this._promptPlayer = true;
    		}
    	}*/
    
    	this.$addEquipmentSpaceItem(p);
    	this._adding = false;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.equipmentRemoved = function (equipmentKey) {
    
    	//if (this._simulator === true) return;
    
    	// make sure we don't end up in a perpetual loop
    	if (this._adding === true) return;
    	if (this._removing === true) return;
    
    	// ignore any of the filler items
    	if (this._filler.indexOf(equipmentKey) >= 0) return;
    
    	// special case for IronHide Armour - clear out the mission variables as well as the equipment.
    	if (equipmentKey === "EQ_IRONHIDE") {
    		missionVariables.ironHide_percentage = 0;
    		missionVariables.ironHide_milFlag = 0;
    		mission.setInstructionsKey(null, "IronHide Armour Script");
    	}
    	// ignore any removal equipment items
    	if (equipmentKey.indexOf("REMOVE") > 0 || equipmentKey.indexOf("REMOVAL") > 0 || equipmentKey.indexOf("REFUND") > 0 ||
    		equipmentKey.indexOf("_DAMAGED") > 0 || equipmentKey.indexOf("_REPAIR") > 0) return;
    
    	// armour handled in it's own script
    	if (this._armour.indexOf(equipmentKey) >= 0) return;
    
    	if (equipmentKey === "EQ_HEAT_SINK") {
    		if (player.ship.equipmentStatus("EQ_HEAT_SINK") != "EQUIPMENT_OK") {
    			player.ship.removeEquipment("EQ_HEAT_SINK_CONTROL");
    			player.ship.removeEquipment("EQ_HEAT_SINK_CONTROL_PASSIVE");
    		}
    	}
    
    	// special cases for when an OXP removes these items directly
    	if (equipmentKey === "EQ_FUEL_INJECTION" && player.ship.docked) {
    		this._removing = true;
    		var fieq = this.$equipmentItemInUse("fuelinjectors", player.ship);
    		if (fieq != "") player.ship.removeEquipment(fieq);
    		this._removing = false;
    		return;
    	}
    	if (equipmentKey === "EQ_FUEL_SCOOPS" && player.ship.docked) {
    		this._removing = true;
    		var fseq = this.$equipmentItemInUse("fuelscoops", player.ship);
    		if (fseq != "") player.ship.removeEquipment(fseq);
    		this._removing = false;
    		return;
    	}
    	if (equipmentKey === "EQ_HEAT_SHIELD" && player.ship.docked) {
    		this._removing = true;
    		var hseq = this.$equipmentItemInUse("heatshields", player.ship);
    		if (hseq != "") player.ship.removeEquipment(hseq);
    		this._removing = false;
    		return;
    	}
    
    	if (this._ignoreEquip.indexOf(equipmentKey) >= 0) return;
    	if (equipmentKey === "EQ_SHIPCONFIG") return;
    
    	var p = player.ship;
    
    	this._removing = true;
    
    	// if we're removing fuel injectors, remove the core equipment item as well
    	if (this._fuelinjectors.indexOf(equipmentKey) >= 0) {
    		p.removeEquipment("EQ_FUEL_INJECTION");
    	}
    	// if we're removing fuel scoops, remove the core equipment item as well
    	if (this._fuelscoops.indexOf(equipmentKey) >= 0) {
    		p.removeEquipment("EQ_FUEL_SCOOPS");
    	}
    	// if we're removing the heat shield, remove the core equipment item as well
    	if (this._heatshields.indexOf(equipmentKey) >= 0) {
    		p.removeEquipment("EQ_HEAT_SHIELD");
    	}
    
    	this.$checkForOverload();
    
    	/*var equipSpace = this.$equipmentSpaceTotal(p);
    	var cargoSpace = this.$cargoSpaceAvailable(p);// + this.$cargoEquipmentSpaceAmount(p));
    
    	var used = this.$calcEquipmentSpace(p);
    	if (used > equipSpace) {
    		// allocate cargo space to equipment space
    		var diff = parseInt(used - equipSpace);
    		if (diff > cargoSpace) {
    			// we don't have space for this
    			// switch into "overloaded" mode so the player can choose what item to remove
    			this._initialSetup = true;
    			this._promptPlayer = true;
    		}
    	}*/
    
    	this.$addEquipmentSpaceItem(p);
    	this._removing = false;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipTakingDamage = function (amount, whom, type) {
    	// pass energy damage onto the unshielded ship as a heat increase
    	if (player.ship && player.ship.temperature && type === "energy damage" && this._heatControl === true && amount > 0) {
    		//if (this._debug) log(this.name, amount + " ... adding to temp (" + player.ship.temperature + ") " + (amount / (player.ship.maxEnergy * player.ship.heatInsulation)));
    		var amt = amount / (player.ship.maxEnergy * player.ship.heatInsulation);
    		player.ship.temperature += Math.pow((1.1 - player.ship.temperature), 4) * amt;
    	}
    	// check for bus overload 
    	if (this._busProcessing === false && player.ship && amount === 0 && type === "energy damage" && this._busOverload > 0 && Math.random() < (this._busOverload / 50)) {
    		this._busProcessing = true;
    		// the higher the busoverload figure, the more frequently the counter will trip and damage is taken somewhere.
    		this._busOverloadCounter += this._busOverload;
    		var damaged = false;
    		if (this._debug) log(this.name, "bus overload actvated - " + this._busOverloadCounter);
    		if (this._busOverloadResetTimer != null && this._busOverloadResetTimer.isRunning) {
    			this._busOverloadResetTimer.stop();
    		}
    		this._busOverloadResetTimer = new Timer(this, this.$decreaseBusOverload, 30, 30);
    		if (this._busOverloadCounter > this._busOverloadLimit) {
    			this._busMessageCounter += 1;
    			if (this._debug) log(this.name, "bus overload hit limit. messagecounter = " + this._busMessageCounter);
    			if (this._debug) log(this.name, "check val = " + ((1 / this._busOverload) * 10));
    			// reset the counter a bit, but not back to zero
    			this._busOverloadCounter /= 2;
    			player.consoleMessage("Warning! Electrical bus overload!");
    			if (this._busMessageCounter > ((1 / this._busOverload) * 10) && Math.random() > 0.1) {
    				if (this._debug) log(this.name, "**HIT** bus overload damage routine");
    				// fully reset the counter now
    				this._busMessageCounter = 0;
    				// ok time to damage a piece of equipment
    				var count = 0;
    				var p = player.ship;
    				var eq = p.equipment;
    				// try 5 times to find an undamaged piece of kit that can be damaged and isn't already
    				do {
    					count += 1;
    					var idx = Math.floor(Math.random() * eq.length);
    					if (eq[idx].isVisible && eq[idx].damageProbability != 0 && p.equipmentStatus(eq[idx].equipmentKey) === "EQUIPMENT_OK") {
    						// make sure the armour doesn't auto-fix the equipment we're about to damage (it shouldn't, but just in case)
    						worldScripts.ShipConfiguration_Armour._override = true;
    						player.consoleMessage("Warning! Power surge! " + eq[idx].name + " damaged!");
    						p.setEquipmentStatus(eq[idx].equipmentKey, "EQUIPMENT_DAMAGED");
    						if (this._debug) log(this.name, "bus overload equipment damage on " + eq[idx].equipmentKey);
    						worldScripts.ShipConfiguration_Armour._override = false;
    						break;
    					}
    				} while (count < 5);
    			}
    		}
    		this._busProcessing = false;
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.playerStartedJumpCountdown = function (type, seconds) {
    	// abort the countdown if the equipment is damaged
    	if (type === "standard") {
    		var p = player.ship;
    		var hd = this.$equipmentItemInUse("hyperdrive", p);
    		if (p.equipmentStatus(hd) === "EQUIPMENT_DAMAGED") {
    			p.hyperspaceSpinTime = 50;
    			if (Math.random() > 0.3) {
    				// sometimes just cancel the countdown
    				p.cancelHyperspaceCountdown();
    				player.consoleMessage("Hyperspace countdown terminated - failed to engage.");
    			} else if (Math.random() > 0.3) {
    				// and sometimes force a misjump
    				p.scriptedMisjump = true;
    			}
    
    		// don't try to reset this here if the equipment isn't damaged
    		// assume the correct spin time was set on launch
    		/*} else {
    			// make sure we get the right spin time for the class of drive
    			// just in case something overwrites the value
    			var info = EquipmentInfo.infoForKey(hd);
    			p.hyperspaceSpinTime = parseInt(info.scriptInfo.spin_time);*/
    		}
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // this will adjust the specs of the player ship whenever missiles are launched (making the ship lighter),
    this.shipFiredMissile = function (missile, target) {
    	this.$updateShipSpecs(player.ship);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // this will adjust the specs of the player ship whenever cargo or a standard escape pod is scooped (making the ship heavier),
    this.shipScoopedOther = function (whom) {
    	this.$updateShipSpecs(player.ship);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipWillLaunchFromStation = function (station) {
    	var p = player.ship;
    	this._counter = 0;
    	this.$updateShipSpecs(p);
    	var energyeq = this.$equipmentItemInUse("energy", p);
    	if (energyeq != "" && p.equipmentStatus(energyeq) === "EQUIPMENT_DAMAGED") {
    		//if (this._debug) log(this.name, "!!ALERT: Energy equipment " + energyeq + " reported as damaged");
    		if (!p.script._energyTimer || !p.script._energyTimer.isRunning) {
    			//if (this._debug) log(this.name, "!!NOTE: Starting timer to drain energy");
    			p.script._energyTimer = new Timer(this, p.script.$checkRemainingEnergy, 1, 1);
    		}
    	}
    	this._busOverload = this.$busOverloadChance(p);
    	// store it in a script value for easy pickup by heat routine
    	p.script._busOverload = this._busOverload;
    	// store the amount of equip extensions installed as this will result in more heat as well
    	p.script._equipExt = this.$getEquipmentExtensions(p);
    	// store values from any equipment items that increase cabin temp
    	p.script._equipmentClassHeat = 0;
    	var eqlist = p.equipment;
    	for (var i = 0; i < eqlist.length; i++) {
    		var eq = eqlist[i];
    		if (this._equipHeatList[eq.equipmentKey]) p.script._equipmentClassHeat += this._equipHeatList[eq.equipmentKey];
    	}
    	//log(this.name, "final class heat = " + p.script._equipmentClassHeat);
    	if (p.temperature < (0.234375 + (p.script._busOverload / 100) + (p.script._equipExt / 100) + p.script._equipmentClassHeat)) {
    		p.temperature = 0.234375 + (p.script._busOverload / 100) + (p.script._equipExt / 100) + p.script._equipmentClassHeat;
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // check when the player launches if this is a simulator run
    this.shipLaunchedFromStation = function (station) {
    	if (this.$simulatorRunning()) this._simulator = true;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipWillDockWithStation = function (station) {
    	if (this._simulator === true) this.$removeEquipSpaceItem();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // this will adjust the specs of the player ship whenever cargo is dumped (making the ship lighter) (pre v1.84)
    this.shipSpawned = function (ship) {
    	// did the player just dump cargo?
    	var p = player.ship;
    	if (p && ship && ship.isCargo && ship.position && p.position && p.position.distanceTo(ship) < 300) {
    		this.$updateShipSpecs(p);
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // this will adjust the specs of the player ship whenever cargo is dumped (making the ship lighter) (post v1.84)
    this.shipDumpedCargo = function(cargo) {
    	this.$updateShipSpecs(player.ship);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.guiScreenChanged = function (to, from) {
    	if (guiScreen === "GUI_SCREEN_SHIPYARD" && this._hyperHangar === true) {
    		this._hyperHangarTimer = new Timer(this, this.$updateHyperHangarShipImage, 1, 0);
    	}
    	if (guiScreen === "GUI_SCREEN_MISSION" && mission.screenID === "HyperspaceHangar" && this._hyperHangarActive === false) {
    		this._hyperHangarActive = true;
    		this.$preResprayFunction();
    	}
    	if (player.ship.docked === true && guiScreen !== "GUI_SCREEN_EQUIP_SHIP") {
    		this.$checkForOverload();
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.guiScreenWillChange = function (to, from) {
    	if (to === "GUI_SCREEN_STATUS" && this._simulator === true) {
    		this._simulator = false;
    		this._startUp = true;
    		this.$postResprayFunction();
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.missionScreenEnded = function () {
    	if (this._configScreen) {
    		this._configScreen = false;
    		player.ship.hudHidden = false;
    	}
    	if (this._hyperHangarActive === true) {
    		this.$postResprayFunction();
    		this._hyperHangarActive = false;
    	}
    }
    
    //=============================================================================================================
    // interface screens
    
    //-------------------------------------------------------------------------------------------------------------
    // initialise the equipment specification list
    this.$initInterface = function $initInterface(station) {
    	if (station.isPolice) {
    		// disable ship config at police/navy stations
    		station.setInterface(this.name, null);
    	} else {
    		station.setInterface(this.name, {
    			title: "View equipment specifications",
    			category: "Ship Systems",
    			summary: "Lists all equipment and the space/weight requirements for each.",
    			callback: this.$openEquipmentListing.bind(this)
    		});
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$openEquipmentListing = function $openEquipmentListing() {
    	this._page = 0;
    	this.$equipmentListing();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$equipmentListing = function $equipmentListing() {
    	function compare(a, b) {
    		return ((a.name > b.name) ? 1 : -1);
    	}
    
    	var list = [];
    	var curChoices = {};
    	var text = "";
    	var pagesize = 14;
    	if (player.ship.hudHidden === true || this.$isBigGuiActive() === true) pagesize = 20;
    
    	var spc = String.fromCharCode(31) + String.fromCharCode(31) + String.fromCharCode(31);
    	var def = "99_EXIT";
    	var col1 = 15;
    	var col2 = 4;
    
    	//text += "Equipment available at this station:\n";
    	text += this.$padTextRight("", col1 + col2) + this.$padTextLeft("Equip", col2) + this.$padTextLeft("Cargo", col2) + "\n";
    	text += this.$padTextRight("Equipment item", col1) +
    		this.$padTextLeft("TL", col2) +
    		this.$padTextLeft("space", col2) +
    		this.$padTextLeft("space", col2) +
    		this.$padTextLeft("Weight", col2) + "\n\n";
    
    	var eqlist = EquipmentInfo.allEquipment;
    	for (var i = 0; i < eqlist.length; i++) {
    		var eq = eqlist[i];
    		//if (eq.name === "GalCop Scanner") log(this.name, "eq " + eq.equipmentKey);
    		// skip any "repair" or "removal" equipment items
    		if ((eq.equipmentKey.indexOf("REPAIR") >= 0 && eq.equipmentKey != "EQ_REPAIRBOTS_MINE" && eq.equipmentKey != "EQ_REPAIRBOTS_CONTROLLER" && eq.equipmentKey != "EQ_REPAIRBOTS_RECHARGE") ||
    			eq.equipmentKey.indexOf("REMOVE") >= 0 || eq.equipmentKey.indexOf("REMOVAL") >= 0 || eq.equipmentKey.indexOf("REFUND") >= 0 || eq.equipmentKey.indexOf("_SALVAGED") >= 0 ||
    			eq.name.indexOf("(RRS discount)") >= 0 || eq.equipmentKey === "EQ_MILITARY_JAMMER" || eq.equipmentKey === "EQ_MILITARY_SCANNER_FILTER" ||
    			eq.equipmentKey.indexOf("EQ_CRIPPLED") >= 0) continue;
    
    		// system.info.techlevel >= eq.techLevel && 
    		if (this._ignoreEquip.indexOf(eq.equipmentKey) === -1 && eq.isVisible === true && eq.techLevel <= 16 && eq.isAvailableToPlayer) {
    			// is this item already in the list?
    			var found = false;
    			for (var j = 0; j < list.length; j++) {
    				if (list[j].name === eq.name) found = true;
    			}
    			if (found === true) continue;
    
    			var space = 0;
    			var weight = 0;
    			var cargo = 0;
    			var lookup = this._equipmentMatrix[eq.equipmentKey];
    			if (lookup) {
    				space = lookup[0];
    				weight = lookup[1];
    				cargo = eq.requiredCargoSpace;
    			} else {
    				if (this._debug) log(this.name, "!!NOTE: Equipment item not found " + eq.equipmentKey);
    				if (eq.requiredCargoSpace === 0) {
    					space = 1;
    					weight = 1;
    					cargo = 0;
    				} else {
    					space = 0;
    					cargo = eq.requiredCargoSpace;
    					weight = eq.requiredCargoSpace;
    				}
    			}
    			if (space > 0 || weight > 0) {
    				list.push({
    					name: eq.name,
    					tl: (parseInt(eq.techLevel) + 1).toString(),
    					space: space,
    					weight: weight,
    					cargo: cargo
    				});
    			}
    		}
    	}
    	list.sort(compare);
    
    	var maxpage = Math.ceil(list.length / (pagesize));
    	var end = ((this._page * (pagesize)) + (pagesize));
    	if (end > list.length) end = list.length;
    	for (var i = (this._page * (pagesize)); i < end; i++) {
    		text += this.$padTextRight(list[i].name, col1) +
    			this.$padTextLeft(list[i].tl, col2) +
    			this.$padTextLeft(list[i].space.toFixed(1) + spc + "t", col2) +
    			this.$padTextLeft(list[i].cargo.toFixed(1) + spc + "t", col2) +
    			this.$padTextLeft(list[i].weight.toFixed(1) + spc + "t", col2) + "\n";
    	}
    
    	if (maxpage > 1 && this._page < (maxpage - 1)) {
    		curChoices["95_NEXT"] = {
    			text: "[sc-nextpage]",
    			color: this._itemColor
    		};
    	} else {
    		curChoices["95_NEXT"] = {
    			text: "[sc-nextpage]",
    			color: this._disabledColor,
    			unselectable: true
    		};
    	}
    	if (this._page > 0) {
    		curChoices["96_PREV"] = {
    			text: "[sc-prevpage]",
    			color: this._itemColor
    		};
    	} else {
    		curChoices["96_PREV"] = {
    			text: "[sc-prevpage]",
    			color: this._disabledColor,
    			unselectable: true
    		};
    	}
    
    	curChoices["99_EXIT"] = {
    		text: "[sc-return]",
    		color: this._itemColor
    	};
    
    	if (this._lastChoice[24] != "") def = this._lastChoice[24];
    
    	var opts = {
    		screenID: "oolite-shipconfig-equipmentlist-map",
    		title: "Equipment Specifications - Page " + (parseInt(this._page) + 1) + " of " + maxpage,
    		overlay: {
    			name: "shipconfig_rocket.png",
    			height: 546
    		},
    		allowInterrupt: true,
    		exitScreen: "GUI_SCREEN_INTERFACES",
    		choices: curChoices,
    		initialChoicesKey: def,
    		message: text
    	};
    
    	mission.runScreen(opts, this.$equipmentListScreenHandler, this);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$equipmentListScreenHandler = function $equipmentListScreenHandler(choice) {
    
    	if (!choice) return;
    
    	if (choice === "95_NEXT") this._page += 1;
    	if (choice === "96_PREV") this._page -= 1;
    	this._lastChoice[24] = choice;
    
    	if (choice != "99_EXIT") {
    		this.$equipmentListing();
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$shipConfig = function $shipConfig() {
    	function compare(a, b) {
    		if (a.space != b.space) {
    			return b.space - a.space;
    		} else if (a.cargo != b.cargo) {
    			return b.cargo - a.cargo;
    		} else if (a.weight != b.weight) {
    			return b.weight - a.weight;
    		} else {
    			return a.name > b.name;
    		}
    	}
    
    	var p = player.ship;
    	var stn = p.dockedStation;
    	var used = this.$calcEquipmentSpace(p);
    	var maxSpace = Math.ceil(this.$equipmentSpaceTotal(p) + this.$cargoSpaceAvailable(p));
    	var spc = String.fromCharCode(31) + String.fromCharCode(31) + String.fromCharCode(31);
    	var curr = this._currEquip;
    
    	var priceFactor = this.$equipmentPriceFactor(p.shipClassName, this.$getShipMass(p));
    
    	var col1 = 19;
    	var col2 = 3.5;
    	var col3 = 6;
    
    	var interrupt = true;
    	var text = "";
    	var curChoices = {};
    	var itemcount = 0;
    
    	var pagesize = 22;
    	if (this.$isBigGuiActive() === false) p.hudHidden = true;
    	this._configScreen = true;
    
    	var def = "99_EXIT";
    	text += this.$pageHeader("config");
    
    	// display the list of options
    	if (used > maxSpace) {
    		// make sure we don't lock the player in during flight
    		if (p.alertCondition === 0) {
    			interrupt = false; // set to false to force the player to sell equipment before continuing
    		}
    	} else {
    		this._initialSetup = false;
    	}
    
    	if (this._display === 0) {
    		text += this.$padTextRight(expandDescription("[sc-mainmenu]"), col1) + this.$padTextLeft("Equip", col2) + "\n";
    		text += this.$padTextRight(expandDescription("[sc-menudescription]"), col1) +
    			this.$padTextLeft("space", col2) +
    			this.$padTextLeft("Weight", col2);
    
    		var itemcolor = this._menuColor;
    		if (p.equipmentStatus(this.$equipmentItemInUse("engines", p)) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
    		curChoices["01_ENGINES"] = {
    			text: this.$padTextRight("Engines (Class " + this.$equipmentItemInUse("engines", p).replace("EQ_ENGINE_TYPE", "") + ")", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("engines", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("engines", p).toFixed(1) + spc + "t", col2),
    			alignment: "LEFT",
    			color: itemcolor
    		};
    		if (this.$shipHasHyperspaceMotor(p.dataKey) === true && this._OXPHyperdrives === false) {
    			itemcolor = this._menuColor;
    			if (p.equipmentStatus(this.$equipmentItemInUse("hyperdrive", p)) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
    			curChoices["02_HYPERDRIVE"] = {
    				text: this.$padTextRight("Hyperdrive (Class " + this.$equipmentItemInUse("hyperdrive", p).replace("EQ_HYPERDRIVE_TYPE", "") + ")", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("hyperdrive", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("hyperdrive", p).toFixed(1) + spc + "t", col2),
    				alignment: "LEFT",
    				color: itemcolor
    			};
    		}
    		var itemcolor = this._menuColor;
    		if (p.equipmentStatus(this.$equipmentItemInUse("thrusters", p)) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
    		curChoices["03_THRUSTERS"] = {
    			text: this.$padTextRight("Manoeuvring Thrusters (Class " + this.$equipmentItemInUse("thrusters", p).replace("EQ_THRUSTERS_TYPE", "") + ")", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("thrusters", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("thrusters", p).toFixed(1) + spc + "t", col2),
    			alignment: "LEFT",
    			color: itemcolor
    		};
    
    		if (this._heatControl === true) {
    			var itemcolor = this._menuColor;
    			var bs = this.$equipmentItemInUse("boosters", p);
    			if (bs != "") {
    				if (p.equipmentStatus(bs) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
    				curChoices["03A_BOOSTERS"] = {
    					text: this.$padTextRight("Boosters (Class " + this.$equipmentItemInUse("boosters", p).replace("EQ_BOOSTERS_TYPE", "") + ")", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("boosters", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("boosters", p).toFixed(1) + spc + "t", col2),
    					alignment: "LEFT",
    					color: itemcolor
    				};
    			} else {
    				curChoices["03A_BOOSTERS"] = {
    					text: this.$padTextRight("Boosters (None)", col1) + this.$padTextLeft("0.0" + spc + "t", col2) + this.$padTextLeft("0.0" + spc + "t", col2),
    					alignment: "LEFT",
    					color: itemcolor
    				};
    			}
    		}
    
    		var itemcolor = this._menuColor;
    		if (p.equipmentStatus(this.$equipmentItemInUse("energy", p)) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
    		curChoices["04_ENERGY"] = {
    			text: this.$padTextRight("Energy Banks (Class " + this.$equipmentItemInUse("energy", p).replace("EQ_ENERGYBANK_TYPE", "") + ")", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("energy", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("energy", p).toFixed(1) + spc + "t", col2),
    			alignment: "LEFT",
    			color: itemcolor
    		};
    		var itemcolor = this._menuColor;
    		var fs = this.$equipmentItemInUse("frontshields", p);
    		if (fs === "EQ_NO_FORWARD_SHIELD") {
    			curChoices["05_FRONTSHIELDS"] = {
    				text: this.$padTextRight("Forward Shields (None)", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("frontshields", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("frontshields", p).toFixed(1) + spc + "t", col2),
    				alignment: "LEFT",
    				color: itemcolor
    			};
    		} else {
    			if (p.equipmentStatus(this.$equipmentItemInUse("frontshields", p)) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
    			curChoices["05_FRONTSHIELDS"] = {
    				text: this.$padTextRight("Forward Shields (Class " + this.$equipmentItemInUse("frontshields", p).replace("EQ_FORWARD_SHIELD_TYPE", "") + ")", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("frontshields", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("frontshields", p).toFixed(1) + spc + "t", col2),
    				alignment: "LEFT",
    				color: itemcolor
    			};
    		}
    		var itemcolor = this._menuColor;
    		var as = this.$equipmentItemInUse("aftshields", p);
    		if (as === "EQ_NO_AFT_SHIELD") {
    			curChoices["06_AFTSHIELDS"] = {
    				text: this.$padTextRight("Aft Shields (None)", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("aftshields", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("aftshields", p).toFixed(1) + spc + "t", col2),
    				alignment: "LEFT",
    				color: itemcolor
    			};
    		} else {
    			if (p.equipmentStatus(this.$equipmentItemInUse("aftshields", p)) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
    			curChoices["06_AFTSHIELDS"] = {
    				text: this.$padTextRight("Aft Shields (Class " + this.$equipmentItemInUse("aftshields", p).replace("EQ_AFT_SHIELD_TYPE", "") + ")", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("aftshields", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("aftshields", p).toFixed(1) + spc + "t", col2),
    				alignment: "LEFT",
    				color: itemcolor
    			};
    		}
    		var itemcolor = this._menuColor;
    		var fi = this.$equipmentItemInUse("fuelinjectors", p);
    		if (fi != "") {
    			if (p.equipmentStatus(fi) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
    			curChoices["07_FUELINJECTORS"] = {
    				text: this.$padTextRight("Fuel Injectors (Class " + this.$equipmentItemInUse("fuelinjectors", p).replace("EQ_FUEL_INJECTION_TYPE", "") + ")", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("fuelinjectors", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("fuelinjectors", p).toFixed(1) + spc + "t", col2),
    				alignment: "LEFT",
    				color: itemcolor
    			};
    		} else {
    			curChoices["07_FUELINJECTORS"] = {
    				text: this.$padTextRight("Fuel Injectors (None)", col1) + this.$padTextLeft("0.0" + spc + "t", col2) + this.$padTextLeft("0.0" + spc + "t", col2),
    				alignment: "LEFT",
    				color: itemcolor
    			};
    		}
    		var itemcolor = this._menuColor;
    		var sc = this.$equipmentItemInUse("fuelscoops", p);
    		if (sc != "") {
    			if (p.equipmentStatus(sc) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
    			curChoices["08_FUELSCOOPS"] = {
    				text: this.$padTextRight("Fuel Scoops (Class " + this.$equipmentItemInUse("fuelscoops", p).replace("EQ_FUEL_SCOOPS_TYPE", "") + ")", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("fuelscoops", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("fuelscoops", p).toFixed(1) + spc + "t", col2),
    				alignment: "LEFT",
    				color: itemcolor
    			};
    		} else {
    			curChoices["08_FUELSCOOPS"] = {
    				text: this.$padTextRight("Fuel Scoops (None)", col1) + this.$padTextLeft("0.0" + spc + "t", col2) + this.$padTextLeft("0.0" + spc + "t", col2),
    				alignment: "LEFT",
    				color: itemcolor
    			};
    		}
    		var itemcolor = this._menuColor;
    		var hs = this.$equipmentItemInUse("heatshields", p);
    		if (hs != "") {
    			if (p.equipmentStatus(hs) === "EQUIPMENT_DAMAGED") itemcolor = this._damagedColor;
    			curChoices["09_HEATSHIELDS"] = {
    				text: this.$padTextRight("Heat Shields (Class " + hs.replace("EQ_HEAT_SHIELD_TYPE", "") + ")", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("heatshields", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("heatshields", p).toFixed(1) + spc + "t", col2),
    				alignment: "LEFT",
    				color: itemcolor
    			};
    		} else {
    			curChoices["09_HEATSHIELDS"] = {
    				text: this.$padTextRight("Heat Shields (None)", col1) + this.$padTextLeft("0.0" + spc + "t", col2) + this.$padTextLeft("0.0" + spc + "t", col2),
    				alignment: "LEFT",
    				color: itemcolor
    			};
    		}
    		var itemcolor = this._menuColor;
    		// if player has alternative armour installed, don't show this item at all
    		if (this.$playerHasOtherArmour() === false) {
    			var arf = this.$equipmentItemInUse("frontarmour", p);
    			if (arf != "") {
    				if (p.script._armourFront < 100) itemcolor = this._damagedColor;
    				curChoices["10_ARMOUR_0FRONT"] = {
    					text: this.$padTextRight("Forward Armour Plating (Class " + arf.replace("EQ_ARMOUR_FORWARD_TYPE", "") + ")", col1) + this.$padTextLeft("0.0" + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("frontarmour", p).toFixed(1) + spc + "t", col2),
    					alignment: "LEFT",
    					color: itemcolor
    				};
    			} else {
    				curChoices["10_ARMOUR_0FRONT"] = {
    					text: this.$padTextRight("Forward Armour Plating (None)", col1) + this.$padTextLeft("0.0" + spc + "t", col2) + this.$padTextLeft("0.0" + spc + "t", col2),
    					alignment: "LEFT",
    					color: itemcolor
    				};
    			}
    			var ara = this.$equipmentItemInUse("aftarmour", p);
    			if (ara != "") {
    				if (p.script._armourAft < 100) itemcolor = this._damagedColor;
    				curChoices["10_ARMOUR_1AFT"] = {
    					text: this.$padTextRight("Aft Armour Plating (Class " + ara.replace("EQ_ARMOUR_AFT_TYPE", "") + ")", col1) + this.$padTextLeft("0.0" + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("aftarmour", p).toFixed(1) + spc + "t", col2),
    					alignment: "LEFT",
    					color: itemcolor
    				};
    			} else {
    				curChoices["10_ARMOUR_1AFT"] = {
    					text: this.$padTextRight("Aft Armour Plating (None)", col1) + this.$padTextLeft("0.0" + spc + "t", col2) + this.$padTextLeft("0.0" + spc + "t", col2),
    					alignment: "LEFT",
    					color: itemcolor
    				};
    			}
    		} else {
    			for (var i = 0; i < this._altArmour.length; i++) {
    				if (p.equipmentStatus(this._altArmour[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._altArmour[i]) === "EQUIPMENT_DAMAGED") {
    					var info = EquipmentInfo.infoForKey(this._altArmour[i]);
    					var wt = 0;
    					if (this._equipmentMatrix[this._altArmour[i]]) wt = this._equipmentMatrix[this._altArmour[i]][1];
    					curChoices["10_ARMOUR"] = {
    						text: this.$padTextRight("Armour (" + info.name + ")", col1) + this.$padTextLeft("0.0" + spc + "t", col2) + this.$padTextLeft(wt.toFixed(1) + spc + "t", col2),
    						alignment: "LEFT",
    						color: this._disabledColor,
    						unselectable: true
    					};
    					break;
    				}
    			}
    		}
    		curChoices["11_ELECTRICAL"] = {
    			text: this.$padTextRight("Electrical Bus/Power Couplings", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("electrical", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("electrical", p).toFixed(1) + spc + "t", col2),
    			alignment: "LEFT",
    			color: this._menuColor
    		};
    
    		for (var i = 0; i < (pagesize - (20 - (this.$shipHasHyperspaceMotor(p.dataKey) === true && this._OXPHyperdrives === false ? 0 : 1))); i++) {
    			curChoices["90_SPACER_" + i] = "";
    		}
    
    		curChoices["96_VIEWEQUIP"] = {
    			text: "[sc-viewinstalled]",
    			color: this._itemColor
    		};
    		if (worldScripts.EquipmentStorage.$stationHasStorageFacilities(stn) === true) {
    			curChoices["97A_STORAGE"] = {
    				text: "[storage-store-equipment]",
    				color: this._itemColor
    			};
    		} else {
    			curChoices["97A_STORAGE"] = {
    				text: "[storage-store-equipment]",
    				color: this._disabledColor,
    				unselectable: true
    			};
    		}
    		curChoices["97_SELL"] = {
    			text: "[sc-sellequip]",
    			color: this._itemColor
    		};
    
    		// display the list of options
    		if (used > maxSpace) {
    			curChoices["99_EXIT"] = {
    				text: "[sc-return]",
    				color: this._disabledColor,
    				unselectable: true
    			};
    		} else {
    			curChoices["99_EXIT"] = {
    				text: "[sc-return]",
    				color: this._itemColor
    			};
    		}
    
    		if (this._lastChoice[this._display] != "") def = this._lastChoice[this._display];
    
    		var opts = {
    			screenID: "oolite-shipconfig-main-map",
    			title: "Ship Configuration",
    			allowInterrupt: interrupt,
    			exitScreen: "GUI_SCREEN_EQUIP_SHIP",
    			choices: curChoices,
    			initialChoicesKey: def,
    			message: text
    		};
    	}
    
    	var list = [];
    	var dam = 1;
    	var coupling = 0;
    	var bus = this.$equipmentCouplingLevelInUse("electricalbus", p);
    	var section = "";
    
    	if (this._display === 1) { // engines
    		section = "[sc-section-engines]";
    		coupling = this.$equipmentCouplingLevelInUse("engines", p);
    		for (var i = 0; i < this._engines.length; i++) {
    			var eq = this._engines[i];
    			var info = EquipmentInfo.infoForKey(eq);
    			var idx = curr.indexOf(eq);
    
    			var check = p.equipmentStatus(eq);
    			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("engines", p)) <= maxSpace)) {
    				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) < this.$equipmentCouplingRequired("engines", eq, p)) check = "UNAVAILABLE";
    				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) === this.$equipmentCouplingRequired("engines", eq, p)) check = "RISK";
    				dam = 1;
    				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
    				list.push({
    					name: info.scriptInfo.short_title,
    					extra: info.scriptInfo.description,
    					key: eq,
    					space: this._equipmentMatrix[eq][0],
    					weight: this._equipmentMatrix[eq][1],
    					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
    					flag: check
    				});
    			}
    		}
    	}
    	if (this._display === 2) { // hyperdrive
    		section = "[sc-section-hyperdrive]";
    		coupling = this.$equipmentCouplingLevelInUse("hyperdrive", p);
    		for (var i = 0; i < this._hyperdrive.length; i++) {
    			var eq = this._hyperdrive[i];
    			var info = EquipmentInfo.infoForKey(eq);
    			var idx = curr.indexOf(eq);
    
    			var check = p.equipmentStatus(eq);
    			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("hyperdrive", p)) <= maxSpace)) {
    				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) < this.$equipmentCouplingRequired("hyperdrive", eq, p)) check = "UNAVAILABLE";
    				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) === this.$equipmentCouplingRequired("hyperdrive", eq, p)) check = "RISK";
    				dam = 1;
    				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
    				list.push({
    					name: info.scriptInfo.short_title,
    					extra: info.scriptInfo.description,
    					key: eq,
    					space: this._equipmentMatrix[eq][0],
    					weight: this._equipmentMatrix[eq][1],
    					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
    					flag: check
    				});
    			}
    		}
    	}
    	if (this._display === 3) { // thrusters
    		section = "[sc-section-thrusters]";
    		coupling = this.$equipmentCouplingLevelInUse("thrusters", p);
    		for (var i = 0; i < this._thrusters.length; i++) {
    			var eq = this._thrusters[i];
    			var info = EquipmentInfo.infoForKey(eq);
    			var idx = curr.indexOf(eq);
    
    			var check = p.equipmentStatus(eq);
    			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("thrusters", p)) <= maxSpace)) {
    				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) < this.$equipmentCouplingRequired("thrusters", eq, p)) check = "UNAVAILABLE";
    				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) === this.$equipmentCouplingRequired("thrusters", eq, p)) check = "RISK";
    				dam = 1;
    				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
    				list.push({
    					name: info.scriptInfo.short_title,
    					extra: info.scriptInfo.description,
    					key: eq,
    					space: this._equipmentMatrix[eq][0],
    					weight: this._equipmentMatrix[eq][1],
    					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
    					flag: check
    				});
    			}
    		}
    	}
    	if (this._display === 18) { // boosters
    		section = "[sc-section-boosters]";
    		coupling = this.$equipmentCouplingLevelInUse("boosters", p);
    		var found = false;
    		var key = "";
    		for (var i = 0; i < this._boosters.length; i++) {
    			if (p.equipmentStatus(this._boosters[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._boosters[i]) === "EQUIPMENT_DAMAGED") {
    				key = this._boosters[i];
    				found = true;
    			}
    		}
    		if (found === true && EquipmentInfo.infoForKey(key).effectiveTechLevel <= stn.equivalentTechLevel) {
    			list.push({
    				name: expandDescription("[sc-remove-boosters]"),
    				extra: "",
    				key: "EQ_BOOSTERS_REMOVE",
    				space: 0,
    				weight: 0,
    				cost: 0,
    				flag: ""
    			});
    		}
    		for (var i = 0; i < this._boosters.length; i++) {
    			var eq = this._boosters[i];
    			var info = EquipmentInfo.infoForKey(eq);
    			var idx = curr.indexOf(eq);
    
    			var check = p.equipmentStatus(eq);
    			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("boosters", p)) <= maxSpace)) {
    				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) < this.$equipmentCouplingRequired("boosters", eq, p)) check = "UNAVAILABLE";
    				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) === this.$equipmentCouplingRequired("boosters", eq, p)) check = "RISK";
    				dam = 1;
    				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
    				list.push({
    					name: info.scriptInfo.short_title,
    					extra: info.scriptInfo.description,
    					key: eq,
    					space: this._equipmentMatrix[eq][0],
    					weight: this._equipmentMatrix[eq][1],
    					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
    					flag: check
    				});
    			}
    		}
    	}
    	if (this._display === 4) { // energy
    		section = "[sc-section-energy]";
    		coupling = this.$equipmentCouplingLevelInUse("energy", p);
    		for (var i = 0; i < this._energy.length; i++) {
    			var eq = this._energy[i];
    			var info = EquipmentInfo.infoForKey(eq);
    			var idx = curr.indexOf(eq);
    
    			var check = p.equipmentStatus(eq);
    			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("energy", p)) <= maxSpace)) {
    				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) < this.$equipmentCouplingRequired("energy", eq, p)) check = "UNAVAILABLE";
    				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) === this.$equipmentCouplingRequired("energy", eq, p)) check = "RISK";
    				dam = 1;
    				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
    				list.push({
    					name: info.scriptInfo.short_title,
    					extra: info.scriptInfo.description,
    					key: eq,
    					space: this._equipmentMatrix[eq][0],
    					weight: this._equipmentMatrix[eq][1],
    					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
    					flag: check
    				});
    			}
    		}
    	}
    	if (this._display === 5) { // front shields
    		var startpoint = 0;
    		section = "[sc-section-frontshields]";
    		coupling = this.$equipmentCouplingLevelInUse("frontshields", p);
    		// if any shield boosters are in place, we can't remove shields
    		if (p.equipmentStatus("EQ_SHIELD_BOOSTER") === "EQUIPMENT_OK" || p.equipmentStatus("EQ_NAVAL_SHIELD_BOOSTER") === "EQUIPMENT_OK") startpoint = 1;
    		for (var i = startpoint; i < this._frontshields.length; i++) {
    			var eq = this._frontshields[i];
    			var info = EquipmentInfo.infoForKey(eq);
    			var idx = curr.indexOf(eq);
    
    			var check = p.equipmentStatus(eq);
    			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("frontshields", p)) <= maxSpace)) {
    				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) < this.$equipmentCouplingRequired("frontshields", eq, p)) check = "UNAVAILABLE";
    				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) === this.$equipmentCouplingRequired("frontshields", eq, p)) check = "RISK";
    				dam = 1;
    				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
    				list.push({
    					name: info.scriptInfo.short_title,
    					extra: info.scriptInfo.description,
    					key: eq,
    					space: this._equipmentMatrix[eq][0],
    					weight: this._equipmentMatrix[eq][1],
    					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
    					flag: check
    				});
    			}
    		}
    	}
    	if (this._display === 6) { // aft shields
    		var startpoint = 0;
    		section = "[sc-section-aftshields]";
    		coupling = this.$equipmentCouplingLevelInUse("aftshields", p);
    		// if any shield boosters are in place, we can't remove shields
    		if (p.equipmentStatus("EQ_SHIELD_BOOSTER") === "EQUIPMENT_OK" || p.equipmentStatus("EQ_NAVAL_SHIELD_BOOSTER") === "EQUIPMENT_OK") startpoint = 1;
    		for (var i = startpoint; i < this._aftshields.length; i++) {
    			var eq = this._aftshields[i];
    			var info = EquipmentInfo.infoForKey(eq);
    			var idx = curr.indexOf(eq);
    
    			var check = p.equipmentStatus(eq);
    			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("aftshields", p)) <= maxSpace)) {
    				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) < this.$equipmentCouplingRequired("aftshields", eq, p)) check = "UNAVAILABLE";
    				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) === this.$equipmentCouplingRequired("aftshields", eq, p)) check = "RISK";
    				dam = 1;
    				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
    				list.push({
    					name: info.scriptInfo.short_title,
    					extra: info.scriptInfo.description,
    					key: eq,
    					space: this._equipmentMatrix[eq][0],
    					weight: this._equipmentMatrix[eq][1],
    					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
    					flag: check
    				});
    			}
    		}
    	}
    	if (this._display === 7) { // fuel injectors
    		// inject a "remove" item into the list
    		// do we have any injectors?
    		section = "[sc-section-fuelinjectors]";
    		coupling = this.$equipmentCouplingLevelInUse("engines", p);
    		var found = false;
    		var key = "";
    		for (var i = 0; i < this._fuelinjectors.length; i++) {
    			if (p.equipmentStatus(this._fuelinjectors[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._fuelinjectors[i]) === "EQUIPMENT_DAMAGED") {
    				found = true;
    				key = this._fuelinjectors[i];
    			}
    		}
    		if (found === true && EquipmentInfo.infoForKey(key).effectiveTechLevel <= stn.equivalentTechLevel) {
    			list.push({
    				name: expandDescription("[sc-remove-fuelinjectors]"),
    				extra: "",
    				key: "EQ_FUEL_INJECTION_REMOVE",
    				space: 0,
    				weight: 0,
    				cost: 0,
    				flag: ""
    			});
    		}
    		for (var i = 0; i < this._fuelinjectors.length; i++) {
    			var eq = this._fuelinjectors[i];
    			var info = EquipmentInfo.infoForKey(eq);
    			var idx = curr.indexOf(eq);
    
    			var check = p.equipmentStatus(eq);
    			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("fuelinjectors", p)) <= maxSpace)) {
    				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) < this.$equipmentCouplingRequired("engines", eq, p)) check = "UNAVAILABLE";
    				if (check === "EQUIPMENT_UNAVAILABLE" && (coupling + 1) === this.$equipmentCouplingRequired("engines", eq, p)) check = "RISK";
    				dam = 1;
    				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
    				list.push({
    					name: info.scriptInfo.short_title,
    					extra: info.scriptInfo.description,
    					key: eq,
    					space: this._equipmentMatrix[eq][0],
    					weight: this._equipmentMatrix[eq][1],
    					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * stn.equipmentPriceFactor,
    					flag: check
    				});
    			}
    		}
    	}
    	if (this._display === 20) { // fuel scoops
    		// inject a "remove" item into the list
    		// do we have any scoops?
    		section = "[sc-section-fuelscoops]";
    		var found = false;
    		var key = "";
    		for (var i = 0; i < this._fuelscoops.length; i++) {
    			if (p.equipmentStatus(this._fuelscoops[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._fuelscoops[i]) === "EQUIPMENT_DAMAGED") {
    				found = true;
    				key = this._fuelscoops[i];;
    			}
    		}
    		if (found === true && EquipmentInfo.infoForKey(key).effectiveTechLevel <= stn.equivalentTechLevel) {
    			list.push({
    				name: expandDescription("[sc-remove-fuelscoops]"),
    				extra: "",
    				key: "EQ_FUEL_SCOOPS_REMOVE",
    				space: 0,
    				weight: 0,
    				cost: 0,
    				flag: ""
    			});
    		}
    		for (var i = 0; i < this._fuelscoops.length; i++) {
    			var eq = this._fuelscoops[i];
    			var info = EquipmentInfo.infoForKey(eq);
    			var idx = curr.indexOf(eq);
    
    			var check = p.equipmentStatus(eq);
    			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || stn.equivalentTechLevel >= info.techLevel) {
    				dam = 1;
    				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
    				list.push({
    					name: info.scriptInfo.short_title,
    					extra: info.scriptInfo.description,
    					key: eq,
    					space: this._equipmentMatrix[eq][0],
    					weight: this._equipmentMatrix[eq][1],
    					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * stn.equipmentPriceFactor,
    					flag: check
    				});
    			}
    		}
    	}
    	if (this._display === 8) { // heat shields
    		// inject a "remove" item into the list
    		// do we have any heat shielding?
    		section = "[sc-section-heatshields]";
    		var found = false;
    		var key = "";
    		for (var i = 0; i < this._heatshields.length; i++) {
    			if (p.equipmentStatus(this._heatshields[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._heatshields[i]) === "EQUIPMENT_DAMAGED") {
    				found = true;
    				key = this._heatshields[i];
    			}
    		}
    		if (found === true && EquipmentInfo.infoForKey(key).effectiveTechLevel <= stn.equivalentTechLevel) {
    			list.push({
    				name: expandDescription("[sc-remove-heatshields]"),
    				extra: "",
    				key: "EQ_HEAT_SHIELD_REMOVE",
    				space: 0,
    				weight: 0,
    				cost: 0,
    				flag: ""
    			});
    		}
    		for (var i = 0; i < this._heatshields.length; i++) {
    			var eq = this._heatshields[i];
    			var info = EquipmentInfo.infoForKey(eq);
    			var idx = curr.indexOf(eq);
    
    			var check = p.equipmentStatus(eq);
    			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || stn.equivalentTechLevel >= info.techLevel) {
    				dam = 1;
    				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
    				list.push({
    					name: info.scriptInfo.short_title,
    					extra: info.scriptInfo.description,
    					key: eq,
    					space: this._equipmentMatrix[eq][0],
    					weight: this._equipmentMatrix[eq][1],
    					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * stn.equipmentPriceFactor,
    					flag: check
    				});
    			}
    		}
    	}
    	if (this._display === 9) { // front armour
    		// inject a "remove" item into the list
    		// do we have any armour?
    		section = "[sc-section-forward-armour]";
    		var found = false;
    		var key = "";
    		for (var i = 0; i < this._frontarmour.length; i++) {
    			if (p.equipmentStatus(this._frontarmour[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._frontarmour[i]) === "EQUIPMENT_DAMAGED") {
    				found = true;
    				key = this._frontarmour[i];
    			}
    		}
    		if (found === true && EquipmentInfo.infoForKey(key).effectiveTechLevel <= stn.equivalentTechLevel) {
    			list.push({
    				name: expandDescription("[sc-remove-front-armour]"),
    				extra: "",
    				key: "EQ_ARMOUR_FORWARD_REMOVE",
    				space: 0,
    				weight: 0,
    				cost: 0,
    				flag: ""
    			});
    		}
    		for (var i = 0; i < this._frontarmour.length; i++) {
    			var eq = this._frontarmour[i];
    			var info = EquipmentInfo.infoForKey(eq);
    			var idx = curr.indexOf(eq);
    
    			var check = p.equipmentStatus(eq);
    
    			if (check === "EQUIPMENT_OK" && p.script._armourFront < 100) check = "EQUIPMENT_DAMAGED";
    
    			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || stn.equivalentTechLevel >= info.techLevel) {
    				dam = 1;
    				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
    				list.push({
    					name: info.scriptInfo.short_title,
    					extra: info.scriptInfo.description,
    					key: eq,
    					space: this._equipmentMatrix[eq][0],
    					weight: this._equipmentMatrix[eq][1],
    					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
    					flag: check
    				});
    			}
    		}
    	}
    	if (this._display === 21) { // aft armour
    		// inject a "remove" item into the list
    		// do we have any armour?
    		section = "[sc-section-aft-armour]";
    		var found = false;
    		var key = "";
    		for (var i = 0; i < this._aftarmour.length; i++) {
    			if (p.equipmentStatus(this._aftarmour[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._aftarmour[i]) === "EQUIPMENT_DAMAGED") {
    				found = true;
    				key = this._aftarmour[i];
    			}
    		}
    		if (found === true && EquipmentInfo.infoForKey(key).effectiveTechLevel <= stn.equivalentTechLevel) {
    			list.push({
    				name: expandDescription("[sc-remove-aft-armour]"),
    				extra: "",
    				key: "EQ_ARMOUR_AFT_REMOVE",
    				space: 0,
    				weight: 0,
    				cost: 0,
    				flag: ""
    			});
    		}
    		for (var i = 0; i < this._aftarmour.length; i++) {
    			var eq = this._aftarmour[i];
    			var info = EquipmentInfo.infoForKey(eq);
    			var idx = curr.indexOf(eq);
    
    			var check = p.equipmentStatus(eq);
    
    			if (check === "EQUIPMENT_OK" && p.script._armourAft < 100) check = "EQUIPMENT_DAMAGED";
    
    			if ((check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") || stn.equivalentTechLevel >= info.techLevel) {
    				dam = 1;
    				if (check === "EQUIPMENT_DAMAGED") dam = 0.5;
    				list.push({
    					name: info.scriptInfo.short_title,
    					extra: info.scriptInfo.description,
    					key: eq,
    					space: this._equipmentMatrix[eq][0],
    					weight: this._equipmentMatrix[eq][1],
    					cost: (info.price * dam) * (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
    					flag: check
    				});
    			}
    		}
    	}
    
    	if (this._display === 11) { // elec bus
    		section = "[sc-section-electricalbus]";
    		for (var i = 0; i < this._electricalbus.length; i++) {
    			var eq = this._electricalbus[i];
    			var info = EquipmentInfo.infoForKey(eq);
    			var idx = curr.indexOf(eq);
    
    			var check = p.equipmentStatus(eq);
    			if ((check === "EQUIPMENT_OK") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("electricalbus", p)) <= maxSpace)) {
    				// check for downgrade case where its not available if a +1 coupling is attached
    				if (check === "EQUIPMENT_UNAVAILABLE" && (i + 1) < bus && (i + 1) <= (this.$maxEquipmentCouplingInUse(p) - 1)) check = "UNAVAILABLE";
    				list.push({
    					name: info.scriptInfo.short_title,
    					extra: info.scriptInfo.description,
    					key: eq,
    					space: this._equipmentMatrix[eq][0],
    					weight: this._equipmentMatrix[eq][1],
    					cost: info.price * (check === "EQUIPMENT_OK" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
    					flag: check
    				});
    			}
    		}
    	}
    	if (this._display === 12) { // engine coupling
    		section = "[sc-section-enginecoupling]";
    		for (var i = 0; i < this._enCoupling.length; i++) {
    			var eq = this._enCoupling[i];
    			var info = EquipmentInfo.infoForKey(eq);
    			var idx = curr.indexOf(eq);
    
    			var check = p.equipmentStatus(eq);
    			if ((check === "EQUIPMENT_OK") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("enginecoupling", p)) <= maxSpace)) {
    				if (check != "EQUIPMENT_OK" && (bus + 1) < this.$equipmentCouplingRequired("all", eq, p)) check = "UNAVAILABLE";
    				if (check != "EQUIPMENT_OK" && (bus + 1) === this.$equipmentCouplingRequired("all", eq, p)) check = "RISK";
    				if (check === "EQUIPMENT_UNAVAILABLE" && (i + 1) < (this.$equipmentLevelInUse("engines", p) - 1)) check = "UNAVAILABLE";
    				list.push({
    					name: info.scriptInfo.short_title,
    					extra: info.scriptInfo.description,
    					key: eq,
    					space: this._equipmentMatrix[eq][0],
    					weight: this._equipmentMatrix[eq][1],
    					cost: info.price * (check === "EQUIPMENT_OK" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
    					flag: check
    				});
    			}
    		}
    	}
    	if (this.$shipHasHyperspaceMotor(p.dataKey) === true && this._OXPHyperdrives === false) { // hyperdrive
    		if (this._display === 13) {
    			section = "[sc-section-hyperdrivecoupling]";
    			for (var i = 0; i < this._hdCoupling.length; i++) {
    				var eq = this._hdCoupling[i];
    				var info = EquipmentInfo.infoForKey(eq);
    				var idx = curr.indexOf(eq);
    
    				var check = p.equipmentStatus(eq);
    				if ((check === "EQUIPMENT_OK") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("hyperdrivecoupling", p)) <= maxSpace)) {
    					if (check != "EQUIPMENT_OK" && (bus + 1) < this.$equipmentCouplingRequired("all", eq, p)) check = "UNAVAILABLE";
    					if (check != "EQUIPMENT_OK" && (bus + 1) === this.$equipmentCouplingRequired("all", eq, p)) check = "RISK";
    					if (check === "EQUIPMENT_UNAVAILABLE" && (i + 1) < (this.$equipmentLevelInUse("hyperdrive", p) - 1)) check = "UNAVAILABLE";
    					list.push({
    						name: info.scriptInfo.short_title,
    						extra: info.scriptInfo.description,
    						key: eq,
    						space: this._equipmentMatrix[eq][0],
    						weight: this._equipmentMatrix[eq][1],
    						cost: info.price * (check === "EQUIPMENT_OK" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
    						flag: check
    					});
    				}
    			}
    		}
    	}
    	if (this._display === 14) { // thrusters coupling
    		section = "[sc-section-thrusterscoupling]";
    		for (var i = 0; i < this._thCoupling.length; i++) {
    			var eq = this._thCoupling[i];
    			var info = EquipmentInfo.infoForKey(eq);
    			var idx = curr.indexOf(eq);
    
    			var check = p.equipmentStatus(eq);
    			if ((check === "EQUIPMENT_OK") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("thrusterscoupling", p)) <= maxSpace)) {
    				if (check != "EQUIPMENT_OK" && (bus + 1) < this.$equipmentCouplingRequired("all", eq, p)) check = "UNAVAILABLE";
    				if (check != "EQUIPMENT_OK" && (bus + 1) === this.$equipmentCouplingRequired("all", eq, p)) check = "RISK";
    				if (check === "EQUIPMENT_UNAVAILABLE" && (i + 1) < (this.$equipmentLevelInUse("thrusters", p) - 1)) check = "UNAVAILABLE";
    				list.push({
    					name: info.scriptInfo.short_title,
    					extra: info.scriptInfo.description,
    					key: eq,
    					space: this._equipmentMatrix[eq][0],
    					weight: this._equipmentMatrix[eq][1],
    					cost: info.price * (check === "EQUIPMENT_OK" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
    					flag: check
    				});
    			}
    		}
    	}
    	if (this._display === 19 && this._heatControl === true) { // boosters
    		section = "[sc-section-boosterscoupling]";
    		for (var i = 0; i < this._bsCoupling.length; i++) {
    			var eq = this._bsCoupling[i];
    			var info = EquipmentInfo.infoForKey(eq);
    			var idx = curr.indexOf(eq);
    
    			var check = p.equipmentStatus(eq);
    			if ((check === "EQUIPMENT_OK") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("boosterscoupling", p)) <= maxSpace)) {
    				if (check != "EQUIPMENT_OK" && (bus + 1) < this.$equipmentCouplingRequired("all", eq, p)) check = "UNAVAILABLE";
    				if (check != "EQUIPMENT_OK" && (bus + 1) === this.$equipmentCouplingRequired("all", eq, p)) check = "RISK";
    				if (check === "EQUIPMENT_UNAVAILABLE" && (i + 1) < (this.$equipmentLevelInUse("boosters", p) - 1)) check = "UNAVAILABLE";
    				list.push({
    					name: info.scriptInfo.short_title,
    					extra: info.scriptInfo.description,
    					key: eq,
    					space: this._equipmentMatrix[eq][0],
    					weight: this._equipmentMatrix[eq][1],
    					cost: info.price * (check === "EQUIPMENT_OK" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
    					flag: check
    				});
    			}
    		}
    	}
    	if (this._display === 15) { // energy coupling
    		section = "[sc-section-energycoupling]";
    		for (var i = 0; i < this._ebCoupling.length; i++) {
    			var eq = this._ebCoupling[i];
    			var info = EquipmentInfo.infoForKey(eq);
    			var idx = curr.indexOf(eq);
    
    			var check = p.equipmentStatus(eq);
    			if ((check === "EQUIPMENT_OK") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("energycoupling", p)) <= maxSpace)) {
    				if (check != "EQUIPMENT_OK" && (bus + 1) < this.$equipmentCouplingRequired("all", eq, p)) check = "UNAVAILABLE";
    				if (check != "EQUIPMENT_OK" && (bus + 1) === this.$equipmentCouplingRequired("all", eq, p)) check = "RISK";
    				if (check === "EQUIPMENT_UNAVAILABLE" && (i + 1) < (this.$equipmentLevelInUse("energy", p) - 1)) check = "UNAVAILABLE";
    				list.push({
    					name: info.scriptInfo.short_title,
    					extra: info.scriptInfo.description,
    					key: eq,
    					space: this._equipmentMatrix[eq][0],
    					weight: this._equipmentMatrix[eq][1],
    					cost: info.price * (check === "EQUIPMENT_OK" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
    					flag: check
    				});
    			}
    		}
    	}
    	if (this._display === 16) { // front shield coupling
    		section = "[sc-section-frontshieldscoupling]";
    		for (var i = 0; i < this._fsCoupling.length; i++) {
    			var eq = this._fsCoupling[i];
    			var info = EquipmentInfo.infoForKey(eq);
    			var idx = curr.indexOf(eq);
    
    			var check = p.equipmentStatus(eq);
    			if ((check === "EQUIPMENT_OK") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("frontshieldscoupling", p)) <= maxSpace)) {
    				if (check != "EQUIPMENT_OK" && (bus + 1) < this.$equipmentCouplingRequired("all", eq, p)) check = "UNAVAILABLE";
    				if (check != "EQUIPMENT_OK" && (bus + 1) === this.$equipmentCouplingRequired("all", eq, p)) check = "RISK";
    				if (check === "EQUIPMENT_UNAVAILABLE" && (i + 1) < (this.$equipmentLevelInUse("frontshields", p) - 1)) check = "UNAVAILABLE";
    				list.push({
    					name: info.scriptInfo.short_title,
    					extra: info.scriptInfo.description,
    					key: eq,
    					space: this._equipmentMatrix[eq][0],
    					weight: this._equipmentMatrix[eq][1],
    					cost: info.price * (check === "EQUIPMENT_OK" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
    					flag: check
    				});
    			}
    		}
    	}
    	if (this._display === 17) { // aft shield coupling
    		section = "[sc-section-aftshieldscoupling]";
    		for (var i = 0; i < this._asCoupling.length; i++) {
    			var eq = this._asCoupling[i];
    			var info = EquipmentInfo.infoForKey(eq);
    			var idx = curr.indexOf(eq);
    
    			var check = p.equipmentStatus(eq);
    			if ((check === "EQUIPMENT_OK") || (stn.equivalentTechLevel >= info.techLevel && (used + this._equipmentMatrix[eq][0] - this.$equipmentSpaceInUse("aftshieldscoupling", p)) <= maxSpace)) {
    				if (check != "EQUIPMENT_OK" && (bus + 1) < this.$equipmentCouplingRequired("all", eq, p)) check = "UNAVAILABLE";
    				if (check != "EQUIPMENT_OK" && (bus + 1) === this.$equipmentCouplingRequired("all", eq, p)) check = "RISK";
    				if (check === "EQUIPMENT_UNAVAILABLE" && (i + 1) < (this.$equipmentLevelInUse("aftshields", p) - 1)) check = "UNAVAILABLE";
    				list.push({
    					name: info.scriptInfo.short_title,
    					extra: info.scriptInfo.description,
    					key: eq,
    					space: this._equipmentMatrix[eq][0],
    					weight: this._equipmentMatrix[eq][1],
    					cost: info.price * (check === "EQUIPMENT_OK" ? (idx >= 0 ? this._refundPct : 1) * -1 : 1) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1) * priceFactor,
    					flag: check
    				});
    			}
    		}
    	}
    
    	if ((this._display >= 1 && this._display <= 9) || (this._display >= 11 && this._display <= 21)) {
    		def = "98_EXIT";
    
    		itemcount -= 2;
    
    		text += this.$padTextRight(expandDescription(section), col1) + this.$padTextLeft("Equip", col2) + "\n";
    		text += this.$padTextRight("Equipment item", col1) +
    			this.$padTextLeft("space", col2) +
    			this.$padTextLeft("Weight", col2) +
    			this.$padTextLeft("Cost", col3);
    
    		if (list.length === 0) {
    			text += expandDescription("[sc-no-items-available]");
    			itemcount += 2;
    		} else {
    			var maxpage = Math.ceil(list.length / (pagesize - 7));
    			var end = ((this._page * (pagesize - 7)) + (pagesize - 7));
    			if (end > list.length) end = list.length;
    			for (var i = (this._page * (pagesize - 7)); i < end; i++) {
    				var c = this._menuColor;
    				switch (list[i].flag) {
    					case "EQUIPMENT_OK":
    						c = this._installedColor;
    						break;
    					case "EQUIPMENT_DAMAGED":
    						c = this._damagedColor;
    						break;
    					case "UNAVAILABLE":
    						c = this._disabledColor;
    						break;
    					case "RISK":
    						c = this._riskColor;
    						break;
    				}
    				curChoices["01_EQUIP-" + (i < 10 ? "0" : "") + i + "~" + list[i].key] = {
    					text: this.$padTextRight(list[i].name + (list[i].extra != "" ? " (" + list[i].extra + ")" : ""), col1) +
    						this.$padTextLeft(list[i].space.toFixed(1) + spc + "t", col2) +
    						this.$padTextLeft(list[i].weight.toFixed(1) + spc + "t", col2) +
    						this.$padTextLeft(formatCredits((list[i].cost / 10), true, true), col3),
    					alignment: "LEFT",
    					color: c,
    					unselectable: (list[i].flag === "EQUIPMENT_OK" || list[i].flag === "EQUIPMENT_DAMAGED" || list[i].flag === "UNAVAILABLE" ? true : false)
    				};
    				itemcount += 1;
    			}
    		}
    
    		for (var i = 0; i < ((pagesize - 8) - itemcount); i++) {
    			curChoices["90_SPACER_" + i] = "";
    		}
    
    		if (maxpage > 1 && this._page < (maxpage - 1)) {
    			curChoices["95_NEXT"] = {
    				text: "[sc-nextpage]",
    				color: this._itemColor
    			};
    		} else {
    			curChoices["95_NEXT"] = {
    				text: "[sc-nextpage]",
    				color: this._disabledColor,
    				unselectable: true
    			};
    		}
    		if (this._page > 0) {
    			curChoices["96_PREV"] = {
    				text: "[sc-prevpage]",
    				color: this._itemColor
    			};
    		} else {
    			curChoices["96_PREV"] = {
    				text: "[sc-prevpage]",
    				color: this._disabledColor,
    				unselectable: true
    			};
    		}
    
    		if (this._display <= 9 || this._display === 18 || this._display >= 20) {
    			curChoices["98_EXIT"] = {
    				text: "[sc-return]",
    				color: this._itemColor
    			};
    		} else {
    			def = "97_EXIT";
    			curChoices["97_EXIT"] = {
    				text: "[sc-return]",
    				color: this._itemColor
    			};
    		}
    
    		if (this._lastChoice[this._display] != "") def = this._lastChoice[this._display];
    
    		var opts = {
    			screenID: "oolite-shipconfig-section-map",
    			title: "Ship Configuration",
    			allowInterrupt: interrupt,
    			exitScreen: "GUI_SCREEN_EQUIP_SHIP",
    			choices: curChoices,
    			initialChoicesKey: def,
    			message: text
    		};
    	}
    
    	// electrical sub menu
    	if (this._display === 10) {
    		text += this.$padTextRight(expandDescription("[sc-section-elecbuscouplings]"), col1) + this.$padTextLeft("Equip", col2) + "\n";
    		text += this.$padTextRight(expandDescription("[sc-menudescription]"), col1) +
    			this.$padTextLeft("space", col2) +
    			this.$padTextLeft("Weight", col2);
    
    		curChoices["11_BUS"] = {
    			text: this.$padTextRight("Electrical Bus (Class " + this.$equipmentItemInUse("electricalbus", p).replace("EQ_ELEC_BUS_TYPE", "") + ")", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("electricalbus", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("electricalbus", p).toFixed(1) + spc + "t", col2),
    			alignment: "LEFT",
    			color: this._menuColor
    		};
    		curChoices["12_ENGINES"] = {
    			text: this.$padTextRight("Engine Power Coupling (Class " + this.$equipmentItemInUse("enginecoupling", p).replace("EQ_ENGINE_COUPLING_TYPE", "") + ")", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("enginecoupling", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("enginecoupling", p).toFixed(1) + spc + "t", col2),
    			alignment: "LEFT",
    			color: this._menuColor
    		};
    		if (this.$shipHasHyperspaceMotor(p.dataKey) === true && this._OXPHyperdrives === false) {
    			curChoices["13_HYPERDRIVE"] = {
    				text: this.$padTextRight("Hyperdrive Power Coupling (Class " + this.$equipmentItemInUse("hyperdrivecoupling", p).replace("EQ_HYPERDRIVE_COUPLING_TYPE", "") + ")", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("hyperdrivecoupling", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("hyperdrivecoupling", p).toFixed(1) + spc + "t", col2),
    				alignment: "LEFT",
    				color: this._menuColor
    			};
    		}
    		// do we have a wide font?
    		var thrText = "Manoeuvring Thrusters";
    		if (defaultFont.measureString("W") > 0.8) thrText = "Thrusters";
    		curChoices["14_THRUSTERS"] = {
    			text: this.$padTextRight(thrText + " Power Coupling (Class " + this.$equipmentItemInUse("thrusterscoupling", p).replace("EQ_THRUSTERS_COUPLING_TYPE", "") + ")", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("thrusterscoupling", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("thrusterscoupling", p).toFixed(1) + spc + "t", col2),
    			alignment: "LEFT",
    			color: this._menuColor
    		};
    		curChoices["14A_BOOSTERS"] = {
    			text: this.$padTextRight("Boosters Power Coupling (Class " + this.$equipmentItemInUse("boosterscoupling", p).replace("EQ_BOOSTERS_COUPLING_TYPE", "") + ")", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("boosterscoupling", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("boosterscoupling", p).toFixed(1) + spc + "t", col2),
    			alignment: "LEFT",
    			color: this._menuColor
    		};
    		curChoices["15_ENERGY"] = {
    			text: this.$padTextRight("Energy Banks Power Coupling (Class " + this.$equipmentItemInUse("energycoupling", p).replace("EQ_ENERGYBANK_COUPLING_TYPE", "") + ")", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("energycoupling", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("energycoupling", p).toFixed(1) + spc + "t", col2),
    			alignment: "LEFT",
    			color: this._menuColor
    		};
    		curChoices["16_FRONTSHIELDS"] = {
    			text: this.$padTextRight("Forward Shields Power Coupling (Class " + this.$equipmentItemInUse("frontshieldscoupling", p).replace("EQ_FORWARD_SHIELD_COUPLING_TYPE", "") + ")", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("frontshieldscoupling", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("frontshieldscoupling", p).toFixed(1) + spc + "t", col2),
    			alignment: "LEFT",
    			color: this._menuColor
    		};
    		curChoices["17_AFTSHIELDS"] = {
    			text: this.$padTextRight("Aft Shields Power Coupling (Class " + this.$equipmentItemInUse("aftshieldscoupling", p).replace("EQ_AFT_SHIELD_COUPLING_TYPE", "") + ")", col1) + this.$padTextLeft(this.$equipmentSpaceInUse("aftshieldscoupling", p).toFixed(1) + spc + "t", col2) + this.$padTextLeft(this.$equipmentWeightInUse("aftshieldscoupling", p).toFixed(1) + spc + "t", col2),
    			alignment: "LEFT",
    			color: this._menuColor
    		};
    
    		for (var i = 0; i < (pagesize - (12 - (this.$shipHasHyperspaceMotor(p.dataKey) === true && this._OXPHyperdrives === false ? 0 : 1))); i++) {
    			curChoices["90_SPACER_" + i] = "";
    		}
    
    		curChoices["98_EXIT"] = {
    			text: "[sc-return]",
    			color: this._itemColor
    		};
    
    		if (this._lastChoice[this._display] != "") def = this._lastChoice[this._display];
    
    		var opts = {
    			screenID: "oolite-shipconfig-electrical-map",
    			title: "Ship Configuration",
    			allowInterrupt: interrupt,
    			exitScreen: "GUI_SCREEN_EQUIP_SHIP",
    			choices: curChoices,
    			initialChoicesKey: def,
    			message: text
    		};
    
    	}
    
    	// view installed equipment
    	if (this._display === 30) {
    		text = expandDescription("[sc-spaceweight-profile]");
    		text += this.$padTextRight("", col1) + this.$padTextLeft("Equip", col2) + this.$padTextLeft("Cargo", col2) + "\n";
    		text += this.$padTextRight("Item", col1) +
    			this.$padTextLeft("space", col2) +
    			this.$padTextLeft("space", col2) +
    			this.$padTextLeft("Weight", col2) + "\n\n";
    
    		var eq = p.equipment;
    		for (var i = 0; i < eq.length; i++) {
    			var item = eq[i];
    			if (this._ignoreEquip.indexOf(item.equipmentKey) >= 0) continue;
    			var space = 0;
    			var weight = 0;
    			var cargos = 0;
    			var lookup = this._equipmentMatrix[item.equipmentKey];
    
    			if (lookup) {
    				space = lookup[0];
    				weight = lookup[1];
    				cargos = item.requiredCargoSpace;
    			} else {
    				if (item.requiredCargoSpace === 0) {
    					space = 1;
    					weight = 1;
    					cargos = 0;
    				} else {
    					space = 0;
    					cargos = item.requiredCargoSpace;
    					weight = item.requiredCargoSpace;
    				}
    			}
    			if (item.isVisible && item.requiresEmptyPylon === false && (space > 0 || weight > 0)) {
    				var dispname = item.name;
    				if (item.equipmentKey === "EQ_PASSENGER_BERTH") {
    					cargos *= p.passengerCapacity;
    					weight *= p.passengerCapacity;
    					dispname = "Passenger Berth";
    					if (p.passengerCapacity > 1) dispname = p.passengerCapacity + " Passenger Berths";
    				}
    				list.push({
    					eq: item.equipmentKey,
    					space: space,
    					weight: weight,
    					cargo: cargos,
    					name: dispname
    				});
    			}
    		}
    		// now add items not in the equipment list:
    		if (p.forwardWeapon && p.forwardWeapon.equipmentKey != "EQ_WEAPON_NONE") {
    			list.push({
    				eq: p.forwardWeapon.equipmentKey,
    				space: 0,
    				weight: this.$weaponWeight(p.forwardWeapon.equipmentKey),
    				cargo: 0,
    				name: "Forward weapon: " + p.forwardWeapon.name
    			});
    		}
    		if (p.aftWeapon && p.aftWeapon.equipmentKey != "EQ_WEAPON_NONE") {
    			list.push({
    				eq: p.aftWeapon.equipmentKey,
    				space: 0,
    				weight: this.$weaponWeight(p.aftWeapon.equipmentKey),
    				cargo: 0,
    				name: "Aft weapon: " + p.aftWeapon.name
    			});
    		}
    		if (p.portWeapon && p.portWeapon.equipmentKey != "EQ_WEAPON_NONE") {
    			list.push({
    				eq: p.portWeapon.equipmentKey,
    				space: 0,
    				weight: this.$weaponWeight(p.portWeapon.equipmentKey),
    				cargo: 0,
    				name: "Port weapon: " + p.portWeapon.name
    			});
    		}
    		if (p.starboardWeapon && p.starboardWeapon.equipmentKey != "EQ_WEAPON_NONE") {
    			list.push({
    				eq: p.starboardWeapon.equipmentKey,
    				space: 0,
    				weight: this.$weaponWeight(p.starboardWeapon.equipmentKey),
    				cargo: 0,
    				name: "Starboard weapon: " + p.starboardWeapon.name
    			});
    		}
    		// any missiles?
    		if (p.missileCapacity > 0) {
    			var flag = false;
    			try {
    				var miss = p.missiles;
    				flag = true;
    			} catch (err) {
    				if (this._debug) log(this.name, "!!ERROR: " + err);
    			}
    			if (flag === true) {
    				for (var i = 0; i < miss.length; i++) {
    					//if (this._debug) log(this.name, p.missileCapacity + " - " + i + ": " + miss[i].equipmentKey);
    					if (this._ignoreEquip.indexOf(miss[i].equipmentKey) >= 0) continue;
    					if (!this._equipmentMatrix[miss[i].equipmentKey]) {
    						list.push({
    							eq: miss[i].equipmentKey,
    							space: 0,
    							weight: 1,
    							cargo: 0,
    							name: (miss[i].name === "Missile" ? "Standard Missile" : miss[i].name)
    						});
    					} else {
    						list.push({
    							eq: miss[i].equipmentKey,
    							space: 0,
    							weight: this._equipmentMatrix[miss[i].equipmentKey][1],
    							cargo: 0,
    							name: miss[i].name
    						});
    					}
    				}
    			}
    		}
    
    		// special items
    		// LMSS weapons
    		var lmss = worldScripts.LMSS_Core;
    		if (lmss) {
    			if (lmss._forwardAltKey != "EQ_WEAPON_NONE" && lmss._forwardAltKey != "") {
    				list.push({
    					eq: lmss._forwardAltKey,
    					space: 0,
    					weight: this.$weaponWeight(lmss._forwardAltKey),
    					cargo: 0,
    					name: "LMSS Secondary weapon: " + EquipmentInfo.infoForKey(lmss._forwardAltKey).name
    				});
    			}
    			if (lmss._aftAltKey != "EQ_WEAPON_NONE" && lmss._aftAltKey != "") {
    				list.push({
    					eq: lmss._aftAltKey,
    					space: 0,
    					weight: this.$weaponWeight(lmss._aftAltKey),
    					cargo: 0,
    					name: "LMSS Secondary weapon: " + EquipmentInfo.infoForKey(lmss._aftAltKey).name
    				});
    			}
    			if (lmss._portAltKey != "EQ_WEAPON_NONE" && lmss._portAltKey != "") {
    				list.push({
    					eq: lmss._portAltKey,
    					space: 0,
    					weight: this.$weaponWeight(lmss._portAltKey),
    					cargo: 0,
    					name: "LMSS Secondary weapon: " + EquipmentInfo.infoForKey(lmss._portAltKey).name
    				});
    			}
    			if (lmss._starboardAltKey != "EQ_WEAPON_NONE" && lmss._starboardAltKey != "") {
    				list.push({
    					eq: lmss._starboardAltKey,
    					space: 0,
    					weight: this.$weaponWeight(lmss._starboardAltKey),
    					cargo: 0,
    					name: "LMSS Secondary weapon: " + EquipmentInfo.infoForKey(lmss._starboardAltKey).name
    				});
    			}
    		}
    
    		var cargo = 0;
    		// add cargo weight
    		if (this.$getCargoCapacity(p) > 0 && p.cargoList.length > 0) {
    			for (var i = 0; i < p.cargoList.length; i++) {
    				var itm = p.cargoList[i];
    				switch (itm.unit) {
    					case "t":
    						cargo += itm.quantity;
    						break;
    					case "kg":
    						cargo += (itm.quantity / 500);
    						break;
    					case "g":
    						cargo += (itm.quantity / 500000);
    						break;
    				}
    			}
    		}
    
    		var smuggling = worldScripts.Smugglers_Equipment;
    		if (smuggling) {
    			// add the weight of any cargo in the smuggling compartment
    			var s_cargo = smuggling.$getSmugglingCargo();
    			for (var i = 0; i < s_cargo.length; i++) {
    				switch (s_cargo[i].unit) {
    					case "t":
    						cargo += s_cargo[i].quantity;
    						break;
    					case "kg":
    						cargo += (s_cargo[i].quantity / 1000);
    						break;
    					case "g":
    						cargo += (s_cargo[i].quantity / 1000000);
    						break;
    				}
    			}
    		}
    
    		if (cargo > 0) {
    			list.push({
    				eq: "cargo",
    				space: 0,
    				weight: parseInt(cargo),
    				cargo: cargo,
    				name: "Cargo"
    			});
    		}
    
    		list.sort(compare);
    
    		var maxpage = Math.ceil(list.length / (pagesize - 2));
    		var end = ((this._page * (pagesize - 2)) + (pagesize - 2));
    		if (end > list.length) end = list.length;
    		for (var i = (this._page * (pagesize - 2)); i < end; i++) {
    			text += this.$padTextRight(list[i].name, col1) +
    				this.$padTextLeft(list[i].space.toFixed(1) + spc + "t", col2) +
    				this.$padTextLeft(list[i].cargo.toFixed(1) + spc + "t", col2) +
    				this.$padTextLeft(list[i].weight.toFixed(1) + spc + "t", col2) + "\n";
    			//itemcount += 1;
    		}
    
    		if (maxpage > 1 && this._page < (maxpage - 1)) {
    			curChoices["95_NEXT"] = {
    				text: "[sc-nextpage]",
    				color: this._itemColor
    			};
    		} else {
    			curChoices["95_NEXT"] = {
    				text: "[sc-nextpage]",
    				color: this._disabledColor,
    				unselectable: true
    			};
    		}
    		if (this._page > 0) {
    			curChoices["96_PREV"] = {
    				text: "[sc-prevpage]",
    				color: this._itemColor
    			};
    		} else {
    			curChoices["96_PREV"] = {
    				text: "[sc-prevpage]",
    				color: this._disabledColor,
    				unselectable: true
    			};
    		}
    
    		def = "98_EXIT";
    		if (this._lastChoice[this._display] != "") def = this._lastChoice[this._display];
    
    
    		curChoices["98_EXIT"] = {
    			text: "[sc-return]",
    			color: this._itemColor
    		};
    
    		var opts = {
    			screenID: "oolite-shipconfig-installed-map",
    			title: "Ship Configuration",
    			allowInterrupt: interrupt,
    			exitScreen: "GUI_SCREEN_EQUIP_SHIP",
    			choices: curChoices,
    			initialChoicesKey: def,
    			message: text
    		};
    
    	}
    
    	this.$addShipModelToScreen(opts);
    	mission.runScreen(opts, this.$shipConfigScreenHandler, this);
    	this.$finaliseShipModel();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns the ship config page header
    this.$pageHeader = function $pageHeader(pageType) {
    
    	var p = player.ship;
    	var shipspec = Ship.shipDataForKey(p.dataKey);
    	var used = this.$calcEquipmentSpace(p);
    	var cargoUsed = this.$cargoEquipmentSpaceAmount(p);
    	var maxCargo = this.$cargoSpaceAvailable(p);
    	var maxSpace = Math.ceil(this.$equipmentSpaceTotal(p) + maxCargo);
    	var spc = String.fromCharCode(31) + String.fromCharCode(31) + String.fromCharCode(31);
    
    	var text = "";
    
    	var addtext = "";
    	switch (pageType) {
    		case "sell":
    			if (used > maxSpace) {
    				addtext = expandDescription("[sc-overload-sell]");
    				cargoUsed = maxCargo;
    			}
    			break;
    		case "store":
    			if (used > maxSpace) {
    				addtext = expandDescription("[sc-overload-store]");
    				cargoUsed = maxCargo;
    			}
    			if (player.ship.dockedStation.isMainStation === true && worldScripts.EquipmentStorage.$storageSystemCount(galaxyNumber, system.ID) === 0) {
    				addtext += expandDescription("[storage-deposit-required]", {
    					fee: formatCredits(worldScripts.EquipmentStorage._establishmentFee, false, true)
    				});
    			}
    			break;
    		case "config":
    			if (used > maxSpace) {
    				addtext = expandDescription("[sc-overload-config]");
    				cargoUsed = maxCargo;
    			}
    			if (this._freeUpgrades === true) addtext += expandDescription("[sc-free-upgrades]");
    			break;
    	}
    
    	text += this.$padTextRight(expandDescription("[sc-header-cash]", {
    		cash: formatCredits(player.credits, true, true)
    	}), 18) + p.shipClassName + expandDescription("[sc-header-statistics]") + "\n";
    	text += this.$padTextRight(expandDescription("[sc-header-equipspace]"), 11) + this.$padTextRight(used.toFixed(1) + spc + "t (" + maxSpace.toFixed(0) + spc + "t)", 7) +
    		this.$padTextRight(expandDescription("[sc-header-thrust]"), 4) + this.$padTextRight(this.$calculatedValue("thrust", p).toFixed(1) + spc + "m/s²", 5) +
    		"(" + parseInt(shipspec["thrust"]) + spc + "m/s²)\n";
    	text += this.$padTextRight(expandDescription("[sc-header-cargo]"), 11) + this.$padTextRight(cargoUsed.toFixed(1) + spc + "t (" + maxCargo + spc + "t)", 7) +
    		this.$padTextRight(expandDescription("[sc-header-speed]"), 4) + this.$padTextRight((this.$calculatedValue("speed", p) / 1000).toFixed(3) + spc + "LS", 5) +
    		"(" + (parseInt(shipspec["max_flight_speed"]) / 1000).toFixed(3) + spc + "LS)\n";
    	text += this.$padTextRight(expandDescription("[sc-header-weight]"), 11) + this.$padTextRight(this.$calcEquipmentWeight(p).toFixed(1) + spc + "t", 7) +
    		this.$padTextRight(expandDescription("[sc-header-pitch]"), 4) + this.$padTextRight(this.$calculatedValue("pitch", p).toFixed(2), 5) +
    		"(" + parseFloat(shipspec["max_flight_pitch"]).toFixed(2) + ")\n";
    	text += this.$padTextRight(expandDescription("[sc-header-busovl]"), 11) + this.$padTextRight(this.$busOverloadChance(p).toFixed(0) + spc + "%", 7) +
    		this.$padTextRight(expandDescription("[sc-header-roll]"), 4) + this.$padTextRight(this.$calculatedValue("roll", p).toFixed(2), 5) +
    		"(" + parseFloat(shipspec["max_flight_roll"]).toFixed(2) + ")\n";
    	text += addtext + "\n";
    
    	return text;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$shipConfigScreenHandler = function $shipConfigScreenHandler(choice) {
    
    	if (!choice) return;
    
    	var p = player.ship;
    	var stn = p.dockedStation;
    
    	this._lastChoice[this._display] = choice;
    
    	if (choice.indexOf("01_EQUIP") >= 0) {
    		var item = choice.substring(choice.indexOf("~") + 1);
    		switch (item) {
    			case "EQ_FUEL_INJECTION_REMOVE":
    				for (var i = 0; i < this._fuelinjectors.length; i++) {
    					if (p.equipmentStatus(this._fuelinjectors[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._fuelinjectors[i]) === "EQUIPMENT_DAMAGED") {
    						this._source = "REMOVEITEM";
    						this.$sellEquipmentScreenHandler("01_EQUIP~" + this._fuelinjectors[i]);
    						break;
    					}
    				}
    				break;
    			case "EQ_FUEL_SCOOPS_REMOVE":
    				for (var i = 0; i < this._fuelscoops.length; i++) {
    					if (p.equipmentStatus(this._fuelscoops[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._fuelscoops[i]) === "EQUIPMENT_DAMAGED") {
    						this._source = "REMOVEITEM";
    						this.$sellEquipmentScreenHandler("01_EQUIP~" + this._fuelscoops[i]);
    						break;
    					}
    				}
    				break;
    			case "EQ_HEAT_SHIELD_REMOVE":
    				for (var i = 0; i < this._heatshields.length; i++) {
    					if (p.equipmentStatus(this._heatshields[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._heatshields[i]) === "EQUIPMENT_DAMAGED") {
    						this._source = "REMOVEITEM";
    						this.$sellEquipmentScreenHandler("01_EQUIP~" + this._heatshields[i]);
    						break;
    					}
    				}
    				break;
    			case "EQ_ARMOUR_FORWARD_REMOVE":
    				for (var i = 0; i < this._frontarmour.length; i++) {
    					if (p.equipmentStatus(this._frontarmour[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._frontarmour[i]) === "EQUIPMENT_DAMAGED") {
    						this._source = "REMOVEITEM";
    						this.$sellEquipmentScreenHandler("01_EQUIP~" + this._frontarmour[i]);
    						break;
    					}
    				}
    				break;
    			case "EQ_ARMOUR_AFT_REMOVE":
    				for (var i = 0; i < this._aftarmour.length; i++) {
    					if (p.equipmentStatus(this._aftarmour[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._aftarmour[i]) === "EQUIPMENT_DAMAGED") {
    						this._source = "REMOVEITEM";
    						this.$sellEquipmentScreenHandler("01_EQUIP~" + this._aftarmour[i]);
    						break;
    					}
    				}
    				break;
    			case "EQ_BOOSTERS_REMOVE":
    				for (var i = 0; i < this._boosters.length; i++) {
    					if (p.equipmentStatus(this._boosters[i]) === "EQUIPMENT_OK" || p.equipmentStatus(this._boosters[i]) === "EQUIPMENT_DAMAGED") {
    						this._source = "REMOVEITEM";
    						this.$sellEquipmentScreenHandler("01_EQUIP~" + this._boosters[i]);
    						break;
    					}
    				}
    				break;
    			default:
    				var info = EquipmentInfo.infoForKey(item);
    				var priceFactor = this.$equipmentPriceFactor(p.shipClassName, this.$getShipMass(p)) * (stn.equivalentTechLevel >= info.techLevel ? stn.equipmentPriceFactor : 1);
    
    				// scoops, injectors and heatshields don't have a price factor
    				if (this._fuelscoops.indexOf(item) >= 0 || this._fuelinjectors.indexOf(item) >= 0 || this._heatshields.indexOf(item) >= 0) priceFactor = 1;
    
    				if (this._freeUpgrades === true || (player.credits >= (info.price / 10) * priceFactor)) {
    					this.$playSound("buy");
    					// reset the holding dict
    					this._current = {};
    					p.awardEquipment(item);
    					if (this._freeUpgrades === false) {
    						player.credits -= (info.price / 10) * priceFactor;
    						// give the player an email, if installed
    						var ga = worldScripts.GalCopAdminServices;
    						if (ga) {
    							ga.playerBoughtEquipment(item);
    						}
    					}
    					if (this._installationTime === true) {
    						clock.addSeconds(600 + (info.price * priceFactor));
    						// perform any callbacks that have been registered
    						if (this._callbacks.length > 0) {
    							for (var cb = 0; cb < this._callbacks.length; cb++) {
    								this._callbacks[cb]();
    							}
    						}
    					}
    				} else {
    					player.consoleMessage("Insufficient credit to purchase item.");
    				}
    		}
    	}
    
    	if (choice === "01_ENGINES") {
    		this._display = 1;
    		this._page = 0;
    	}
    	if (choice === "02_HYPERDRIVE") {
    		this._display = 2;
    		this._page = 0;
    	}
    	if (choice === "03_THRUSTERS") {
    		this._display = 3;
    		this._page = 0;
    	}
    	if (choice === "03A_BOOSTERS") {
    		this._display = 18;
    		this._page = 0;
    	}
    	if (choice === "04_ENERGY") {
    		this._display = 4;
    		this._page = 0;
    	}
    	if (choice === "05_FRONTSHIELDS") {
    		this._display = 5;
    		this._page = 0;
    	}
    	if (choice === "06_AFTSHIELDS") {
    		this._display = 6;
    		this._page = 0;
    	}
    	if (choice === "07_FUELINJECTORS") {
    		this._display = 7;
    		this._page = 0;
    	}
    	if (choice === "08_FUELSCOOPS") {
    		this._display = 20;
    		this._page = 0;
    	}
    	if (choice === "09_HEATSHIELDS") {
    		this._display = 8;
    		this._page = 0;
    	}
    	if (choice === "10_ARMOUR_0FRONT") {
    		this._display = 9;
    		this._page = 0;
    	}
    	if (choice === "10_ARMOUR_1AFT") {
    		this._display = 21;
    		this._page = 0;
    	}
    	if (choice === "11_ELECTRICAL") {
    		this._display = 10;
    		this._page = 0;
    	}
    
    	if (choice === "11_BUS") {
    		this._display = 11;
    		this._page = 0;
    	}
    	if (choice === "12_ENGINES") {
    		this._display = 12;
    		this._page = 0;
    	}
    	if (choice === "13_HYPERDRIVE") {
    		this._display = 13;
    		this._page = 0;
    	}
    	if (choice === "14_THRUSTERS") {
    		this._display = 14;
    		this._page = 0;
    	}
    	if (choice === "14A_BOOSTERS") {
    		this._display = 19;
    		this._page = 0;
    	}
    	if (choice === "15_ENERGY") {
    		this._display = 15;
    		this._page = 0;
    	}
    	if (choice === "16_FRONTSHIELDS") {
    		this._display = 16;
    		this._page = 0;
    	}
    	if (choice === "17_AFTSHIELDS") {
    		this._display = 17;
    		this._page = 0;
    	}
    
    	if (choice === "97_EXIT") {
    		this._display = 10;
    		this._page = 0;
    	}
    	if (choice === "98_EXIT") {
    		this._display = 0;
    		this._page = 0;
    	}
    
    	if (choice === "95_NEXT") this._page += 1;
    	if (choice === "96_PREV") this._page -= 1;
    
    	if (choice === "96_VIEWEQUIP") {
    		this._display = 30;
    		this._page = 0;
    	}
    
    	if (choice === "97_SELL") {
    		this._source = "CONFIGSCREEN";
    		this.$sellEquipment();
    		return;
    	}
    	if (choice === "97A_STORAGE") {
    		this._source = "CONFIGSCREEN";
    		worldScripts.EquipmentStorage.$storeEquipment();
    		return;
    	}
    	if (choice != "99_EXIT") {
    		this.$shipConfig();
    	}
    	//worldScripts.ShipConfiguration_F3HUDControl.guiScreenChanged();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$sellEquipment = function $sellEquipment() {
    	function compare(a, b) {
    		return b.space - a.space;
    	}
    
    	var p = player.ship;
    	var stn = p.dockedStation;
    	var used = this.$calcEquipmentSpace(p);
    	var maxSpace = Math.ceil(this.$equipmentSpaceTotal(p) + this.$cargoSpaceAvailable(p));
    	var interrupt = true;
    	var spc = String.fromCharCode(31) + String.fromCharCode(31) + String.fromCharCode(31);
    
    	var text = "";
    	var curChoices = {};
    	var itemcount = 0;
    
    	var pagesize = 15;
    	if (this.$isBigGuiActive() === false) p.hudHidden = true;
    	this._configScreen = true;
    
    	// display the list of options
    	if (used > maxSpace) {
    		// make sure we don't lock the player in during flight
    		if (p.alertCondition === 0) {
    			interrupt = false; // set to false to force the player to sell equipment before continuing
    		}
    		curChoices["98_SWITCH"] = {
    			text: "[sc-change-config]",
    			color: this._itemColor
    		};
    		curChoices["99_EXIT"] = {
    			text: "[sc-return]",
    			color: this._disabledColor,
    			unselectable: true
    		};
    		pagesize -= 1;
    	} else {
    		curChoices["99_EXIT"] = {
    			text: "[sc-return]",
    			color: this._itemColor
    		};
    		this._initialSetup = false;
    	}
    
    	text += this.$pageHeader("sell");
    
    	text += this.$padTextRight(expandDescription("[sc-selling-equipment]"), 16) + this.$padTextLeft("Equip", 4) + "\n";
    	text += this.$padTextRight("Equipment Item", 16) +
    		this.$padTextLeft("space", 4) +
    		this.$padTextLeft("Weight", 4) +
    		this.$padTextLeft("Refund", 8) + "\n\n";
    
    	var eq = p.equipment;
    	var list = [];
    	var priceFactor = this.$equipmentPriceFactor(p.shipClassName, this.$getShipMass(p));
    	var curr = this._currEquip;
    
    	for (var i = 0; i < eq.length; i++) {
    		var item = eq[i];
    		// don't include "no sell" items
    		if (this._noSell.indexOf(item.equipmentKey) >= 0) continue;
    		// don't include any items in the ignore equipment list
    		if (this._ignoreEquip.indexOf(item.equipmentKey) >= 0) continue;
    		// don't include any items that have a zero cost
    		if (item.cost === 0) continue;
    		var space = 0;
    		var weight = 0;
    		var lookup = this._equipmentMatrix[item.equipmentKey];
    		if (lookup) {
    			space = lookup[0];
    			weight = lookup[1];
    		} else {
    			if (item.requiredCargoSpace === 0) {
    				space = 1;
    				weight = 1;
    			} else {
    				space = 0;
    				weight = item.requiredCargoSpace;
    			}
    		}
    		var colr = this._menuColor;
    		var dam = 1;
    		if (p.equipmentStatus(item.equipmentKey) === "EQUIPMENT_DAMAGED") {
    			colr = this._damagedColor;
    			dam = 0.5;
    		}
    		// special case for armour
    		if (this._frontarmour.indexOf(item.equipmentKey) >= 0 && p.script._armourFront < 100) {
    			colr = this._damagedColor;
    			dam = 0.5;
    		}
    		if (this._aftarmour.indexOf(item.equipmentKey) >= 0 && p.script._armourAft < 100) {
    			colr = this._damagedColor;
    			dam = 0.5;
    		}
    
    		if (item.isVisible && item.requiresEmptyPylon === false && (space > 0 || weight > 0)) {
    			// any items in the negotiate list will show as "???" in the cost column
    			// if the player chooses to sell this item he will have to negotiate a price
    			var loop = 1;
    			// special case for passenger berths - only 1 item is in the equipment list, but you could have multiple installed
    			if (item.equipmentKey === "EQ_PASSENGER_BERTH") loop = p.passengerCapacity;
    
    			var pf = stn.equipmentPriceFactor;
    			// these items don't use the price factoring
    			if (this._priceFactor.indexOf(item.equipmentKey) >= 0) {
    				pf = priceFactor;
    			}
    			var idx = curr.indexOf(item.equipmentKey);
    			var disabled = "";
    			if (item.effectiveTechLevel > stn.equivalentTechLevel) {disabled = "Low TL"; colr = this._disabledColor;}
    			if (this.$equipmentIsRequired(item.equipmentKey) === true) {disabled = "Required"; colr = this._disabledColor;}
    
    			for (var j = 1; j <= loop; j++) {
    				list.push({
    					eq: item.equipmentKey,
    					space: space,
    					weight: weight,
    					cost: (this._sellNegotiate.indexOf(item.equipmentKey) >= 0 ? "???" : (item.price / 10) * dam * (idx >= 0 ? this._refundPct : 1) * pf),
    					color: colr,
    					name: (item.equipmentKey === "EQ_PASSENGER_BERTH" ? "Passenger Berth" : item.name),
    					section: "",
    					disabled: disabled
    				});
    			}
    		}
    	}
    	// laser weapons
    	colr = this._menuColor;
    	var lmss = worldScripts.LMSS_Core;
    	var section = ["Forward", "Aft", "Port", "Starboard", "Forward (Secondary)", "Aft (Secondary)", "Port (Secondary)", "Starboard (Secondary)"];
    	for (var i = 0; i < 7; i++) {
    		var key = "";
    		switch (i) {
    			case 0:
    				key = p.forwardWeapon.equipmentKey;
    				break;
    			case 1:
    				key = p.aftWeapon.equipmentKey;
    				break;
    			case 2:
    				key = p.portWeapon.equipmentKey;
    				break;
    			case 3:
    				key = p.starboardWeapon.equipmentKey;
    				break;
    			case 4:
    				if (lmss) key = lmss._forwardAltKey;
    				break;
    			case 5:
    				if (lmss) key = lmss._aftAltKey;
    				break;
    			case 6:
    				if (lmss) key = lmss._portAltKey;
    				break;
    			case 7:
    				if (lmss) key = lmss._starboardAltKey;
    				break;
    		}
    		if (key !== "" && key !== "EQ_WEAPON_NONE") {
    			var item = EquipmentInfo.infoForKey(key);
    			var space = 0;
    			var weight = 0;
    			var zeroSpace = 0;
    
    			var lookup = this._equipmentMatrix[item.equipmentKey];
    			if (lookup) {
    				space = parseFloat(lookup[0]);
    				weight = parseFloat(lookup[1]);
    			} else {
    				space = 0;
    				weight = 1;
    			}
    
    			if (item.effectiveTechLevel <= stn.equivalentTechLevel) {
    				list.push({
    					eq: item.equipmentKey,
    					space: space,
    					weight: weight,
    					cost: (item.price / 10),
    					color: colr,
    					name: item.name + " (" + section[i] + ")",
    					section: i,
    					disabled: ""
    				});
    			}
    		}
    	}
    
    	if (list.length > 0) {
    		list.sort(compare);
    
    		var maxpage = Math.ceil(list.length / pagesize);
    		if (maxpage < (this._page + 1)) this._page -= 1;
    		var end = ((this._page * pagesize) + pagesize);
    		if (end > list.length) end = list.length;
    		// note: then station equipmentPriceFactor has been removed to prevent exploitation of equipment sales at different stations (galcop => rock hermit)
    		for (var i = (this._page * pagesize); i < end; i++) {
    			curChoices["01_EQUIP-" + (i < 10 ? "0" : "") + i + "~" + list[i].eq + (list[i].section !== "" ? "|" + list[i].section : "")] = {
    				text: this.$padTextRight(list[i].name, 16) +
    					this.$padTextLeft(list[i].space.toFixed(1) + spc + "t", 4) +
    					this.$padTextLeft(list[i].weight.toFixed(1) + spc + "t", 4) +
    					(list[i].disabled === "" ? (list[i].cost === "???" ? this.$padTextLeft("???", 8) :
    						this.$padTextLeft(formatCredits((list[i].cost), true, true), 8)) : this.$padTextLeft(list[i].disabled, 8)), //* stn.equipmentPriceFactor
    				alignment: "LEFT",
    				color: list[i].color,
    				unselectable: (list[i].disabled != "" ? true : false)
    			};
    			itemcount += 1;
    		}
    		for (var i = 0; i < ((pagesize + 1) - itemcount); i++) {
    			curChoices["90_SPACER_" + i] = "";
    		}
    	} else {
    		text += expandDescription("[sc-equipment-none-to-sell]");
    	}
    
    	if (maxpage > 1 && this._page < (maxpage - 1)) {
    		curChoices["95_NEXT"] = {
    			text: "[sc-nextpage]",
    			color: this._itemColor
    		};
    	} else {
    		curChoices["95_NEXT"] = {
    			text: "[sc-nextpage]",
    			color: this._disabledColor,
    			unselectable: true
    		};
    	}
    	if (this._page > 0) {
    		curChoices["96_PREV"] = {
    			text: "[sc-prevpage]",
    			color: this._itemColor
    		};
    	} else {
    		curChoices["96_PREV"] = {
    			text: "[sc-prevpage]",
    			color: this._disabledColor,
    			unselectable: true
    		};
    	}
    
    	var def = "99_EXIT";
    	if (this._lastChoice[20] != "") def = this._lastChoice[20];
    
    	var opts = {
    		screenID: "oolite-shipconfig-sell-map",
    		title: "Sell Equipment",
    		allowInterrupt: interrupt,
    		exitScreen: this._sellEquipExitScreen,
    		choices: curChoices,
    		initialChoicesKey: def,
    		message: text
    	};
    
    	this.$addShipModelToScreen(opts);
    	mission.runScreen(opts, this.$sellEquipmentScreenHandler, this);
    	this.$finaliseShipModel();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$sellEquipmentScreenHandler = function $sellEquipmentScreenHandler(choice) {
    	if (!choice) return;
    
    	var p = player.ship;
    	var stn = p.dockedStation;
    
    	if (this._source != "REMOVEITEM") this._lastChoice[20] = choice;
    
    	if (choice.indexOf("01_EQUIP") >= 0) {
    		var item = choice.substring(choice.indexOf("~") + 1);
    		var section = "";
    		// check for a laser position
    		if (item.indexOf("|") >= 0) {
    			section = item.split("|")[1];
    			item = item.split("|")[0];
    		}
    
    		var info = EquipmentInfo.infoForKey(item);
    		if (section === "") {
    			if (this._sellNegotiate.indexOf(item) >= 0) {
    				var cost = (info.price / 10) * this._refundPct;
    				if (p.equipmentStatus(item) === "EQUIPMENT_DAMAGED") cost *= 0.5;
    				worldScripts.ShipConfiguration_SellNegotiate.$displayInitialScreen(item, cost);
    				return;
    			}
    			var dam = p.equipmentStatus(item);
    
    			// special case for passenger berths
    			if (item === "EQ_PASSENGER_BERTH") {
    				var creds = player.credits;
    				p.awardEquipment("EQ_PASSENGER_BERTH_REMOVAL");
    				p.credits = creds;
    			} else {
    				p.removeEquipment(item);
    			}
    		} else {
    			var lmss = worldScripts.LMSS_Core;
    			switch (section) {
    				case "0":
    					p.forwardWeapon = "EQ_WEAPON_NONE";
    					break;
    				case "1":
    					p.aftWeapon = "EQ_WEAPON_NONE";
    					break;
    				case "2":
    					p.portWeapon = "EQ_WEAPON_NONE";
    					break;
    				case "3":
    					p.starboardWeapon = "EQ_WEAPON_NONE"
    					break;
    				case "4":
    					lmss._forwardAltKey = "EQ_WEAPON_NONE";
    					p.removeEquipment("EQ_LMSS_FRONT_WEAPON");
    					break;
    				case "5":
    					lmss._aftAltKey = "EQ_WEAPON_NONE";
    					p.removeEquipment("EQ_LMSS_AFT_WEAPON");
    					break;
    				case "6":
    					lmss._portAltKey = "EQ_WEAPON_NONE";
    					p.removeEquipment("EQ_LMSS_PORT_WEAPON");
    					break;
    				case "7":
    					lmss._starboardAltKey = "EQ_WEAPON_NONE";
    					p.removeEquipment("EQ_LMSS_STARBOARD_WEAPON");
    					break;
    			}
    			if (lmss) lmss.$updateManifest();
    			var dam = "EQUIPMENT_OK"; // lasers can't be damaged
    		}
    		// is this new or used? idx === -1 means new, otherwise any number >= 0 means used
    		var idx = this._currEquip.indexOf(item);
    		if (idx >= 0) this._currEquip.splice(idx, 1);
    
    		var doRefund = true;
    		// reset the holding dict
    		this._current = {};
    		if (this._freeUpgrades === true) {
    			// don't give the player a refund for these, otherwise they can make money by buying and selling the same thing
    			if (this._fuelinjectors.indexOf(item) >= 0 ||
    				this._fuelscoops.indexOf(item) >= 0 ||
    				this._heatshields.indexOf(item) >= 0 ||
    				this._armour.indexOf(item) >= 0 ||
    				this._boosters.indexOf(item) >= 0)
    				doRefund = false;
    		}
    		var priceFactor = stn.equipmentPriceFactor;
    		if (this._priceFactor.indexOf(item) >= 0) {
    			priceFactor = this.$equipmentPriceFactor(p.shipClassName, this.$getShipMass(p));
    		}
    		// lasers get a full refund, to match what happens when you do a buy/replace
    		var refund = (info.price / 10) * (info.equipmentKey.indexOf("EQ_WEAPON") >= 0 || (idx === -1 ? 1 : this._refundPct)) * priceFactor;
    		if (dam === "EQUIPMENT_DAMAGED") refund *= 0.5;
    		if (doRefund === true) player.credits += refund;
    
    		// give the player an email, if installed
    		var ga = worldScripts.GalCopAdminServices;
    		if (ga && doRefund === true) {
    			ga._oldCredits = player.credits - (doRefund === true ? refund : 0);
    			ga.playerBoughtEquipment(item);
    		}
    		this.$addEquipmentSpaceItem(p);
    		this.$playSound("sell");
    	}
    
    	if (choice === "95_NEXT") this._page += 1;
    	if (choice === "96_PREV") this._page -= 1;
    	if (choice === "98_SWITCH") {
    		this._source = "";
    		this.$shipConfig();
    		return;
    	}
    
    	if (this._source === "REMOVEITEM") return;
    
    	if (choice != "99_EXIT") {
    		this.$sellEquipment();
    		return;
    	}
    
    	if (choice === "99_EXIT" && this._source === "CONFIGSCREEN") {
    		this._source = "";
    		this.$shipConfig();
    	}
    	worldScripts.ShipConfiguration_F3HUDControl.guiScreenChanged();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // add the ship model, or an overlay, to the options for a mission screen
    this.$addShipModelToScreen = function $addShipModelToScreen(opts) {
    	var p = player.ship;
    	if (this._shipModel === true) {
    		opts["model"] = "[" + p.dataKey + "]";
    		opts["modelPersonality"] = p.entityPersonality;
    		opts["spinModel"] = false;
    		if (p.hudHidden === true || this.$isBigGuiActive() === true) {
    			opts["overlay"] = {
    				name: "shipconfig_mask.png",
    				height: 546
    			};
    		} else {
    			opts["overlay"] = {
    				name: "shipconfig_mask_sml.png",
    				height: 546
    			};
    		}
    	} else {
    		opts["overlay"] = {
    			name: "shipconfig_rocket.png",
    			height: 546
    		};
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$finaliseShipModel = function $finaliseShipModel() {
    
    	if (this._shipModel === false) return;
    
    	var m = mission.displayModel;
    	// rotate model for a better view
    	if (m) {
    		// if gallery has been loaded and used, remove the frame callback
    		var w = worldScripts.gallery;
    		if (w && isValidFrameCallback(w.$GalleryFCB)) removeFrameCallback(w.$GalleryFCB);
    
    		var zoom_factor = 3.6;
    		if (this._shipModel) {
    			if (this._zoomOverride[player.ship.shipClassName]) zoom_factor = this._zoomOverride[player.ship.shipClassName];
    		}
    		// zoom and rotate the image
    		m.position = Vector3D(0, 0, m.collisionRadius * zoom_factor);
    		m.orientation = m.orientation.rotate([0, 0, 0]);
    		m.orientation = m.orientation.rotateZ(Math.PI * 1.2);
    		m.orientation = m.orientation.rotateX(-1.1);
    	}
    }
    
    //=============================================================================================================
    // calculation/general functions
    
    //-------------------------------------------------------------------------------------------------------------
    // attach our equipment processing scripts to the player ship script object
    this.$setUpScriptConfig = function $setUpScriptConfig() {
    	var p = player.ship;
    	if (!p.script.$equipmentDamaged_Event) p.script.$equipmentDamaged_Event = this.$equipmentDamaged_Event;
    	if (!p.script.$awaitEquipmentDamaged) p.script.$awaitEquipmentDamaged = this.$awaitEquipmentDamaged;
    	if (!p.script.$checkRemainingEnergy) p.script.$checkRemainingEnergy = this.$checkRemainingEnergy;
    	if (p.script.hasOwnProperty("_damagedItems") === false) p.script._damagedItems = []; // list of damaged items that required config adjustment
    	if (p.script.hasOwnProperty("_checkForDamage") === false) p.script._checkForDamage = null; // timer used to call "$awaitEquipmentDamaged" to check the "damagedItems" array
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // this script should be attached to a ship.script object, including the player ship, for use inside the ship in question
    this.$equipmentDamaged_Event = function $equipmentDamaged_Event(equipmentKey) {
    
    	var isPlayer = this.ship.isPlayer;
    	var sc = worldScripts.ShipConfiguration_Core;
    
    	if (isPlayer && sc._damaging === true) return;
    
    	// armour handled in it's own script
    	if (sc._armour.indexOf(equipmentKey) >= 0) return;
    
    	if (isPlayer) sc._damaging = true;
    
    	if (equipmentKey === "EQ_HEAT_SINK") {
    		// do we have any working heat sinks?
    		if (this.ship.equipmentStatus("EQ_HEAT_SINK", true)["EQUIPMENT_OK"] == 0) {
    			this.ship.removeEquipment("EQ_HEAT_SINK_CONTROL");
    			this.ship.removeEquipment("EQ_HEAT_SINK_CONTROL_PASSIVE");
    		}
    	}
    
    	if (!this.ship.script._damagedItems) this.ship.script._damagedItems = [];
    
    	// when engines are damaged, reduce maxThrust/maxSpeed
    	// when thrusters are damaged, reduce maxPitch and maxRoll
    	// when hyperdrive is damaged, disable hyperjumps
    	// when energy banks are disabled, stop recharging, start a slow energy leak
    	// when shields are damaged, reduce to 0
    	// when heat shield is damaged, reduce heat shielding on ship
    
    	if (sc._engines.indexOf(equipmentKey) >= 0) {
    		// damage the injectors before the engine
    		if (this.ship.equipmentStatus(sc.$equipmentItemInUse("fuelinjectors", this.ship)) === "EQUIPMENT_OK") {
    			this.ship.setEquipmentStatus(equipmentKey, "EQUIPMENT_OK");
    			if (isPlayer) sc._damaging = false;
    			this.ship.setEquipmentStatus(sc.$equipmentItemInUse("fuelinjectors", this.ship), "EQUIPMENT_DAMAGED");
    			return;
    		}
    		this.ship.script._damagedItems.push(equipmentKey);
    		if (!this.ship.script._checkForDamage || !this.ship.script._checkForDamage.isRunning) {
    			this.ship.script._checkForDamage = new Timer(this, this.ship.script.$awaitEquipmentDamaged, 0.25, 0);
    		}
    	}
    	if (sc._thrusters.indexOf(equipmentKey) >= 0) {
    		this.ship.script._damagedItems.push(equipmentKey);
    		if (!this.ship.script._checkForDamage || !this.ship.script._checkForDamage.isRunning) {
    			this.ship.script._checkForDamage = new Timer(this, this.ship.script.$awaitEquipmentDamaged, 0.25, 0);
    		}
    	}
    	if (sc._energy.indexOf(equipmentKey) >= 0) {
    		// damage extra energy units before base energy units
    		if (this.ship.equipmentStatus("EQ_ENERGY_GRID") === "EQUIPMENT_OK") {
    			this.ship.setEquipmentStatus(equipmentKey, "EQUIPMENT_OK");
    			this.ship.setEquipmentStatus("EQ_ENERGY_GRID", "EQUIPMENT_DAMAGED");
    			if (isPlayer) {
    				sc.$playSound("explosion");
    				sc._damaging = false;
    			}
    			return;
    		}
    		if (this.ship.equipmentStatus("EQ_NAVAL_GRID") === "EQUIPMENT_OK") {
    			this.ship.setEquipmentStatus(equipmentKey, "EQUIPMENT_OK");
    			this.ship.setEquipmentStatus("EQ_NAVAL_GRID", "EQUIPMENT_DAMAGED");
    			if (isPlayer) {
    				sc.$playSound("explosion");
    				sc._damaging = false;
    			}
    			return;
    		}
    		if (this.ship.equipmentStatus("EQ_NAVAL_ENERGY_UNIT") === "EQUIPMENT_OK") {
    			this.ship.setEquipmentStatus(equipmentKey, "EQUIPMENT_OK");
    			this.ship.setEquipmentStatus("EQ_NAVAL_ENERGY_UNIT", "EQUIPMENT_DAMAGED");
    			if (isPlayer) {
    				sc.$playSound("explosion");
    				sc._damaging = false;
    			}
    			return;
    		}
    		if (this.ship.equipmentStatus("EQ_ENERGY_UNIT") === "EQUIPMENT_OK") {
    			this.ship.setEquipmentStatus(equipmentKey, "EQUIPMENT_OK");
    			this.ship.setEquipmentStatus("EQ_ENERGY_UNIT", "EQUIPMENT_DAMAGED");
    			if (isPlayer) {
    				sc.$playSound("explosion");
    				sc._damaging = false;
    			}
    			return;
    		}
    		this.ship.script._damagedItems.push(equipmentKey);
    		if (!this.ship.script._checkForDamage || !this.ship.script._checkForDamage.isRunning) {
    			this.ship.script._checkForDamage = new Timer(this, this.ship.script.$awaitEquipmentDamaged, 0.25, 0);
    		}
    	}
    
    	if (sc._frontshields.indexOf(equipmentKey) >= 0 || sc._aftshields.indexOf(equipmentKey) >= 0 || sc._shieldEquipment.indexOf(equipmentKey) >= 0) {
    		// damage the naval grid, shield booster and mil shield enhancements first
    		/* if (this.ship.equipmentStatus("EQ_ENERGY_GRID") === "EQUIPMENT_OK") {
    			this.ship.setEquipmentStatus(equipmentKey, "EQUIPMENT_OK");
    			this.ship.setEquipmentStatus("EQ_ENERGY_GRID", "EQUIPMENT_DAMAGED");
    			if (isPlayer) {
    				sc.$playSound("explosion");
    				sc._damaging = false;
    			}
    			return;
    		}
    		if (this.ship.equipmentStatus("EQ_NAVAL_GRID") === "EQUIPMENT_OK") {
    			this.ship.setEquipmentStatus(equipmentKey, "EQUIPMENT_OK");
    			this.ship.setEquipmentStatus("EQ_NAVAL_GRID", "EQUIPMENT_DAMAGED");
    			if (isPlayer) {
    				sc.$playSound("explosion");
    				sc._damaging = false;
    			}
    			return;
    		}
    		if (this.ship.equipmentStatus("EQ_NAVAL_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
    			this.ship.setEquipmentStatus(equipmentKey, "EQUIPMENT_OK");
    			this.ship.setEquipmentStatus("EQ_NAVAL_SHIELD_BOOSTER", "EQUIPMENT_DAMAGED");
    			if (isPlayer) {
    				sc.$playSound("explosion");
    				sc._damaging = false;
    			}
    			return;
    		}
    		if (this.ship.equipmentStatus("EQ_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
    			this.ship.setEquipmentStatus(equipmentKey, "EQUIPMENT_OK");
    			this.ship.setEquipmentStatus("EQ_SHIELD_BOOSTER", "EQUIPMENT_DAMAGED");
    			if (isPlayer) {
    				sc.$playSound("explosion");
    				sc._damaging = false;
    			}
    			return;
    		} */
    		this.ship.script._damagedItems.push(equipmentKey);
    		if (!this.ship.script._checkForDamage || !this.ship.script._checkForDamage.isRunning) {
    			this.ship.script._checkForDamage = new Timer(this, this.ship.script.$awaitEquipmentDamaged, 0.25, 0);
    		}
    	}
    	if (sc._heatshields.indexOf(equipmentKey) >= 0) {
    		this.ship.script._damagedItems.push(equipmentKey);
    		if (!this.ship.script._checkForDamage || !this.ship.script._checkForDamage.isRunning) {
    			this.ship.script._checkForDamage = new Timer(this, this.ship.script.$awaitEquipmentDamaged, 0.25, 0);
    		}
    	}
    	// special case for when another OXP causes damage to heat shield
    	if (equipmentKey === "EQ_HEAT_SHIELD") {
    		if (isPlayer) sc._damaging = false;
    		this.ship.setEquipmentStatus(sc.$equipmentItemInUse("heatshields", this.ship), "EQUIPMENT_DAMAGED");
    		return;
    	}
    	if (sc._fuelinjectors.indexOf(equipmentKey) >= 0) {
    		this.ship.script._damagedItems.push(equipmentKey);
    		if (!this.ship.script._checkForDamage || !this.ship.script._checkForDamage.isRunning) {
    			this.ship.script._checkForDamage = new Timer(this, this.ship.script.$awaitEquipmentDamaged, 0.25, 0);
    		}
    	}
    	// special case for when another OXP causes damage to fuel injectors
    	if (equipmentKey === "EQ_FUEL_INJECTION") {
    		if (isPlayer) sc._damaging = false;
    		this.ship.setEquipmentStatus(sc.$equipmentItemInUse("fuelinjectors", this.ship), "EQUIPMENT_DAMAGED");
    		return;
    	}
    	if (sc._fuelscoops.indexOf(equipmentKey) >= 0) {
    		this.ship.script._damagedItems.push(equipmentKey);
    		if (!this.ship.script._checkForDamage || !this.ship.script._checkForDamage.isRunning) {
    			this.ship.script._checkForDamage = new Timer(this, this.ship.script.$awaitEquipmentDamaged, 0.25, 0);
    		}
    	}
    	// special case for when another OXP causes damage to fuel scoops
    	if (equipmentKey === "EQ_FUEL_SCOOPS") {
    		if (isPlayer) sc._damaging = false;
    		this.ship.setEquipmentStatus(sc.$equipmentItemInUse("fuelscoops", this.ship), "EQUIPMENT_DAMAGED");
    		return;
    	}
    	if (sc._hyperdrive.indexOf(equipmentKey) >= 0) {
    		this.ship.script._damagedItems.push(equipmentKey);
    		if (!this.ship.script._checkForDamage || !this.ship.script._checkForDamage.isRunning) {
    			this.ship.script._checkForDamage = new Timer(this, this.ship.script.$awaitEquipmentDamaged, 0.25, 0);
    		}
    	}
    
    	if (isPlayer) sc._damaging = false;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // this script should be attached to a ship.script object, for use inside the ship in question
    this.$awaitEquipmentDamaged = function $awaitEquipmentDamaged() {
    
    	if (this.ship == null) return;
    	if (!this.ship.script) return;
    	
    	//var p = player.ship;
    	var sc = worldScripts.ShipConfiguration_Core;
    	var isPlayer = this.ship.isPlayer;
    
    	delete this.ship.script._checkForDamage;
    	for (var i = this.ship.script._damagedItems.length - 1; i >= 0; i--) {
    		// make sure the equipment didn't get repaired by the armour script
    		if (this.ship.equipmentStatus(this.ship.script._damagedItems[i]) === "EQUIPMENT_DAMAGED") {
    			if (isPlayer) sc.$playSound("explosion");
    			if (sc._engines.indexOf(this.ship.script._damagedItems[i]) >= 0) {
    				this.ship.maxSpeed = this.ship.maxSpeed * 0.67;
    				this.ship.maxThrust = this.ship.maxThrust * 0.67;
    				this.ship.thrust = this.ship.maxThrust;
    				if (isPlayer) player.consoleMessage("Warning! Engines damaged!", 4);
    			}
    			if (sc._thrusters.indexOf(this.ship.script._damagedItems[i]) >= 0) {
    				this.ship.maxPitch = this.ship.maxPitch * 0.75;
    				this.ship.maxRoll = this.ship.maxRoll * 0.75;
    				if (isPlayer) player.consoleMessage("Warning! Thrusters damaged!", 4);
    			}
    			if (sc._boosters.indexOf(this.ship.script._damagedItems[i]) >= 0) {
    				this.ship.script._boosterHeatPoint = 0;
    				this.ship.maxSpeed = sc.$calculatedValue("speed", this.ship);
    				this.ship.maxThrust = sc.$calculatedValue("thrust", this.ship);
    				this.ship.thrust = this.ship.maxThrust;
    				this.ship.maxPitch = sc.$calculatedValue("pitch", this.ship);
    				this.ship.maxRoll = sc.$calculatedValue("roll", this.ship);
    				this.ship.maxYaw = sc.$calculatedValue("yaw", this.ship);
    				if (isPlayer) player.consoleMessage("Warning! Boosters damaged!", 4);
    			}
    			if (sc._energy.indexOf(this.ship.script._damagedItems[i]) >= 0) {
    				this.ship.script._energyRechargeRate_Stored = this.ship.energyRechargeRate;
    				this.ship.energyRechargeRate = 0;
    				if (isPlayer) player.consoleMessage("Warning! Energy banks damaged!", 4);
    				if (this.ship.alertCondition != 0) {
    					if (!this.ship.script._energyTimer || !this.ship.script._energyTimer.isRunning) {
    						this.ship.script._energyTimer = new Timer(this, this.ship.script.$checkRemainingEnergy, 1, 1);
    					}
    				}
    			}
    			if (sc._frontshields.indexOf(this.ship.script._damagedItems[i]) >= 0) {
    				// should be compatible with naval grid - we are damaging those items before allowing damage to shields
    				// so NG should have reset the recharge rate by this point
    				//this.ship.script._forwardShieldRechargeRate_Stored = this.ship.forwardShieldRechargeRate;
    				//this.ship.forwardShieldRechargeRate = -0.5;
    				sc.$updateShieldValues(this.ship);
    				if (isPlayer) {
    					player.consoleMessage("Warning! Front shield generator damaged!", 4);
    					sc.$disableShieldOXPs();
    				}
    			}
    			if (sc._aftshields.indexOf(this.ship.script._damagedItems[i]) >= 0) {
    				//this.ship.script._aftshieldsRechargeRate_Stored = this.ship.aftShieldRechargeRate;
    				//this.ship.aftShieldRechargeRate = -0.5;
    				sc.$updateShieldValues(this.ship);
    				if (isPlayer) {
    					player.consoleMessage("Warning! Aft shield generator damaged!", 4);
    					sc.$disableShieldOXPs();
    				}
    			}
    			if (sc._shieldEquipment.indexOf(this.ship.script._damagedItems[i]) >= 0) {
    				sc.$updateShieldValues(this.ship);
    			}
    			if (sc._fuelinjectors.indexOf(this.ship.script._damagedItems[i]) >= 0) {
    				if (isPlayer) player.consoleMessage("Warning! Fuel injectors damaged!", 4);
    				if (isPlayer) sc._damaging = true;
    				this.ship.setEquipmentStatus("EQ_FUEL_INJECTION", "EQUIPMENT_DAMAGED");
    				if (isPlayer) sc._damaging = false;
    			}
    			if (sc._fuelscoops.indexOf(this.ship.script._damagedItems[i]) >= 0) {
    				if (isPlayer) player.consoleMessage("Warning! Fuel scoops damaged!", 4);
    				if (isPlayer) sc._damaging = true;
    				this.ship.setEquipmentStatus("EQ_FUEL_SCOOPS", "EQUIPMENT_DAMAGED");
    				if (isPlayer) sc._damaging = false;
    			}
    			if (sc._heatshields.indexOf(this.ship.script._damagedItems[i]) >= 0) {
    				// reset heat shield strength back to the baseline for the ship
    				var shipspec = Ship.shipDataForKey(this.ship.dataKey);
    				this.ship.heatInsulation = parseFloat((shipspec["heat_insulation"] ? shipspec["heat_insulation"] : 1.0));
    				this.ship.script._heat_sink_factor = parseFloat(this._defaultHeatShieldHSFactor);
    				if (isPlayer) player.consoleMessage("Warning! Heat shield damaged!", 4);
    				if (isPlayer) sc._damaging = true;
    				this.ship.setEquipmentStatus("EQ_HEAT_SHIELD", "EQUIPMENT_DAMAGED");
    				if (isPlayer) sc._damaging = false;
    			}
    			if (sc._hyperdrive.indexOf(this.ship.script._damagedItems[i]) >= 0) {
    				this.ship.hyperdriveSpinTime = 50;
    				if (isPlayer) player.consoleMessage("Warning! Hyperdrive damaged!", 4);
    				if (Math.random() < 0.34) {
    					this.ship.fuelLeakRate = 0.25;
    					if (isPlayer) player.consoleMessage("ALERT! Quirium fuel leakage detected!", 3);
    				}
    			}
    		}
    		this.ship.script._damagedItems.splice(i, 1);
    	}
    
    	// if something got damaged while we were processing, set the timer up again
    	if (this.ship.script._damagedItems.length > 0) {
    		this.ship.script._checkForDamage = new Timer(this, this.ship.script.$awaitEquipmentDamaged, 0.25, 0);
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // this script should be attached to a ship.script object, for use inside the ship in question
    this.$checkRemainingEnergy = function $checkRemainingEnergy() {
    	// make sure we're still attached to a valid entity
    	if (this.ship.isValid === false || this.ship.isInSpace === false) {
    		if (this.ship.script) {
    			this.ship.script._energyTimer.stop();
    			delete this.ship.script._energyTimer;
    		}
    		return;
    	}
    	this.ship.energy -= 1;
    	this.ship.script._counter += 1;
    	if (this.ship.script._counter === 30) {
    		if (this.ship.isPlayer) player.consoleMessage("Warning! Energy levels depleting!", 4);
    		this.ship.script._counter = 0;
    	}
    	if (this.ship.energy < 30) {
    		this.ship.script._energyTimer.stop();
    		delete this.ship.script._energyTimer;
    		this.ship.energyRechargeRate = 0;
    		if (this.ship.isPlayer) player.consoleMessage("Warning! Energy levels critical!", 4);
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // turn off shield cycler and shield equaliser, if installed
    this.$disableShieldOXPs = function $disableShieldOXPs() {
    	var p = player.ship;
    	// disables Shield Cycler if fitted and active to prevent catastrophic shield/energy loss.
    	if (p.equipmentStatus("EQ_SC_SHIELD_CYCLER_INTERNAL") === "EQUIPMENT_OK" && !worldScripts["Shield Cycler"].deactivated) {
    		if (worldScripts["Shield Cycler"]._sc_stop()) {
    			this._stoppedSC = true;
    			player.consoleMessage("All Shield Cycler functionality disabled pending Primary Shield Generator repair.", 4);
    		}
    	}
    	// disables Shield Equaliser (and Capacitors) if fitted to prevent catastrophic Shield Loss.
    	if (p.equipmentStatus("EQ_SHIELD_EQUALIZER") === "EQUIPMENT_OK" && worldScripts["shieldequalizercapacitors"].shieldCheckTimer.isRunning) {
    		worldScripts["shieldequalizercapacitors"].shieldCheckTimer.stop();
    		this._stoppedSEC = true;
    		player.consoleMessage("All Shield Equalizer functionality disabled pending Primary Shield Generator repair.", 4);
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // turn on shield cycler and shield equaliser, if installed
    this.$enableShieldOXPs = function $enableShieldOXPs() {
    	var p = player.ship;
    	if (this._stoppedSC && worldScripts["Shield Cycler"].deactivated) {
    		if (worldScripts["Shield Cycler"]._sc_start()) {
    			delete this._stoppedSC;
    			if (p.equipmentStatus("EQ_SC_SHIELD_CYCLER_INTERNAL") === "EQUIPMENT_OK") {
    				player.consoleMessage("All Shield Cycler functionality re-enabled.", 4);
    			}
    		}
    	}
    	if (this._stoppedSEC && worldScripts["shieldequalizercapacitors"].shieldCheckTimer) {
    		worldScripts["shieldequalizercapacitors"].shieldCheckTimer.start();
    		delete this._stoppedSEC;
    		if (player.ship.equipmentStatus("EQ_SHIELD_EQUALIZER") === "EQUIPMENT_OK") {
    			player.consoleMessage("All Shield Equalizer functionality re-enabled.", 4);
    		}
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$stopTimers = function $stopTimers() {
    	var p = player.ship;
    	if (p && p.script && p.script._energyTimer && p.script._energyTimer.isRunning) {
    		p.script._energyTimer.stop();
    		delete p.script._energyTimer;
    	}
    	if (this._busOverloadResetTimer && this._busOverloadResetTimer.isRunning) {
    		this._busOverloadResetTimer.stop();
    	}
    	delete this._busOverloadResetTimer;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // checks for an overload state and then sets up the flags if overloaded
    this.$checkForOverload = function $checkForOverload() {
    	var p = player.ship;
    	var equipSpace = this.$equipmentSpaceTotal(p);
    	var cargoSpace = this.$cargoSpaceAvailable(p); // + this.$cargoEquipmentSpaceAmount(p));
    
    	var used = this.$calcEquipmentSpace(p);
    	if (used > equipSpace) {
    		// allocate cargo space to equipment space
    		var diff = parseInt(used - equipSpace);
    		if (diff > cargoSpace) {
    			// we don't have space for this
    			// switch into "overloaded" mode so the player can choose what item to remove
    			this._initialSetup = true;
    			this._promptPlayer = true;
    		}
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns true if the player has an alternative armour installed, otherwise false
    this.$playerHasOtherArmour = function $playerHasOtherArmour() {
    	var p = player.ship;
    	var result = false;
    	for (var i = 0; i < this._altArmour.length; i++) {
    		var sts = p.equipmentStatus(this._altArmour[i]);
    		if (sts === "EQUIPMENT_OK" || sts === "EQUIPMENT_DAMAGED") result = true;
    	}
    	return result;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // calculate how much bus overload exists on the ship
    this.$busOverloadChance = function $busOverloadChance(ship) {
    
    	if (!ship) return 0;
    
    	// work out if anything is over the coupling/bus class
    	var total = 0;
    	var eq = 0;
    	var check = 0;
    
    	var bus = this.$equipmentCouplingLevelInUse("electricalbus", ship);
    
    	eq = parseInt(this.$equipmentCouplingLevelInUse("engines", ship));
    	check = parseInt(this.$equipmentCouplingRequired("engines", this.$equipmentItemInUse("engines", ship), ship));
    	if ((check - eq) > 0) total += ((check - eq) * 2);
    	if ((eq - bus) > 0) total += (eq - bus);
    
    	// fi use the engines power coupling
    	eq = parseInt(this.$equipmentCouplingLevelInUse("fuelinjectors", ship));
    	check = parseInt(this.$equipmentCouplingRequired("fuelinjectors", this.$equipmentItemInUse("fuelinjectors", ship), ship));
    	if ((check - eq) > 0) total += ((check - eq) * 2);
    	if ((eq - bus) > 0) total += (eq - bus);
    
    	if (this.$shipHasHyperspaceMotor(ship.dataKey) === true && this._OXPHyperdrives === false) {
    		eq = parseInt(this.$equipmentCouplingLevelInUse("hyperdrive", ship));
    		check = parseInt(this.$equipmentCouplingRequired("hyperdrive", this.$equipmentItemInUse("hyperdrive", ship), ship));
    		if ((check - eq) > 0) total += ((check - eq) * 2);
    		if ((eq - bus) > 0) total += (eq - bus);
    	}
    
    	eq = parseInt(this.$equipmentCouplingLevelInUse("thrusters", ship));
    	check = parseInt(this.$equipmentCouplingRequired("thrusters", this.$equipmentItemInUse("thrusters", ship), ship));
    	if ((check - eq) > 0) total += ((check - eq) * 2);
    	if ((eq - bus) > 0) total += (eq - bus);
    
    	eq = parseInt(this.$equipmentCouplingLevelInUse("boosters", ship));
    	check = parseInt(this.$equipmentCouplingRequired("boosters", this.$equipmentItemInUse("boosters", ship), ship));
    	if ((check - eq) > 0) total += ((check - eq) * 2);
    	if ((eq - bus) > 0) total += (eq - bus);
    
    	eq = parseInt(this.$equipmentCouplingLevelInUse("energy", ship));
    	check = parseInt(this.$equipmentCouplingRequired("energy", this.$equipmentItemInUse("energy", ship), ship));
    	if ((check - eq) > 0) total += ((check - eq) * 2);
    	if (eq > 7) eq = 7; // limit equipment coupling level to 7 - bus level 7 handles all energy couplings over 7
    	if ((eq - bus) > 0) total += (eq - bus);
    
    	eq = parseInt(this.$equipmentCouplingLevelInUse("frontshields", ship));
    	check = parseInt(this.$equipmentCouplingRequired("frontshields", this.$equipmentItemInUse("frontshields", ship), ship));
    	if ((check - eq) > 0) total += ((check - eq) * 2);
    	if ((eq - bus) > 0) total += (eq - bus);
    
    	eq = parseInt(this.$equipmentCouplingLevelInUse("aftshields", ship));
    	check = parseInt(this.$equipmentCouplingRequired("aftshields", this.$equipmentItemInUse("aftshields", ship), ship));
    	if ((check - eq) > 0) total += ((check - eq) * 2);
    	if ((eq - bus) > 0) total += (eq - bus);
    
    	return total;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // decrease the bus overload counter if we haven't been hit for 30 seconds
    this.$decreaseBusOverload = function $decreaseBusOverload() {
    	if (this._busOverloadCounter > 0) {
    		this._busOverloadCounter -= 1;
    		if (this._busOverloadCounter < 0) this._busOverloadCounter = 0;
    	} else {
    		if (this._busOverloadResetTimer && this._busOverloadResetTimer.isRunning) this._busOverloadResetTimer.stop();
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns true if the passed equipment key is required by another piece of installed equipment, otherwise false
    this.$equipmentIsRequired = function $equipmentIsRequired(equipmentKey) {
    
    	// todo: look at requiresAnyEquipment as well
    	var p = player.ship;
    	var eq = p.equipment;
    	var result = false;
    
    	// special case for passengers: make sure we always have enough berths for the number of passengers currently on board.
    	if (equipmentKey === "EQ_PASSENGER_BERTH") {
    		if (p.passengerCount > 0 && p.passengerCapacity <= p.passengerCount) {
    			result = true;
    		}
    	} else {
    		for (var i = 0; i < eq.length; i++) {
    			// special case that isn't listed in equipment config
    			//if (equipmentKey === "EQ_SHIELD_BOOSTER" && eq[i].equipmentKey === "EQ_NAVAL_SHIELD_BOOSTER") {
    			//	result = true;
    			//	break;
    			// }
    			var info = EquipmentInfo.infoForKey(eq[i].equipmentKey);
    			if (info.requiresEquipment) {
    				if (info.requiresEquipment.indexOf(equipmentKey) >= 0 || 
    					// some special cases for ShipConfig items
    					((equipmentKey.indexOf("EQ_FUEL_SCOOPS") >= 0 && info.requiresEquipment.indexOf("EQ_FUEL_SCOOPS") >= 0) ||
    					(equipmentKey.indexOf("EQ_FUEL_INJECTION") >= 0 && info.requiresEquipment.indexOf("EQ_FUEL_INJECTION") >= 0) || 
    					(equipmentKey.indexOf("EQ_HEAT_SHIELD") >= 0 && info.requiresEquipment.indexOf("EQ_HEAT_SHIELD") >= 0))) {
    					result = true;
    					break;
    				}
    			}
    		}
    	}
    	return result;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns the equipment item of a particular section of the ship
    this.$equipmentItemInUse = function $equipmentItemInUse(section, ship) {
    	if (!ship) return "";
    
    	var item = "";
    	var check = "";
    
    	// check if we have a value stored in this._current. if so, we can pick it up from there
    	// otherwise we'll scan through the various equipment item arrays
    	if (ship.isPlayer === false || (!this._current[section] || this._current[section] === "")) {
    		switch (section) {
    			case "engines":
    				for (var i = 0; i < this._engines.length; i++) {
    					check = ship.equipmentStatus(this._engines[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._engines[i];
    						break;
    					}
    				}
    				break;
    			case "hyperdrive":
    				for (var i = 0; i < this._hyperdrive.length; i++) {
    					check = ship.equipmentStatus(this._hyperdrive[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._hyperdrive[i];
    						break;
    					}
    				}
    				break;
    			case "thrusters":
    				for (var i = 0; i < this._thrusters.length; i++) {
    					check = ship.equipmentStatus(this._thrusters[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._thrusters[i];
    						break;
    					}
    				}
    				break;
    			case "boosters":
    				for (var i = 0; i < this._boosters.length; i++) {
    					check = ship.equipmentStatus(this._boosters[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._boosters[i];
    						break;
    					}
    				}
    				break;
    			case "energy":
    				for (var i = 0; i < this._energy.length; i++) {
    					check = ship.equipmentStatus(this._energy[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._energy[i];
    						break;
    					}
    				}
    				break;
    			case "frontshields":
    				for (var i = 0; i < this._frontshields.length; i++) {
    					check = ship.equipmentStatus(this._frontshields[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._frontshields[i];
    						break;
    					}
    				}
    				break;
    			case "aftshields":
    				for (var i = 0; i < this._aftshields.length; i++) {
    					check = ship.equipmentStatus(this._aftshields[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._aftshields[i];
    						break;
    					}
    				}
    				break;
    			case "heatshields":
    				for (var i = 0; i < this._heatshields.length; i++) {
    					check = ship.equipmentStatus(this._heatshields[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._heatshields[i];
    						break;
    					}
    				}
    				break;
    			case "fuelinjectors":
    				for (var i = 0; i < this._fuelinjectors.length; i++) {
    					check = ship.equipmentStatus(this._fuelinjectors[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._fuelinjectors[i];
    						break;
    					}
    				}
    				break;
    			case "fuelscoops":
    				for (var i = 0; i < this._fuelscoops.length; i++) {
    					check = ship.equipmentStatus(this._fuelscoops[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._fuelscoops[i];
    						break;
    					}
    				}
    				break;
    			case "frontarmour":
    				for (var i = 0; i < this._frontarmour.length; i++) {
    					check = ship.equipmentStatus(this._frontarmour[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._frontarmour[i];
    						break;
    					}
    				}
    				break;
    			case "aftarmour":
    				for (var i = 0; i < this._aftarmour.length; i++) {
    					check = ship.equipmentStatus(this._aftarmour[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._aftarmour[i];
    						break;
    					}
    				}
    				break;
    			case "electricalbus":
    				for (var i = 0; i < this._electricalbus.length; i++) {
    					check = ship.equipmentStatus(this._electricalbus[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._electricalbus[i];
    						break;
    					}
    				}
    				break;
    			case "hyperdrivecoupling":
    				for (var i = 0; i < this._hdCoupling.length; i++) {
    					check = ship.equipmentStatus(this._hdCoupling[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._hdCoupling[i];
    						break;
    					}
    				}
    				break;
    			case "enginecoupling":
    				for (var i = 0; i < this._enCoupling.length; i++) {
    					check = ship.equipmentStatus(this._enCoupling[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._enCoupling[i];
    						break;
    					}
    				}
    				break;
    			case "thrusterscoupling":
    				for (var i = 0; i < this._thCoupling.length; i++) {
    					check = ship.equipmentStatus(this._thCoupling[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._thCoupling[i];
    						break;
    					}
    				}
    				break;
    			case "boosterscoupling":
    				for (var i = 0; i < this._bsCoupling.length; i++) {
    					check = ship.equipmentStatus(this._bsCoupling[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._bsCoupling[i];
    						break;
    					}
    				}
    				break;
    			case "energycoupling":
    				for (var i = 0; i < this._ebCoupling.length; i++) {
    					check = ship.equipmentStatus(this._ebCoupling[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._ebCoupling[i];
    						break;
    					}
    				}
    				break;
    			case "frontshieldscoupling":
    				for (var i = 0; i < this._fsCoupling.length; i++) {
    					check = ship.equipmentStatus(this._fsCoupling[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._fsCoupling[i];
    						break;
    					}
    				}
    				break;
    			case "aftshieldscoupling":
    				for (var i = 0; i < this._asCoupling.length; i++) {
    					check = ship.equipmentStatus(this._asCoupling[i]);
    					if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    						item = this._asCoupling[i];
    						break;
    					}
    				}
    				break;
    		}
    		if (ship.isPlayer) this._current[section] = item;
    	} else {
    		item = this._current[section];
    	}
    
    	return item;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns the space element of a particular section of the ship
    this.$equipmentSpaceInUse = function $equipmentSpaceInUse(section, ship) {
    	if (!ship) return 0;
    	if (section === "electrical") {
    		var total = 0;
    		total += this._equipmentMatrix[this.$equipmentItemInUse("electricalbus", ship)][0];
    		total += this._equipmentMatrix[this.$equipmentItemInUse("enginecoupling", ship)][0];
    		total += this._equipmentMatrix[this.$equipmentItemInUse("energycoupling", ship)][0];
    		total += this._equipmentMatrix[this.$equipmentItemInUse("thrusterscoupling", ship)][0];
    		if (this.$equipmentItemInUse("boosterscoupling", ship))
    			total += this._equipmentMatrix[this.$equipmentItemInUse("boosterscoupling", ship)][0];
    		if (this.$shipHasHyperspaceMotor(ship.dataKey) === true && this._OXPHyperdrives === false) {
    			total += this._equipmentMatrix[this.$equipmentItemInUse("hyperdrivecoupling", ship)][0];
    		}
    		total += this._equipmentMatrix[this.$equipmentItemInUse("frontshieldscoupling", ship)][0];
    		total += this._equipmentMatrix[this.$equipmentItemInUse("aftshieldscoupling", ship)][0];
    		return total;
    	} else {
    		var item = this.$equipmentItemInUse(section, ship);
    		if (item != "") {
    			return this._equipmentMatrix[item][0];
    		} else {
    			return 0;
    		}
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns the weight element of a particular section of the ship
    this.$equipmentWeightInUse = function $equipmentWeightInUse(section, ship) {
    	if (!ship) return 0;
    	if (section === "electrical") {
    		var total = 0;
    		total += this._equipmentMatrix[this.$equipmentItemInUse("electricalbus", ship)][1];
    		total += this._equipmentMatrix[this.$equipmentItemInUse("enginecoupling", ship)][1];
    		total += this._equipmentMatrix[this.$equipmentItemInUse("energycoupling", ship)][1];
    		total += this._equipmentMatrix[this.$equipmentItemInUse("thrusterscoupling", ship)][1];
    		if (this.$equipmentItemInUse("boosterscoupling", ship))
    			total += this._equipmentMatrix[this.$equipmentItemInUse("boosterscoupling", ship)][1];
    		if (this.$shipHasHyperspaceMotor(ship.dataKey) === true && this._OXPHyperdrives === false) {
    			total += this._equipmentMatrix[this.$equipmentItemInUse("hyperdrivecoupling", ship)][1];
    		}
    		total += this._equipmentMatrix[this.$equipmentItemInUse("frontshieldscoupling", ship)][1];
    		total += this._equipmentMatrix[this.$equipmentItemInUse("aftshieldscoupling", ship)][1];
    		return total;
    	} else {
    		var item = this.$equipmentItemInUse(section, ship);
    		if (item != "") {
    			return this._equipmentMatrix[item][1];
    		} else {
    			return 0;
    		}
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$equipmentLevelInUse = function $equipmentLevelInUse(section, ship) {
    	if (!ship) return 0;
    	var item = this.$equipmentItemInUse(section, ship);
    	return (this.$equipmentCouplingRequired(section, item, ship));
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns the coupling level for the equipment in use
    this.$equipmentCouplingLevelInUse = function $equipmentCouplingLevelInUse(section, ship) {
    
    	if (!ship) return 0;
    
    	var level = 0;
    	var coupling = "";
    
    	switch (section) {
    		case "electricalbus":
    			coupling = this.$equipmentItemInUse("electricalbus", ship);
    			level = this._electricalbus.indexOf(coupling);
    			break;
    		case "engines":
    		case "fuelinjectors":
    			coupling = this.$equipmentItemInUse("enginecoupling", ship);
    			level = this._enCoupling.indexOf(coupling);
    			break;
    		case "hyperdrive":
    			coupling = this.$equipmentItemInUse("hyperdrivecoupling", ship);
    			level = this._hdCoupling.indexOf(coupling);
    			break;
    		case "thrusters":
    			coupling = this.$equipmentItemInUse("thrusterscoupling", ship);
    			level = this._thCoupling.indexOf(coupling);
    			break;
    		case "boosters":
    			coupling = this.$equipmentItemInUse("boosterscoupling", ship);
    			level = this._bsCoupling.indexOf(coupling);
    			break;
    		case "energy":
    			coupling = this.$equipmentItemInUse("energycoupling", ship);
    			level = this._ebCoupling.indexOf(coupling);
    			break;
    		case "frontshields":
    			coupling = this.$equipmentItemInUse("frontshieldscoupling", ship);
    			level = this._fsCoupling.indexOf(coupling);
    			break;
    		case "aftshields":
    			coupling = this.$equipmentItemInUse("aftshieldscoupling", ship);
    			level = this._asCoupling.indexOf(coupling);
    			break;
    	}
    
    	return (level + 1);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // return max coupling level in use
    this.$maxEquipmentCouplingInUse = function $maxEquipmentCouplingInUse(ship) {
    
    	if (!ship) return 0;
    
    	var coupling = "";
    	var maxcoupling = 0;
    	var level = 0;
    
    	coupling = this.$equipmentItemInUse("enginecoupling", ship);
    	level = this._enCoupling.indexOf(coupling);
    	if (level > maxcoupling) maxcoupling = level;
    
    	if (this.$shipHasHyperspaceMotor(ship.dataKey) === true && this._OXPHyperdrives === false) {
    		coupling = this.$equipmentItemInUse("hyperdrivecoupling", ship);
    		level = this._hdCoupling.indexOf(coupling);
    		if (level > maxcoupling) maxcoupling = level;
    	}
    
    	coupling = this.$equipmentItemInUse("thrusterscoupling", ship);
    	level = this._thCoupling.indexOf(coupling);
    	if (level > maxcoupling) maxcoupling = level;
    
    	coupling = this.$equipmentItemInUse("boosterscoupling", ship);
    	if (coupling) {
    		level = this._bsCoupling.indexOf(coupling);
    		if (level > maxcoupling) maxcoupling = level;
    	}
    
    	coupling = this.$equipmentItemInUse("energycoupling", ship);
    	level = this._ebCoupling.indexOf(coupling);
    	if (level > maxcoupling) maxcoupling = level;
    
    	if (this.$equipmentItemInUse("frontshields", ship) != "EQ_NO_FORWARD_SHIELD") {
    		coupling = this.$equipmentItemInUse("frontshieldscoupling", ship);
    		level = this._fsCoupling.indexOf(coupling);
    		if (level > maxcoupling) maxcoupling = level;
    	}
    
    	if (this.$equipmentItemInUse("aftshields", ship) != "EQ_NO_AFT_SHIELD") {
    		coupling = this.$equipmentItemInUse("aftshieldscoupling", ship);
    		level = this._asCoupling.indexOf(coupling);
    		if (level > maxcoupling) maxcoupling = level;
    	}
    
    	return maxcoupling;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns the required level of coupling for a particular component
    this.$equipmentCouplingRequired = function $equipmentCouplingRequired(section, equipmentKey, ship) {
    
    	if (!ship) return 0;
    
    	var level = 0;
    	var coupling = "";
    
    	switch (section) {
    		case "all":
    		case "engines":
    		case "fuelinjectors":
    		case "hyperdrive":
    		case "thrusters":
    		case "boosters":
    		case "frontshields":
    		case "aftshields":
    			if (equipmentKey.indexOf("_TYPE1") >= 0) level = 1;
    			if (equipmentKey.indexOf("_TYPE2") >= 0) level = 2;
    			if (equipmentKey.indexOf("_TYPE3") >= 0) level = 3;
    			if (equipmentKey.indexOf("_TYPE4") >= 0) level = 4;
    			if (equipmentKey.indexOf("_TYPE5") >= 0) level = 5;
    			if (equipmentKey.indexOf("_TYPE6") >= 0) level = 6;
    			if (equipmentKey.indexOf("_TYPE7") >= 0) level = 7;
    			if (equipmentKey.indexOf("_TYPE8") >= 0) level = 7;
    			break;
    		case "energy":
    			var bustype = this._equipCouplingBus[equipmentKey];
    			level = this._ebCoupling.indexOf(bustype) + 1;
    			break;
    	}
    
    	return level;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // puts all required equipment into the "no sell" array - this is only run once at startup
    this.$populateNoSellList = function $populateNoSellList() {
    
    	for (var i = 0; i < this._electricalbus.length; i++) {
    		if (this._noSell.indexOf(this._electricalbus[i]) === -1) this._noSell.push(this._electricalbus[i]);
    	}
    	for (var i = 0; i < this._engines.length; i++) {
    		if (this._noSell.indexOf(this._engines[i]) === -1) this._noSell.push(this._engines[i]);
    	}
    	for (var i = 0; i < this._enCoupling.length; i++) {
    		if (this._noSell.indexOf(this._enCoupling[i]) === -1) this._noSell.push(this._enCoupling[i]);
    	}
    	for (var i = 0; i < this._hyperdrive.length; i++) {
    		if (this._noSell.indexOf(this._hyperdrive[i]) === -1) this._noSell.push(this._hyperdrive[i]);
    	}
    	for (var i = 0; i < this._hdCoupling.length; i++) {
    		if (this._noSell.indexOf(this._hdCoupling[i]) === -1) this._noSell.push(this._hdCoupling[i]);
    	}
    	for (var i = 0; i < this._thrusters.length; i++) {
    		if (this._noSell.indexOf(this._thrusters[i]) === -1) this._noSell.push(this._thrusters[i]);
    	}
    	for (var i = 0; i < this._thCoupling.length; i++) {
    		if (this._noSell.indexOf(this._thCoupling[i]) === -1) this._noSell.push(this._thCoupling[i]);
    	}
    	for (var i = 0; i < this._energy.length; i++) {
    		if (this._noSell.indexOf(this._energy[i]) === -1) this._noSell.push(this._energy[i]);
    	}
    	for (var i = 0; i < this._ebCoupling.length; i++) {
    		if (this._noSell.indexOf(this._ebCoupling[i]) === -1) this._noSell.push(this._ebCoupling[i]);
    	}
    	for (var i = 0; i < this._frontshields.length; i++) {
    		if (this._noSell.indexOf(this._frontshields[i]) === -1) this._noSell.push(this._frontshields[i]);
    	}
    	for (var i = 0; i < this._fsCoupling.length; i++) {
    		if (this._noSell.indexOf(this._fsCoupling[i]) === -1) this._noSell.push(this._fsCoupling[i]);
    	}
    	for (var i = 0; i < this._aftshields.length; i++) {
    		if (this._noSell.indexOf(this._aftshields[i]) === -1) this._noSell.push(this._aftshields[i]);
    	}
    	for (var i = 0; i < this._asCoupling.length; i++) {
    		if (this._noSell.indexOf(this._asCoupling[i]) === -1) this._noSell.push(this._asCoupling[i]);
    	}
    	for (var i = 0; i < this._bsCoupling.length; i++) {
    		if (this._noSell.indexOf(this._bsCoupling[i]) === -1) this._noSell.push(this._bsCoupling[i]);
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // installs the default factory equipment into a ship
    this.$installBaseEquipment = function $installBaseEquipment(ship) {
    
    	if (!ship) return;
    
    	var changed = false;
    	var equip = "";
    	var maxSpace = 0;
    	var equipmentList = [];
    	if (ship.isPlayer === false) {
    		maxSpace = Math.ceil(this.$equipmentSpaceTotal(ship) + this.$cargoSpaceAvailable(ship));
    		equipmentList = this.$getNPCEquipmentList(ship.primaryRole, ship.roles, maxSpace);
    		if (!equipmentList || equipmentList.length === 0) {
    			if (this._debug) log(this.name, "!!NOTE: No match found for " + ship.primaryRole + ", ship type " + ship.shipClassName + ", space " + maxSpace + " - adding default equipment");
    			equipmentList = [];
    		} else {
    			// based on accuracy (skill level) potentially remove some items from the list
    			// the higher the accuracy, the fewer items will be removed
    			// range is -5 to +10
    			// below 0 = remove up to 3 items
    			// 0 - 3 = remove up to 2 items
    			// 3.1 - 6 = remove 1 item
    			// above 6 no removal
    			if (ship.isPolice === false) {
    				var remove_count = 0;
    				if (ship.accuracy <= 0) remove_count = 3;
    				if (ship.accuracy > 0 && ship.accuracy <= 3) remove_count = 2;
    				if (ship.accuracy > 3 && ship.accuracy <= 6) remove_count = 1;
    				if (remove_count > 0) {
    					for (var i = 1; i <= remove_count; i++) {
    						// lower accuracy means more chance of removal
    						// blanking out the equipmentList item will mean default equipment only
    						if (Math.random() > ((ship.accuracy + 5) / 15)) {
    							var idx = Math.floor(Math.random() * equipmentList.length);
    							//if (this._debug && equipmentList[idx] != "") log(this.name, "removing " + equipmentList[idx] + " from " + ship);
    							equipmentList[idx] = "";
    						}
    					}
    				}
    			}
    		}
    	}
    
    	// are any of the default items installed? If no, install them now.
    	// main electrical bus
    	var found = false;
    	var bus = -1;
    	for (var i = 0; i < this._electricalbus.length; i++) {
    		var check = ship.equipmentStatus(this._electricalbus[i]);
    		if (check === "EQUIPMENT_OK") {
    			found = true;
    			bus = (i + 1);
    		}
    	}
    	if (found === false) {
    		if (ship.isPlayer) {
    			equip = "EQ_ELEC_BUS_TYPE2";
    			bus = 2;
    		} else {
    			equip = this.$selectNPCEquipment("electricalbus", equipmentList);
    			bus = this._electricalbus.indexOf(equip) + 1;
    		}
    		ship.awardEquipment(equip);
    		changed = true;
    	}
    
    	// engines
    	found = false;
    	var eng = -1;
    	for (var i = 0; i < this._engines.length; i++) {
    		var check = ship.equipmentStatus(this._engines[i]);
    		if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    			found = true;
    			eng = Math.floor(i / 6) + 1;
    		}
    	}
    	if (found === false) {
    		// for NPC ships, change the engine type based on primary role
    		if (ship.isPlayer) {
    			equip = "EQ_ENGINE_TYPE2A";
    			eng = 2;
    		} else {
    			equip = this.$selectNPCEquipment("engines", equipmentList);
    			eng = Math.floor(this._engines.indexOf(equip) / 6) + 1;
    		}
    		ship.awardEquipment(equip);
    		changed = true;
    	}
    	found = false;
    	for (var i = 0; i < this._enCoupling.length; i++) {
    		var check = ship.equipmentStatus(this._enCoupling[i]);
    		if (check === "EQUIPMENT_OK") found = true;
    	}
    	if (found === false) {
    		ship.awardEquipment("EQ_ENGINE_COUPLING_TYPE" + eng);
    		changed = true;
    	}
    
    	// hyperspace motor
    	found = false;
    	if (this.$shipHasHyperspaceMotor(ship.dataKey) === true && this._OXPHyperdrives === false) {
    		var hd = -1;
    		for (var i = 0; i < this._hyperdrive.length; i++) {
    			var check = ship.equipmentStatus(this._hyperdrive[i]);
    			if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    				found = true;
    				hd = i + 1;
    			}
    		}
    		if (found === false) {
    			if (ship.isPlayer) {
    				equip = "EQ_HYPERDRIVE_TYPE2";
    				hd = 2;
    			} else {
    				equip = this.$selectNPCEquipment("hyperdrive", equipmentList);
    				hd = this._hyperdrive.indexOf(equip) + 1;
    			}
    			ship.awardEquipment(equip);
    			changed = true;
    		}
    		found = false;
    		for (var i = 0; i < this._hdCoupling.length; i++) {
    			var check = ship.equipmentStatus(this._hdCoupling[i]);
    			if (check === "EQUIPMENT_OK") found = true;
    		}
    		if (found === false) {
    			ship.awardEquipment("EQ_HYPERDRIVE_COUPLING_TYPE" + hd);
    			changed = true;
    		}
    	}
    
    	// thrusters
    	found = false;
    	//var thr = -1;
    	for (var i = 0; i < this._thrusters.length; i++) {
    		var check = ship.equipmentStatus(this._thrusters[i]);
    		if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    			equip = this._thrusters[i];
    			found = true;
    			break;
    		}
    	}
    	if (found === false) {
    		equip = "EQ_THRUSTERS_TYPE2A";
    		if (!ship.isPlayer) {
    			equip = this.$selectNPCEquipment("thrusters", equipmentList);
    		}
    		ship.awardEquipment(equip);
    		changed = true;
    	}
    	found = false;
    	for (var i = 0; i < this._thCoupling.length; i++) {
    		var check = ship.equipmentStatus(this._thCoupling[i]);
    		if (check === "EQUIPMENT_OK") found = true;
    	}
    	if (found === false) {
    		var thcp = this._equipCouplingBus[equip];
    		ship.awardEquipment(thcp);
    		changed = true;
    	}
    
    	// boosters - just install the minimum power coupling by default
    	if (this._heatControl === true) {
    		found = false;
    		for (var i = 0; i < this._bsCoupling.length; i++) {
    			var check = ship.equipmentStatus(this._bsCoupling[i]);
    			if (check === "EQUIPMENT_OK") {
    				found = true;
    				break;
    			}
    		}
    		if (found === false) {
    			ship.awardEquipment("EQ_BOOSTERS_COUPLING_TYPE1");
    			changed = true;
    		}
    	}
    
    	// energy banks (standard class only, not class "A" types)
    	found = false;
    	var en = -1;
    	for (var i = 0; i < this._energy.length; i++) {
    		var check = ship.equipmentStatus(this._energy[i]);
    		if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    			found = true;
    			en = (i + 1);
    		}
    	}
    	if (found === false) {
    		var banks = Math.floor(ship.maxEnergy / 64);
    		if (banks <= 25) {
    			if (banks === 0 && ship.maxEnergy > 0) banks = 1;
    			// this should never happen, but just in case... default max energy should be 200, which is 3 banks
    			if (ship.maxEnergy === 0) banks = 3;
    			if (ship.isPlayer === false) {
    				// check to see if this NPC configuration is overriding the number of banks
    				equip = this.$selectNPCEquipment("energy", equipmentList, banks);
    				if (equip != "") banks = this._energy.indexOf(equip) + 1;
    				//log(this.name, "final equip = " + equip);
    			}
    			ship.awardEquipment("EQ_ENERGYBANK_TYPE" + banks);
    			en = banks;
    			changed = true;
    		}
    	}
    	found = false;
    	for (var i = 0; i < this._ebCoupling.length; i++) {
    		var check = ship.equipmentStatus(this._ebCoupling[i]);
    		if (check === "EQUIPMENT_OK") found = true;
    	}
    	// make sure the right electrical bus is fitted for the number of energy banks we have
    	if (found === false) {
    		switch (en) {
    			case 1:
    			case 2:
    			case 3:
    			case 4:
    				ship.awardEquipment("EQ_ENERGYBANK_COUPLING_TYPE1");
    				break;
    			case 5:
    			case 6:
    			case 7:
    				ship.awardEquipment("EQ_ENERGYBANK_COUPLING_TYPE2");
    				break;
    			case 8:
    			case 9:
    			case 10:
    				ship.awardEquipment("EQ_ENERGYBANK_COUPLING_TYPE3");
    				if (bus < 3) {
    					ship.removeEquipment("EQ_ELEC_BUS_TYPE" + bus);
    					ship.awardEquipment("EQ_ELEC_BUS_TYPE3");
    				}
    				break;
    			case 11:
    			case 12:
    			case 13:
    				ship.awardEquipment("EQ_ENERGYBANK_COUPLING_TYPE4");
    				if (bus < 4) {
    					ship.removeEquipment("EQ_ELEC_BUS_TYPE" + bus);
    					ship.awardEquipment("EQ_ELEC_BUS_TYPE4");
    				}
    				break;
    			case 14:
    			case 15:
    			case 16:
    				ship.awardEquipment("EQ_ENERGYBANK_COUPLING_TYPE5");
    				if (bus < 5) {
    					ship.removeEquipment("EQ_ELEC_BUS_TYPE" + bus);
    					ship.awardEquipment("EQ_ELEC_BUS_TYPE5");
    				}
    				break;
    			case 17:
    			case 18:
    			case 19:
    				ship.awardEquipment("EQ_ENERGYBANK_COUPLING_TYPE6");
    				if (bus < 6) {
    					ship.removeEquipment("EQ_ELEC_BUS_TYPE" + bus);
    					ship.awardEquipment("EQ_ELEC_BUS_TYPE6");
    				}
    				break;
    			case 20:
    			case 21:
    			case 22:
    				ship.awardEquipment("EQ_ENERGYBANK_COUPLING_TYPE7");
    				if (bus < 7) {
    					ship.removeEquipment("EQ_ELEC_BUS_TYPE" + bus);
    					ship.awardEquipment("EQ_ELEC_BUS_TYPE7");
    				}
    				break;
    			case 23:
    			case 24:
    			case 25:
    				ship.awardEquipment("EQ_ENERGYBANK_COUPLING_TYPE8");
    				if (bus < 7) {
    					ship.removeEquipment("EQ_ELEC_BUS_TYPE" + bus);
    					ship.awardEquipment("EQ_ELEC_BUS_TYPE7");
    				}
    				break;
    		}
    		changed = true;
    	}
    
    	// note: we'll add the shield equipment to NPC's, even if they don't officially have shields - the game compensates for the lack of shields with addition energy
    	// and we want the weight profile to be the same as for the player
    	// front shields
    	found = false;
    	var fs = -1;
    	for (var i = 0; i < this._frontshields.length; i++) {
    		var check = ship.equipmentStatus(this._frontshields[i]);
    		if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    			found = true;
    			fs = i;
    		}
    	}
    	if (found === false) {
    		if (ship.isPlayer) {
    			equip = "EQ_FORWARD_SHIELD_TYPE2";
    			fs = 2;
    		} else {
    			equip = this.$selectNPCEquipment("frontshields", equipmentList);
    			fs = this._frontshields.indexOf(equip);
    		}
    		ship.awardEquipment(equip);
    		changed = true;
    	}
    	found = false;
    	if (fs === 0) fs = 1;
    	for (var i = 0; i < this._fsCoupling.length; i++) {
    		var check = ship.equipmentStatus(this._fsCoupling[i]);
    		if (check === "EQUIPMENT_OK") found = true;
    	}
    	if (found === false) {
    		ship.awardEquipment("EQ_FORWARD_SHIELD_COUPLING_TYPE" + fs);
    		changed = true;
    	}
    
    	// aft shields
    	found = false;
    	var as = -1;
    	for (var i = 0; i < this._aftshields.length; i++) {
    		var check = ship.equipmentStatus(this._aftshields[i]);
    		if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    			found = true;
    			as = i;
    		}
    	}
    	if (found === false) {
    		if (ship.isPlayer) {
    			equip = "EQ_AFT_SHIELD_TYPE2";
    			as = 2;
    		} else {
    			equip = this.$selectNPCEquipment("aftshields", equipmentList);
    			as = this._aftshields.indexOf(equip);
    		}
    		ship.awardEquipment(equip);
    		changed = true;
    	}
    	found = false;
    	if (as === 0) as = 1;
    	for (var i = 0; i < this._asCoupling.length; i++) {
    		var check = ship.equipmentStatus(this._asCoupling[i]);
    		if (check === "EQUIPMENT_OK") found = true;
    	}
    	if (found === false) {
    		ship.awardEquipment("EQ_AFT_SHIELD_COUPLING_TYPE" + as);
    		changed = true;
    	}
    
    	// fuel injectors
    	var fi = ship.equipmentStatus("EQ_FUEL_INJECTION");
    	equip = "";
    	if (fi === "EQUIPMENT_OK" || fi === "EQUIPMENT_DAMAGED") {
    		var fi_idx = -1;
    		for (var i = 0; i < this._fuelinjectors.length; i++) {
    			var check = ship.equipmentStatus(this._fuelinjectors[i]);
    			if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    				equip = this._fuelinjectors[i];
    				fi_idx = i;
    			}
    		}
    		if (fi_idx === -1) {
    			if (ship.isPlayer) {
    				equip = "EQ_FUEL_INJECTION_TYPE2";
    			} else {
    				equip = this.$selectNPCEquipment("fuelinjectors", equipmentList);
    			}
    		}
    		if (equip != "") {
    			ship.awardEquipment(equip);
    			changed = true;
    		}
    		if (fi === "EQUIPMENT_DAMAGED") ship.setEquipmentStatus(equip, "EQUIPMENT_DAMAGED");
    	}
    	// special case for NPCs with fuel injectors: don't install it if they don't already have it.
    	/*if (!ship.isPlayer && fi === "EQUIPMENT_UNAVAILABLE") {
    		equip = this.$selectNPCEquipment("fuelinjectors", equipmentList);
    		if (equip != "") {
    			ship.awardEquipment(equip);
    			changed = true;
    		}
    	} */
    	// fuel scoops
    	var sc = ship.equipmentStatus("EQ_FUEL_SCOOPS");
    	equip = "";
    	if (sc === "EQUIPMENT_OK" || sc === "EQUIPMENT_DAMAGED") {
    		var sc_idx = -1;
    		for (var i = 0; i < this._fuelscoops.length; i++) {
    			var check = ship.equipmentStatus(this._fuelscoops[i]);
    			if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    				equip = this._fuelscoops[i];
    				sc_idx = i;
    			}
    		}
    		if (sc_idx === -1) {
    			if (ship.isPlayer) {
    				equip = "EQ_FUEL_SCOOPS_TYPE1";
    			} else {
    				equip = this.$selectNPCEquipment("fuelscoops", equipmentList);
    			}
    		}
    		if (equip != "") {
    			ship.awardEquipment(equip);
    			changed = true;
    		}
    		if (sc === "EQUIPMENT_DAMAGED") ship.setEquipmentStatus(equip, "EQUIPMENT_DAMAGED");
    	}
    
    	// heat shields
    	var hs = ship.equipmentStatus("EQ_HEAT_SHIELD");
    	equip = "";
    	// first check to see if we have a heat shield installed, but without the base Heat shield item (possibly it got lost)
    	var equipHS = this.$equipmentItemInUse("heatshields", ship);
    	var checkHS = ship.equipmentStatus(equipHS);
    	if (checkHS === "EQUIPMENT_OK" || checkHS === "EQUIPMENT_DAMAGED") {
    		if (hs === "EQUIPMENT_UNAVAILABLE") {
    			ship.awardEquipment("EQ_HEAT_SHIELD");
    			if (checkHS !== "EQUIPMENT_OK") ship.setEquipmentStatus("EQ_HEAT_SHIELD", checkHS);
    			hs = checkHS;
    		}
    	}
    	if ((hs === "EQUIPMENT_OK" || hs === "EQUIPMENT_DAMAGED") && equipHS === "") {
    		if (ship.isPlayer) {
    			equipHS = "EQ_HEAT_SHIELD_TYPE2";
    		} else {
    			equipHS = this.$selectNPCEquipment("heatshields", equipmentList);
    		}
    		if (equipHS != "") {
    			ship.awardEquipment(equipHS);
    			changed = true;
    		}
    		if (hs === "EQUIPMENT_DAMAGED") ship.setEquipmentStatus(equipHS, "EQUIPMENT_DAMAGED");
    	}
    	// only allocate NPC heat shields if they don't already have heat shields
    	if (!ship.isPlayer && hs === "EQUIPMENT_UNAVAILABLE") {
    		equip = this.$selectNPCEquipment("heatshields", equipmentList);
    		if (equip != "") {
    			ship.awardEquipment(equip);
    			changed = true;
    		}
    	}
    
    	// armour
    	if (ship.isPlayer === false) {
    		equip = this.$selectNPCEquipment("frontarmour", equipmentList);
    		if (equip != "") {
    			ship.awardEquipment(equip);
    			changed = true;
    		}
    		equip = this.$selectNPCEquipment("aftarmour", equipmentList);
    		if (equip != "") {
    			ship.awardEquipment(equip);
    			changed = true;
    		}
    	}
    
    	// heatsinks
    	// just need to make sure ship have enough cargo space for them
    	var equip = this.$selectNPCEquipment("heatsinks", equipmentList);
    	if (equip != "") {
    		if (equip.indexOf(",") >= 0) {
    			var itms = equip.split(",");
    			for (var i = 0; i < itms.length; i++) {
    				if (this.$cargoSpaceAvailable(ship) > 0) ship.awardEquipment(itms[i]);
    			}
    		} else {
    			if (this.$cargoSpaceAvailable(ship) > 0) ship.awardEquipment(equip);
    		}
    	}
    
    	return changed;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // logic for NPC equipment choices
    this.$selectNPCEquipment = function $selectNPCEquipment(section, equipmentList, defaultValue) {
    
    	var result = "";
    	switch (section) {
    		case "engines":
    			// logic hear to switch engines based on ship role and available space
    			if (equipmentList) {
    				for (var i = 0; i < this._engines.length; i++) {
    					if (equipmentList.indexOf(this._engines[i]) >= 0) {
    						result = this._engines[i];
    						break;
    					}
    				}
    				var change = 0;
    				if (result === "") {
    					for (var i = 0; i < equipmentList.length; i++) {
    						if (equipmentList[i].indexOf("engines:") >= 0) {
    							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
    							break;
    						}
    					}
    				}
    				if (change != 0) {
    					var newidx = this._engines.indexOf("EQ_ENGINE_TYPE2A") + (change * 3);
    					if (newidx > this._engines.length - 1) newidx = this._engines.length - 1;
    					if (newidx < 0) newidx = 0;
    					result = this._engines[newidx];
    				}
    			}
    			if (result === "") result = "EQ_ENGINE_TYPE2A";
    			break;
    		case "thrusters":
    			if (equipmentList) {
    				for (var i = 0; i < this._thrusters.length; i++) {
    					if (equipmentList.indexOf(this._thrusters[i]) >= 0) {
    						result = this._thrusters[i];
    						break;
    					}
    				}
    				var change = 0;
    				if (result === "") {
    					for (var i = 0; i < equipmentList.length; i++) {
    						if (equipmentList[i].indexOf("thrusters:") >= 0) {
    							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
    							break;
    						}
    					}
    				}
    				if (change != 0) {
    					var newidx = this._thrusters.indexOf("EQ_THRUSTERS_TYPE2A") + change;
    					if (newidx > this._thrusters.length - 1) newidx = this._thrusters.length - 1;
    					if (newidx < 0) newidx = 0;
    					result = this._thrusters[newidx];
    				}
    			}
    			if (result === "") result = "EQ_THRUSTERS_TYPE2A";
    			break;
    		case "boosters":
    			if (equipmentList) {
    				for (var i = 0; i < this._boosters.length; i++) {
    					if (equipmentList.indexOf(this._boosters[i]) >= 0) {
    						result = this._boosters[i];
    						break;
    					}
    				}
    				var change = 0;
    				if (result === "") {
    					for (var i = 0; i < equipmentList.length; i++) {
    						if (equipmentList[i].indexOf("boosters:") >= 0) {
    							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
    							break;
    						}
    					}
    				}
    				if (change != 0) {
    					if (change > this._boosters.length - 1) change = this._boosters.length - 1;
    					if (change >= 0) result = this._boosters[change];
    				}
    			}
    			break;
    		case "hyperdrive":
    			if (equipmentList) {
    				for (var i = 0; i < this._hyperdrive.length; i++) {
    					if (equipmentList.indexOf(this._hyperdrive[i]) >= 0) {
    						result = this._hyperdrive[i];
    						break;
    					}
    				}
    				var change = 0;
    				if (result === "") {
    					for (var i = 0; i < equipmentList.length; i++) {
    						if (equipmentList[i].indexOf("hyperdrive:") >= 0) {
    							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
    							break;
    						}
    					}
    				}
    				if (change != 0) {
    					var newidx = this._hyperdrive.indexOf("EQ_HYPERDRIVE_TYPE2") + change;
    					if (newidx > this._hyperdrive.length - 1) newidx = this._hyperdrive.length - 1;
    					if (newidx < 0) newidx = 0;
    					result = this._hyperdrive[newidx];
    				}
    			}
    			if (result === "") result = "EQ_HYPERDRIVE_TYPE2";
    			break;
    		case "energy":
    			// note: if NPC's need to get class "A" energy units installed, some changes to this routine will be required.
    			// for the moment, though, I'm assuming that only standard class units will be installed
    			if (equipmentList) {
    				for (var i = 0; i < this._energy.length; i++) {
    					if (equipmentList.indexOf(this._energy[i]) >= 0) {
    						result = this._energy[i];
    						break;
    					}
    				}
    				var change = 0;
    				if (result === "") {
    					for (var i = 0; i < equipmentList.length; i++) {
    						if (equipmentList[i].indexOf("energy:") >= 0) {
    							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
    							break;
    						}
    					}
    				}
    				if (change != 0) {
    					var newidx = this._energy.indexOf("EQ_ENERGYBANK_TYPE" + defaultValue) + change;
    					if (newidx > 24) newidx = 24;
    					if (newidx < 0) newidx = 0;
    					result = this._energy[newidx];
    				}
    			}
    			if (result === "" && defaultValue) result = "EQ_ENERGYBANK_TYPE" + defaultValue;
    			break;
    		case "frontshields":
    			if (equipmentList) {
    				for (var i = 0; i < this._frontshields.length; i++) {
    					if (equipmentList.indexOf(this._frontshields[i]) >= 0) {
    						result = this._frontshields[i];
    						break;
    					}
    				}
    				var change = 0;
    				if (result === "") {
    					for (var i = 0; i < equipmentList.length; i++) {
    						if (equipmentList[i].indexOf("frontshields:") >= 0) {
    							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
    							break;
    						}
    					}
    				}
    				if (change != 0) {
    					var newidx = this._frontshields.indexOf("EQ_FORWARD_SHIELD_TYPE2") + change;
    					if (newidx > this._frontshields.length - 1) newidx = this._frontshields.length - 1;
    					if (newidx < 0) newidx = 0;
    					result = this._frontshields[newidx];
    				}
    			}
    			if (result === "") result = "EQ_FORWARD_SHIELD_TYPE2";
    			break;
    		case "aftshields":
    			if (equipmentList) {
    				for (var i = 0; i < this._aftshields.length; i++) {
    					if (equipmentList.indexOf(this._aftshields[i]) >= 0) {
    						result = this._aftshields[i];
    						break;
    					}
    				}
    				var change = 0;
    				if (result === "") {
    					for (var i = 0; i < equipmentList.length; i++) {
    						if (equipmentList[i].indexOf("aftshields:") >= 0) {
    							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
    							break;
    						}
    					}
    				}
    				if (change != 0) {
    					var newidx = this._aftshields.indexOf("EQ_AFT_SHIELD_TYPE2") + change;
    					if (newidx > this._aftshields.length - 1) newidx = this._aftshields.length - 1;
    					if (newidx < 0) newidx = 0;
    					result = this._aftshields[newidx];
    				}
    			}
    			if (result === "") result = "EQ_AFT_SHIELD_TYPE2";
    			break;
    		case "electricalbus":
    			result = "EQ_ELEC_BUS_TYPE2";
    			if (equipmentList) {
    				for (var i = 0; i < this._electricalbus.length; i++) {
    					if (equipmentList.indexOf(this._electricalbus[i]) >= 0) {
    						result = this._electricalbus[i];
    						break;
    					}
    				}
    			}
    			break;
    		case "fuelinjectors":
    			if (equipmentList) {
    				for (var i = 0; i < this._fuelinjectors.length; i++) {
    					if (equipmentList.indexOf(this._fuelinjectors[i]) >= 0) {
    						result = this._fuelinjectors[i];
    						break;
    					}
    				}
    				var change = 0;
    				if (result === "") {
    					for (var i = 0; i < equipmentList.length; i++) {
    						if (equipmentList[i].indexOf("fuelinjectors:") >= 0) {
    							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
    							break;
    						}
    					}
    				}
    				if (change != 0) {
    					var newidx = this._fuelinjectors.indexOf("EQ_FUEL_INJECTION_TYPE2") + change;
    					if (newidx > this._fuelinjectors.length - 1) newidx = this._fuelinjectors.length - 1;
    					if (newidx < 0) newidx = 0;
    					result = this._fuelinjectors[newidx];
    				}
    			}
    			if (result === "") result = "EQ_FUEL_INJECTION_TYPE2";
    			break;
    		case "fuelscoops":
    			if (equipmentList) {
    				for (var i = 0; i < this._fuelscoops.length; i++) {
    					if (equipmentList.indexOf(this._fuelscoops[i]) >= 0) {
    						result = this._fuelscoops[i];
    						break;
    					}
    				}
    				var change = 0;
    				if (result === "") {
    					for (var i = 0; i < equipmentList.length; i++) {
    						if (equipmentList[i].indexOf("fuelscoops:") >= 0) {
    							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
    							break;
    						}
    					}
    				}
    				if (change != 0) {
    					var newidx = this._fuelscoops.indexOf("EQ_FUEL_SCOOPS_TYPE1") + change;
    					if (newidx > this._fuelscoops.length - 1) newidx = this._fuelscoops.length - 1;
    					if (newidx < 0) newidx = 0;
    					result = this._fuelscoops[newidx];
    				}
    			}
    			if (result === "") result = "EQ_FUEL_SCOOPS_TYPE1";
    			break;
    		case "heatshields":
    			if (equipmentList) {
    				for (var i = 0; i < this._heatshields.length; i++) {
    					if (equipmentList.indexOf(this._heatshields[i]) >= 0) {
    						result = this._heatshields[i];
    						break;
    					}
    				}
    				var change = 0;
    				if (result === "") {
    					for (var i = 0; i < equipmentList.length; i++) {
    						if (equipmentList[i].indexOf("heatshields:") >= 0) {
    							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
    							break;
    						}
    					}
    				}
    				if (change != 0) {
    					var newidx = this._heatshields.indexOf("EQ_HEAT_SHIELD_TYPE2") + change;
    					if (newidx > this._heatshields.length - 1) newidx = this._heatshields.length - 1;
    					if (newidx < 0) newidx = 0;
    					result = this._heatshields[newidx];
    				}
    			}
    			if (result === "") result = "EQ_HEAT_SHIELD_TYPE2";
    			break;
    		case "frontarmour":
    			if (equipmentList) {
    				for (var i = 0; i < this._frontarmour.length; i++) {
    					if (equipmentList.indexOf(this._frontarmour[i]) >= 0) {
    						result = this._frontarmour[i];
    						break;
    					}
    				}
    				var change = 0;
    				if (result === "") {
    					for (var i = 0; i < equipmentList.length; i++) {
    						if (equipmentList[i].indexOf("frontarmour:") >= 0) {
    							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
    							break;
    						}
    					}
    				}
    				// the default is no armour, so if a change value is entered it has to be always positive
    				if (change != 0) {
    					if (change > this._frontarmour.length - 1) change = this._frontarmour.length - 1;
    					if (change >= 0) result = this._frontarmour[change];
    				}
    			}
    			break;
    		case "aftarmour":
    			if (equipmentList) {
    				for (var i = 0; i < this._aftarmour.length; i++) {
    					if (equipmentList.indexOf(this._aftarmour[i]) >= 0) {
    						result = this._aftarmour[i];
    						break;
    					}
    				}
    				var change = 0;
    				if (result === "") {
    					for (var i = 0; i < equipmentList.length; i++) {
    						if (equipmentList[i].indexOf("aftarmour:") >= 0) {
    							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
    							break;
    						}
    					}
    				}
    				// the default is no armour, so if a change value is entered it has to be always positive
    				if (change != 0) {
    					if (change > this._aftarmour.length - 1) change = this._aftarmour.length - 1;
    					if (change >= 0) result = this._aftarmour[change];
    				}
    			}
    			break;
    		case "heatsinks":
    			if (equipmentList) {
    				if (equipmentList.indexOf("EQ_HEAT_SINK") >= 0) result = "EQ_HEAT_SINK";
    				var change = 0;
    				if (result === "") {
    					for (var i = 0; i < equipmentList.length; i++) {
    						if (equipmentList[i].indexOf("heatsinks:") >= 0) {
    							change = parseInt(equipmentList[i].substring(equipmentList[i].indexOf(":") + 1));
    							break;
    						}
    					}
    				}
    				// the default is no armour, so if a change value is entered it has to be always positive
    				if (change != 0) {
    					for (var i = 1; i <= change; i++)
    						result += (result === "" ? "" : ",") + "EQ_HEAT_SINK";
    				}
    			}
    			break;
    	}
    
    	return result;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns the NPC equipment array for a given role and space
    this.$getNPCEquipmentList = function $getNPCEquipmentList(primRole, roleList, equipmentSpace) {
    	var role = primRole;
    	// check if there is a translation item for the primary role
    	if (this._NPCEquivalents[primRole] != null) role = this._NPCEquivalents[primRole];
    	// try with the primary role first
    	for (var i = 0; i < this._NPCConfig.length; i++) {
    		if (this._NPCConfig[i].primaryRole == role && equipmentSpace >= this._NPCConfig[i].minSpace && equipmentSpace <= this._NPCConfig[i].maxSpace) {
    			return this._NPCConfig[i].equipmentList;
    		}
    	}
    	// if we get here there was no match for the primary role
    	// now we'll check all the other roles
    	for (var j = 0; j < roleList.length; j++) {
    		for (var i = 0; i < this._NPCConfig.length; i++) {
    			if (this._NPCConfig[i].primaryRole === roleList[j] && equipmentSpace >= this._NPCConfig[i].minSpace && equipmentSpace <= this._NPCConfig[i].maxSpace) {
    				return this._NPCConfig[i].equipmentList;
    			}
    		}
    	}
    	// no match at all - return null
    	return null;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // adds the cargo space filler item for when the equipment requirements outstrip the base equipment space capacity
    this.$addEquipmentSpaceItem = function $addEquipmentSpaceItem(ship) {
    	if (!ship) return true;
    
    	// don't add for NPC's
    	if (ship.isPlayer === false) return true;
    	// don't add during flight
    	if (ship.alertCondition != 0) return true;
    
    	var stn = system.mainStation;
    	if (ship.dockedStation) stn = ship.dockedStation;
    	var mkt = stn.market;
    
    	// remove any existing equipment space items
    	var remove = "";
    	for (var i = 1; i <= 40; i++) {
    		remove = "EQ_EQUIPSPACE_" + i;
    		if (ship.equipmentStatus(remove) === "EQUIPMENT_OK") {
    			ship.removeEquipment(remove);
    			break;
    		}
    	}
    
    	var equipSpace = this.$equipmentSpaceTotal(ship);
    	var cargoSpace = this.$cargoSpaceAvailable(ship);
    	var used = this.$calcEquipmentSpace(ship);
    	if (used > equipSpace) {
    		// allocate cargo space to equipment space
    		var diff = parseInt(used - equipSpace);
    		if (diff > cargoSpace) {
    			// put in the maximum anyway
    			if (cargoSpace > 0) ship.awardEquipment("EQ_EQUIPSPACE_" + cargoSpace);
    			return false;
    		} else if (diff > 0) {
    			// add the new one
    			var item = "EQ_EQUIPSPACE_" + diff;
    			//if (this._debug) log(this.name, "adding item " + item);
    			var result = false;
    			var tries = 0;
    			do {
    				result = ship.awardEquipment(item);
    				if (result === false) {
    					// sell cargo until we fit in.
    					if (ship.isPlayer) {
    						var cargo = ship.manifest.list;
    						for (var i = 0; i < cargo.length; i++) {
    							if (cargo[i].quantity > 0 && cargo[i].unit === "t") {
    								ship.manifest[cargo[i].commodity] -= 1;
    								if (ship.isPlayer) {
    									player.credits += (mkt[cargo[i].commodity].price / 10);
    								}
    								break;
    							}
    						}
    					}
    				}
    				tries += 1;
    			} while (result === false && tries < ship.cargoSpaceCapacity);
    
    			this.$updateShipSpecs(ship);
    			return result;
    		}
    	} else {
    		this.$updateShipSpecs(ship);
    		return true;
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns calculated values for particular types of settings
    this.$calculatedValue = function $calculatedValue(calcType, ship, shipspec, booster, weight, maxweight, damageFactor) {
    
    	var loadData = false;
    	var boostEq = null;
    
    	if (!shipspec) {
    		loadData = true;
    		var shipspec = Ship.shipDataForKey(ship.dataKey);
    		var weight = this.$calcEquipmentWeight(ship);
    		var maxweight = this.$calcShipMaxWeight(ship.shipClassName, this.$getShipMass(ship));
    		if (maxweight < weight) maxweight = weight;
    		var damageFactor = 1;
    	}
    	if (!booster) {
    		boostEq = EquipmentInfo.infoForKey(this.$equipmentItemInUse("boosters", ship));
    	} else {
    		boostEq = booster;
    	}
    
    	var thrust = parseInt(shipspec["thrust"]);
    	if (isNaN(thrust)) thrust = 30;
    	var speed = parseInt(shipspec["max_flight_speed"]);
    	if (isNaN(speed)) speed = 350;
    	var pitch = parseFloat(shipspec["max_flight_pitch"]);
    	if (isNaN(pitch)) pitch = 1;
    	var roll = parseFloat(shipspec["max_flight_roll"]);
    	if (isNaN(roll)) roll = 2;
    	if (shipspec["max_flight_yaw"]) {
    		var yaw = parseFloat(shipspec["max_flight_yaw"]);
    	} else {
    		var yaw = pitch;
    	}
    	var result = 0;
    	var boost = 1;
    
    	switch (calcType) {
    		case "thrust":
    			var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("engines", ship));
    			if (boostEq != null) boost = parseFloat(boostEq.scriptInfo.thrust_adjust);
    			result = ((thrust * parseFloat(info.scriptInfo.thrust_adjust)) * boost * (1 - (weight / (maxweight * this._weightFactor)))) * damageFactor;
    			break;
    		case "speed":
    			var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("engines", ship));
    			if (boostEq != null) boost = parseFloat(boostEq.scriptInfo.speed_adjust);
    			result = ((speed * parseFloat(info.scriptInfo.speed_adjust)) * boost * (1 - (weight / (maxweight * this._weightFactor)))) * damageFactor;
    			break;
    		case "pitch":
    			var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("thrusters", ship));
    			if (boostEq != null) boost = parseFloat(boostEq.scriptInfo.pitch_adjust);
    			result = ((pitch * parseFloat(info.scriptInfo.pitch_adjust)) * boost * (1 - (weight / (maxweight * this._weightFactor)))) * damageFactor;
    			break;
    		case "roll":
    			var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("thrusters", ship));
    			if (boostEq != null) boost = parseFloat(boostEq.scriptInfo.roll_adjust);
    			result = ((roll * parseFloat(info.scriptInfo.roll_adjust)) * boost * (1 - (weight / (maxweight * this._weightFactor)))) * damageFactor;
    			break;
    		case "yaw":
    			var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("thrusters", ship));
    			if (boostEq != null) boost = parseFloat(boostEq.scriptInfo.pitch_adjust);
    			result = ((yaw * parseFloat(info.scriptInfo.yaw_adjust)) * boost * (1 - (weight / (maxweight * this._weightFactor)))) * damageFactor;
    			break;
    	}
    
    	if (loadData) shipspec = null;
    
    	return result;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // adjust the ships performance based on equipment and weight
    this.$updateShipSpecs = function $updateShipSpecs(ship) {
    
    	if (!ship || ship.isValid === false) return;
    
    	var shipspec = Ship.shipDataForKey(ship.dataKey);
    	var weight = this.$calcEquipmentWeight(ship);
    	var mass = this.$getShipMass(ship);
    	var maxweight = this.$calcShipMaxWeight(ship.shipClassName, mass);
    	if (maxweight < weight) maxweight = weight;
    	var check = "";
    
    	/*if (this._debug && ship.isPlayer) {
    		log(this.name, "Pre settings for ship " + ship + ":");
    		log(this.name, "Max Thrust:           " + ship.maxThrust);
    		log(this.name, "Max Speed:            " + ship.maxSpeed);
    		log(this.name, "Hyperspace Spin Time: " + ship.hyperspaceSpinTime);
    		log(this.name, "Pitch:                " + ship.maxPitch);
    		log(this.name, "Roll:                 " + ship.maxRoll);
    		log(this.name, "Yaw:                  " + ship.maxYaw);
    		log(this.name, "Max Energy:           " + ship.maxEnergy);
    		if (ship.isPlayer) {
    			log(this.name, "Front Shield:         " + ship.maxForwardShield);
    			log(this.name, "Aft Shield:           " + ship.maxAftShield);
    		}
    		log(this.name, "Heat Shield:          " + ship.heatInsulation);
    		log(this.name, "Injector Burn Rate:   " + ship.injectorBurnRate);
    		log(this.name, "Injector Speed Factor:" + ship.injectorSpeedFactor);
    	}*/
    
    	// boosters (if installed)
    	var bstr = this.$equipmentItemInUse("boosters", ship);
    	ship.script._boosterHeatPoint = 0;
    	if (ship.equipmentStatus(bstr) === "EQUIPMENT_OK") {
    		var boostEq = EquipmentInfo.infoForKey(bstr);
    		if (boostEq != null) ship.script._boosterHeatPoint = boostEq.scriptInfo.heat_buildup;
    	}
    
    	// engine performance
    	check = ship.equipmentStatus(this.$equipmentItemInUse("engines", ship));
    	if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    		var dam = 1;
    		if (check === "EQUIPMENT_DAMAGED") dam = 0.67;
    		ship.maxSpeed = this.$calculatedValue("speed", ship, shipspec, boostEq, weight, maxweight, dam);
    		ship.maxThrust = this.$calculatedValue("thrust", ship, shipspec, boostEq, weight, maxweight, dam);
    		ship.thrust = ship.maxThrust;
    	}
    
    	// hyperspace performance
    	if (this.$shipHasHyperspaceMotor(ship.dataKey) === true && this._OXPHyperdrives === false) {
    		check = ship.equipmentStatus(this.$equipmentItemInUse("hyperdrive", ship));
    		if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    			if (check === "EQUIPMENT_OK") {
    				var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("hyperdrive", ship));
    				ship.hyperspaceSpinTime = parseInt(info.scriptInfo.spin_time);
    			} else {
    				ship.hyperspaceSpinTime = 50;
    			}
    		}
    	}
    
    	// thruster performance
    	check = ship.equipmentStatus(this.$equipmentItemInUse("thrusters", ship));
    	if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    		var dam = 1;
    		if (check === "EQUIPMENT_DAMAGED") dam = 0.75;
    		ship.maxPitch = this.$calculatedValue("pitch", ship, shipspec, boostEq, weight, maxweight, dam);
    		ship.maxRoll = this.$calculatedValue("roll", ship, shipspec, boostEq, weight, maxweight, dam);
    		ship.maxYaw = this.$calculatedValue("yaw", ship, shipspec, boostEq, weight, maxweight, dam);
    	}
    
    
    	// energy banks
    	check = ship.equipmentStatus(this.$equipmentItemInUse("energy", ship));
    	if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    		var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("energy", ship));
    		var initial = 200;
    		if (typeof shipspec["max_energy"] != "undefined") initial = parseInt(shipspec["max_energy"]);
    		var checkbanks = Math.floor(initial / 64);
    		if (checkbanks === 0) checkbanks = 1;
    		if (checkbanks != parseInt(info.scriptInfo.energy_banks)) {
    			initial = (parseInt(info.scriptInfo.energy_banks) * 64);
    		}
    		if (check === "EQUIPMENT_DAMAGED" && ship.isPlayer) {
    			if (this._energyRechargeRate_Stored === 0) this._energyRechargeRate_Stored = ship.energyRechargeRate;
    			ship.energyRechargeRate = 0;
    		}
    		ship.maxEnergy = initial;
    		ship.energy = ship.maxEnergy;
    	}
    
    	// shield settings
    	this.$updateShieldValues(ship);
    
    	// heat shield
    	check = ship.equipmentStatus(this.$equipmentItemInUse("heatshields", ship));
    	ship.script._heat_sink_factor = parseFloat(this._defaultHeatShieldHSFactor);
    	/*
    	// work out how fast cabin heat will rise
    	// smaller ships will heat faster, larger ships will heat slower
    	if (this._shipHeatRateExceptions[ship.shipClassName]) {
    		ship.script._heat_rate = this._shipHeatRateExceptions[ship.shipClassName];
    	} else {
    		//ship.script._heat_rate = 1 + (((214737.6875 - mass) / (mass > 214737 ? 50000 : 70000)) * 0.1);
    		ship.script._heat_rate = 1 + (((250000 - mass) / (mass * 0.9)) * 0.15);
    		//ship.script._heat_rate = 1 + ((1 - (mass / 500000)) / 1.2);
    
    		if (this._debug && ship.isPlayer) log(this.name, "ship heat rate = " + ship.script._heat_rate);
    	}
    	*/
    
    	// set the default heat shield value first
    	var shipdef = 1;
    	if (typeof shipspec["heat_insulation"] != "undefined") shipdef = parseFloat(shipspec["heat_insulation"]);
    	ship.heatInsulation = shipdef;
    	if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    		if (check === "EQUIPMENT_OK") {
    			var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("heatshields", ship));
    			ship.heatInsulation = shipdef + parseFloat(info.scriptInfo.oolite_heat_insulation_strength);
    			ship.script._heat_sink_factor = parseFloat(info.scriptInfo.heat_sink_factor);
    		}
    	}
    
    	// fuel injection
    	check = ship.equipmentStatus(this.$equipmentItemInUse("fuelinjectors", ship));
    	if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    		var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("fuelinjectors", ship));
    		var burn = 0.25;
    		if (typeof shipspec["injector_burn_rate"] != "undefined") burn = shipspec["injector_burn_rate"];
    		ship.injectorBurnRate = parseFloat(burn) * parseFloat(info.scriptInfo.burn_rate);
    		var factor = 7;
    		if (typeof shipspec["injector_speed_factor"] != "undefined") factor = shipspec["injector_speed_factor"];
    		ship.injectorSpeedFactor = parseFloat(factor) * parseFloat(info.scriptInfo.speed_factor);
    	}
    
    	// fuel scoops
    	check = ship.equipmentStatus(this.$equipmentItemInUse("fuelscoops", ship));
    	if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    		var info = EquipmentInfo.infoForKey(this.$equipmentItemInUse("fuelscoops", ship));
    		ship.script._fuelScoopAccumulator = parseFloat(info.scriptInfo.accumulator_size);
    	}
    
    	/*if (this._debug && ship.isPlayer) {
    		log(this.name, "Post settings:");
    		log(this.name, "Max Thrust:           " + ship.maxThrust);
    		log(this.name, "Max Speed:            " + ship.maxSpeed);
    		log(this.name, "Hyperspace Spin Time: " + ship.hyperspaceSpinTime);
    		log(this.name, "Pitch:                " + ship.maxPitch);
    		log(this.name, "Roll:                 " + ship.maxRoll);
    		log(this.name, "Yaw:                  " + ship.maxYaw);
    		log(this.name, "Max Energy:           " + ship.maxEnergy);
    		if (ship.isPlayer) {
    			log(this.name, "Front Shield:         " + ship.maxForwardShield);
    			log(this.name, "Aft Shield:           " + ship.maxAftShield);
    		}
    		log(this.name, "Heat Shield:          " + ship.heatInsulation);
    		log(this.name, "Injector Burn Rate:   " + ship.injectorBurnRate);
    		log(this.name, "Injector Speed Factor:" + ship.injectorSpeedFactor);
    	}*/
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // due to their complexity, shield settings are performed in this separate routine
    // this allows us to call it from multiple places
    this.$updateShieldValues = function $updateShieldValues(ship) {
    
    	var check = "";
    
    	// shields (only for the player ship)
    	if (ship.isPlayer) {
    		// force the naval grid to update
    		if (ship.equipmentStatus("EQ_NAVAL_GRID") === "EQUIPMENT_OK" || ship.equipmentStatus("EQ_ENERGY_GRID") === "EQUIPMENT_OK") {
    			var ng = worldScripts["Naval Grid"];
    			if (ng) ng._ng_player_modifiers();
    		}
    
    		var ctrl = worldScripts["Oolite Equipment Control"];
    		// make sure the baselines have been set before we go any further.
    		if (typeof ctrl.$baseline.maxForwardShield === "undefined") ctrl.playerBoughtNewShip();
    
    		var eq = this.$equipmentItemInUse("frontshields", ship);
    		check = ship.equipmentStatus(eq);
    		if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    			var info = EquipmentInfo.infoForKey(eq);
    
    			// need to apply shield booster and naval shield booster values
    			if (eq === "EQ_NO_FORWARD_SHIELD") {
    				ship.maxForwardShield = 0;
    			} else if (check === "EQUIPMENT_DAMAGED") {
    				//if (this._forwardShieldRechargeRate_Stored === 0) this._forwardShieldRechargeRate_Stored = ship.forwardShieldRechargeRate;
    				ship.forwardShieldRechargeRate = -0.5;
    			} else {
    				// reset the shield values
    				var base = ship.maxForwardShield;
    				if (typeof ctrl.$baseline.maxForwardShield != "undefined") base = ctrl.$baseline.maxForwardShield;
    				ship.maxForwardShield = base + parseFloat(info.scriptInfo.oolite_shield_increase);
    				ship.forwardShieldRechargeRate = 2;
    				if (ship.equipmentStatus("EQ_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
    					var boost = EquipmentInfo.infoForKey("EQ_SHIELD_BOOSTER");
    					ship.maxForwardShield += parseFloat(boost.scriptInfo.oolite_shield_increase);
    					ship.forwardShieldRechargeRate *= parseFloat(boost.scriptInfo.oolite_shield_recharge_multiplier);
    				}
    				if (ship.equipmentStatus("EQ_NAVAL_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
    					var boost = EquipmentInfo.infoForKey("EQ_NAVAL_SHIELD_BOOSTER");
    					ship.maxForwardShield += parseFloat(boost.scriptInfo.oolite_shield_increase);
    					ship.forwardShieldRechargeRate *= parseFloat(boost.scriptInfo.oolite_shield_recharge_multiplier);
    				}
    			}
    			if (ship.docked) ship.forwardShield = ship.maxForwardShield;
    		}
    
    		eq = this.$equipmentItemInUse("aftshields", ship);
    		check = ship.equipmentStatus(eq);
    		if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    			var info = EquipmentInfo.infoForKey(eq);
    
    			// need to apply shield booster and naval shield booster values
    			if (eq === "EQ_NO_AFT_SHIELD") {
    				ship.maxAftShield = 0;
    			} else if (check === "EQUIPMENT_DAMAGED") {
    				//if (this._aftshieldsRechargeRate_Stored === 0) this._aftshieldsRechargeRate_Stored = ship.aftShieldRechargeRate;
    				ship.aftShieldRechargeRate = -0.5;
    			} else {
    				var base = ship.maxAftShield;
    				if (typeof ctrl.$baseline.maxAftShield != "undefined") base = ctrl.$baseline.maxAftShield;
    				ship.aftShieldRechargeRate = 2;
    				ship.maxAftShield = base + parseFloat(info.scriptInfo.oolite_shield_increase);
    				if (ship.equipmentStatus("EQ_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
    					var boost = EquipmentInfo.infoForKey("EQ_SHIELD_BOOSTER");
    					ship.maxAftShield += parseFloat(boost.scriptInfo.oolite_shield_increase);
    					ship.aftShieldRechargeRate *= parseFloat(boost.scriptInfo.oolite_shield_recharge_multiplier);
    				}
    				if (ship.equipmentStatus("EQ_NAVAL_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
    					var boost = EquipmentInfo.infoForKey("EQ_NAVAL_SHIELD_BOOSTER");
    					ship.maxAftShield += parseFloat(boost.scriptInfo.oolite_shield_increase);
    					ship.aftShieldRechargeRate *= parseFloat(boost.scriptInfo.oolite_shield_recharge_multiplier);
    				}
    			}
    			if (ship.docked) ship.aftShield = ship.maxAftShield;
    		}
    	} else {
    		// NPC's only have shields if one of these OXP's is installed.
    		if (worldScripts["customshields"] || worldScripts["NPC-shields"]) {
    			// based on the way things are set up, we should be confident that customshields has set the right value by now.
    			// we're going to redo the settings, based on the factor that equipment choices might have moved things up or down
    			// with customshields, the recharge rate is already handled, and as ShipConfig doesn't have any special equipment that adjusts the recharge rate, we can leave that part alone.
    			// start with the front shields
    			var front_shield = 0;
    			var eq = this.$equipmentItemInUse("frontshields", ship);
    			check = ship.equipmentStatus(eq);
    			if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    				var info = EquipmentInfo.infoForKey(eq);
    
    				// need to apply shield booster and naval shield booster values
    				if (eq === "EQ_NO_FORWARD_SHIELD" || check === "EQUIPMENT_DAMAGED") {
    					front_shield = 0;
    				} else {
    					// reset the shield values
    					var base = 128;
    					front_shield = base + parseFloat(info.scriptInfo.oolite_shield_increase);
    					if (ship.equipmentStatus("EQ_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
    						var boost = EquipmentInfo.infoForKey("EQ_SHIELD_BOOSTER");
    						front_shield += parseFloat(boost.scriptInfo.oolite_shield_increase);
    					}
    					if (ship.equipmentStatus("EQ_NAVAL_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
    						var boost = EquipmentInfo.infoForKey("EQ_NAVAL_SHIELD_BOOSTER");
    						front_shield += parseFloat(boost.scriptInfo.oolite_shield_increase);
    					}
    				}
    			}
    			// now the aft shields
    			var aft_shield = 0;
    			var eq = this.$equipmentItemInUse("aftshields", ship);
    			check = ship.equipmentStatus(eq);
    			if (check === "EQUIPMENT_OK" || check === "EQUIPMENT_DAMAGED") {
    				var info = EquipmentInfo.infoForKey(eq);
    
    				// need to apply shield booster and naval shield booster values
    				if (eq === "EQ_NO_AFT_SHIELD" || check === "EQUIPMENT_DAMAGED") {
    					aft_shield = 0;
    				} else {
    					// reset the shield values
    					var base = 128;
    					aft_shield = base + parseFloat(info.scriptInfo.oolite_shield_increase);
    					if (ship.equipmentStatus("EQ_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
    						var boost = EquipmentInfo.infoForKey("EQ_SHIELD_BOOSTER");
    						aft_shield += parseFloat(boost.scriptInfo.oolite_shield_increase);
    					}
    					if (ship.equipmentStatus("EQ_NAVAL_SHIELD_BOOSTER") === "EQUIPMENT_OK") {
    						var boost = EquipmentInfo.infoForKey("EQ_NAVAL_SHIELD_BOOSTER");
    						aft_shield += parseFloat(boost.scriptInfo.oolite_shield_increase);
    					}
    				}
    			}
    			// now we have the correct shield amount, apply it to the appropriate OXP
    			if (worldScripts["customshields"]) {
    				ship.script.customshieldsmaxforwardshieldlevel = front_shield;
    				ship.script.customshieldsmaxaftshieldlevel = aft_shield;
    			}
    			if (worldScripts["NPC-shields"]) {
    				// this OXP only has 1 shield value, so we'll ignore the aft shields in this instance
    				ship.script.maxShieldStrength = front_shields;
    				ship.script.shieldStrength = front_shields;
    			}
    		}
    	}
    
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns the total amount of equipment space available for a ship of a particular mass
    // a cobra mk3 should have about 20t of equipment space
    this.$equipmentSpaceTotal = function $equipmentSpaceTotal(ship) {
    	if (!ship) return 0;
    	// cobra3 			214737.6875 or 219634.265625
    	// moray starboat	51203.4375
    	// adder			16045.4931640625
    	// python			259688.28125
    	// cobra1			52291.8359375
    	// miner			12074.4453125
    	// gecko			24669.99609375
    
    	// check for an exception entry for this ship data key
    	if (this._shipSpaceExceptions[ship.shipClassName] && this._shipSpaceExceptions[ship.shipClassName] != "") {
    		// we'll trust this number to be correct
    		space = parseInt(this._shipSpaceExceptions[ship.shipClassName]);
    	} else {
    		// do a calc
    		var space = parseInt((this.$getShipMass(ship) / 429475.375) * 40);
    
    		if (space < 15) space = 15; // min of 15
    		// do a check on cargo capacity
    		if (space < 20) {
    			var cargo = this.$getCargoCapacity(ship)
    			// if our calc is less than 20 but the cargo is greater than 35, then set the min to 20 and add an extra 1 of equip space for each 5 tons of cargo space above 35 tons
    			if (cargo > 35) space = 20 + parseInt((cargo - 35) / 5);
    		}
    		if (space > 40) space = 40; // max of 40
    	}
    	var ext = this.$getEquipmentExtensions(ship);
    	return (space + ext);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // external routine to return the equipment space and cargo space for a ship key
    // we'll create a temporary ship object and use that to get the details
    // returns a dictionary with 3 elements: "equipSpace", "cargoSpace", and "mass"
    this.$getEquipmentSpaceFromShipKey = function $getEquipmentSpaceFromShipKey(shipKey) {
    	var result = {};
    	// find a spot well away from any possible objects
    	if (system.sun) {
    		var temppos = system.sun.position.cross(system.mainPlanet.position).direction().multiply(4E9).subtract(system.mainPlanet.position);
    	} else {
    		var temppos = Vector3D(0, 0, 0);
    	}
    	// add a ship with the particular key
    	var tempship = system.addShips("[" + shipKey + "]", 1, temppos, 0);
    	if (tempship != null) {
    		// force this ship to be "dead" in space - we don't want it to do anything disruptive!
    		tempship[0].switchAI("oolite-nullAI.js");
    		// now we have a ship, we can use the standard functions for calculating available space
    		result["equipSpace"] = this.$equipmentSpaceTotal(tempship[0]);
    		result["cargoSpace"] = this.$cargoSpaceAvailable(tempship[0]);
    		result["mass"] = this.$getShipMass(tempship[0]);
    		// clean up our temp ship
    		tempship[0].remove(true);
    	} else {
    		// this could happen if the ship is not allowed to be spawned in this system due to constraints in the shipdata.plist file for the ship
    		result["equipSpace"] = "N/A";
    		result["cargoSpace"] = "N/A";
    		result["mass"] = "N/A";
    	}
    	return result;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns the max permissible amount of cargo space that can be converted to equipment space
    // attempting to avoid the issue of buying an anaconda and just putting max of everything in it.
    this.$cargoSpaceAvailable = function $cargoSpaceAvailable(ship) {
    	if (!ship) return 0;
    
    	var reduction = this.$checkCargoReduction(ship);
    	var maxCargo = this.$getCargoCapacity(ship);
    	var curCargo = maxCargo - reduction;
    	// if the ship doesn't have any cargo space to allocate, return 0
    	if (curCargo === 0) return 0;
    
    	var calc = parseInt(maxCargo * 0.75);
    	if (calc > curCargo) calc = curCargo;
    
    	if (calc > 40) {
    		return 40;
    	} else {
    		// ships with small cargo holds can allocate it all
    		if (calc < 10) {
    			return curCargo;
    		} else {
    			return calc;
    		}
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns the current cargo space conversion amount
    this.$cargoEquipmentSpaceAmount = function $cargoEquipmentSpaceAmount(ship) {
    	if (!ship) return 0;
    
    	for (var i = 0; i < this._filler.length; i++) {
    		if (ship.equipmentStatus(this._filler[i]) === "EQUIPMENT_OK") return (i + 1);
    	}
    	return 0;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns the space current available for equipment (including available reused cargo space)
    this.$availableEquipmentSpace = function $availableEquipmentSpace(ship) {
    	var equipSpace = this.$equipmentSpaceTotal(ship);
    	var cargoSpace = this.$cargoSpaceAvailable(ship); // + this.$cargoEquipmentSpaceAmount(p));
    	var used = this.$calcEquipmentSpace(ship);
    	return ((equipSpace + cargoSpace) - used);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // get the original capacity for this ship
    // this will be independant of any item that reduces the cargo bay (eg passenger berths)
    this.$getCargoCapacity = function $getCargoCapacity(ship) {
    	if (!ship) return 0;
    
    	var shipData = Ship.shipDataForKey(ship.dataKey);
    	if (!shipData) return 0;
    	var cargoAvail = 0;
    	if (shipData["max_cargo"]) cargoAvail = parseInt(shipData["max_cargo"]);
    	if (ship.equipmentStatus("EQ_CARGO_BAY") === "EQUIPMENT_OK") {
    		var extra = 15;
    		if (shipData["extra_cargo"]) extra = parseInt(shipData["extra_cargo"]);
    		cargoAvail += extra;
    	}
    	return cargoAvail;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns the total of equip items that that up cargo space
    this.$checkCargoReduction = function $checkCargoReduction(ship) {
    	var total = 0;
    	var eq = ship.equipment;
    	var mult = 0;
    	// check that the equipment element is valid (it might not be after an ejection)
    	if (!eq) return 0;
    	for (var i = 0; i < eq.length; i++) {
    		var itm = eq[i];
    		if (this._filler.indexOf(itm.equipmentKey) >= 0) continue;
    		mult = 1;
    		if (itm.requiredCargoSpace > 0) {
    			if (itm.equipmentKey === "EQ_PASSENGER_BERTH") mult = ship.passengerCapacity;
    			total += itm.requiredCargoSpace * mult;
    		}
    	}
    	return total;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns the amount of space taken up by all ship equipment
    this.$calcEquipmentSpace = function $calcEquipmentSpace(ship) {
    
    	if (!ship) return 0;
    
    	var equipSpace = this.$equipmentSpaceTotal(ship);
    	//var cargoSpace = this.$cargoSpaceAvailable(ship);
    	var used = 0;
    
    	// cycle through the installed equipment
    	var eq = ship.equipment;
    	if (!eq) return 0;
    	for (var i = 0; i < eq.length; i++) {
    		var e_item = eq[i];
    		if (this._ignoreEquip.indexOf(e_item.equipmentKey) >= 0) continue;
    		if (!this._equipmentMatrix[e_item.equipmentKey]) {
    			// don't know what this is, so try to work it out
    			//var info = EquipmentInfo.infoForKey(e_item.equipmentKey);
    			if (e_item.isVisible === true && e_item.requiredCargoSpace === 0) {
    				// if it's not taking up space already, assume 1t
    				used += 1;
    				if (this._debug) log(this.name, "didn't find " + e_item.equipmentKey + " in matrix, using default");
    			}
    		} else {
    			used += this._equipmentMatrix[e_item.equipmentKey][0];
    		}
    	}
    	return used;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // calculates a price factor for equipment, based on ship mass
    this.$equipmentPriceFactor = function $equipmentPriceFactor(shipClass, shipMass, techlvl, sysID) {
    	var factor = shipMass / 100000;
    	if (factor < 0.4) factor = 0.4;
    	if (factor > 3) factor = 3;
    	// the cobra is the exception
    	if (shipClass === "Cobra Mark III") {
    		factor = 1;
    	}
    	if (typeof techlvl == "undefined") {
    		// I've taken out the station equivalent tech level, because it's being applied in other ways
    		//if (player.ship.dockedStation && player.ship.dockedStation.equivalentTechLevel < 16) {
    		//	techlvl = player.ship.dockedStation.equivalentTechLevel;
    		//} else {
    		techlvl = system.info.techlevel;
    		//}
    	}
    	if (typeof sysID == "undefined") sysID = system.ID;
    	//if (this._debug) log(this.name, "price factor (pre tl factor)= " + factor);
    	return (factor * this.$equipmentTechFactor(techlvl, sysID));
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns a calculated max weight for a shipclass
    this.$calcShipMaxWeight = function $calcShipMaxWeight(shipClass, shipMass) {
    	// cobra3 			214737.6875 or 219634.265625
    	// anaconda			437686.875
    	// moray starboat	51203.4375
    	// adder			16045.4931640625
    	// python			259688.28125
    	// cobra1			52291.8359375
    	// miner			12074.4453125
    	// constrictor		28490.8984375
    	// asp mk ii		75881.5625
    	// ferdelance		65457.94921875
    	// boa				181788.90625
    	// Boa cc			215810.5
    	// gecko			24669.99609375
    	// krait			93291.40625
    	// sidewinder		24966.326171875
    	// transporter		12074.4453125
    	// worm 			14597.208984375
    	var mult = 1;
    	if (this._shipPowerToWeight[shipClass]) {
    		// get the preset value, if stored
    		mult = this._shipPowerToWeight[shipClass];
    	} else {
    		// smaller ships have a greater power to weight ratio
    		// add 1 point for every 15000 under 100000
    		if (shipMass < 100000) mult = mult + (1 * (100000 - shipMass) / 15000);
    		// larger ships have a lower power to weight ratio
    		// take off 0.1 point for every 50000 over 200000
    		if (shipMass > 200000) mult = mult - (0.1 * ((shipMass - 200000) / 50000));
    	}
    	var weight = ((shipMass * mult) / 700);
    	return weight;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns the weight (in whole t's) of all equipment and cargo on a ship
    this.$calcEquipmentWeight = function $calcEquipmentWeight(ship) {
    
    	if (!ship) return 0;
    
    	var weight = 0;
    
    	// any weapons?
    	if (ship.aftWeapon && ship.aftWeapon.equipmentKey != "EQ_WEAPON_NONE") {
    		weight += this.$weaponWeight(ship.aftWeapon.equipmentKey);
    	}
    	if (ship.forwardWeapon && ship.forwardWeapon.equipmentKey != "EQ_WEAPON_NONE") {
    		weight += this.$weaponWeight(ship.forwardWeapon.equipmentKey);
    	}
    	if (ship.portWeapon && ship.portWeapon.equipmentKey != "EQ_WEAPON_NONE") {
    		weight += this.$weaponWeight(ship.portWeapon.equipmentKey);
    	}
    	if (ship.starboardWeapon && ship.starboardWeapon.equipmentKey != "EQ_WEAPON_NONE") {
    		weight += this.$weaponWeight(ship.starboardWeapon.equipmentKey);
    	}
    
    	// any missiles?
    	if (ship.missileCapacity > 0) {
    		var noerr = false;
    		// have to do this because attempting to access ship.missiles when no missiles are installed will generate an Objective-C error
    		try {
    			var miss = ship.missiles;
    			noerr = true;
    		} catch (err) {
    			if (this._debug && ship.isPlayer) log(this.name, "!!ERROR: " + err);
    		}
    		if (noerr) {
    			for (var i = 0; i < miss.length; i++) {
    				if (this._ignoreEquip.indexOf(miss[i].equipmentKey) >= 0) continue;
    				if (!this._equipmentMatrix[miss[i].equipmentKey]) {
    					weight += 1;
    				} else {
    					weight += this._equipmentMatrix[miss[i].equipmentKey][1];
    				}
    			}
    		}
    	}
    
    	// cycle through the installed equipment
    	var eq = ship.equipment;
    	for (var i = 0; i < eq.length; i++) {
    		var e_item = eq[i];
    		if (this._ignoreEquip.indexOf(e_item.equipmentKey) >= 0) continue;
    		if (!this._equipmentMatrix[e_item.equipmentKey]) {
    			// don't know what this is, so try to work it out
    			var info = EquipmentInfo.infoForKey(e_item.equipmentKey);
    			// add it up if it's either (a) visible or (b) taking up space
    			if (info.isVisible === true || info.requiredCargoSpace > 0) {
    				if (info.requiredCargoSpace === 0) {
    					// if it's not taking up space already, assume 1t
    					weight += 1;
    				} else {
    					weight += info.requiredCargoSpace;
    					if (info.equipmentKey === "EQ_PASSENGER_BERTH") weight *= ship.passengerCapacity;
    				}
    			}
    		} else {
    			weight += this._equipmentMatrix[e_item.equipmentKey][1];
    		}
    	}
    	// special items:
    	// LMSS weapons
    	var lmss = worldScripts.LMSS_Core;
    	if (lmss) {
    		if (lmss._forwardAltKey != "EQ_WEAPON_NONE" && lmss._forwardAltKey != "") {
    			weight += this.$weaponWeight(lmss._forwardAltKey);
    		}
    		if (lmss._aftAltKey != "EQ_WEAPON_NONE" && lmss._aftAltKey != "") {
    			weight += this.$weaponWeight(lmss._aftAltKey);
    		}
    		if (lmss._portAltKey != "EQ_WEAPON_NONE" && lmss._portAltKey != "") {
    			weight += this.$weaponWeight(lmss._portAltKey);
    		}
    		if (lmss._starboardAltKey != "EQ_WEAPON_NONE" && lmss._starboardAltKey != "") {
    			weight += this.$weaponWeight(lmss._starboardAltKey);
    		}
    	}
    
    	// add cargo weight
    	if (this.$getCargoCapacity(ship) > 0 && ship.cargoList.length > 0) {
    		for (var i = 0; i < ship.cargoList.length; i++) {
    			var itm = ship.cargoList[i];
    			switch (itm.unit) {
    				case "t":
    					weight += itm.quantity;
    					break;
    				case "kg":
    					weight += (itm.quantity / 1000);
    					break;
    				case "g":
    					weight += (itm.quantity / 1000000);
    					break;
    			}
    		}
    	}
    
    	if (ship.isPlayer) {
    		var smuggling = worldScripts.Smugglers_Equipment;
    		if (smuggling) {
    			// add the weight of any cargo in the smuggling compartment
    			var cargo = smuggling.$getSmugglingCargo();
    
    			for (var i = 0; i < cargo.length; i++) {
    				switch (cargo[i].unit) {
    					case "t":
    						weight += cargo[i].quantity;
    						break;
    					case "kg":
    						weight += (cargo[i].quantity / 1000);
    						break;
    					case "g":
    						weight += (cargo[i].quantity / 1000000);
    						break;
    				}
    			}
    		}
    	}
    
    	return weight;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns the weight (or calculated weight) of a paricular weapon
    this.$weaponWeight = function $weaponWeight(weaponKey) {
    	if (weaponKey === "EQ_WEAPON_NONE") return 0;
    	if (!this._equipmentMatrix[weaponKey]) {
    		var info = EquipmentInfo.infoForKey(weaponKey);
    		// calc weight based on weapon range
    		if (info && info.weaponInfo) {
    			if (info.weaponInfo.range < 12000) {
    				return 1;
    			} else if (info.weaponInfo.range < 20000) {
    				return 3;
    			} else {
    				return 5;
    			}
    		} else {
    			// weird... shouldn't really happen
    			return 1;
    		}
    	} else {
    		return this._equipmentMatrix[weaponKey][1];
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns true if a HUD with allowBigGUI is enabled, otherwise false
    this.$isBigGuiActive = function $isBigGuiActive() {
    	if (oolite.compareVersion("1.83") <= 0) {
    		return player.ship.hudAllowsBigGui;
    	} else {
    		var bigGuiHUD = ["XenonHUD.plist", "coluber_hud_ch01-dock.plist"]; // until there is a property we can check, I'll be listing HUD's that have the allow_big_gui property set here
    		if (bigGuiHUD.indexOf(player.ship.hud) >= 0) {
    			return true;
    		} else {
    			return false;
    		}
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // appends space to currentText to the specified length in 'em'
    this.$padTextRight = function $padTextRight(currentText, desiredLength, leftSwitch) {
    	if (currentText == null) currentText = "";
    	var hairSpace = String.fromCharCode(31);
    	var ellip = "…";
    	var currentLength = defaultFont.measureString(currentText.replace(/%%/g, "%"));
    	var hairSpaceLength = defaultFont.measureString(hairSpace);
    	// 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 (defaultFont.measureString(tmp.replace(/%%/g, "%")) > desiredLength);
    		currentLength = defaultFont.measureString(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) {
    		return currentText + new Array(padsNeeded).join(hairSpace);
    	} else {
    		return new Array(padsNeeded).join(hairSpace) + currentText;
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // appends space to currentText to the specified length in 'em'
    this.$padTextLeft = function $padTextLeft(currentText, desiredLength) {
    	return this.$padTextRight(currentText, desiredLength, true);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // adds any equipment space/weight values from script_info data
    // this way we can just look in our array, rather than in two places
    // this is only run once at startup
    this.$addEquipmentDataFromScriptInfo = function $addEquipmentDataFromScriptInfo() {
    	var eqlist = EquipmentInfo.allEquipment;
    	for (var i = 0; i < eqlist.length; i++) {
    		var eq = eqlist[i];
    		if (eq.isVisible && eq.scriptInfo) {
    			var space = -1;
    			var weight = -1;
    			if (eq.scriptInfo.equipment_space && parseFloat(eq.scriptInfo.equipment_space) >= 0) space = parseFloat(eq.scriptInfo.equipment_space);
    			if (eq.scriptInfo.equipment_weight && parseFloat(eq.scriptInfo.equipment_weight) >= 0) weight = parseFloat(eq.scriptInfo.equipment_weight);
    			// have we only been given a space setting? assume weight is the same
    			if (space >= 0 && weight === -1) weight = space;
    			// if the space or weight values are greater than zero, add the definition to the matrix
    			if (space > 0 || weight > 0) this._equipmentMatrix[eq.equipmentKey] = [space, weight];
    			// if the values are both zero, add it to the ignored list
    			if (space === 0 && weight === 0) this._ignoreEquip.push(eq.equipmentKey);
    		}
    		// look for any equipment items that are outside the bounds for general sale but could potentially be sold (as they take up space/weight)
    		if (this._ignoreEquip.indexOf(eq.equipmentKey) === -1 && eq.isVisible && eq.techLevel >= 15 && eq.techLevel < 100 && eq.effectiveTechLevel >= 15 && eq.isAvailableToPlayer === true && eq.isExternalStore === false) {
    			var wt = 0;
    			if (!this._equipmentMatrix[eq.equipmentKey]) {
    				// don't know what this is, so try to work it out
    				// add it up if it's either (a) visible or (b) taking up space
    				if (eq.requiredCargoSpace > 0) {
    					wt = eq.requiredCargoSpace;
    				} else {
    					wt = 1;
    				}
    			} else {
    				wt = this._equipmentMatrix[eq.equipmentKey][1];
    			}
    			if (wt > 0) this._sellNegotiate.push(eq.equipmentKey);
    		}
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // adds script info data from ship data keys
    // this way we can just look in our arrays, rather than in two places
    // this is only run once at startup
    this.$addShipDataFromScriptInfo = function $addShipDataFromScriptInfo() {
    	var shipkeys = Ship.keys();
    	for (var i = 0; i < shipkeys.length; i++) {
    		var shipspec = Ship.shipDataForKey(shipkeys[i]);
    		if (shipspec["script_info"]) {
    			if (shipspec["script_info"].equipment_space) {
    				var space = parseInt(shipspec["script_info"].equipment_space);
    				this._shipSpaceExceptions[shipspec.name] = space;
    			}
    			if (shipspec["script_info"].power_to_weight) {
    				var ratio = parseFloat(shipspec["script_info"].power_to_weight);
    				this._shipPowerToWeight[shipspec.name] = ratio;
    			}
    			if (shipspec["script_info"].role_translation) {
    				var def = shipspec["script_info"].role_translation;
    				if (def.indexOf("|") >= 0) {
    					var pri = def.split("|")[0].trim();
    					var trans = def.split("|")[1].trim();
    					if (pri.length > 0 && trans.length > 0) this._NPCEquivalents[pri] = trans;
    				}
    			}
    		}
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // player the buy/sell sound effects
    this.$playSound = function $playSound(soundtype) {
    	var mySound = new SoundSource;
    	switch (soundtype) {
    		case "explosion":
    			mySound.sound = "[player-scrape-damage]";
    			break;
    		case "buy":
    			mySound.sound = "[buy-commodity]";
    			break;
    		case "sell":
    			mySound.sound = "[sell-commodity]";
    			break;
    		case "deploy_heat_sink":
    			mySound.sound = "heat_sink_deployed.ogg";
    			break;
    		case "booster_warning":
    			if (this._disableBoosterSound === true) return;
    			mySound.sound = "booster_warning.ogg";
    			break;
    	}
    	mySound.loop = false;
    	mySound.play();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns the standard maximum speed for a ship
    this.$getShipSpecSpeed = function $getShipSpecSpeed(ship) {
    	var spec = Ship.shipDataForKey(ship.dataKey);
    	var specspeed = parseInt(spec["max_flight_speed"]);
    	return specspeed;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns the ships mass, either from the exception list, or from the ship itself
    this.$getShipMass = function $getShipMass(ship) {
    	var mass = this._shipMassExceptions[ship.shipClassName];
    	if (!mass) mass = ship.mass;
    	return mass;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns true if the ship data spec says this ship has a hyperspace motor
    this.$shipHasHyperspaceMotor = function $shipHasHyperspaceMotor(shipDataKey) {
    	var check = Ship.shipDataForKey(shipDataKey)["hyperspace_motor"];
    	if (typeof check === "undefined") return true;
    	return (this._trueValues.indexOf(check) != -1);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns the number of heat sinks remaining
    this.$countHeatSinks = function $countHeatSinks() {
    	var hs = 0;
    	var eq = player.ship.equipment;
    	for (var i = 0; i < eq.length; i++) {
    		if (eq[i].equipmentKey === "EQ_HEAT_SINK") hs += 1;
    	}
    	return hs;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // routine to check the combat simulator worldscript, to see if it's running or not
    this.$simulatorRunning = function $SimulatorRunning() {
    	var w = worldScripts["Combat Simulator"];
    	if (w && w.$checkFight && w.$checkFight.isRunning) return true;
    	return false;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // gets the sum of all equipment space extensions installed
    this.$getEquipmentExtensions = function $getEquipmentExtensions(ship) {
    	var ext = 0;
    	var eqlist = ship.equipment;
    	if (eqlist) {
    		for (var i = 0; i < eqlist.length; i++) {
    			var eq = eqlist[i];
    			if (eq.scriptInfo.equipment_extension && parseFloat(eq.scriptInfo.equipment_extension) >= 0) ext += parseFloat(eq.scriptInfo.equipment_extension);
    		}
    	}
    	return ext;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // these routines all relate to circumventing issues with ship storage helper
    //-------------------------------------------------------------------------------------------------------------
    // routine to be called before a respray to set things up for a change of ship
    this.$preResprayFunction = function $preResprayFunction() {
    	this._startUp = true;
    	this._resprayActive = true;
    	// remove the equipment space item before respray, otherwise strange things seem to happen to the amount of available cargo space
    	for (var i = 1; i <= 40; i++) {
    		var remove = "EQ_EQUIPSPACE_" + i;
    		if (player.ship.equipmentStatus(remove) === "EQUIPMENT_OK") {
    			this._holdEquipSpace = remove;
    			player.ship.removeEquipment(remove);
    			break;
    		}
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$restoreEquipSpaceItem = function $restoreEquipSpaceItem() {
    	if (this._holdEquipSpace != "") player.ship.awardEquipment(this._holdEquipSpace);
    	this._startUp = false;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$removeEquipSpaceItem = function $removeEquipSpaceItem() {
    	this._removing = true;
    	if (this._holdEquipSpace != "") player.ship.removeEquipment(this._holdEquipSpace);
    	this._removing = false;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // routine to be called after a respray to get things setup correctly again
    this.$postResprayFunction = function $postResprayFunction() {
    	this._current = {};
    	var result = this.$installBaseEquipment(player.ship);
    	this._startUp = false;
    	this.equipmentAdded("");
    	this._resprayActive = false;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // ensures that hyperspace hangar doesn't store ships with the equipspace item
    this.$updateHyperHangarShipImage = function $updateHyperHangarShipImage() {
    	var hh = worldScripts.HyperspaceHangar;
    	this._startUp = true;
    	// remove the equipment space item before respray, otherwise strange things seem to happen to the amount of available cargo space
    	for (var i = 1; i <= 40; i++) {
    		var remove = "EQ_EQUIPSPACE_" + i;
    		if (player.ship.equipmentStatus(remove) === "EQUIPMENT_OK") {
    			this._holdEquipSpace = remove;
    			player.ship.removeEquipment(remove);
    			break;
    		}
    	}
    	// put the updated storage data into the Hyperspace hangar variable
    	hh._shipsStored[hh._shipTempKey] = worldScripts["Ship_Storage_Helper.js"].storeCurrentShip();
    	// put equipment space item back again
    	this.$restoreEquipSpaceItem();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // we're monkey patching combat sim so we can do a couple of steps in the right order
    // essentially we need to remove the equipment space item before SSH stores the ship config, then put it back immediately after so the ship will work as normal
    // then, just before the ship is restored we remove the equipment space item again, allow SSH to restore the ship and then add it back again.
    this.$combatSim_startFight = function $combatSim_startFight() {
    	worldScripts.ShipConfiguration_Core.$preResprayFunction();
    	worldScripts["Ship_Storage_Helper.js"].disableTCATPBNSFunc();
    	this.$shipState = worldScripts["Ship_Storage_Helper.js"].storeCurrentShip();
    	worldScripts.ShipConfiguration_Core.$restoreEquipSpaceItem();
    	this._setUpHandlers();
    	this._setUpEnvironment();
    	player.ship.removeEquipment("EQ_ESCAPE_POD");
    	player.ship.launch();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // returns the price factor for equipment based on the system's techlevel
    this.$equipmentTechFactor = function $equipmentTechFactor(techlvl, sysID) {
    	// prices would be higher in low tech worlds, cheaper in high-tech
    	// range is high tech 14 (even 15) to low tech 0
    	// prices should'nt vary by too much - 0.7 - 1.3 should probably be the greatest range
    	// we'll add a small variance to the price, so no two systems should have exactly the same prices
    	// but the price will always be the same in that system
    
    	var factor = (((16 - techlvl) / 16) * 0.6) + 0.7;
    	var sysFactor = 0.5;
    	// make sure we're not in interstellar space
    	if (sysID >= 0) {
    		sysFactor = system.scrambledPseudoRandomNumber(sysID);
    	}
    	factor *= (1 + (sysFactor * 0.1 - 0.05));
    	//if (this._debug) log(this.name, "tech factor = " + factor);
    	return factor;
    }
    Scripts/shipconfig_f3hud.js
    "use strict";
    this.name = "ShipConfiguration_F3HUDControl";
    this.author = "phkb";
    this.copyright = "2018 phkb";
    this.description = "Handles the swapping in/out of specialised HUD for F3 screen";
    this.licence = "CC BY-NC-SA 3.0";
    
    this._equipSpaceHUD = "shipconfig_hud.plist";
    
    //-------------------------------------------------------------------------------------------------------------
    this.startUp = function () {
        if (worldScripts.ShipConfiguration_Core._disabled) {
            delete this.guiScreenChanged;
            delete this.missionScreenEnded;
            delete this.playerBoughtEquipment;
            delete this.startUpComplete;
            return;
        }
        // make sure we're using the appropriate F3 HUD, one that matches the big gui setting of the current HUD.
        if (this._equipSpaceHUD.indexOf("shipconfig") >= 0) {
            this._equipSpaceHUD = "shipconfig_hud.plist";
        }
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.guiScreenChanged = function (to, from) {
        var p = player.ship;
        if (!p.docked) return;
        if (worldScripts.ShipConfiguration_Core._disableF3HUD === true) return;
        if (guiScreen === "GUI_SCREEN_EQUIP_SHIP") {
            //swap to special hud
            if (p.hud !== this._equipSpaceHUD) {
                this._restoreHUD = p.hud;
                this._restoreTargetSensitivity = p.reticleTargetSensitive;
                p.hud = this._equipSpaceHUD;
            }
            this.$updateEquipmentSpaceHUD();
        } else {
            if (from === "GUI_SCREEN_EQUIP_SHIP") {
                if (p.hud === this._equipSpaceHUD) {
                    if (this._restoreHUD) {
                        p.hud = this._restoreHUD;
                        p.reticleTargetSensitive = this._restoreTargetSensitivity;
                        delete this._restoreHUD;
                    }
                }
                p.setCustomHUDDial("equipment_space", "");
                p.setCustomHUDDial("cargo_space", "");
            }
        }
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.missionScreenEnded = function () {
        // make sure we're using the appropriate F3 HUD, one that matches the big gui setting of the current HUD.
        if (this._equipSpaceHUD.indexOf("shipconfig") >= 0) {
            if (worldScripts.ShipConfiguration_Core.$isBigGuiActive() === true) {
                this._equipSpaceHUD = "shipconfig_biggui_hud.plist";
            } else {
                this._equipSpaceHUD = "shipconfig_hud.plist";
            }
        }
        this.guiScreenChanged();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.playerBoughtEquipment = function (equipmentKey) {
        var p = player.ship;
        if (!p.docked) return;
        var s = worldScripts.ShipConfiguration_Core;
        if (s._disableF3HUD === true) return;
        if (s._ignoreEquip.indexOf(equipmentKey) >= 0) return;
        this.$updateEquipmentSpaceHUD();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$updateEquipmentSpaceHUD = function $updateEquipmentSpaceHUD() {
        if (guiScreen === "GUI_SCREEN_EQUIP_SHIP") {
            var pad = 14.5;
            var p = player.ship;
            var s = worldScripts.ShipConfiguration_Core;
            if (s._disableF3HUD === true) return;
            var used = s.$calcEquipmentSpace(p);
            var cargoUsed = s.$cargoEquipmentSpaceAmount(p);
            var maxCargo = s.$cargoSpaceAvailable(p);
            var maxSpace = Math.ceil(s.$equipmentSpaceTotal(p) + maxCargo);
            var text = s.$padTextLeft(expandDescription("[sc-header-equipspace]") + " " + used.toFixed(1) + "t (" + maxSpace.toFixed(0) + "t)", pad);
            p.setCustomHUDDial("equipment_space", text);
            text = s.$padTextLeft(expandDescription("[sc-header-cargo]") + " " + cargoUsed.toFixed(1) + "t (" + maxCargo + "t)", pad);
            p.setCustomHUDDial("cargo_space", text);
        }
    }
    Scripts/shipconfig_fuelscoops.js
    "use strict";
    this.name = "ShipConfiguration_FuelScoops";
    this.author = "phkb";
    this.copyright = "2017 phkb";
    this.description = "Routines for fuel scoop control";
    this.licence = "CC BY-NC-SA 3.0";
    
    this.shipScoopedFuel = function () {
        var p = player.ship;
        // this is only for player - NPC's don't seem to have an equivalent event at the moment
        var accum = p.script._fuelScoopAccumulator;
        // add the additional fuel "accumulated"
        p.fuel += accum;
        if (p.fuel > 7) p.fuel = 7
    }
    Scripts/shipconfig_heatsink.js
    "use strict";
    this.name = "ShipConfiguration_HeatSink";
    this.author = "phkb";
    this.copyright = "2016 phkb";
    this.description = "Activation and control script for heat sink usage.";
    this.licence = "CC BY-NC-SA 3.0";
    
    this._mode = 0; // current mode of heat sinks (0 = manual, 1 = auto)
    this._warnPlayerOfHeat = true; // flag to indicate that player will be reminder of dangerous heat levels
    this._controlMode = 0; // control mode: 0 = normal (ie primable equipment), 1 = passive
    this._tempCheck = null; // timer to do automatic heat level checks for heat sink deployment
    this._amountToDump = 0.5; // max percentage of heat to be dumped (reduced by ship mass)
    this._menuColor = "orangeColor"; // color of general menu items
    this._itemColor = "yellowColor"; // color of special menu items (eg exit menu items)
    this._disabledColor = "darkGrayColor"; // color of disabled equipment items
    this._lastChoice = ""; // last selection on the config screen
    //this._hsTimer = null;					// timer to monitor items in the hsDeployed array to automatically explode deployed heat sinks
    this._fcbID = 0; // frame callback ID for heat control
    this._heatWarning = null; // timer for informing the player of critical heat levels
    this._warning1 = false;
    this._warning2 = false;
    this._warning3 = false;
    this._warningPoint1 = 0.70;
    this._warningPoint2 = 0.80;
    this._warningPoint3 = 0.90;
    
    //-------------------------------------------------------------------------------------------------------------
    this.activated = function () {
    	var p = player.ship;
    	if (p.equipmentStatus("EQ_HEAT_SINK_CONTROL") === "EQUIPMENT_OK" || p.equipmentStatus("EQ_HEAT_SINK_CONTROL_PASSIVE") === "EQUIPMENT_OK") {
    		// ok we're ready to dump
    		var sc = worldScripts.ShipConfiguration_Core;
    		// how much will we be dumping
    		var dumpAmount = this._amountToDump * (1 - (sc.$getShipMass(p) / 500000));
    		// ensure we will always have something to dump, even if it's only a little bit
    		if (dumpAmount < 0.1) dumpAmount = 0.1;
    		// is this actually worth it?
    		if ((p.temperature - dumpAmount) < (0.234375 + (p.script._busOverload / 100))) {
    			player.consoleMessage("Temperature not at sufficient level to warrant heat sink use.");
    			return;
    		}
    		sc.$playSound("deploy_heat_sink");
    		worldScripts.ShipConfiguration_HeatSink.$deployHeatSink(player.ship);
    		var hs = p.equipmentStatus("EQ_HEAT_SINK", true)["EQUIPMENT_OK"];
    		// smaller ships will dump a larger percentage of heat
    		//p.temperature -= dumpAmount;
    		player.consoleMessage("Heat sink deployed - " + hs + " remaining");
    	} else {
    		player.consoleMessage("Heat sink control unit damaged - unable to deploy heat sink");
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.mode = function () {
    	var p = player.ship;
    	if (p.equipmentStatus("EQ_HEAT_SINK_CONTROL") === "EQUIPMENT_OK" || p.equipmentStatus("EQ_HEAT_SINK_CONTROL_PASSIVE") === "EQUIPMENT_OK") {
    		var hs = worldScripts.ShipConfiguration_HeatSink;
    		if (hs._mode === 0) {
    			hs._mode = 1;
    			player.consoleMessage("Automatic heat sink deployment mode selected");
    			hs._tempCheck = new Timer(hs, hs.$checkShipTemp, 3, 3);
    		} else {
    			hs._mode = 0;
    			player.consoleMessage("Manual heat sink deployment mode selected");
    			if (hs._tempCheck && hs._tempCheck.isRunning) hs._tempCheck.stop();
    		}
    	} else {
    		player.consoleMessage("Heat sink control unit damaged - unable to change mode");
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.startUpComplete = function () {
    	var sc = worldScripts.ShipConfiguration_Core;
    	if (sc._disabled) {
    		delete this.shipWillDockWithStation;
    		delete this.shipDied;
    		delete this.shipLaunchedFromStation;
    		delete this.playerWillSaveGame;
    		delete this.equipmentRemoved;
    		delete this.playerBoughtEquipment;
    		delete this.startUpComplete;
    		return;
    	}
    
    	if (missionVariables.ShipConfig_HeatSinkMode) this._mode = parseInt(missionVariables.ShipConfig_HeatSinkMode);
    	if (missionVariables.ShipConfig_HeatSinkControl) this._controlMode = parseInt(missionVariables.ShipControl_HeatSinkControl);
    
    	this.$checkOutOfSyncMode();
    
    	this.$initInterface(player.ship.dockedStation);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipWillDockWithStation = function (station) {
    	this.$stopTimers();
    	this.$checkOutOfSyncMode();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipDied = function (whom, why) {
    	this.$stopTimers();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipLaunchedFromStation = function (station) {
    	var sc = worldScripts.ShipConfiguration_Core;
    	if (sc._heatControl === true) {
    		// if we're in active mode, start a timer to check the temp now
    		if (this._mode === 1) this._tempCheck = new Timer(this, this.$checkShipTemp, 2, 2);
    		// set up the frame callback for doing the heat transfer
    		var ps = player.ship.script;
    		ps.thirdPartyHeat = 0;
    		ps._warningPoint1 = this._warningPoint1;
    		ps._warningPoint2 = this._warningPoint2;
    		ps._warningPoint3 = this._warningPoint3;
    		ps._warning1 = false;
    		ps._warning2 = false;
    		ps._warning3 = false;
    		if (this._fcbID === 0) {
    			this._fcbID = addFrameCallback(function (delta) {
    				if (delta === 0) return;
    				var p = player.ship;
    				var ps = p.script;
    				if (!p || !ps) return;
    				// temp is impacted by laser temp, use of injectors and use of cloak
    				var scale = ps._heat_sink_factor;
    				//var ship_rate = p.script._heat_rate;
    				// apply the minimum temp based on the bus overload level, equip extensions installed, and other factors
    				if (p.temperature < (0.234375 + (ps._busOverload / 100) + (ps._equipExt / 100) + ps._equipmentClassHeat)) {
    					p.temperature = 0.234375 + (ps._busOverload / 100) + (ps._equipExt / 100) + ps._equipmentClassHeat;
    				}
    				// add temp based on equipment activity, slowing the rate down from 0.5 to 1.0
    				// special case - is system is going nova, don't make it too much harder
    				var exch_rate = (p.temperature > 0.5 ? (1.5 - p.temperature) : 1) * (system.sun && system.sun.hasGoneNova ? 0.5 : 1);
    				p.temperature += (((p.laserHeatLevelAft + p.laserHeatLevelForward + p.laserHeatLevelPort + p.laserHeatLevelStarboard +
    					(p.isCloaked ? 0.8 : 0) +
    					((p.injectorsEngaged || ps._ficcEngaged === true) ? ((p.injectorBurnRate / 0.25)) : 0) +
    					(ps.thirdPartyHeat && ps.thirdPartyHeat > 0 ? ps.thirdPartyHeat : 0) // third party heat properties
    				) * exch_rate) / 3) * (delta / (5 / scale));
    			});
    		}
    		if (this._warnPlayerOfHeat === true) {
    			// set up timer for heat warning sounds/notifications
    			this._heatWarning = new Timer(this, this.$warnPlayerOfHeat, 2, 2);
    		}
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.playerWillSaveGame = function () {
    	missionVariables.ShipConfig_HeatSinkMode = this._mode;
    	missionVariables.ShipConfig_HeatSinkControl = this._controlMode;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.equipmentRemoved = function (equipment) {
    	if (equipment === "EQ_HEAT_SINK" && player.ship.docked) this.$initInterface(player.ship.dockedStation);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.playerBoughtEquipment = function (equipment) {
    	if (equipment === "EQ_HEAT_SINK") this.$initInterface(player.ship.dockedStation);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$stopTimers = function $stopTimers() {
    	if (this._tempCheck && this._tempCheck.isRunning) this._tempCheck.stop();
    	this.$stopFCB();
    	if (this._heatWarning && this._heatWarning.isRunning) this._heatWarning.stop();
    	var ps = player.ship.script;
    	if (ps) {
    		ps._warning1 = false;
    		ps._warning2 = false;
    		ps._warning3 = false;
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$stopFCB = function $stopFCB() {
    	if (this._fcbID != 0) {
    		if (isValidFrameCallback(this._fcbID)) removeFrameCallback(this._fcbID);
    		this._fcbID = 0;
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$warnPlayerOfHeat = function $warnPlayerOfHeat() {
    	var p = player.ship;
    	var ps = p.script;
    	if (!p || !ps) return;
    	if (p.temperature >= ps._warningPoint1 && ps._warning1 === false) {
    		worldScripts.ShipConfiguration_Core.$playSound("booster_warning");
    		player.consoleMessage("Warning: Heat level critical.", 5);
    		ps._warning1 = true;
    		return;
    	}
    	if (p.temperature < ps._warningPoint1 && ps._warning1 === true) ps._warning1 = false;
    
    	
    	if (p.temperature >= ps._warningPoint2 && ps._warning2 === false) {
    		worldScripts.ShipConfiguration_Core.$playSound("booster_warning");
    		player.consoleMessage("Warning: Heat level critical.", 5);
    		ps._warning2 = true;
    		return;
    	}
    	if (p.temperature < ps._warningPoint2 && ps._warning2 === true) ps._warning2 = false;
    
    	// for third warning, play sound repeatedly
    	if (p.temperature >= ps._warningPoint3) {
    		worldScripts.ShipConfiguration_Core.$playSound("booster_warning");
    		if (ps._warning3 === false) {
    			player.consoleMessage("Warning: Heat damage imminent.", 5);
    			ps._warning3 = true;
    		}
    		return;
    	}
    	if (p.temperature < ps._warningPoint3 && ps._warning3 === true) ps._warning3 = false;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$checkShipTemp = function $checkShipTemp() {
    	var p = player.ship;
    	if (p.equipmentStatus("EQ_HEAT_SINK_CONTROL") != "EQUIPMENT_OK" && p.equipmentStatus("EQ_HEAT_SINK_CONTROL_PASSIVE") != "EQUIPMENT_OK") return;
    	if (p.temperature > 0.75) {
    		this.activated();
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$initInterface = function $initInterface(station) {
    	if (player.ship.equipmentStatus("EQ_HEAT_SINK") === "EQUIPMENT_OK") {
    		station.setInterface(this.name, {
    			title: "Heat sink control",
    			category: "Ship Systems",
    			summary: "Provides access to the Heat Sink Control system.",
    			callback: this.$heatSinkControl.bind(this)
    		});
    	} else {
    		station.setInterface(this.name, null);
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$heatSinkControl = function $heatSinkControl() {
    
    	var curChoices = {};
    	var text = "";
    	var def = "";
    
    	var col1 = 10;
    	var damaged = false;
    
    	var sc = worldScripts.ShipConfiguration_Core;
    	var p = player.ship;
    	var hs = sc.$countHeatSinks();
    
    	text = sc.$padTextRight("Number of heat sinks:", col1) + hs + "\n";
    	var dmg = p.equipmentStatus("EQ_HEAT_SINK", true)["EQUIPMENT_DAMAGED"];
    	if (dmg > 0) {
    		text += sc.$padTextRight("Damged heat sinks:", col1) + dmg + "\n";
    	}
    	text += "\n";
    
    	text += sc.$padTextRight("Heat sink mode:", col1) + (this._mode === 0 ? "Manual" : "Automatic") + "\n";
    	text += sc.$padTextRight(" ", col1) + (this._mode === 0 ? "- Heat sinks must be deployed manually.\n\n" : "- Heat sinks will deploy automatically when\n");
    	if (this._mode === 1) text += sc.$padTextRight(" ", col1) + "  the cabin temperature is critical.\n\n";
    
    	text += sc.$padTextRight("Control mode:", col1) + (this._controlMode === 0 ? "Active" : "Passive") + "\n";
    	text += sc.$padTextRight(" ", col1) + (this._controlMode === 0 ? "- primable Heat Sink Control will be visible in flight." : "- no primable equipment will be visible in flight.") + "\n";
    	if (player.ship.equipmentStatus("EQ_HEAT_SINK_CONTROL") === "EQUIPMENT_DAMAGED" || player.ship.equipmentStatus("EQ_HEAT_SINK_CONTROL_PASSIVE") === "EQUIPMENT_DAMAGED") {
    		text += "\nWARNING: Heat Sink Control mechanism is damaged. No changes can be made.\n";
    		damaged = true;
    	}
    
    	if (this._controlMode === 0 && damaged === false) {
    		curChoices["01_CHANGE_MODE"] = {
    			text: "Change heat sink mode to " + (this._mode === 0 ? "Automatic" : "Manual"),
    			color: this._menuColor
    		};
    	} else {
    		curChoices["01_CHANGE_MODE"] = {
    			text: "Change heat sink mode to " + (this._mode === 0 ? "Automatic" : "Manual"),
    			color: this._disabledColor,
    			unselectable: true
    		};
    	}
    	if (damaged === false) {
    		curChoices["02_CHANGE_CONTROL"] = {
    			text: "Change control mode to " + (this._controlMode === 0 ? "Passive" : "Active"),
    			color: this._menuColor
    		};
    	} else {
    		curChoices["02_CHANGE_CONTROL"] = {
    			text: "Change control mode to " + (this._controlMode === 0 ? "Passive" : "Active"),
    			color: this._disabledColor,
    			unselectable: true
    		};
    	}
    	curChoices["99_EXIT"] = {
    		text: "[sc-return]",
    		color: this._itemColor
    	};
    
    	def = "99_EXIT";
    	if (this._lastChoice != "") def = this._lastChoice;
    
    	var opts = {
    		screenID: "oolite-shipconfig-heatsinks-map",
    		title: "Heat Sink Control",
    		allowInterrupt: true,
    		overlay: {
    			name: "shipconfig_heatsink.png",
    			height: 546
    		},
    		exitScreen: "GUI_SCREEN_INTERFACES",
    		choices: curChoices,
    		initialChoicesKey: def,
    		message: text
    	};
    
    	mission.runScreen(opts, this.$heatSinkScreenHandler, this);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$heatSinkScreenHandler = function $heatSinkScreenHandler(choice) {
    
    	if (!choice) return;
    
    	this._lastChoice = choice;
    
    	if (choice === "01_CHANGE_MODE") {
    		if (this._mode === 0) {
    			this._mode = 1;
    		} else {
    			this._mode = 0;
    		}
    	}
    	if (choice === "02_CHANGE_CONTROL") {
    		if (this._controlMode === 0) {
    			if (player.ship.equipmentStatus("EQ_HEAT_SINK_CONTROL") === "EQUIPMENT_OK") {
    				player.ship.removeEquipment("EQ_HEAT_SINK_CONTROL");
    				player.ship.awardEquipment("EQ_HEAT_SINK_CONTROL_PASSIVE");
    				this._controlMode = 1;
    				this._mode = 1;
    			}
    		} else {
    			if (player.ship.equipmentStatus("EQ_HEAT_SINK_CONTROL_PASSIVE") === "EQUIPMENT_OK") {
    				this._controlMode = 0;
    				player.ship.removeEquipment("EQ_HEAT_SINK_CONTROL_PASSIVE");
    				player.ship.awardEquipment("EQ_HEAT_SINK_CONTROL");
    			}
    		}
    	}
    
    	if (choice != "99_EXIT") this.$heatSinkControl();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // deploys a HS object from a ship
    this.$deployHeatSink = function $deployHeatSink(ship) {
    	var sc = worldScripts.ShipConfiguration_Core;
    	var dumpAmount = this._amountToDump * (1 - (sc.$getShipMass(ship) / 500000));
    	if (dumpAmount < 0.1) dumpAmount = 0.1;
    	// create a heat sink object that appears briefly on the scanner
    	// not using .spawn as there is a chance that won't create an object
    	// system.addShips("heatsink", 1, ship.position.add(ship.vectorUp.multiply((ship.boundingBox.y + 5) * -1)), 0)[0]; // p.spawn("heatsink", 1); 
    	// new method
    	ship.ejectSpecificItem("heatsink");
    	// smaller ships will dump a larger percentage of heat
    	ship.removeEquipment("EQ_HEAT_SINK");
    	ship.temperature -= dumpAmount;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // check for out of sync equipment control mode
    this.$checkOutOfSyncMode = function $checkOutOfSyncMode() {
    	var p = player.ship;
    	if (this._controlMode == 0) {
    		if (p.equipmentStatus("EQ_HEAT_SINK_CONTROL_PASSIVE") != "EQUIPMENT_UNAVAILABLE") this._controlMode = 1;
    	} else {
    		if (p.equipmentStatus("EQ_HEAT_SINK_CONTROL") != "EQUIPMENT_UNAVAILABLE") this._controlMode = 0;
    	}
    }
    Scripts/shipconfig_npc.js
    "use strict";
    this.name = "ShipConfiguration_NPCShips";
    this.author = "phkb";
    this.copyright = "2016 phkb";
    this.description = "Routines for applying ShipConfiguration details to NPC ships.";
    this.licence = "CC BY-NC-SA 3.0";
    
    this._useExclusions = true; // flag to control which method will be used to apply config: includeRoles or excludeRoles
    //this._disable_NShields_compatibility = true;
    
    // includeRoles only used when "this._useExclusions === false". All ships with these primaryRoles will get config applied. No other ships will.
    this._includeRoles = ["trader", "trader-courier", "trader-smuggler", "shuttle", "scavenger", "miner",
    	"pirate", "pirate-light-fighter", "pirate-medium-fighter", "pirate-heavy-fighter", "pirate-interceptor",
    	"pirate-light-freighter", "pirate-medium-freighter", "pirate-heavy-freighter",
    	"pirate-light-fighter", "pirate-medium-fighter", "pirate-heavy-fighter",
    	"hunter", "hunter-medium", "hunter-heavy", "assassin-light", "assassin-medium", "assassin-heavy",
    	"escort", "escort-light", "escort-medium", "escort-heavy", "wingman", "police", "police-station-patrol", "police-witchpoint-patrol"
    ];
    
    // excludeRoles only used when "this._useExclusions === true". Ships with these primaryRoles won't get configuration. All other ships will.
    // however, only those ships with data defined in core._NPCConfig will have a specific configuration. If no config is found, ships will be given default equipment.
    this._excludeRoles = ["RSsatellite"];
    
    /* note the following roles/ship types are already excluded:
    	Thargoids
    	Stations
    	Cargo
    	Missiles/Mines/Weapons
    	Subentities
    	Visual Effects
    	Ships with no pilot
    	Rocks
    
    	To exclude a particular ship, include the following in the "script_info" section of the shipdata.plist entry for the ship:
    		"no_sc_config" = "yes";
    */
    this._trueValues = ["yes", "1", "true", 1, true];
    
    //-------------------------------------------------------------------------------------------------------------
    this.startUpComplete = function () {
    	if (worldScripts.ShipConfiguration_Core._disabled) {
    		delete this.shipSpawned;
    		delete this.startUpComplete;
    		return;
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipSpawned = function (ship) {
    	if (ship.isStation === true) return;
    	if (ship.isThargoid === true) return;
    	if (ship.isPiloted === false) return;
    	if (ship.isCargo === true) return;
    	if (ship.isRock === true) return;
    	if (ship.isWeapon === true) return;
    	if (ship.isMissile === true) return;
    	if (ship.isMine === true) return;
    	if (ship.isSubEntity === true) return;
    	if (ship.isBeacon === true) return;
    	if (ship.isVisualEffect === true) return;
    	if (ship.scanClass == "CLASS_NO_DRAW") return;
    	if (ship.scanClass == "CLASS_ROCK") return;
    	if ((this._useExclusions === false && this.$indexInList(ship.primaryRole, this._includeRole) >= 0) ||
    		(this._useExclusions === true && this.$indexInList(ship.primaryRole, this._excludeRoles) === -1)) {
    		if (!ship.scriptInfo.no_sc_config || this.$indexInList(ship.scriptInfo.no_sc_config, this._trueValues) === -1) {
    			var conf = worldScripts.ShipConfiguration_Core;
    			if (conf._applyToNPC === true) {
    				// add base equipment
    				conf.$installBaseEquipment(ship);
    				// adjust performance
    				conf.$updateShipSpecs(ship);
    
    				ship.script._debugShipConfig = false;
    
    				// make sure existing scripts are kept in monkey patch locations
    				// check if NShields are installed
    				if (worldScripts.NShields && worldScripts.NShields.$shipHasShields(ship)) {
    					// add our shipTaking damage script to NShield's array
    					if (!ship.script.NShields_damageHandlers) ship.script.NShields_damageHandlers = []; //N-Shields alteration: set up handler array if it doesn't yet
    					ship.script.NShields_damageHandlers.push(this.$npc_shipTakingDamage); //and push the shipconfig handler onto it
    				} else {
    					// otherwise do a standard monkey patch
    					if (ship.script.shipTakingDamage) ship.script.$sc_hold_shipTakingDamage = ship.script.shipTakingDamage;
    					// attach our new scripts
    					ship.script.shipTakingDamage = this.$npc_shipTakingDamage;
    				}
    
    				// attach our new scripts
    				if (ship.script.shipRemoved) ship.script.$sc_hold_shipRemoved = ship.script.shipRemoved;
    				ship.script.shipRemoved = this.$npc_shipRemoved;
    				if (ship.script.shipDied) ship.script.$sc_hold_shipDied = ship.script.shipDied;
    				ship.script.shipDied = this.$npc_shipDied;
    				if (ship.script.shilWillEnterWormhole) ship.script.$sc_hold_shipWillEnterWormhole = ship.script.shipWillEnterWormhole;
    				ship.script.shipWillEnterWormhole = this.$npc_shipWillEnterWormhole;
    
    				ship.script.$sc_stopTimer = this.$sc_stopTimer;
    				if (conf._heatControl === true) {
    					ship.script.$npc_checkTemp = this.$npc_checkTemp;
    					ship.script.$initialise = this.$initialiseTimer;
    				}
    				ship.script.$damageDirection = worldScripts.ShipConfiguration_Armour.$damageDirection;
    
    				ship.script._frontArmourType = conf.$equipmentItemInUse("frontarmour", ship);
    				if (ship.script._frontArmourType != "") {
    					var info = EquipmentInfo.infoForKey(ship.script._frontArmourType);
    					ship.script._armourFront = 100;
    					ship.script._frontDamagePoint = info.scriptInfo.damage_point;
    					ship.script._frontArmourStrength = info.scriptInfo.armour_strength;
    				}
    				ship.script._aftArmourType = conf.$equipmentItemInUse("aftarmour", ship);
    				if (ship.script._aftArmourType != "") {
    					var info = EquipmentInfo.infoForKey(ship.script._aftArmourType);
    					ship.script._armourAft = 100;
    					ship.script._aftDamagePoint = info.scriptInfo.damage_point;
    					ship.script._aftArmourStrength = info.scriptInfo.armour_strength;
    				}
    
    				// add special routines to ship so they can be executed by NPC equipment damage
    				if (worldScripts.NPC_Equipment_Damage) {
    					ship.script.$equipmentDamaged_Event = conf.$equipmentDamaged_Event;
    					ship.script.$awaitEquipmentDamaged = conf.$awaitEquipmentDamaged;
    					ship.script.$checkRemainingEnergy = conf.$checkRemainingEnergy;
    					ship.script._damagedItems = []; // list of damaged items that required config adjustment
    					ship.script._checkForDamage = null; // timer used to call "$awaitEquipmentDamaged" to check the "damagedItems" array
    				}
    
    				ship.script.$initialise();
    			}
    		}
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // sets up the timer to apply heat transfer to NPC's
    this.$initialiseTimer = function $initialiseTimer() {
    	// set up the timer with a random interval between 0.5 and 1.5 so we don't get lots of ships updating at the same time
    	var freq = parseInt((Math.random() + 0.5) * 100) / 100;
    	this.ship.script.$sc_stopTimer();
    	this.ship.script._tempCheck = new Timer(this, this.ship.script.$npc_checkTemp, 2 + freq, freq);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // stops all the timers
    this.$sc_stopTimer = function $sc_stopTimer() {
    	if (this.ship.script._tempCheck && this.ship.script._tempCheck.isRunning) {
    		this.ship.script._tempCheck.stop();
    	}
    	delete this.ship.script._tempCheck;
    
    	if (this.ship.script._energyTimer && this.ship.script._energyTimer.isRunning) {
    		this.ship.script._energyTimer.stop();
    	}
    	delete this.ship.script._energyTimer;
    
    	if (this.ship.script._checkForDamage && this.ship.script._checkForDamage.isRunning) {
    		this.ship.script._checkForDamage.stop();
    	}
    	delete this.ship.script._checkForDamage;
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // routine to apply temp transfer
    this.$npc_checkTemp = function $npc_checkTemp() {
    	if (this.ship.isValid === false) {
    		this.ship.script.$sc_stopTimer();
    		return;
    	}
    
    	var injectorsEngaged = false;
    	if (this.ship.maxSpeed > 0 && this.ship.speed > this.ship.maxSpeed) injectorsEngaged = true;
    
    	var curr = this.ship.temperature;
    
    	// adjust the ship's temp, based on what it's doing at the moment
    	// work out the factor, based on the tempcheck interval and heatsink factor
    	// that means, if we ever adjust the timer interval, we won't have to also change the factor calc
    	// we're also not making the factor as strong as for the player, as the player has real shields and NPC's don't
    	var factor = (this.ship.script._tempCheck.interval / (5 / parseFloat(this.ship.script._heat_sink_factor))) * 0.5;
    	var exch_rate = (this.ship.temperature > 0.5 ? (1.5 - this.ship.temperature) : 1);
    	this.ship.temperature += (((this.ship.laserHeatLevelAft + this.ship.laserHeatLevelForward + this.ship.laserHeatLevelPort + this.ship.laserHeatLevelStarboard +
    		(this.ship.isCloaked ? 0.8 : 0) +
    		(injectorsEngaged ? (this.ship.injectorBurnRate / 0.25) : 0)) * exch_rate) / 3) * factor;
    
    	//if (this.ship.script._debugShipConfig && curr != this.ship.temperature) {
    	//	log(this.name, "Use Orig temp " + curr + ", New temp " + this.ship.temperature + " applied to " + this.ship);
    	//}
    	if (this.ship.temperature > 0.75 && this.ship.equipmentStatus("EQ_HEAT_SINK") !== "EQUIPMENT_OK") {
    		// better turn off that cloak, son
    		if (this.ship.isCloaked) this.ship.isCloaked = false;
    	}
    	// NPC's have to operate with auto-deployment of heat-sinks
    	if (this.ship.temperature > 0.75 && this.ship.equipmentStatus("EQ_HEAT_SINK") === "EQUIPMENT_OK") {
    		worldScripts.ShipConfiguration_HeatSink.$deployHeatSink(this.ship);
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$npc_shipTakingDamage = function $npc_shipTakingDamage(amount, whom, type) {
    	// run monkey patch, if present
    	if (this.ship.script.$sc_hold_shipTakingDamage) this.ship.script.$sc_hold_shipTakingDamage(amount, whom, type);
    
    	var thisship = this.ship;
    	var scr = thisship.script;
    
    	var fsh = 0;
    	var ash = 0;
    	// check for NPC shields
    	if (worldScripts["NPC-shields"]) {
    		fsh += scr.shieldStrength;
    		ash += scr.shieldStrength;
    	}
    	// check for customshields
    	if (worldScripts.customshields) {
    		fsh += scr.customshieldsforwardshieldlevel;
    		ash += scr.customshieldsaftshieldlevel;
    	}
    
    	if (whom) scr._lastDamageDirection = scr.$damageDirection(thisship, whom);
    
    	// pass energy damage onto the unshielded ship as a heat increase
    	var sc = worldScripts.ShipConfiguration_Core;
    	if (type === "energy damage" && sc._heatControl === true && amount > 0 && ((scr._lastDamageDirection === true && fsh === 0) || (scr._lastDamageDirection === false && ash === 0))) {
    		var curr = thisship.temperature;
    		// npc's already dont have shields, so we're decreasing the ratio of energy that is passed through, as compared with the player.
    		var amt = amount / ((thisship.maxEnergy * thisship.heatInsulation) * 2);
    		thisship.temperature += Math.pow((1.1 - thisship.temperature), 4) * amt;
    
    		//if (scr._debugShipConfig && curr != thisship.temperature) {
    		//	log(this.name, "Hit Orig temp " + curr + ", New temp " + thisship.temperature + " applied to " + thisship);
    		//}
    	}
    
    	// don't go any further if we don't have ShipConfig armour installed
    	if (scr._frontArmourType === "" && scr._aftArmourType === "") return;
    
    	if (whom) {
    		// record where the last damage came from. True = front, false = aft
    		if (scr._lastDamageDirection === true) {
    			scr._lastDamageDirectionArmour = scr._armourFront;
    			//if (scr._debugShipConfig && fsh > 0) log(this.name, amount + " hit (absorbed by front shield " + fsh + ") from " + (this._lastDamageDirection === true ? "front" : "aft") + ", ship = " + thisship);
    			if (fsh > 0) return; // if we have shields and they're still in place, we don't need to do anything
    		} else {
    			scr._lastDamageDirectionArmour = scr._armourAft;
    			//if (scr._debugShipConfig && ash > 0) log(this.name, amount + " hit (absorbed by front shield " + ash + ") from " + (this._lastDamageDirection === true ? "front" : "aft") + ", ship = " + thisship);
    			if (ash > 0) return; // if we have shields and they're still in place, we don't need to do anything
    		}
    		//if (scr._debugShipConfig) log(this.name, amount + " hit from " + (this._lastDamageDirection === true ? "front" : "aft") + ", ship = " + thisship);
    
    		if (amount && amount > 0 && type === "energy damage") { // if we have energy damage
    			var shield = 0;
    			if (scr._lastDamageDirection === true) {
    				shield = scr._frontArmourStrength * (scr._armourFront / 100);
    			} else {
    				shield = scr._aftArmourStrength * (scr._armourAft / 100);
    			}
    
    			//if (scr._debugShipConfig) log(this.name, "amount = " + amount + ", front = " + scr._armourFront + ", aft = " + scr._armourAft + ", shield = " + shield + ", energy = " + thisship.energy + ", maxEnergy = " + thisship.maxEnergy + ", ship = " + thisship);
    
    			if (amount < shield && shield > 0) {
    				if ((thisship.energy + amount) < thisship.maxEnergy) {
    					thisship.energy += amount;
    				} else {
    					thisship.energy = thisship.maxEnergy;
    				}
    
    				if (scr._lastDamageDirection === true) {
    					scr._armourFront -= Math.floor(100 * (amount / scr._frontArmourStrength));
    					//if (scr._armourFront < 100) {
    					//	if (scr._debugShipConfig) log(this.name, "Forward armour down to " + scr._armourFront + "%, ship = " + thisship);
    					//}
    				} else {
    					scr._armourAft -= Math.floor(100 * (amount / scr._aftArmourStrength));
    					//if (scr._armourAft < 100) {
    					//	if (scr._debugShipConfig) log(this.name, "Aft armour down to " + scr._armourAft + "%, ship = " + thisship);
    					//}
    				}
    			} else {
    				if (shield > 0) thisship.energy += shield;
    				if (scr._lastDamageDirection === true) {
    					scr._armourFront = 0;
    				} else {
    					scr._armourAft = 0;
    				}
    			}
    		}
    		// check to see if the armour has been completely destroyed
    		if (amount && amount > 0 && thisship.equipmentStatus(scr._frontArmourType) === "EQUIPMENT_OK" && scr._armourFront <= 0) { // if the armour is destroyed by damage
    			thisship.removeEquipment(scr._frontArmourType);
    			scr._frontArmourType = "";
    		}
    		if (amount && amount > 0 && thisship.equipmentStatus(scr._aftArmourType) === "EQUIPMENT_OK" && scr._armourAft <= 0) { // if the armour is destroyed by damage
    			thisship.removeEquipment(scr._aftArmourType);
    			scr._aftArmourType = "";
    		}
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // may not be neccesary if the ent destroyed function runs in all cases.
    this.$npc_shipRemoved = function $npc_shipRemoved(suppressDeathEvent) {
    	// run monkey patch, if present
    	if (this.ship.script.$sc_hold_shipRemoved) this.ship.script.$sc_hold_shipRemoved(suppressDeathEvent);
    	//if (this.ship.script._debugShipConfig) log(this.name, "*** shipRemoved for " + this.ship);
    	this.ship.script.$sc_stopTimer();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$npc_shipDied = function $npc_shipDied(whom, why) {
    	if (this.ship.script.$sc_hold_shipDied) this.ship.script.$sc_hold_shipDied(whom, why);
    	this.ship.script.$sc_stopTimer();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$npc_shipWillEnterWormhole = function $npc_shipWillEnterWormhole() {
    	if (this.ship.script.$sc_hold_shipWillEnterWormhole) this.ship.script.$sc_hold_shipWillEnterWormhole();
    	this.ship.script.$sc_stopTimer();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    // by cag for speed improvements instead of using "indexOf"
    this.$indexInList = function $indexInList(item, list) { // for arrays only
    	var k = list.length;
    	while (k--) {
    		if (list[k] === item) return k;
    	}
    	return -1;
    }
    Scripts/shipconfig_scfix.js
    "use strict";
    this.name = "ShipConfiguration_ShieldCyclerFix";
    this.author = "phkb";
    this.copyright = "2016 phkb";
    this.licence = "CC BY-NC-SA 3.0";
    
    //-------------------------------------------------------------------------------------------------------------
    this.startUpComplete = function () {
    	var sc = worldScripts["Shield Cycler"];
    	if (sc && (sc.version == "1.12" || sc.version == "1.12.1")) {
    		// there's a really small bug in Shield Cycler 1.12 and 1.12.1
    		// patch these versions of shield cycler to fix it
    		sc._sc_stop = this.$scFix_sc_stop;
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$scFix_sc_stop = function $scFix_sc_stop(device) {
    	/*	device is a string to indicate which devices handled by SC oxp need to be stopped
    		currently has 2 possible values : 
    		"ALL" : disable all devices
    		"SC" : disables just the shieldcycler
    		In future versions there will be more options
    
    		returns
    		-3 if SC was disabled
    		-2 if device was stopped already
    		-1 device string invalid
    		0 if stopping was succesfull
    		NOTE : no messages to player or logfile, imo this is the responsibility of the calling oxp
    		NOTE : calling worldScripts["Shield Cycler"]._sc_stop("SC") DOES NOT disable the entire oxp.
    	*/
    	var success = -3;
    	if (this._sc_error == 0) {
    		switch (device) {
    			case "ALL":
    				if (this._sc_settings.general.disabled) {
    					success = -2;
    				} else {
    					this._sc_settings.general.disabled = true;
    					this._sc_update_oxpconfig_vars();
    					success = 0;
    				};
    				break;
    			case "SC":
    				if (this._sc_settings.general.sc_disabled) {
    					success = -2;
    				} else {
    					this._sc_settings.general.sc_disabled = true;
    					this._sc_update_oxpconfig_vars;
    					success = 0;
    				};
    				break;
    			default:
    				success = -1; // bug was here. this originally read "succes = -1;"
    				break;
    		};
    	};
    	return success;
    };
    Scripts/shipconfig_sellnegotiate.js
    "use strict";
    this.name = "ShipConfiguration_SellNegotiate";
    this.author = "phkb";
    this.copyright = "2016 phkb";
    this.description = "Handles the process of selling the rare equipment items (eg cloaking device)";
    this.licence = "CC BY-NC-SA 3.0";
    
    this._value = 0;
    this._offer = 0;
    this._currentMessage = "";
    this._extra = "";
    this._acceptValues = ["y", "yes", "accept", "sell"];
    this._returnValues = ["n", "no", "return", "no sale", "go back", "back", "cancel", "cancel sale"];
    this._equipmentKey = "";
    this._tries = {};
    
    //-------------------------------------------------------------------------------------------------------------
    this.startUpComplete = function () {
    	if (worldScripts.ShipConfiguration_Core._disabled) {
    		delete this.playerWillSaveGame;
    		delete this.shipWillEnterWitchspace;
    		delete this.startUpComplete;
    		return;
    	}
    	if (missionVariables.ShipConfig_SellNegotiateTries) {
    		// load in any try information
    		this._tries = JSON.parse(missionVariables.ShipConfig_SellNegotiateTries);
    		delete missionVariables.ShipConfig_SellNegotiateTries;
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.playerWillSaveGame = function () {
    	// save the tries dictionary so the player can't get save, reload and try again
    	missionVariables.ShipConfig_SellNegotiateTries = JSON.stringify(this._tries);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipWillEnterWitchspace = function (cause, destination) {
    	// reset the tries dictionary
    	this._tries = {};
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$displayInitialScreen = function $displayInitialScreen(equipmentKey, baseCost) {
    	// work out the maximum value of this item, based on economy and techlevel factors
    	this._value = (baseCost +
    			((7 - system.economy) / 7) * (baseCost * 0.4) // economy-based factor - higher economy means better price
    			+
    			(system.techLevel / 14) * (baseCost * 0.8)) // techlevel based factor - higher techlevel means better price
    		*
    		((system.scrambledPseudoRandomNumber(baseCost) * 0.5) + 0.5); // multiply by a random value between 0.5 and 1, so occasionally item will be offered at less than base cost
    
    	this._offer = baseCost * (system.scrambledPseudoRandomNumber(baseCost) * 0.8);
    	if (this._offer < 100 && this._offer > 10) this._offer = parseInt(this._offer / 10) * 10;
    	if (this._offer < 1000 && this._offer > 99) this._offer = parseInt(this._offer / 100) * 100;
    	if (this._offer > 1000) this._offer = parseInt(this._offer / 1000) * 1000;
    
    	// get the initial message to display to the player
    	this._currentMessage = expandDescription("[sc_sellnegotiate_initial]", {
    		guess: formatCredits(this._offer, false, true)
    	});
    	this._extra = "type 'Y' to accept the offered amount, ";
    
    	// special notice for the cloaking device - you can't buy it again later if you sell it now
    	if (equipmentKey === "EQ_CLOAKING_DEVICE") this._currentMessage += "\n\n(Note: If you sell the cloaking device you will not be able to purchase it again.)";
    	// store the equipment key for use later
    	this._equipmentKey = equipmentKey;
    
    	// has the player already tried to negotiate a price
    	var tries = 0;
    	if (this._tries[this._equipmentKey + "_" + player.ship.dockedStation.name]) tries = this._tries[this._equipmentKey + "_" + player.ship.dockedStation.name];
    	if (tries >= 3) {
    		// if the player has already tried too many times, go straight to the no deal screen
    		this.$noDeal();
    	} else {
    		this.$showScreen();
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$showScreen = function $showScreen() {
    	var opts = {
    		screenID: "oolite-shipconfig-sellnegotiate-map",
    		title: "Sell Equipment",
    		allowInterrupt: false,
    		overlay: {
    			name: "shipconfig_chat.png",
    			height: 546
    		},
    		exitScreen: "GUI_SCREEN_INTERFACES",
    		message: this._currentMessage + expandDescription("[sc_sellnegotiate_additional]", {
    			extra_info: (this._offer != 0 ? this._extra : "")
    		}),
    		textEntry: true
    	};
    	mission.runScreen(opts, this.$getEstimate, this);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$getEstimate = function $getEstimate(param) {
    	if (param == null) {
    		this.$goBack();
    		return;
    	}
    	if (parseInt(param) >= 1 && parseInt(param) <= 9999999) {
    		this._offer = 0;
    		// is the estimate inside or outside the calculated value
    		if (parseInt(param) > (this._value * 1.1)) {
    			// check to see how many times we've tried to negotiate a price on this station for this piece of equipment.
    			var tries = 0;
    			if (this._tries[this._equipmentKey + "_" + player.ship.dockedStation.name]) tries = this._tries[this._equipmentKey + "_" + player.ship.dockedStation.name];
    			tries += 1;
    			this._tries[this._equipmentKey + "_" + player.ship.dockedStation.name] = tries;
    			// if we're tried too many times, give the "No Deal" message
    			if (tries >= 3) {
    				this.$noDeal();
    			} else {
    				// otherwise, tell the player their estimate was unreasonable
    				this._currentMessage = expandDescription("[sc_sellnegotiate_unreasonable]");
    				this.$showScreen();
    			}
    		} else {
    			// OK, it's a deal.
    			player.credits += parseInt(param);
    			player.ship.removeEquipment(this._equipmentKey);
    			worldScripts.ShipConfiguration_Core.$playSound("sell");
    
    			mission.runScreen({
    				screenID: "oolite-shipconfig-sellnegotiate-map",
    				title: "Sell Equipment",
    				overlay: {
    					name: "shipconfig_chat.png",
    					height: 546
    				},
    				message: expandDescription("[sc_sellnegotiate_complete]"),
    				allowInterrupt: false,
    			}, this.$saleComplete, this);
    		}
    	} else {
    		// check to see if the entered text was one of the "return" values
    		if (param === "" || this._returnValues.indexOf(param.toLowerCase()) >= 0) {
    			this.$goBack();
    			return;
    		}
    		if (this._acceptValues.indexOf(param.toLowerCase()) >= 0 && this._offer != 0) {
    			// OK, it's a deal.
    			player.credits += this._offer;
    			player.ship.removeEquipment(this._equipmentKey);
    			worldScripts.ShipConfiguration_Core.$playSound("sell");
    
    			mission.runScreen({
    				screenID: "oolite-shipconfig-sellnegotiate-map",
    				title: "Sell Equipment",
    				overlay: {
    					name: "shipconfig_chat.png",
    					height: 546
    				},
    				message: expandDescription("[sc_sellnegotiate_complete]"),
    				allowInterrupt: false,
    			}, this.$saleComplete, this);
    
    			return;
    		}
    		// otherwise show the "I don't understand" message
    		this._offer = 0;
    		this._currentMessage = expandDescription("[sc_sellnegotiate_syntax]");
    		this.$showScreen();
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$saleComplete = function $saleComplete(choice) {
    	this.$goBack();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$goBack = function $goBack() {
    	worldScripts.ShipConfiguration_Core.$sellEquipment();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$noDeal = function $noDeal() {
    	mission.runScreen({
    		screenID: "oolite-shipconfig-sellnegotiate-map",
    		title: "Sell Equipment",
    		overlay: {
    			name: "shipconfig_chat.png",
    			height: 546
    		},
    		message: expandDescription("[sc_sellnegotiate_nodeal]"),
    		allowInterrupt: false,
    	}, this.$saleComplete, this);
    }
    Scripts/shipconfig_witchdriveheat.js
    "use strict";
    this.name = "ShipConfiguration_WitchdriveHeat";
    this.author = "phkb";
    this.copyright = "2016 phkb";
    this.description = "Process of adding cabin heat when building up to a witchspace jump";
    this.licence = "CC BY-NC-SA 3.0";
    
    this._disabled = false; // set to true to disable witchdrive heat buildup
    this._heatDelta = 0.0; // amount of heat to add - set when turning on heat
    this._heatMonitor = null;
    this._misJumpSet = false;
    
    //-------------------------------------------------------------------------------------------------------------
    this.startUpComplete = function () {
    	if (this._disabled === true) {
    		delete this.playerStartedJumpCountdown;
    		delete this.playerCancelledJumpCountdown;
    		delete this.playerJumpFailed;
    		delete this.playerStartedAutoPilot;
    		delete this.shipWillExitWitchspace;
    		delete this.startUpComplete;
    		return;
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.playerStartedJumpCountdown = function (type, seconds) {
    	this.$turnOnHeat();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.playerCancelledJumpCountdown = function () {
    	this.$turnOffHeat();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.playerStartedAutoPilot = function() {
    	this.$turnOffHeat();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.playerJumpFailed = function (reason) {
    	this.$turnOffHeat();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipWillExitWitchspace = function () {
    	this.$turnOffHeat();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.shipDied = function (whom, why) {
    	if (this._heatMonitor && this._heatMonitor.isRunning) this._heatMonitor.stop();
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$turnOffHeat = function $turnOffHeat() {
    	var ps = player.ship.script;
    	ps.thirdPartyHeat -= this._heatDelta;
    	this._heatDelta = 0;
    	if (ps.thirdPartyHeat < 0) ps.thirdPartyHeat = 0;
    	if (this._heatMonitor && this._heatMonitor.isRunning === true) this._heatMonitor.stop();
    	if (this._misJumpSet) {
    		player.ship.scriptedMisjump = false;
    		this._misJumpSet = false;
    	}
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$turnOnHeat = function $turnOnHeat() {
    	if (system.sun && system.sun.hasGonaNova) {
    		this._heatDelta = 0.2;
    	} else {
    		switch (player.ship.hyperspaceSpinType) {
    			case 30:
    				this._heatDelta = 0.87;
    				break;
    			case 10:
    				this._heatDelta = 0.91;
    				break;
    			case 5:
    				this._heatDelta = 0.92;
    				break;
    			default:
    				this._heatDelta = 0.9;
    				break;
    		}
    	}
    	player.ship.script.thirdPartyHeat += this._heatDelta;
    	if (this._heatMonitor && this._heatMonitor.isRunning === true) this._heatMonitor.stop();
    	this._heatMonitor = new Timer(this, this.$checkHeat.bind(this), 1, 1);
    }
    
    //-------------------------------------------------------------------------------------------------------------
    this.$checkHeat = function $checkHeat() {
    	var p = player.ship;
    	var ps = p.script;
    	if (system.sun && system.sun.hasGoneNova && this._heatDelta != 0.2) {
    		ps.thirdPartyHeat -= this._heatDelta;
    		if (ps.thirdPartyHeat < 0) ps.thirdPartyHeat = 0;
    		this._heatDelta = 0.2;
    		ps.thirdPartyHeat += this._heatDelta;
    	}
    	var heat = p.temperature;
    	if (heat > 0.65) {
    		// increase the chance of a misjump the higher the temp
    		if (Math.random() < (0.35 - (1 - heat)) && p.scriptedMisjump === false) {
    			p.scriptedMisjump = true;
    			this._misJumpSet = true;
    		}
    	}
    }