Back to Index Page generated: May 8, 2024, 6:16:03 AM

Expansion Fuel Injection Cruise Control

Content

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description Engages a fuel injection-like system that doesn't require the fuel injection key to be held down. Engages a fuel injection-like system that doesn't require the fuel injection key to be held down.
Identifier oolite.oxp.phkb.FuelInjectionCruiseControl oolite.oxp.phkb.FuelInjectionCruiseControl
Title Fuel Injection Cruise Control Fuel Injection Cruise Control
Category Equipment Equipment
Author phkb phkb
Version 1.0 1.0
Tags fuel injection fuel injection
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
Conflict Expansions
Information URL https://wiki.alioth.net/index.php/Fuel_Injection_Cruise_Control n/a
Download URL https://wiki.alioth.net/img_auth.php/b/b4/FuelInjectionCruiseControl_1.0.oxz n/a
License CC BY-NA-SA 4.0 CC BY-NA-SA 4.0
File Size n/a
Upload date 1698953217

Documentation

Also read http://wiki.alioth.net/index.php/Fuel%20Injection%20Cruise%20Control

readme.txt

Fuel Injection Cruise Control
By Nick Rogers

Overview
========
This OXP adds primable equipment that enables a pilot to engage their fuel injectors in the same way as they can for the torus drive, that is, they can start and stop the injectors by pressing a button, rather than having to hold down the injectors key. For most joystick players this will seem unnecessary, as usually the injectors are assigned to a convenient button which can be pressed at the same time as other buttons. But for keyboard players, holding the down the injector key while attempting to steer the ship or shoot can create some very twisty hand contortions.

Equipment Operations
====================
The "Fuel Injection Cruise Control" equipment item can be purchased from any TL11 system (the same as for standard fuel injectors) for 1150cr. 

After purchasing, you will need to prime the equipment by pressing "Shift-N", then activating it by pressing "n". You must accelerate to your maximum speed before engaging the equipment. Press the "n" key again to de-activate the cruise control.

Cruise Control can be set to auto-engage when the maximum speed is reached, by priming the equipment and pressing the "b". Using Library Config, you can set a red alert and docking override for this mode, so that in those conditions, setting the speed to maximum will not auto-engage the cruise control, even if the auto-engage is on.

The Fuel Injection cruise control will be automatically turned off in any of these scenarios:
- The Torus drive is engaged.
- The normal injectors key is pressed.
- The player manually reduces speed.
- The ship runs out of fuel.

Note: If the normal injectors key is pressed while cruise control is active, there will be a brief slowdown while the cruise control is turned off and the normal injector function is activated.

Library Config settings
=======================
If the Library OXP is installed the following settings are available:

- Auto-engage (true/false): Setting this to true will engage the FICC without needing to prime the equipment and activating it manually (defaults to true).
- Red alert disable auto on (true/false): Setting this to true with disable the auto-engage feature during red alert conditions (defaults to false).
- Docking disable auto on (true/false): Setting this to true will disable the auto-engage feature during docking procedures (defaults to false).
- Passive mode (true/false): Setting this to true will remove the primable equipment. Auto-engage will always be on in this mode (defaults to false).

OXP Interfaces
==============
Because this OXP is simulating the injectors, the normal JavaScript property "player.ship.injectorsEngaged" will not return true when the cruise control is engaged. To allow other OXP's to easily determine that the cruise control is on, two properties are now set.

    worldScripts.FuelInjectionCruiseControl._engaged (boolean)
    player.ship.script._ficcEngaged (boolean)

Scripts may check either of these settings to determine whether cruise control is active.

License
=======
This work is licensed under the Creative Commons Attribution-Noncommercial-Share Alike 4.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/

Thanks to Damocles Edge for suggesting the equipment in the first place, and for excellent bug testing, and to Norby for suggesting some different methods of implementing the solution.
Thanks to Milo for the improved QCharger integration code.

