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();
} |