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

Expansion Laser Mount Switching System

Content

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description Allows multiple lasers on a single laser mount that can be switched inflight. Allows multiple lasers on a single laser mount that can be switched inflight.
Identifier oolite.oxp.phkb.LMSS oolite.oxp.phkb.LMSS
Title Laser Mount Switching System Laser Mount Switching System
Category Equipment Equipment
Author phkb phkb
Version 2.6 2.6
Tags Equipment, Weapons Equipment, Weapons
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
Conflict Expansions
Information URL https://wiki.alioth.net/index.php/Laser_Mount_Switching_System_OXP n/a
Download URL https://wiki.alioth.net/img_auth.php/0/02/LaserMountSwitchingSystem_2.6.oxz n/a
License CC-BY-NC-SA 4.0 CC-BY-NC-SA 4.0
File Size n/a
Upload date 1697428424

Documentation

Also read http://wiki.alioth.net/index.php/Laser%20Mount%20Switching%20System

readme.txt

Laser Mount Switching System (LMSS)
By Nick Rogers

Overview
========
The Laser Mount Switching System (LMSS) provides a way for pilots to have two lasers installed at each laser mount, and easily switch between them. The goal of this system is to give pilots a way of reconfiguring their ship inflight for different roles. For example, some pilots prefer to use a military laser and "snipe" their enemies from a distance. However, not every fight can be done at a distance, and there will inevitably be situations where pilots need to engage in a dogfight at close quarters. Using the LMSS, pilots can switch between their military laser and a beam laser that is more suited for dogfighting. Another example is where a ship has been set up for mining. In this instance the pilot may prefer to have their mining laser installed in the front mount. However, doing so makes it extremely awkward for any sort of battle situation. Using the LMSS, the pilot can easily switch between their mining laser and another laser (like a pulse or beam laser), so they can switch from "mining mode" to "fighting mode".

Installation
============
There are two components to the LMSS system: the assembly, plus an additional laser. The assemblies can be purchased at any system with a techlevel of 8. If the pilot wants switchable lasers in all four laser mounts, then four LMSS systems must be purchased. After the assembly is installed on a laser mount, the pilot can then choose what additional laser they want to install. First, they must switch the current laser to the secondary position via the "LMSS dockside services" F4 interface screen. Once the primary laser is moved into the secondary position, additional lasers can be purchased in the primary position in the normal way.

An additional piece of equipment, the LMSS Actuator Upgrade, can be purchased at techlevel 13 systems. This upgrade speeds up the switching process, almost halving the time it takes to switch between lasers.

The LMSS can be used with all lasers, including all the built it ones (pulse, beam, mining and military lasers), plus any lasers provided by OXP's.

Secondary lasers can't be viewed on the F5 ship equipment list. To see all secondary laser installations, go to the F5 F5 Manifest screen, where the secondary lasers will be listed under the heading "LMSS Secondary Laser Installations".

Flight Operation
================
Once the assembly and secondary lasers are installed, the process to switch lasers is as follows: 
1. Select the view where the assembly is installed (front, aft, port, or starboard).
2. Select the primable equipment "LMSS Activator"
3. Activate the equipment by pressing "n" on the keyboard.
There will be a delay between dismounting the current laser and mounting the secondary one. During that delay no laser can be fired in that position.

Laser Temperature
=================
The LMSS installs an additional laser mount beneath the existing mount, and includes an assembly and actuator to switch the mounts around. However, the heat dispersal system is shared between both mounts. Heat that is accumulated on one laser still needs to be dispersed even if the secondary laser is activated. Switching lasers does not give the pilot more firepower.

Damage
======
If the LMSS assembly is damaged while it is switching lasers, the laser mount will be unavailable until the next time the ship docks. Upon docking, the primary laser will be restored to its mount, but the switching mechanism will be unavailable until repaired.

Licence
=======
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International Public License. To view a copy of this license, visit http://http://creativecommons.org/licenses/by-sa/4.0/ or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. 

Sound files taken from "Large Industrial Robot" WAV file, created by Mike Koenig and sourced from soundbible.com. Licenced under Creative Commons Attribution 3.0.

Version History
===============
2.6
- Fixed JS error when attempting to change lasers that can't be switched.

2.5
- Added a message to go along with the sound when lasers cannot be switched.

2.4
- Added a sound for when the player attempts to switch lasers and it cannot be switched (either because there is no secondary laser, or no actuator in that view).
- Removed some debug messages.

2.3
- Fixed issue that was preventing lasers from being switched successfully.

2.2
- Added links for integration with planned OXP's.

2.1
- Integration with Laser Arrangement.
- Code refactoring.

2.0.12
- Improved integration with latest version of Xenon HUD.

2.0.11
- Automatically remove the LMSS Activator when the assembly is removed.
- Code refactoring.

2.0.10
- Bug fixes.

2.0.9
- Trimmed equipment.plist.
- Code refactoring.

2.0.8
- Fixed default setting for the switch that 3rd party lasers can use to detect when lasers are being switched. It was on by default, instead of off.

2.0.7
- Fixed issue where purchasing the actuator upgrade does not impact switch performance until after a save/reload.
- Changed "==" comparisons to "===" for performance improvements.

2.0.6
- Updated screenID to enable BGS background sounds.
- Renamed background overlay image to prevent possibility of future duplication.
- Toned down overlay image.

2.0.5
- Small display tweaks.

2.0.4
- Tweaked the dockside interface screen to work better with long laser names.
- Added switch so that 3rd party lasers can know when the LMSS is operating and provide an override in their condition scripts.
- Added OXP hook code to condition script.

2.0.3
- Made compatible with Ship Storage Helper.
- Made compatible with Laser Cooler OXP.
- Made compatible with Repair Bots OXP.

2.0.2
- Cleaned up some redundant code.

2.0.1
- Fixed incompatibility with Ship Respray OXP.

2.0.0
- Made the LMSS compatible with all OXP lasers.
- Added interface screen to allow dockside laser configuration.
- Added manifest entries to display secondary laser installations.
- Fixed bug where the startUpComplete function wasn't being executed due to badly formed definition.
- Switched terminology from "Front" to "Forward" for better in-game consistency.
- Added compatibility with Xenon HUD's image crosshairs.
- Added the ability to remove all LMSS components. Removing a mount will also remove the secondary laser (if installed) and refund the cost of the laser.

1.0.4
- Fixed techLevel setting for Actuator upgrade
- Fixed damageProbability of the Actuator upgrade so it can be damaged, and added a check to switch the delay back to 10 seconds when it is damaged.

1.0.3
- Fixed a bug where a ship with no laser in a laser mount would cause an error.
- Added maintenance item descriptions for integration with email system maintenance overhaul email
- Adjusted costs of equipment items to be less premium.
- Added sounds to accompany the laser switching process.

1.0.2
- Fixed the "shipDied" function to correctly shut down timers when the player dies.

1.0.1
- Fixed bug where docking (or dying) while switching weapons would cause some unpredictable results.
- If an OXP laser gets installed after the LMSS system, the LMSS will now not switch the laser and potentially lose it.
- If a LMSS laser is purchased to replace an existing laser, a refund is now given on the laser that is removed (100% of standard laser cost).
- Code refactoring
- Put correct tags in manifest file.