Version History
===============
1.0
- Prevented speed check FCB from starting twice when equipment is repaired in flight.

0.9 
- Another attempt to fix issue where FCB keeps firing when it shouldn't.

0.8
- Attempt to fix issue where disengaged notice was appearing repeated, even when docked.

0.7
- Improvement to QCharger integration. FICC will now only engage at 100% throttle, QCharger at 95-99%.
- Changed auto-engage default state to "true".
- Added a "passive" mode (selected via Library Config) that removes the requirement for primable equipment.

0.6
- Bug fix for Surjector integration.

0.5
- Acceleration up to injector speed will now vary based on thrust level of ship (ie Asp MkII will accelerate faster than an Anaconda).
- Pressing injectors key when cruise control is engaged will now avoid the "sliding" issue during transition.
- Simplified setting of velocity vectors.
- Improved integration with Surjectors.

0.4
- Cruise control injector speed is now equivalent to normal injector speed.
- Fixed issue where "sliding" could occur when slowing down.
- Slowed acceleration up to injector speed will now only happen if current speed is less than injector speed.
- Added some flags to allow other OXP's to easily determine when the FICC is engaged.
- Turning off auto-engage mode when the cruise control is active will now turn off the cruise control as well.
- Auto-engage mode is now saved between sessions, and can be set with Library Config.
- Code improvements as suggested by Norby.

0.3
- Acceleration up to injector speed is now slower, similar to applying injectors normally.
- Removed debug code.
- Bug fixes.

0.2
- Added player message when attempting to engage CC while in Torus drive.
- Added options to auto-engage CC when max speed attained using mode key (b). Can be disabled in red alert and when docking using Library Config.
- Made compatible with Q-Charger.
- Made compatible with Surjectors.

0.1
- Initial release.

Equipment

Name Visible Cost [deci-credits] Tech-Level
Fuel Injection Cruise Control yes 11500 11+
Fuel Injection Cruise Control yes 11500 11+

Ships

This expansion declares no ships.

Models

This expansion declares no models.

Scripts

Path
Scripts/ficc_conditions.js
"use strict";
this.name = "FuelInjectionCruiseControl_Conditions";
this.author = "phkb";
this.copyright = "2020 phkb";
this.description = "Condition script for FICC equipment items";
this.licence = "CC BY-NC-SA 4.0";

//-------------------------------------------------------------------------------------------------------------
this.allowAwardEquipment = function(equipment, ship, context) {
	if (context === "scripted") return true;
	// just want to hide the "passive" item from the purchase screen
	// passive mode selected elsewhere
    if (equipment === "EQ_FUEL_INJECTION_CRUISECONTROL_PASSIVE") return false;
    return true;
}
Scripts/ficc_equipment.js
"use strict";
this.name = "FuelInjectionCruiseControl";
this.author = "phkb";
this.copyright = "2018 phkb";
this.description = "Mode/Activation code for the FICC equipment";
this.licence = "CC BY-NC-SA 4.0";

this._bgs = false; // is BGS installed?
this._qcharger = false; // is the Q-Charger OXP installed?
this._surjectors = false; // is the Surjectors OXP installed?
this._engaged = false;

this._autoEngage = true;
this._disableAutoOnRedAlert = false;
this._disableAutoOnDocking = false;
this._passive = false;
this._trueValues = ["yes", "1", 1, "true", true];

/*
	TODO:
		Can we get the space dust effect to work the same as it does for normal injectors?
		Chase mode - match speed to target, or match speed when within 10km of target?
*/

