Config/script.js |
"use strict";
this.name = "NavBeaconsMFD";
this.author = "phkb";
this.copyright = "2023 phkb";
this.description = "Lists all nav beacons in the system, along with distances to them.";
this.license = "CC BY-NC-SA 4.0";
this._hairSpace = String.fromCharCode(31);
this._hairSpaceLength = defaultFont.measureString(this._hairSpace);
this._ellip = "…";
this._bullet = "•";
this._bulletSpace = "";
this._timer = null;
this._distTimer = null;
this._beaconShips = [];
this._final = [];
this._finalID = [];
this._current = 0;
this._rightCol = defaultFont.measureString("9999 km") + 0.1;
this._leftCol = 14.2 - this._rightCol;
this._shipsOnly = false;
this._unitSetting = 1;
//distance unit to show in mfd.
this._distUnits = ["OU", "km", "m", "CZ"];
//basis in meters for one distUnit.
//for kiloometers, set to 1000
//for OUs, set to 905520, which is roughly the distance of planet and sun in Lave in an unmodified game.
this._unitFactor = [905520, 1000, 1, 2.08641];
this._unitRounding = [4, 0, 0, 0];
this._libSettings = {
Name: this.name, Display: "Settings", Alias: "Navigation Beacons MFD", Alive: "_libSettings",
Bool: {
B0: { Name:"_shipsOnly", Def: false, Desc:"Ship/Station beacons only"},
Info: "0 = Display beacons from ships and stations only"
},
SInt: {
S0: { Name: "_unitSetting", Def: 1, Min: 0, Max: 3, Desc: "Display units" },
Info: "0 = OU, 1 = km, 2 = m, 3 = CZ (Cavezzi)"
},
};
//-------------------------------------------------------------------------------------------------------------
this.startUp = function() {
if (missionVariables.NavigationBeaconsMFD_Units) {
this._unitSetting = parseInt(missionVariables.NavigationBeaconsMFD_Units);
}
if (missionVariables.NavigationBeaconsMFD_ShipsOnly) {
this._shipsOnly = (missionVariables.NavigationBeaconsMFD_ShipsOnly == "yes" ? true : false);
}
}
//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function () {
var measure = defaultFont.measureString;
// register our settings, if Lib_Config is present
if (worldScripts.Lib_Config) worldScripts.Lib_Config._registerSet(this._libSettings);
this._bulletWidth = defaultFont.measureString(this._bullet);
while (measure(this._bulletSpace) < this._bulletWidth) {
this._bulletSpace += this._hairSpace;
}
}
//-------------------------------------------------------------------------------------------------------------
this.playerWillSaveGame = function () {
missionVariables.NavigationBeaconsMFD_Units = this._unitSetting;
missionVariables.NavigationBeaconsMFD_ShipsOnly = (this._shipsOnly == true ? "yes" : "no");
}
//-------------------------------------------------------------------------------------------------------------
this.shipWillLaunchFromStation = function() {
// recalc the left/right col widths, based on unit setting
this._rightCol = defaultFont.measureString("9999" + (this._unitSetting > 1 ? "99" : "") + " " + this._unitFactor[this._unitSetting]) + 0.1;
this._leftCol = 14.2 - this._rightCol;
}
//-------------------------------------------------------------------------------------------------------------
this.shipExitedWitchspace = this.shipLaunchedFromStation = function() {
if (!player.ship.hasEquipmentProviding("EQ_ADVANCED_COMPASS")) return;
if (player.ship.equipmentStatus("EQ_NAVBEACONS_MFD") != "EQUIPMENT_OK") return;
if (!player.ship.isInSpace) return;
// do a quick update to put "scanning" on the display
this._final.length = 0;
this._beaconShips.length = 0;
this.$updateMFD(true);
// first run after 2 seconds, rerun every 5 seconds
this._timer = new Timer(this, this.$collateInfo.bind(this), 2, 5);
}
//-------------------------------------------------------------------------------------------------------------
this.shipWillEnterWitchspace = function() {
this.$stopTimers();
if (player.ship.equipmentStatus("EQ_NAVBEACONS_MFD") == "EQUIPMENT_OK")
player.ship.setMultiFunctionText("NavigationBeaconsMFD", "NAVIGATION BEACONS:\n\n\nInitialising...\n", false);
}
//-------------------------------------------------------------------------------------------------------------
this.shipDockedWithStation = this.shipDied = function() {
this.$stopTimers()
// switch the display to "Scanning" now, so when we next launch we don't get an old display showing up first before the timer clears it
this.$updateMFD(true);
}
//-------------------------------------------------------------------------------------------------------------
this.equipmentDamaged = function(equipKey) {
if (equipKey == "EQ_NAVBEACONS_MFD" || equipKey == "EQ_ADVANCED_COMPASS") {
this.$updateMFD();
this.$stopTimers();
}
}
//-------------------------------------------------------------------------------------------------------------
this.equipmentRepaired = function(equipKey) {
var p = player.ship;
if (player.ship.equipmentStatus("EQ_NAVBEACONS_MFD") != "EQUIPMENT_DAMAGED" && p.hasEquipmentProviding("EQ_ADVANCED_COMPASS")) {
this.shipExitedWitchspace();
} else {
this.$updateMFD();
}
}
//-------------------------------------------------------------------------------------------------------------
this.compassTargetChanged = function(whom, mode) {
this.$updateMFD();
}
//-------------------------------------------------------------------------------------------------------------
this.$stopTimers = function() {
if (this._timer && this._timer.isRunning) this._timer.stop();
if (this._distTimer && this._distTimer.isRunning) this._distTimer.stop();
}
//-------------------------------------------------------------------------------------------------------------
this.$collateInfo = function $collateInfo() {
this._beaconShips = this.$findShipsWithBeacons();
var i = this._beaconShips.length;
while (i--) {
this._beaconShips[i]._nb_ID = i;
}
if (this._distTimer && this._distTimer.isRunning) return;
this._distTimer = new Timer(this, this.$calcDistances.bind(this), 0.25, 1.5);
}
//-------------------------------------------------------------------------------------------------------------
this.$calcDistances = function $calcDistances() {
var that = $calcDistances;
var measure = (that.measure = that.measure || defaultFont.measureString);
var _p = (that._p = that._p || player.ship);
this._final.length = 0;
this._finalID.length = 0;
if (!_p || !_p.isValid || !_p.position) return;
var i = this._beaconShips.length;
if (i > 9) i = 9;
while (i--) {
var shp = this._beaconShips[i];
var check = ~~((_p.position.distanceTo(shp) - shp.collisionRadius - _p.collisionRadius) + 0.5);
var dist = check > 0 ? check : 0;
var nm = (shp.beaconLabel != "" && shp.beaconLabel != null ? shp.beaconLabel : shp.displayName);
this._finalID.unshift(shp._nb_ID);
var distOut = " " + (dist / this._unitFactor[this._unitSetting]).toFixed(this._unitRounding[this._unitSetting]) + " " + this._distUnits[this._unitSetting] + " ";
var width = measure(distOut) + 0.5;
this._final.unshift(this.$padText(this._bullet + nm, 15 - width) + distOut);
}
this.$updateMFD();
}
//-------------------------------------------------------------------------------------------------------------
this.$findShipsWithBeacons = function() {
function _beacons(entity) {
return !(entity.isPlayer) &&
(this._shipsOnly == false || entity.isShip) &&
(entity.beaconCode != "" && entity.beaconCode != null) &&
(entity.displayName != "Jump Marker") &&
(entity.AI != "EscortDeck_AI.plist") &&
(entity.isVisualEffect == false || entity.dataKey == "almanacCompass_planet" || entity.dataKey == "almanacCompass_moon");
}
return system.filteredEntities(this, _beacons, player.ship);
}
//-------------------------------------------------------------------------------------------------------------
this.$updateMFD = function(init) {
var p = player.ship
if (!p || !p.isValid) return;
var output = "NAVIGATION BEACONS:\n";
if (p.equipmentStatus("EQ_NAVBEACONS_MFD") == "EQUIPMENT_DAMAGED") {
output += "\n\nEquipment damaged.\n";
} else if (!p.hasEquipmentProviding("EQ_ADVANCED_COMPASS")) {
output += "\n\nNo data. ASC not available.";
} else {
if (init == true) {
output += "\n\nScanning...\n";
} else {
var max = this._final.length;
if (max == 0) {
output += "\n\nNo beacons in range\n";
} else {
if (max > 9) max = 9
var ct = p.compassTarget;
if (ct) {
//var ctn = (ct.beaconLabel != "" && ct.beaconLabel != null ? ct.beaconLabel : ct.displayName)
var ctn = ct._nb_ID;
for (var i = 0; i < max; i++) {
var txt = this._final[i];
if (ctn == this._finalID[i]) {
txt = this._bullet + txt.replace(this._bullet, "");
} else {
txt = txt.replace(this._bullet, this._bulletSpace);
}
output += txt + "\n";
}
}
}
}
}
p.setMultiFunctionText("NavigationBeaconsMFD", output, false);
}
//-------------------------------------------------------------------------------------------------------------
// appends space to currentText to the specified length in 'em'
this.$padText = function $padText(currentText, desiredLength, leftSwitch, centreSwitch) {
var that = $padText;
var hairSpace = (that.hairSpace = that.hairSpace || this._hairSpace);
var ellip = (that.ellip = that.ellip || this._ellip);
var hairSpaceLength = (that.hairSpaceLength = that.hairSpaceLength || this._hairSpaceLength);
var measure = (that.measure = that.measure || defaultFont.measureString);
if (currentText == null) currentText = "";
var currentLength = measure(currentText.replace(/%%/g, "%"));
// calculate number needed to fill remaining length
var padsNeeded = ~~((desiredLength - currentLength) / hairSpaceLength);
if (padsNeeded < 1) {
// text is too long for column, so start pulling characters off
var tmp = currentText;
do {
tmp = tmp.substring(0, tmp.length - 2) + ellip;
if (tmp === ellip) break;
} while (measure(tmp.replace(/%%/g, "%")) > desiredLength);
currentLength = measure(tmp.replace(/%%/g, "%"));
padsNeeded = ~~((desiredLength - currentLength) / hairSpaceLength);
currentText = tmp;
}
// quick way of generating a repeated string of that number
if (!leftSwitch || leftSwitch === false) {
if (!centreSwitch || centreSwitch === false) {
return currentText + new Array(padsNeeded).join(hairSpace);
} else {
return currentText + new Array(parseInt(padsNeeded / 2)).join(hairSpace);
}
} else {
if (!centreSwitch || centreSwitch === false) {
return new Array(padsNeeded).join(hairSpace) + currentText;
} else {
return new Array(parseInt(padsNeeded / 2)).join(hairSpace) + currentText;
}
}
}
|