1.0
Initial release

Equipment

Name Visible Cost [deci-credits] Tech-Level
LMSS Activator no 0 1+
LMSS - Actuator Upgrade yes 42000 13+
Remove LMSS - Actuator Upgrade no 2000 8+
LMSS - Aft Assembly yes 36000 8+
LMSS - Aft Beam Laser no 0 1+
LMSS - Aft Military Laser no 0 1+
LMSS - Aft Mining Laser no 0 1+
LMSS - Aft Pulse Laser no 0 1+
Remove LMSS - Aft Assembly no 2000 5+
LMSS - Aft Weapon no 0 1+
LMSS - Forward Assembly yes 36000 8+
LMSS - Front Beam Laser no 0 1+
LMSS - Front Military Laser no 0 1+
LMSS - Front Mining Laser no 0 1+
LMSS - Front Pulse Laser no 0 1+
Remove LMSS - Forward Assembly no 2000 5+
LMSS - Forward Weapon no 0 1+
LMSS - Port Assembly yes 36000 8+
LMSS - Port Beam Laser no 0 1+
LMSS - Port Military Laser no 0 1+
LMSS - Port Mining Laser no 0 1+
LMSS - Port Pulse Laser no 0 1+
Remove LMSS - Port Assembly no 2000 5+
LMSS - Port Weapon no 0 1+
LMSS - Starboard Assembly yes 36000 8+
LMSS - Starboard Beam Laser no 0 1+
LMSS - Starboard Military Laser no 60500 11+
LMSS - Starboard Mining Laser no 0 1+
LMSS - Starboard Pulse Laser no 0 1+
Remove LMSS - Starboard Assembly no 2000 5+
LMSS - Starboard Weapon no 0 1+

Ships

This expansion declares no ships.

Models

This expansion declares no models.

Scripts

Path
Scripts/lmss_activator.js
"use strict";
this.name = "LMSS_Activator";
this.author = "phkb";
this.copyright = "2015 phkb";
this.description = "Switches the laser mount inflight between two lasers.";
this.licence = "CC BY-NC-SA 4.0";