// Library config
this._libraryConfig = {
	Name: this.name,
	Alias: "Fuel Injection Cruise Control",
	Display: "Config",
	Alive: "_libraryConfig",
	Notify: "$onChange",
	Bool: {
		B0: {
			Name: "_autoEngage",
			Def: true,
			Desc: "Auto-engage FICC"
		},
		B1: {
			Name: "_disableAutoOnRedAlert",
			Def: false,
			Desc: "Red alert disable auto on"
		},
		B2: {
			Name: "_disableAutoOnDocking",
			Def: false,
			Desc: "Docking disable auto on"
		},
        B3: {
            Name: "_passive",
            Def: false,
            Desc: "Passive mode"
        },
		Info: "0 - Auto-engage FICC when maximum speed reached.\n1 - Disable auto on feature during red alert condition.\n2 - Disable auto on feature during docking.\n3 - Passive mode (no primable equipment required)"
	},
};

//-------------------------------------------------------------------------------------------------------------
this.$onChange = function () {
	var p = player.ship;
	var w = worldScripts.FuelInjectionCruiseControl;
	if (w._passive == true) {
		if (p.equipmentStatus("EQ_FUEL_INJECTION_CRUISECONTROL") == "EQUIPMENT_OK") {
			p.removeEquipment("EQ_FUEL_INJECTION_CRUISECONTROL");
			p.awardEquipment("EQ_FUEL_INJECTION_CRUISECONTROL_PASSIVE");
		}
		w._autoEngage = true; // must be on for passive mode
		return;
	}
	if (w._passive == true) {
		if (p.equipmentStatus("EQ_FUEL_INJECTION_CRUISECONTROL") == "EQUIPMENT_DAMAGED") {
			p.removeEquipment("EQ_FUEL_INJECTION_CRUISECONTROL");
			p.awardEquipment("EQ_FUEL_INJECTION_CRUISECONTROL_PASSIVE");
			p.setEquipmentStatus("EQ_FUEL_INJECTION_CRUISECONTROL_PASSIVE", "EQUIPMENT_DAMAGED");
		}
		w._autoEngage = true; // must be on for passive mode
		return;
	}
	if (w._passive == false && p.equipmentStatus("EQ_FUEL_INJECTION_CRUISECONTROL_PASSIVE") == "EQUIPMENT_OK") {
		p.removeEquipment("EQ_FUEL_INJECTION_CRUISECONTROL_PASSIVE");
		p.awardEquipment("EQ_FUEL_INJECTION_CRUISECONTROL");
		return;
	}
	if (w._passive == true && p.equipmentStatus("EQ_FUEL_INJECTION_CRUISECONTROL_PASSIVE") == "EQUIPMENT_DAMAGED") {
		p.removeEquipment("EQ_FUEL_INJECTION_CRUISECONTROL_PASSIVE");
		p.awardEquipment("EQ_FUEL_INJECTION_CRUISECONTROL");
		p.setEquipmentStatus("EQ_FUEL_INJECTION_CRUISECONTROL", "EQUIPMENT_DAMAGED");
		return;
	}
}

//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function () {
	if (worldScripts.BGS) this._bgs = true;
	if (worldScripts["Q-Charger"]) this._qcharger = true;
	if (worldScripts.Surjectors) this._surjectors = true;

	if (missionVariables.FICC_AutoEngage) this._autoEngage = (this._trueValues.indexOf(missionVariables.FICC_AutoEngage) >= 0 ? true : false);
	// register our settings, if Lib_Config is present
	if (worldScripts.Lib_Config) {
		worldScripts.Lib_Config._registerSet(this._libraryConfig);
		// only restore settings if library config is present - otherwise, we'll keep the values set in the script (in case of manual override)
		if (missionVariables.FICC_AutoEngageRedAlertDisable) this._disableAutoOnRedAlert = (this._trueValues.indexOf(missionVariables.FICC_AutoEngageRedAlertDisable) >= 0 ? true : false);
		if (missionVariables.FICC_AutoEngageDockingDisable) this._disableAutoOnDocking = (this._trueValues.indexOf(missionVariables.FICC_AutoEngageDockingDisable) >= 0 ? true : false);
	}
	// make sure the passive flag is set correctly
	if (["EQUIPMENT_OK","EQUIPMENT_DAMAGED"].indexOf(player.ship.equipmentStatus("EQ_FUEL_INJECTION_CRUISECONTROL_PASSIVE")) >= 0) {
		this._passive = true;
	}
}

//-------------------------------------------------------------------------------------------------------------
this.playerWillSaveGame = function () {
	missionVariables.FICC_AutoEngage = this._autoEngage;
	if (worldScripts.Lib_Config) {
		missionVariables.FICC_AutoEngageRedAlertDisable = this._disableAutoOnRedAlert;
		missionVariables.FICC_AutoEngageDockingDisable = this._disableAutoOnDocking;
	} else {
		delete missionVariables.FICC_AutoEngageRedAlertDisable;
		delete missionVariables.FICC_AutoEngageDockingDisable;
	}
}

//-------------------------------------------------------------------------------------------------------------
this.shipWillLaunchFromStation = function (station) {
	var p = player.ship, ps = p.script;
	ps._fuelDeduct = 0;
	ps._qcharger_toggled = false;
	ps._surjectorsApplied = false;
	ps._surjectors = (this._surjectors === true);
}

//-------------------------------------------------------------------------------------------------------------
this.shipLaunchedFromStation = this.shipExitedWitchspace = function () {
	var p = player.ship, ps = p.script;
	ps._qchargerCheck = (this._qcharger === true && p.equipmentStatus("EQ_Q-CHARGER") === "EQUIPMENT_OK" && ((p.equipmentStatus("EQ_ENERGY_UNIT") === "EQUIPMENT_OK") || (p.equipmentStatus("EQ_NAVAL_ENERGY_UNIT") === "EQUIPMENT_OK")));
	ps._ficc_ok = (p.hasEquipmentProviding("EQ_FUEL_INJECTION") === true && p.hasEquipmentProviding("EQ_FICC") == true);
	if (this._autoEngage === true) {
		this.$startCheckSpeedFCB(true);
	}
}

//-------------------------------------------------------------------------------------------------------------
this.shipDied = this.shipWillDockWithStation = this.shipWillEnterWitchspace = function () {
	//if (isValidFrameCallback(this._cbID)) removeFrameCallback(this._cbID);
	this.$stopFCB();
	// turn the speed check fcb off as well, although if this is the shipWillEnterWitchspace event, it will be turned back on again when we exit witchspace
	if (isValidFrameCallback(this._speedFCB)) removeFrameCallback(this._speedFCB);
}

//-------------------------------------------------------------------------------------------------------------
this.playerRequestedDockingClearance = function (message) {
	var ps = player.ship.script;
	if (message === "DOCKING_CLEARANCE_GRANTED" || message === "DOCKING_CLEARANCE_EXTENDED" || message === "DOCKING_CLEARANCE_DENIED_TRAFFIC_INBOUND" || message === "DOCKING_CLEARANCE_DENIED_TRAFFIC_OUTBOUND") {
		ps._ficc_playerIsDocking = true;
	} else {
		ps._ficc_playerIsDocking = false;
	}
}

//-------------------------------------------------------------------------------------------------------------
// for oolite 1.85++
this.playerDockingClearanceCancelled = function () {
	var ps = player.ship.script;
	ps._ficc_playerIsDocking = false;
}

//-------------------------------------------------------------------------------------------------------------
// for oolite 1.83++
this.playerDockingClearanceExpired = function () {
	this.playerDockingClearanceCancelled();
}

//-------------------------------------------------------------------------------------------------------------
this.equipmentAdded = function(equipmentKey) {
	// make sure we don't end up with a mismatch on the passive flag
	// if the player has previously set passive mode via library config, maintain that config with the right equipment
	if (equipmentKey == "EQ_FUEL_INJECTION_CRUISECONTROL" && this._passive == true) {
		var p = player.ship;
		p.removeEquipment(equipmentKey);
		p.awardEquipment("EQ_FUEL_INJECTION_CRUISECONTROL_PASSIVE");
	}
}