//======================================================================================================================
this.activated = function () {

	var p = player.ship;
	var w = worldScripts.LMSS_Core;
	var check = false;

	switch (p.viewDirection) {
		case "VIEW_FORWARD":
			check = w.$hasForwardLMSS();
			if (check === true && (!w._forwardTimer || w._forwardTimer.isRunning === false)) {
				w.$switchForward();
			} else {
				if (check === false) this.$playAlertSound();
			}
			break;
		case "VIEW_AFT":
			check = w.$hasAftLMSS();
			if (check === true && (!w._aftTimer || w._aftTimer.isRunning === false)) {
				w.$switchAft();
			} else {
				if (check === false) this.$playAlertSound();
			}
			break;
		case "VIEW_PORT":
			check = w.$hasPortLMSS();
			if (check === true && (!w._portTimer || w._portTimer.isRunning === false)) {
				w.$switchPort();
			} else {
				if (check === false) this.$playAlertSound();
			}
			break;
		case "VIEW_STARBOARD":
			check = w.$hasStarboardLMSS();
			if (check === true && (!w._starboardTimer || w._starboardTimer.isRunning === false)) {
				w.$switchStarboard();
			} else {
				if (check === false) this.$playAlertSound();
			}
			break;
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$playAlertSound = function $playAlertSound() {
	var mySound = new SoundSource;
	mySound.sound = "[@boop]";
	mySound.loop = false;
	mySound.play();
	player.consoleMessage("Unable to activate - installation error");
}
Scripts/lmss_conditions.js
"use strict";
this.name = "LMSS_Conditions";
this.author = "phkb";
this.copyright = "2015 phkb";
this.description = "Condition script for LMSS equipment items.";
this.licence = "CC BY-NC-SA 4.0";

this.allowAwardEquipment = function (equipment, ship, context) {
	// none of these items should be on a new ship
	if (context === "newShip") return false;

	if (equipment === "EQ_LMSS_ACTIVATOR") {
		if (context === "purchase") return false;
	}

	// these can only be installed via a script.
	if ((equipment === "EQ_LMSS_FRONT_WEAPON" || equipment === "EQ_LMSS_AFT_WEAPON" || equipment === "EQ_LMSS_PORT_WEAPON" || equipment === "EQ_LMSS_STARBOARD_WEAPON") && context != "scripted") return false;

	// old equipment items aren't available for purchase anymore, but we need them for backwards compatibility
	if (equipment.indexOf("EQ_LMSS_FRONT_") >= 0 && equipment.indexOf("_WEAPON") === -1) return false;
	if (equipment.indexOf("EQ_LMSS_AFT_") >= 0 && equipment.indexOf("_WEAPON") === -1) return false;
	if (equipment.indexOf("EQ_LMSS_PORT_") >= 0 && equipment.indexOf("_WEAPON") === -1) return false;
	if (equipment.indexOf("EQ_LMSS_STARBOARD_") >= 0 && equipment.indexOf("_WEAPON") === -1) return false;

	if (equipment === "EQ_LMSS_FRONT") {
		// does the ship have a forward mount?
		if (" 1 3 5 7 9 11 13 15 ".indexOf(" " + ship.weaponFacings.toString() + " ") === -1)
			return false;
	}
	if (equipment === "EQ_LMSS_AFT") {
		// does the ship have an aft mount?
		if (" 2 3 6 7 10 11 14 15 ".indexOf(" " + ship.weaponFacings.toString() + " ") === -1)
			return false;
	}
	if (equipment === "EQ_LMSS_PORT") {
		// does the ship have a port mount?
		if (" 4 5 6 7 12 13 14 15 ".indexOf(" " + ship.weaponFacings.toString() + " ") === -1)
			return false;
	}
	if (equipment === "EQ_LMSS_STARBOARD") {
		// does the ship have a starboard mount?
		if (" 8 9 10 11 12 13 14 15 ".indexOf(" " + ship.weaponFacings.toString() + " ") === -1)
			return false;
	}

	// OXP hook to allow stations to forbid specific equipment
	if (context === "purchase" && player.ship.dockedStation && player.ship.dockedStation.scriptInfo["oolite-barred-equipment"]) {
		if (player.ship.dockedStation.scriptInfo["oolite-barred-equipment"].indexOf(equipment) != -1) {
			return false;
		}
	}

	// OXP hook to allow ships to forbid specific "available to all" equipment
	if (ship.scriptInfo && ship.scriptInfo["oolite-barred-equipment"] && ship.scriptInfo["oolite-barred-equipment"].indexOf(equipment) != -1) {
		return false;
	}

	// otherwise allowed
	return true;
}
Scripts/lmss_core.js
"use strict";
this.name = "LMSS_Core";
this.author = "phkb";
this.copyright = "2015 phkb";
this.description = "Laser Mount Switching System - Core code for weapon switcher";
this.licence = "CC BY-NC-SA 4.0";

this._forwardAltKey = "EQ_WEAPON_NONE";          // .
this._aftAltKey = "EQ_WEAPON_NONE";              //  | stores the equipment keys of the secondary laser mounts
this._portAltKey = "EQ_WEAPON_NONE";             //  |
this._starboardAltKey = "EQ_WEAPON_NONE";        // .
this._forwardHoldKey = "";                       // .
this._aftHoldKey = "";                           //  | Holding variables, used when switching lasers
this._portHoldKey = "";                          //  |
this._starboardHoldKey = "";                     // .
this._disableEquipmentSale = false;              // flag to allow ship respray to know to keep any secondary lasers
this._switching = false;

this._defaultDelay = 10;                         // default amount of time it takes to switch weapons in flight
this._incompatible = ["EQ_WEAPON_LASER_COOLER"]; // array of laser keys that can't be switched

//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function () {
	var p = player.ship;
	// check whether the actuator is installed, and if so, reduce the switching delay
	if (p.equipmentStatus("EQ_LMSS_ACTUATOR") === "EQUIPMENT_OK") this._defaultDelay = 6;

	// read the secondary lasers from mission variables
	this._forwardAltKey = missionVariables.LMSS_ForwardKey;
	if (this._forwardAltKey === null) this._forwardAltKey = "EQ_WEAPON_NONE";

	this._aftAltKey = missionVariables.LMSS_AftKey;
	if (this._aftAltKey === null) this._aftAltKey = "EQ_WEAPON_NONE";

	this._portAltKey = missionVariables.LMSS_PortKey;
	if (this._portAltKey === null) this._portAltKey = "EQ_WEAPON_NONE";

	this._starboardAltKey = missionVariables.LMSS_StarboardKey;
	if (this._starboardAltKey === null) this._starboardAltKey = "EQ_WEAPON_NONE";

	// some cleanup from previous versions
	if (missionVariables.LMSS_ForwardName) delete missionVariables.LMSS_ForwardName;
	if (missionVariables.LMSS_AftName) delete missionVariables.LMSS_AftName;
	if (missionVariables.LMSS_PortName) delete missionVariables.LMSS_PortName;
	if (missionVariables.LMSS_StarboardName) delete missionVariables.LMSS_StarboardName;

	// look for any lasers from the previous version and convert
	if (p.equipmentStatus("EQ_LMSS_FRONT_PULSE") === "EQUIPMENT_OK") {
		this._forwardAltKey = "EQ_WEAPON_PULSE_LASER";
		p.removeEquipment("EQ_LMSS_FRONT_PULSE");
		p.awardEquipment("EQ_LMSS_FRONT_WEAPON");
	}
	if (p.equipmentStatus("EQ_LMSS_FRONT_BEAM") === "EQUIPMENT_OK") {
		this._forwardAltKey = "EQ_WEAPON_BEAM_LASER";
		p.removeEquipment("EQ_LMSS_FRONT_BEAM");
		p.awardEquipment("EQ_LMSS_FRONT_WEAPON");
	}
	if (p.equipmentStatus("EQ_LMSS_FRONT_MINING") === "EQUIPMENT_OK") {
		this._forwardAltKey = "EQ_WEAPON_MINING_LASER";
		p.removeEquipment("EQ_LMSS_FRONT_MINING");
		p.awardEquipment("EQ_LMSS_FRONT_WEAPON");
	}
	if (p.equipmentStatus("EQ_LMSS_FRONT_MILITARY") === "EQUIPMENT_OK") {
		this._forwardAltKey = "EQ_WEAPON_MILITARY_LASER";
		p.removeEquipment("EQ_LMSS_FRONT_MILITARY");
		p.awardEquipment("EQ_LMSS_FRONT_WEAPON");
	}

	if (p.equipmentStatus("EQ_LMSS_AFT_PULSE") === "EQUIPMENT_OK") {
		this._aftAltKey = "EQ_WEAPON_PULSE_LASER";
		p.removeEquipment("EQ_LMSS_AFT_PULSE");
		p.awardEquipment("EQ_LMSS_AFT_WEAPON");
	}
	if (p.equipmentStatus("EQ_LMSS_AFT_BEAM") === "EQUIPMENT_OK") {
		this._aftAltKey = "EQ_WEAPON_BEAM_LASER";
		p.removeEquipment("EQ_LMSS_AFT_BEAM");
		p.awardEquipment("EQ_LMSS_AFT_WEAPON");
	}
	if (p.equipmentStatus("EQ_LMSS_AFT_MINING") === "EQUIPMENT_OK") {
		this._aftAltKey = "EQ_WEAPON_MINING_LASER";
		p.removeEquipment("EQ_LMSS_AFT_MINING");
		p.awardEquipment("EQ_LMSS_AFT_WEAPON");
	}
	if (p.equipmentStatus("EQ_LMSS_AFT_MILITARY") === "EQUIPMENT_OK") {
		this._aftAltKey = "EQ_WEAPON_MILITARY_LASER";
		p.removeEquipment("EQ_LMSS_AFT_MILITARY");
	}

	if (p.equipmentStatus("EQ_LMSS_PORT_PULSE") === "EQUIPMENT_OK") {
		this._portAltKey = "EQ_WEAPON_PULSE_LASER";
		p.removeEquipment("EQ_LMSS_PORT_PULSE");
		p.awardEquipment("EQ_LMSS_PORT_WEAPON");
	}
	if (p.equipmentStatus("EQ_LMSS_PORT_BEAM") === "EQUIPMENT_OK") {
		this._portAltKey = "EQ_WEAPON_BEAM_LASER";
		p.removeEquipment("EQ_LMSS_PORT_BEAM");
		p.awardEquipment("EQ_LMSS_PORT_WEAPON");
	}
	if (p.equipmentStatus("EQ_LMSS_PORT_MINING") === "EQUIPMENT_OK") {
		this._portAltKey = "EQ_WEAPON_MINING_LASER";
		p.removeEquipment("EQ_LMSS_PORT_MINING");
		p.awardEquipment("EQ_LMSS_PORT_WEAPON");
	}
	if (p.equipmentStatus("EQ_LMSS_PORT_MILITARY") === "EQUIPMENT_OK") {
		this._portAltKey = "EQ_WEAPON_MILITARY_LASER";
		p.removeEquipment("EQ_LMSS_PORT_MILITARY");
		p.awardEquipment("EQ_LMSS_PORT_WEAPON");
	}

	if (p.equipmentStatus("EQ_LMSS_STARBOARD_PULSE") === "EQUIPMENT_OK") {
		this._starboardAltKey = "EQ_WEAPON_PULSE_LASER";
		p.removeEquipment("EQ_LMSS_STARBOARD_PULSE");
		p.awardEquipment("EQ_LMSS_STARBOARD_WEAPON");
	}
	if (p.equipmentStatus("EQ_LMSS_STARBOARD_BEAM") === "EQUIPMENT_OK") {
		this._starboardAltKey = "EQ_WEAPON_BEAM_LASER";
		p.removeEquipment("EQ_LMSS_STARBOARD_BEAM");
		p.awardEquipment("EQ_LMSS_STARBOARD_WEAPON");
	}
	if (p.equipmentStatus("EQ_LMSS_STARBOARD_MINING") === "EQUIPMENT_OK") {
		this._starboardAltKey = "EQ_WEAPON_MINING_LASER";
		p.removeEquipment("EQ_LMSS_STARBOARD_MINING");
		p.awardEquipment("EQ_LMSS_STARBOARD_WEAPON");
	}
	if (p.equipmentStatus("EQ_LMSS_STARBOARD_MILITARY") === "EQUIPMENT_OK") {
		this._starboardAltKey = "EQ_WEAPON_MILITARY_LASER";
		p.removeEquipment("EQ_LMSS_STARBOARD_MILITARY");
		p.awardEquipment("EQ_LMSS_STARBOARD_WEAPON");
	}

	this.$resetInterface();
}

//-------------------------------------------------------------------------------------------------------------
this.playerWillSaveGame = function () {
	missionVariables.LMSS_ForwardKey = this._forwardAltKey;
	missionVariables.LMSS_ForwardName = this._forwardAltName;
	missionVariables.LMSS_AftKey = this._aftAltKey;
	missionVariables.LMSS_AftName = this._aftAltName;
	missionVariables.LMSS_PortKey = this._portAltKey;
	missionVariables.LMSS_PortName = this._portAltName;
	missionVariables.LMSS_StarboardKey = this._starboardAltKey;
	missionVariables.LMSS_StarboardName = this._starboardAltName;
}

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

	this.$stopTimers();

	// if an assembly was damaged during switching (or we were switching while docking), put the hold laser back in now
	// the assumption is that we kicked the machine and got main laser back, but the switch assembly is still damaged
	if (this._forwardHoldKey != "") p.forwardWeapon = this._forwardHoldKey;
	if (this._aftHoldKey != "") p.aftWeapon = this._aftHoldKey;
	if (this._portHoldKey != "") p.portWeapon = this._portHoldKey;
	if (this._starboardHoldKey != "") p.starboardWeapon = this._starboardHoldKey;
	this._forwardHoldKey = "";
	this._aftHoldKey = "";
	this._portHoldKey = "";
	this._starboardHoldKey = "";

	if (p.equipmentStatus("EQ_LMSS_ACTIVATOR") === "EQUIPMENT_OK") {
		this.$initInterface(station);
	}
	this.$updateManifest();
}

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