//-------------------------------------------------------------------------------------------------------------
this.activated = function () {
	var ficc = worldScripts.FuelInjectionCruiseControl;
	// if it's already on, turn it off
	if (isValidFrameCallback(ficc._cbID)) {
		player.consoleMessage(expandDescription("[ficc_disengaged]"));
		ficc.$playSound("engineDown");
		ficc.$stopFCB();
		return;
	}
	var p = player.ship;
	if (p.torusEngaged) {
		player.consoleMessage(expandDescription("[ficc_torus]"));
		return;
	}
	// no injectors
	if (p.hasEquipmentProviding("EQ_FUEL_INJECTION") === false) {
		player.consoleMessage(expandDescription("[ficc_unavailable]"));
		return;
	}
	// no fuel
	if (p.fuel <= 0) {
		player.consoleMessage(expandDescription("[fuel-out]"));
		return;
	}
	// not at max speed
	if (p.speed < p.maxSpeed) {
		player.consoleMessage(expandDescription("[ficc_accelerate]"));
		return;
	}
	// qcharger only operates if fuel is >= 0.1 and there is a working energy unit (normal or naval)
	/*if (p.equipmentStatus("EQ_Q-CHARGER") === "EQUIPMENT_OK" &&
		(worldScripts["Q-Charger"].qchargercondition === "ON" || (p.fuel >= 0.1 && (p.equipmentStatus("EQ_ENERGY_UNIT") == "EQUIPMENT_DAMAGED" || p.equipmentStatus("EQ_NAVAL_ENERGY_UNIT") === "EQUIPMENT_DAMAGED")))) {
		player.consoleMessage(expandDescription("[ficc_qcharger]"));
		return;
	}*/
	player.consoleMessage(expandDescription("[ficc_engaged]"));
	ficc.$startFCB();
}

//-------------------------------------------------------------------------------------------------------------
this.mode = function () {
	var ficc = worldScripts.FuelInjectionCruiseControl;
	if (isValidFrameCallback(ficc._speedFCB)) {
		ficc._autoEngage = false;
		removeFrameCallback(ficc._speedFCB);
		player.consoleMessage(expandDescription("[ficc_autoEngageOff]"));
		if (ficc._engaged) this.activated();
	} else {
		// start a fcb to monitor speed and auto-engage CC when max speed reached
		ficc._autoEngage = true;
		ficc.$startCheckSpeedFCB(false)
	}
}

//-------------------------------------------------------------------------------------------------------------
this.equipmentDamaged = function (equipmentKey) {
	var p = player.ship, ps = p.script;
	if (!ps) return; // script is undefined when player ship is destroyed
	if (p.hasEquipmentProviding("EQ_FICC") == false || p.hasEquipmentProviding("EQ_FUEL_INJECTION") === false) {
		ps._ficc_ok = false;
		if (isValidFrameCallback(this._cbID)) {
			player.consoleMessage(expandDescription("[ficc_disengaged]"));
			this.$playSound("engineDown");
			this.$stopFCB();
		}
		if (isValidFrameCallback(this._speedFCB)) removeFrameCallback(this._speedFCB);
	}
	// monitor when the qcharger state changes (needs either EQ_ENERGY_UNIT or EQ_NAVAL_ENERGY_UNIT in addition to its own equipment)
	if (this._qcharger === true && ps._qchargerCheck === true &&
		(p.equipmentStatus("EQ_Q-CHARGER") !== "EQUIPMENT_OK" || (p.equipmentStatus("EQ_ENERGY_UNIT") !== "EQUIPMENT_OK" && p.equipmentStatus("EQ_NAVAL_ENERGY_UNIT") !== "EQUIPMENT_OK")) ) {
		ps._qchargerCheck = false;
	}
}

//-------------------------------------------------------------------------------------------------------------
this.equipmentRepaired = function (equipmentKey) { // if in-flight repairs restored functionality
	if (player.ship.status === "STATUS_IN_FLIGHT") this.shipLaunchedFromStation(); // check FICC and Q-Charger equipment and re-activate FICC auto-engage monitoring FCB if configured to do so
}

//-------------------------------------------------------------------------------------------------------------
this.$startFCB = function $startFCB() {
	var p = player.ship;
	p.script._soundCounter = 0;
	p.script._accel = (p.speed / (p.maxSpeed * p.injectorSpeedFactor));
	if (p.script._accel > 1) p.script._accel = 1; // in case we're slowing from torus speed

	// turn on some flags so other OXP's have an easier way of determining that the ficc is engaged
	this._engaged = true;
	p.script._ficcEngaged = true;

	// only play the engine up sound if we are actually speeding up
	if (p.speed < (p.maxSpeed * p.injectorSpeedFactor)) this.$playSound("engineUp");
	this.$playSound("afterburner");

	// set up the frame callback
	this._cbID = addFrameCallback(function _fcbID(delta) {
		var p = (_fcbID.p = _fcbID.p || player.ship), ps = (_fcbID.ps = _fcbID.ps || p.script); // cache the player.ship and player.ship.script references
		var ficc = (_fcbID.ficc = _fcbID.ficc || worldScripts.FuelInjectionCruiseControl); // cache the worldScript reference
		var wsq = (_fcbID.wsq = _fcbID.wsq || worldScripts["Q-Charger"]); // cache the worldScript reference
		if (!p || !p.isValid || !ps._ficc_ok) {
			ficc.$stopFCB();
			return;
		}
		if (p.torusEngaged || p.injectorsEngaged) {
			player.consoleMessage(expandDescription("[ficc_disengaged]"));
			ficc.$stopFCB();
			return;
		}
		if (p.speed < p.maxSpeed) {
			player.consoleMessage(expandDescription("[ficc_disengaged]"));
			ficc.$playSound("engineDown");
			ficc.$stopFCB();
			return;
		}
		if (p.fuel <= 0) {
			player.consoleMessage(expandDescription("[fuel-out]"));
			ficc.$playSound("engineDown");
			ficc.$stopFCB();
			return;
		}
		if (ps._qchargerCheck === true && wsq) { // this is a do-once
			if (wsq.qchargerenabled) {
			 	// FICC takes over from Q-Charger at 100% speed (Q-Charger handles 95-99% speed)
				ps._qcharger_toggled = true;
				wsq.qchargerCheckTimer.stop(); // stop Q-Charger's timer while FICC is running (expectation, currently true: if the player toggles Q-Charger manually, it doesn't restart the timer)
				//ficc.$playSound("engineDown");
				//ficc.$stopFCB();
				//return;
			}
			ps._qchargerCheck = false; // don't need to check Q-Charger again while FICC is running
		}
		ps._soundCounter += delta;
		if (ps._soundCounter > 1) {
			ps._soundCounter = 0;
			ficc.$playSound("afterburner");
		}

		// note: this method will not change the actual speed of the ship, 
		// so I've included the requirement that the ship must be at full speed before engaging

		// velocity adjustment method
		p.velocity = p.vectorForward.multiply(parseFloat(p.maxSpeed * p.injectorSpeedFactor) * ps._accel);
		if (ps._accel < 1) ps._accel += 0.01 + (p.maxThrust / 15000);
		else if (ps._accel > 1) ps._accel = 1;

		// deduct fuel
		var br = p.injectorBurnRate;

		// surjectors changes the way injectors work at the base level, rather than at an equipment level
		// so, if the OXP is installed, and weapons are offline, the code kicks in
		// because we are simulating injectors here, not actually doing injectors, we need to implement the surjector code
		if (ps._surjectors && !p.weaponsOnline) {
			ps._surjectorsApplied = true;
			br = 0.01;
			p.aftShield -= 0.1;
			p.forwardShield -= 0.1;
			p.aftShieldRechargeRate = 0;
			p.forwardShieldRechargeRate = 0;
			p.energyRechargeRate = 0;
		}

		ps._fuelDeduct += ((br / 10) * delta);
		if (ps._fuelDeduct > 0.1) {
			p.fuel -= 0.1;
			ps._fuelDeduct -= 0.1;
			if (p.fuel < 0) p.fuel = 0;
		}
	});
}