//-------------------------------------------------------------------------------------------------------------
this.equipmentDamaged = function (equipmentKey) {
	// check if the associated timer is running - if it is, stop it - we just lost the laser!
	switch (equipmentKey) {
		case "EQ_LMSS_ACTUATOR":
			// if the actuator gets damaged, switch back to the longer delay
			this._defaultDelay = 10;
			break;
		case "EQ_LMSS_FRONT":
			if (this._forwardTimer && this._forwardTimer.isRunning) this._forwardTimer.stop();
			break;
		case "EQ_LMSS_AFT":
			if (this._aftTimer && this._aftTimer.isRunning) this._aftTimer.stop();
			break;
		case "EQ_LMSS_PORT":
			if (this._portTimer && this._portTimer.isRunning) this._portTimer.stop();
			break;
		case "EQ_LMSS_STARBOARD":
			if (this._starboardTimer && this._starboardTimer.isRunning) this._starboardTimer.stop();
			break;
	}
}

//-------------------------------------------------------------------------------------------------------------
// handles any repair that happens mid-flight (via repair bots)
this.equipmentRepaired = function (equipmentKey) {
	var p = player.ship;
	if (p.status != "STATUS_IN_FLIGHT") return;

	switch (equipmentKey) {
		case "EQ_LMSS_ACTUATOR":
			// if the actuator gets repaired in flight (via repair bots), switch to the shorter delay
			this._defaultDelay = 6;
			break;
		case "EQ_LMSS_FRONT":
			if (this._forwardHoldKey != "") {
				p.forwardWeapon = this._forwardHoldKey;
				this._forwardHoldKey = "";
				this.$updateManifest();
			}
			break;
		case "EQ_LMSS_AFT":
			if (this._aftHoldKey != "") {
				p.aftWeapon = this._aftHoldKey;
				this._aftHoldKey = "";
				this.$updateManifest();
			}
			break;
		case "EQ_LMSS_PORT":
			if (this._portHoldKey != "") {
				p.portWeapon = this._portHoldKey;
				this._portHoldKey = "";
				this.$updateManifest();
			}
			break;
		case "EQ_LMSS_STARBOARD":
			if (this._starboardHoldKey != "") {
				p.starboardWeapon = this._starboardHoldKey;
				this._starboardHoldKey = "";
				this.$updateManifest();
			}
			break;
	}
}