//-------------------------------------------------------------------------------------------------------------
this.$stopFCB = function $stopFCB() {
	if (isValidFrameCallback(this._cbID)) {
		removeFrameCallback(this._cbID);
		var p = player.ship, ps = p.script;
		ps._ficcEngaged = false;
		this._engaged = false;
		// restore surjector shield/energy recharge rates	
		if (ps._surjectorsApplied) {
			var s = worldScripts.Surjectors;
			if (!p.injectorsEngaged) { // don't reset anything if the injectors are engaged, otherwise we might override surjectors
				p.aftShieldRechargeRate = s.$savedAftRate;
				p.forwardShieldRechargeRate = s.$savedFwdRate;
				p.energyRechargeRate = s.$savedERate;
			}
			ps._surjectorsApplied = false;
		}
		// reset velocity
		// we have to set this back to the current speed value, otherwise we'll get the "sliding" issue
		p.velocity = p.vectorForward.multiply(p.speed);
		// resume Q-Charger if it was active before FICC took over
		if (ps._qcharger_toggled === true) {
			ps._qcharger_toggled = false;
			worldScripts["Q-Charger"].qchargerCheckTimer.start();
		}
		ps._qchargerCheck = true; // need to check Q-Charger again next time FICC starts		
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$startCheckSpeedFCB = function $startCheckSpeedFCB(silent) {
	var p = player.ship, ps = p.script;
	if (ps._ficc_ok) {
		if (silent === false) player.consoleMessage(expandDescription("[ficc_autoEngageOn]"));
		if (!isValidFrameCallback(this._speedFCB)) {
			this._speedFCB = addFrameCallback(function _checkSpeedFCB(delta) {
				var p = (_checkSpeedFCB.p = _checkSpeedFCB.p || player.ship); // cache the player.ship reference
				if (p && p.isInSpace && p.isValid) { // removed && p.script._qchargerCheck === false
					var ficc = (_checkSpeedFCB.ficc = _checkSpeedFCB.ficc || worldScripts.FuelInjectionCruiseControl); // cache the worldScript reference
					if (p.speed == p.maxSpeed && p.fuel > 0 && p.torusEngaged === false && p.injectorsEngaged === false && !isValidFrameCallback(ficc._cbID)) {
						var _disableAutoOnRedAlert = (_checkSpeedFCB._disableAutoOnRedAlert = _checkSpeedFCB._disableAutoOnRedAlert || ficc._disableAutoOnRedAlert); // cache the config value
						var _disableAutoOnDocking  = (_checkSpeedFCB._disableAutoOnDocking  = _checkSpeedFCB._disableAutoOnDocking  || ficc._disableAutoOnDocking); // cache the config value
						if (_disableAutoOnRedAlert && p.alertCondition === 3) return;
						if (_disableAutoOnDocking && p.script._ficc_playerIsDocking) return;
						ficc.activated();
					}
				}
			});
		}
	}
}

//-------------------------------------------------------------------------------------------------------------
// player the buy/sell sound effects
this.$playSound = function $playSound(soundtype) {
	var mySound;
	switch (soundtype) {
		case "afterburner":
			mySound = new SoundSource;
			mySound.sound = "afterburner1.ogg";
			break;
		case "engineUp":
			if (this._bgs) {
				mySound = new SoundSource;
				mySound.sound = worldScripts.BGS.$BGS.def["engineUp"];
			} else return;
			break;
		case "engineDown":
			if (this._bgs) {
				mySound = new SoundSource;
				mySound.sound = worldScripts.BGS.$BGS.def["engineDown"];
			} else return;
			break;
	}
	mySound.loop = false;
	mySound.play();
}