//-------------------------------------------------------------------------------------------------------------
this.equipmentAdded = function (equipmentKey) {
	// auto add the switcher utility, so we only get one of them
	if (equipmentKey === "EQ_LMSS_FRONT" || equipmentKey === "EQ_LMSS_AFT" || equipmentKey === "EQ_LMSS_PORT" || equipmentKey === "EQ_LMSS_STARBOARD") {
		var p = player.ship;
		if (p.equipmentStatus("EQ_LMSS_ACTIVATOR") != "EQUIPMENT_OK") {
			p.awardEquipment("EQ_LMSS_ACTIVATOR");
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
this.equipmentRemoved = function (equipmentKey) {
	// auto-remove the switcher utility
	if (equipmentKey === "EQ_LMSS_FRONT" || equipmentKey === "EQ_LMSS_AFT" || equipmentKey === "EQ_LMSS_PORT" || equipmentKey === "EQ_LMSS_STARBOARD") {
		var p = player.ship;
		if (p.equipmentStatus("EQ_LMSS_FRONT") != "EQUIPMENT_OK" && p.equipmentStatus("EQ_LMSS_AFT") != "EQUIPMENT_OK" && p.equipmentStatus("EQ_LMSS_PORT") != "EQUIPMENT_OK" && p.equipmentStatus("EQ_LMSS_STARBOARD") != "EQUIPMENT_OK") {
			if (p.equipmentStatus("EQ_LMSS_ACTIVATOR") == "EQUIPMENT_OK") {
				p.removeEquipment("EQ_LMSS_ACTIVATOR");
			}
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
this.guiScreenChanged = function (to, from) {
	// monitor which screens we go to, and reset the "disable equipment sale" flag when we move away from one one these screens
	if (guiScreen != "GUI_SCREEN_EQUIP_SHIP" && guiScreen != "GUI_SCREEN_MISSION" && guiScreen != "GUI_SCREEN_STATUS") {
		this._disableEquipmentSale === false
	}
}

//-------------------------------------------------------------------------------------------------------------
this.playerBoughtEquipment = function (equipmentKey) {
	var p = player.ship;

	// if the player purchases a respray for their ship, turn on a flag to stop the sale of equipment items during the "playerBoughtNewShip" event
	if (equipmentKey === "EQ_SHIP_RESPRAY" || equipmentKey === "EQ_SHIP_RESPRAY_180") {
		this._disableEquipmentSale = true;
		return;
	}

	// auto add the switcher utility, so we only get one of them
	if (equipmentKey === "EQ_LMSS_FRONT" || equipmentKey === "EQ_LMSS_AFT" || equipmentKey === "EQ_LMSS_PORT" || equipmentKey === "EQ_LMSS_STARBOARD") {
		/*if (p.equipmentStatus("EQ_LMSS_ACTIVATOR") != "EQUIPMENT_OK") {
			p.awardEquipment("EQ_LMSS_ACTIVATOR");
		}*/
		this.$initInterface(p.dockedStation);
	}
	// are we removing one of the positions?
	if (equipmentKey.indexOf("EQ_LMSS_") >= 0 && equipmentKey.indexOf("_REMOVAL") >= 0) {
		if (equipmentKey === "EQ_LMSS_FRONT_REMOVAL") {
			p.removeEquipment("EQ_LMSS_FRONT");
			p.removeEquipment("EQ_LMSS_FRONT_REMOVAL");
			if (this._forwardAltKey != "" && this._forwardAltKey != "EQ_WEAPON_NONE") {
				p.removeEquipment("EQ_LMSS_FRONT_WEAPON");
				this.$refundItemAfterNewShip(this._forwardAltKey);
			}
			this._forwardAltKey = "EQ_WEAPON_NONE";
		}
		if (equipmentKey === "EQ_LMSS_AFT_REMOVAL") {
			p.removeEquipment("EQ_LMSS_AFT");
			p.removeEquipment("EQ_LMSS_AFT_REMOVAL");
			if (this._aftAltKey != "" && this._aftAltKey != "EQ_WEAPON_NONE") {
				p.removeEquipment("EQ_LMSS_AFT_WEAPON");
				this.$refundItemAfterNewShip(this._aftAltKey);
			}
			this._aftAltKey = "EQ_WEAPON_NONE";
		}
		if (equipmentKey === "EQ_LMSS_PORT_REMOVAL") {
			p.removeEquipment("EQ_LMSS_PORT");
			p.removeEquipment("EQ_LMSS_PORT_REMOVAL");
			if (this._portAltKey != "" && this._portAltKey != "EQ_WEAPON_NONE") {
				p.removeEquipment("EQ_LMSS_PORT_WEAPON");
				this.$refundItemAfterNewShip(this._portAltKey);
			}
			this._portAltKey = "EQ_WEAPON_NONE";
		}
		if (equipmentKey === "EQ_LMSS_STARBOARD_REMOVAL") {
			p.removeEquipment("EQ_LMSS_STARBOARD");
			p.removeEquipment("EQ_LMSS_STARBOARD_REMOVAL");
			if (this._starboardAltKey != "" && this._starboardAltKey != "EQ_WEAPON_NONE") {
				p.removeEquipment("EQ_LMSS_STARBOARD_WEAPON");
				this.$refundItemAfterNewShip(this._starboardAltKey);
			}
			this._starboardAltKey = "EQ_WEAPON_NONE";
		}
		// if we've removed all the positions, then remove the activator as well
		if (p.equipmentStatus("EQ_LMSS_FRONT") != "EQUIPMENT_OK" && p.equipmentStatus("EQ_LMSS_AFT") != "EQUIPMENT_OK" &&
			p.equipmentStatus("EQ_LMSS_PORT") != "EQUIPMENT_OK" && p.equipmentStatus("EQ_LMSS_STARBOARD") != "EQUIPMENT_OK") {
			p.removeEquipment("EQ_LMSS_ACTIVATOR");
		}
		this.$resetInterface();
	}
	if (equipmentKey === "EQ_LMSS_ACTUATOR_REMOVAL") {
		p.removeEquipment("EQ_LMSS_ACTUATOR");
		p.removeEquipment("EQ_LMSS_ACTUATOR_REMOVAL");
		// reset the delay back to the original time
		this._defaultDelay = 10;
	}
	if (equipmentKey === "EQ_LMSS_ACTUATOR") {
		this._defaultDelay = 6;
	}
}

//-------------------------------------------------------------------------------------------------------------
// if a new ship is bought, refund any secondary lasers to the player
this.playerBoughtNewShip = function (ship, price) {
	// if the new ship is part of a respray, don't sell anything, but set a timer to reset the interfaces after the sale has completed.
	if (this._disableEquipmentSale === true) {
		this._resetInterface = new Timer(this, this.$resetInterface, 1, 0);
		return;
	}

	if (this._forwardAltKey != "" && this._forwardAltKey != "EQ_WEAPON_NONE") this.$refundItemAfterNewShip(this._forwardAltKey);
	if (this._aftAltKey != "" && this._aftAltKey != "EQ_WEAPON_NONE") this.$refundItemAfterNewShip(this._aftAltKey);
	if (this._portAltKey != "" && this._portAltKey != "EQ_WEAPON_NONE") this.$refundItemAfterNewShip(this._portAltKey);
	if (this._starboardAltKey != "" && this._starboardAltKey != "EQ_WEAPON_NONE") this.$refundItemAfterNewShip(this._starboardAltKey);
	// reset the secondary laser variables
	this._forwardAltKey = "EQ_WEAPON_NONE";
	this._aftAltKey = "EQ_WEAPON_NONE";
	this._portAltKey = "EQ_WEAPON_NONE";
	this._starboardAltKey = "EQ_WEAPON_NONE";

	this.$resetInterface();
}

//-------------------------------------------------------------------------------------------------------------
// used to reset the interface screen after equipment purchase
this.$resetInterface = function $resetInterface() {
	this.$updateManifest();
	this.$initInterface(player.ship.dockedStation);
}

//-------------------------------------------------------------------------------------------------------------
// refund price of equipment to player
this.$refundItemAfterNewShip = function $refundItemAfterNewShip(equipment) {
	var laser = EquipmentInfo.infoForKey(equipment);
	player.credits += laser.price / 10;
}

//-------------------------------------------------------------------------------------------------------------
// updates the manifest screen with details of all secondary lasers
this.$updateManifest = function $updateManifest() {
	var list = [];
	var p = player.ship;
	list.push("LMSS Secondary Laser Installations:");

	if (p.equipmentStatus("EQ_LMSS_FRONT_WEAPON") === "EQUIPMENT_OK") {
		if (this._forwardHoldKey != "") {
			list.push("Forward: --being switched--");
		} else {
			list.push("Forward: " + this.$getEquipmentName(this._forwardAltKey, "FORWARD", false));
		}
	}
	if (p.equipmentStatus("EQ_LMSS_AFT_WEAPON") === "EQUIPMENT_OK") {
		if (this._aftHoldKey != "") {
			list.push("Aft: --being switched--");
		} else {
			list.push("Aft: " + this.$getEquipmentName(this._aftAltKey, "AFT", false));
		}
	}
	if (p.equipmentStatus("EQ_LMSS_PORT_WEAPON") === "EQUIPMENT_OK") {
		if (this._portHoldKey != "") {
			list.push("Port: --being switched--");
		} else {
			list.push("Port: " + this.$getEquipmentName(this._portAltKey, "PORT", false));
		}
	}
	if (p.equipmentStatus("EQ_LMSS_STARBOARD_WEAPON") === "EQUIPMENT_OK") {
		if (this._starboardHoldKey != "") {
			list.push("Starboard: --being switched--");
		} else {
			list.push("Starboard: " + this.$getEquipmentName(this._starboardAltKey, "STARBOARD", false));
		}
	}

	if (list.length === 1) {
		// no secondary lasers installed
		mission.setInstructions(null);
	} else {
		mission.setInstructions(list, this.name);
	}

	this.$updateXenonHUD();

}

//-------------------------------------------------------------------------------------------------------------
// establishes the F4 interface for switching laser mounts while docked
this.$initInterface = function $initInterface(station) {
	var p = player.ship;
	if (p.equipmentStatus("EQ_LMSS_ACTIVATOR") === "EQUIPMENT_OK") {
		station.setInterface(this.name, {
			title: "LMSS dockside services",
			category: "Ship Systems",
			summary: "Provides configuration options for the Laser Mount Switching system while in dock",
			callback: this.$showLMSSList.bind(this)
		});
	} else {
		station.setInterface(this.name, null);
	}
}

//-------------------------------------------------------------------------------------------------------------
// displays the dockside switching options
this.$showLMSSList = function $showLMSSList() {
	var p = player.ship;
	var curChoices = {};
	var text = "Select the laser mount you want to switch:\n\n";
	var def = "99_EXIT";

	if (worldScripts.LaserArrangement && p.weaponFacings > 1) {
		curChoices["00_LA"] = {
			text: "Primary laser arrangement"
		};
	}

	if (p.equipmentStatus("EQ_LMSS_FRONT") === "EQUIPMENT_OK") {
		text += "Forward:\n";
		text += "  Primary: " + (p.forwardWeapon.equipmentKey === "EQ_WEAPON_NONE" ? "--None--" : this.$getEquipmentName(p.forwardWeapon.equipmentKey, "FORWARD", true)) + "\n";
		text += "  Secondary: " + this.$getEquipmentName(this._forwardAltKey, "FORWARD", false) + "\n";
		curChoices["01_FORWARD"] = {
			text: "Switch forward lasers",
			color: "orangeColor"
		};
	}
	if (p.equipmentStatus("EQ_LMSS_AFT") === "EQUIPMENT_OK") {
		text += "Aft:\n";
		text += "  Primary: " + (p.aftWeapon.equipmentKey === "EQ_WEAPON_NONE" ? "--None--" : this.$getEquipmentName(p.aftWeapon.equipmentKey, "AFT", true)) + "\n";
		text += "  Secondary: " + this.$getEquipmentName(this._aftAltKey, "AFT", false) + "\n";
		curChoices["02_AFT"] = {
			text: "Switch aft lasers",
			color: "orangeColor"
		};
	}
	if (p.equipmentStatus("EQ_LMSS_PORT") === "EQUIPMENT_OK") {
		text += "Port:\n";
		text += "  Primary: " + (p.portWeapon.equipmentKey === "EQ_WEAPON_NONE" ? "--None--" : this.$getEquipmentName(p.portWeapon.equipmentKey, "PORT", true)) + "\n";
		text += "  Secondary: " + this.$getEquipmentName(this._portAltKey, "PORT", false) + "\n";
		curChoices["03_PORT"] = {
			text: "Switch port lasers",
			color: "orangeColor"
		};
	}
	if (p.equipmentStatus("EQ_LMSS_STARBOARD") === "EQUIPMENT_OK") {
		text += "Starboard:\n";
		text += "  Primary: " + (p.starboardWeapon.equipmentKey === "EQ_WEAPON_NONE" ? "--None--" : this.$getEquipmentName(p.starboardWeapon.equipmentKey, "STARBOARD", true)) + "\n";
		text += "  Secondary: " + this.$getEquipmentName(this._starboardAltKey, "STARBOARD", false) + "\n";
		curChoices["04_STARBOARD"] = {
			text: "Switch starboard lasers",
			color: "orangeColor"
		};
	}

	curChoices["99_EXIT"] = "Exit";

	var opts = {
		screenID: "oolite-lmss-dockside-map",
		title: "LMSS Dockside Services",
		allowInterrupt: true,
		exitScreen: "GUI_SCREEN_INTERFACES",
		overlay: {
			name: "lmss-arrow.png",
			height: 546
		},
		choices: curChoices,
		initialChoicesKey: def,
		message: text
	};
	mission.runScreen(opts, this.$screenHandler, this);
}

//-------------------------------------------------------------------------------------------------------------
// handles user input from the interface screen
this.$screenHandler = function $screenHandler(choice) {
	if (choice == null) return;

	switch (choice) {
		case "00_LA":
			worldScripts.LaserArrangement.$showInitial();
			return;
		case "01_FORWARD":
			this.$switchImmediate("FORWARD");
			break;
		case "02_AFT":
			this.$switchImmediate("AFT");
			break;
		case "03_PORT":
			this.$switchImmediate("PORT");
			break;
		case "04_STARBOARD":
			this.$switchImmediate("STARBOARD");
			break;
	}

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

//-------------------------------------------------------------------------------------------------------------
// switches laser mounts immediately (used only when docked)
this.$switchImmediate = function $switchImmediate(position) {
	var p = player.ship;
	var key = "";

	this._switching = true;

	//log(this.name, "pre forward primary " + p.forwardWeapon.equipmentKey);
	//log(this.name, "pre forward secondary " + this._forwardAltKey);
	switch (position) {
		case "FORWARD":
			if (this._forwardAltKey === "EQ_WEAPON_NONE") p.awardEquipment("EQ_LMSS_FRONT_WEAPON");
			if (p.forwardWeapon.equipmentKey === "EQ_WEAPON_NONE") p.removeEquipment("EQ_LMSS_FRONT_WEAPON");
			key = p.forwardWeapon.equipmentKey;
			p.forwardWeapon = this._forwardAltKey;
			this._forwardAltKey = key;
			break;
		case "AFT":
			if (this._aftAltKey === "EQ_WEAPON_NONE") p.awardEquipment("EQ_LMSS_AFT_WEAPON");
			if (p.aftWeapon.equipmentKey === "EQ_WEAPON_NONE") p.removeEquipment("EQ_LMSS_AFT_WEAPON");
			key = p.aftWeapon.equipmentKey;
			p.aftWeapon = this._aftAltKey;
			this._aftAltKey = key;
			break;
		case "PORT":
			if (this._portAltKey === "EQ_WEAPON_NONE") p.awardEquipment("EQ_LMSS_PORT_WEAPON");
			if (p.portWeapon.equipmentKey === "EQ_WEAPON_NONE") p.removeEquipment("EQ_LMSS_PORT_WEAPON");
			key = p.portWeapon.equipmentKey;
			p.portWeapon = this._portAltKey;
			this._portAltKey = key;
			break;
		case "STARBOARD":
			if (this._starboardAltKey === "EQ_WEAPON_NONE") p.awardEquipment("EQ_LMSS_STARBOARD_WEAPON");
			if (p.starboardWeapon.equipmentKey === "EQ_WEAPON_NONE") p.removeEquipment("EQ_LMSS_STARBOARD_WEAPON");
			key = p.starboardWeapon.equipmentKey;
			p.starboardWeapon = this._starboardAltKey;
			this._starboardAltKey = key;
			break;
	}
	//log(this.name, "post forward primary " + p.forwardWeapon.equipmentKey);
	//log(this.name, "post forward secondary " + this._forwardAltKey);
	// switch breakable laser info, if present
	if (worldScripts.BreakableLasers_Main) worldScripts.BreakableLasers_Main.$switchPosition(position);

	this._switching = false;

	this.$updateManifest();
}

//-------------------------------------------------------------------------------------------------------------
// stops any running timers
this.$stopTimers = function $stopTimers() {
	if (this._forwardTimer && this._forwardTimer.isRunning) this._forwardTimer.stop();
	if (this._aftTimer && this._aftTimer.isRunning) this._aftTimer.stop();
	if (this._portTimer && this._portTimer.isRunning) this._portTimer.stop();
	if (this._starboardTimer && this._starboardTimer.isRunning) this._starboardTimer.stop();
}

//-------------------------------------------------------------------------------------------------------------
// does player have the activator and a secondary laser in the forward mount?
this.$hasForwardLMSS = function $hasForwardLMSS() {
	var p = player.ship;
	if (p.equipmentStatus("EQ_LMSS_FRONT") === "EQUIPMENT_OK" &&
		p.equipmentStatus("EQ_LMSS_FRONT_WEAPON") === "EQUIPMENT_OK" &&
		this._incompatible.indexOf(p.forwardWeapon.equipmentKey) === -1) {
		return true;
	} else {
		return false;
	}
}

//-------------------------------------------------------------------------------------------------------------
// does player have the activator and a secondary laser in the aft mount?
this.$hasAftLMSS = function $hasAftLMSS() {
	var p = player.ship;
	if (p.equipmentStatus("EQ_LMSS_AFT") === "EQUIPMENT_OK" &&
		p.equipmentStatus("EQ_LMSS_AFT_WEAPON") === "EQUIPMENT_OK" &&
		this._incompatible.indexOf(p.aftWeapon.equipmentKey) === -1) {
		return true;
	} else {
		return false;
	}
}

//-------------------------------------------------------------------------------------------------------------
// does player have the activator and a secondary laser in the port mount?
this.$hasPortLMSS = function $hasPortLMSS() {
	var p = player.ship;
	if (p.equipmentStatus("EQ_LMSS_PORT") === "EQUIPMENT_OK" &&
		p.equipmentStatus("EQ_LMSS_PORT_WEAPON") === "EQUIPMENT_OK" &&
		this._incompatible.indexOf(p.portWeapon.equipmentKey) === -1) {
		return true;
	} else {
		return false;
	}
}

//-------------------------------------------------------------------------------------------------------------
// does player have the activator and a secondary laser in the starboard mount?
this.$hasStarboardLMSS = function $hasStarboardLMSS() {
	var p = player.ship;
	if (p.equipmentStatus("EQ_LMSS_STARBOARD") === "EQUIPMENT_OK" &&
		p.equipmentStatus("EQ_LMSS_STARBOARD_WEAPON") === "EQUIPMENT_OK" &&
		this._incompatible.indexOf(p.starboardWeapon.equipmentKey) === -1) {
		return true;
	} else {
		return false;
	}
}

//-------------------------------------------------------------------------------------------------------------
// start the process of switching the forward laser
this.$switchForward = function $switchForward() {
	var p = player.ship;
	if (p.equipmentStatus("EQ_LBOOST_PULSE_FWD") == "EQUIPMENT_DAMAGED" || 
		p.equipmentStatus("EQ_LBOOST_BEAM_FWD") == "EQUIPMENT_DAMAGED" || 
		p.equipmentStatus("EQ_LBOOST_MINING_FWD") == "EQUIPMENT_DAMAGED" || 
		p.equipmentStatus("EQ_LBOOST_MILITARY_FWD") == "EQUIPMENT_DAMAGED") {
		player.consoleMessage("Unable to activate - forward laser damaged");
		return;
	}
	// first, remove the existing laser and store a value so that we can put it back
	player.consoleMessage("FORWARD laser deactivated");
	// put the key in the holding spot
	this._forwardHoldKey = p.forwardWeapon.equipmentKey;
	p.forwardWeapon = "EQ_WEAPON_NONE";
	this.$updateManifest();
	// start a timer to load up the secondary laser
	this._forwardTimer = new Timer(this, this.$installLaserForward, this._defaultDelay, 0);
	this.$playSound();
}

//-------------------------------------------------------------------------------------------------------------
// start the process of switching the aft laser
this.$switchAft = function $switchAft() {
	var p = player.ship;
	if (p.equipmentStatus("EQ_LBOOST_PULSE_AFT") == "EQUIPMENT_DAMAGED" || 
		p.equipmentStatus("EQ_LBOOST_BEAM_AFT") == "EQUIPMENT_DAMAGED" || 
		p.equipmentStatus("EQ_LBOOST_MINING_AFT") == "EQUIPMENT_DAMAGED" || 
		p.equipmentStatus("EQ_LBOOST_MILITARY_AFT") == "EQUIPMENT_DAMAGED") {
		player.consoleMessage("Unable to activate - aft laser damaged");
		return;
	}
	// first, remove the existing laser and store a value so that we can put it back
	player.consoleMessage("AFT laser deactivated");
	// put the key in the holding spot
	this._aftHoldKey = p.aftWeapon.equipmentKey;
	p.aftWeapon = "EQ_WEAPON_NONE";
	this.$updateManifest();
	// start a timer to load up the secondary laser
	this._aftTimer = new Timer(this, this.$installLaserAft, this._defaultDelay, 0);
	this.$playSound();
}

//-------------------------------------------------------------------------------------------------------------
// start the process of switching the port laser
this.$switchPort = function $switchPort() {
	var p = player.ship;
	if (p.equipmentStatus("EQ_LBOOST_PULSE_PORT") == "EQUIPMENT_DAMAGED" || 
		p.equipmentStatus("EQ_LBOOST_BEAM_PORT") == "EQUIPMENT_DAMAGED" || 
		p.equipmentStatus("EQ_LBOOST_MINING_PORT") == "EQUIPMENT_DAMAGED" || 
		p.equipmentStatus("EQ_LBOOST_MILITARY_PORT") == "EQUIPMENT_DAMAGED") {
		player.consoleMessage("Unable to activate - port laser damaged");
		return;
	}
	// first, remove the existing laser and store a value so that we can put it back
	player.consoleMessage("PORT laser deactivated");
	// put the key in the holding spot
	this._portHoldKey = p.portWeapon.equipmentKey;
	p.portWeapon = "EQ_WEAPON_NONE";
	this.$updateManifest();
	// start a timer to load up the secondary laser
	this._portTimer = new Timer(this, this.$installLaserPort, this._defaultDelay, 0);
	this.$playSound();
}

//-------------------------------------------------------------------------------------------------------------
// start the process of switching the starboard laser
this.$switchStarboard = function $switchStarboard() {
	var p = player.ship;
	if (p.equipmentStatus("EQ_LBOOST_PULSE_STAR") == "EQUIPMENT_DAMAGED" || 
		p.equipmentStatus("EQ_LBOOST_BEAM_STAR") == "EQUIPMENT_DAMAGED" || 
		p.equipmentStatus("EQ_LBOOST_MINING_STAR") == "EQUIPMENT_DAMAGED" || 
		p.equipmentStatus("EQ_LBOOST_MILITARY_STAR") == "EQUIPMENT_DAMAGED") {
		player.consoleMessage("Unable to activate - starboard laser damaged");
		return;
	}
	// first, remove the existing laser and store a value so that we can put it back
	player.consoleMessage("STARBOARD laser deactivated");
	// put the key in the holding spot
	this._starboardHoldKey = p.starboardWeapon.equipmentKey;
	p.starboardWeapon = "EQ_WEAPON_NONE";
	this.$updateManifest();
	// start a timer to load up the secondary laser
	this._starboardTimer = new Timer(this, this.$installLaserStarboard, this._defaultDelay, 0);
	this.$playSound();
}

//-------------------------------------------------------------------------------------------------------------
// end points for the timers so we can call one function
this.$installLaserForward = function $installLaserForward() {
	this.$installLaser("FORWARD");
}
this.$installLaserAft = function $installLaserAft() {
	this.$installLaser("AFT");
}
this.$installLaserPort = function $installLaserPort() {
	this.$installLaser("PORT");
}
this.$installLaserStarboard = function $installLaserStarboard() {
	this.$installLaser("STARBOARD");
}

//-------------------------------------------------------------------------------------------------------------
// install the lasers after the appropriate delay
this.$installLaser = function $installLaser(position) {
	var p = player.ship;

	this._switching = true;

	// get the equipment key of the original laser
	switch (position) {
		case "FORWARD":
			p.forwardWeapon = this._forwardAltKey;
			this._forwardAltKey = this._forwardHoldKey;
			this._forwardHoldKey = "";
			if (this._forwardAltKey === "EQ_WEAPON_NONE") {
				p.removeEquipment("EQ_LMSS_FRONT_WEAPON");
			}
			break;
		case "AFT":
			p.aftWeapon = this._aftAltKey;
			this._aftAltKey = this._aftHoldKey;
			this._aftHoldKey = "";
			if (this._aftAltKey === "EQ_WEAPON_NONE") {
				p.removeEquipment("EQ_LMSS_AFT_WEAPON");
			}
			break;
		case "PORT":
			p.portWeapon = this._portAltKey;
			this._portAltKey = this._portHoldKey;
			this._portHoldKey = "";
			if (this._portAltKey === "EQ_WEAPON_NONE") {
				p.removeEquipment("EQ_LMSS_PORT_WEAPON");
			}
			break;
		case "STARBOARD":
			p.starboardWeapon = this._starboardAltKey;
			this._starboardAltKey = this._starboardHoldKey;
			this._starboardHoldKey = "";
			if (this._starboardAltKey === "EQ_WEAPON_NONE") {
				p.removeEquipment("EQ_LMSS_STARBOARD_WEAPON");
			}
			break;
	}
	// switch breakable laser info, if present
	if (worldScripts.BreakableLasers_Main) worldScripts.BreakableLasers_Main.$switchPosition(position);

	this._switching = false;
	player.consoleMessage(position + " laser switched");
	this.$updateManifest();
}

//-------------------------------------------------------------------------------------------------------------
// plays the hydraulic sound of the lasers being switched
this.$playSound = function $playSound() {
	var mySound = new SoundSource;
	if (this._defaultDelay === 6) {
		mySound.sound = "actuator-6.ogg";
	} else {
		mySound.sound = "actuator-10.ogg";
	}
	mySound.loop = false;
	mySound.play();
}

//-------------------------------------------------------------------------------------------------------------
// updates the crosshairs on Xenon HUD (which uses images rather than standard crosshairs
this.$updateXenonHUD = function $updateXenonHUD() {
	var p = player.ship;
	var xHUDList = ["XenonHUD.plist", "XenonHUD_hicontrast.plist", "XenonHUD_alt.plist", "XenonHUD_narrow.plist", "XenonHUD_narrow_hicontrast.plist",
		"XenonHUD_amber.plist", "XenonHUD_hicontrast_amber.plist", "XenonHUD_alt_amber.plist", "XenonHUD_narrow_amber.plist", "XenonHUD_narrow_hicontrast_amber.plist"];

	if (p.status === "STATUS_IN_FLIGHT" && xHUDList.indexOf(p.hud) >= 0) {
		var w = worldScripts.XenonHUD;
		w.viewDirectionChanged(p.viewDirection);
	}
}

//-------------------------------------------------------------------------------------------------------------
// returns the name of a particular equipment item
this.$getEquipmentName = function $getEquipmentName(equipment, position, isPrimary) {
	var laser = EquipmentInfo.infoForKey(equipment);
	var bl = worldScripts.BreakableLasers_Main;
	var extra = "";
	if (bl && equipment == bl._damagedEq) {
		if (isPrimary) {
			laser = EquipmentInfo.infoForKey(bl._holdDamage[position].primary);
		} else {
			laser = EquipmentInfo.infoForKey(bl._holdDamage[position].secondary);
		}
		extra = " (Damaged)";
	}
	if (!laser || laser.name === "Remove Laser") {
		return "--None--";
	} else {
		return laser.name + extra;
	}
}

//-------------------------------------------------------------------------------------------------------------
// returns a JSON string of all settings (for Ship Storage Helper)
this.$retrieveLaserSettings = function $retrieveLaserSettings() {
	var ret = [];
	ret.push({
		position: "forward",
		key: this._forwardAltKey
	});
	ret.push({
		position: "aft",
		key: this._aftAltKey
	});
	ret.push({
		position: "port",
		key: this._portAltKey
	});
	ret.push({
		position: "starboard",
		key: this._starboardAltKey
	});
	return JSON.stringify(ret);
}

//-------------------------------------------------------------------------------------------------------------
// parses a JSON string and reads values from the array into all settings (for Ship Storage Helper)
this.$restoreLaserSettings = function $restoreLaserSettings(dataString) {
	var arr = JSON.parse(dataString);

	// reset the keys
	this._forwardAltKey = "EQ_WEAPON_NONE";
	this._aftAltKey = "EQ_WEAPON_NONE";
	this._portAltKey = "EQ_WEAPON_NONE";
	this._starboardAltKey = "EQ_WEAPON_NONE";

	// load values from the array
	for (var i = 0; i < arr.length; i++) {
		switch (arr[i].position) {
			case "forward":
				this._forwardAltKey = arr[i].key;
				break;
			case "aft":
				this._aftAltKey = arr[i].key;
				break;
			case "port":
				this._portAltKey = arr[i].key;
				break;
			case "starboard":
				this._starboardAltKey = arr[i].key;
				break;
		}
	}
	this.$resetInterface();
}

//-------------------------------------------------------------------------------------------------------------
// returns true if there is a secondary laser in any position, otherwise false
this.$weaponInstalled = function $weaponInstalled() {
	if (this.$hasForwardLMSS() || this.$hasAftLMSS() || this.$hasPortLMSS() || this.$hasStarboardLMSS()) return true;
	return false;
}