Scripts/shiplib.js |
"use strict";
this.name = "shiplib";
this.author = "Norby";
this.copyright = "2013 Norbert Nagy";
this.licence = "CC BY-NC-SA 3.0";
this.description = "Contains data about player ships.";
this.version = "1.0";
//please configure these to your custom ship if not in the list below
this.$ShipLibViewPosition = { //must be equal with view_position_* of your ship in the shipdata.plist
aft:[0.0, 7.5, -32.5], forward:[0.0, 7.25, 16.25], port:[-30.0, 4.75, 0.0], starboard:[30.0, 4.75, 0.0]};
//internal data, should not touch
this.$ShipLibVP = [
{k:"default", a:this.$ShipLibViewPosition.aft, f:this.$ShipLibViewPosition.forward,
p:this.$ShipLibViewPosition.port, s:this.$ShipLibViewPosition.starboard},
//original player ships
{k:"adder", a:[0.0, 2.5, -22.5], f:[0.0, 2.5, 14.0], p:[-12.0, 1.5, -1.0], s:[12.0, 1.5, -1.0]},
{k:"anaconda", a:[0.0, -4.0, -80.0], f:[0.0, -0.5, 70.0], p:[-2.15, -0.5, 70.0], s:[2.15, -0.5, 70.0]},
{k:"asp", a:[0.0, 5.0, -35.0], f:[0.0, 5.31, 17.5], p:[-27.0, 5.0, 0.0], s:[27.0, 5.0, 0.0]},
{k:"boa", a:[0.0, 20.5, -50.75], f:[0.0, 16.25, 23.9], p:[-7.3, 16.25, -23.9], s:[7.3, 16.25, -23.9]},
{k:"boa-mk2", a:[0.0, 22.875, -47.375], f:[0.0, 12.5, 19.4375], p:[-20.67, 11.17, -14.67], s:[20.67, 11.17, -14.67]},
{k:"cobra", a:[0.0, 7.5, -32.5], f:[0.0, 7.25, 16.25], p:[-30.0, 4.75, 0.0], s:[30.0, 4.75, 0.0]},
{k:"cobra3", a:[0.0, 7.5, -32.5], f:[0.0, 7.25, 16.25], p:[-30.0, 4.75, 0.0], s:[30.0, 4.75, 0.0]},
{k:"cobramk1", a:[0.0, 3.75, -27.5], f:[0.0, 2.925, 15.125], p:[-13.0, 3.75, 0.0], s:[13.0, 3.75, 0.0]},
{k:"ferdelance", a:[0.0, 5.0, -32.5], f:[0.0, 0.0, 9.0], p:[-16.875, 2.0, 3.5], s:[16.875, 2.0, 3.5]},
{k:"moray", a:[0.0, 8.875, 5.5], f:[0.0, 4.4, 22.5], p:[-22.5, 5.25, 11.875], s:[22.5, 5.25, 11.875]},
{k:"morayMED", a:[0.0, 8.875, 5.5], f:[0.0, 4.4, 22.5], p:[-22.5, 5.25, 11.875], s:[22.5, 5.25, 11.875]},
{k:"python", a:[0.0, 15.0, -49.5], f:[0.0, 10.0, 31.5], p:[-16.0, 4.0, 15.2], s:[16.0, 4.0, 15.2]},
//custom ships
{k:"base", a:[0.0, 500.0, -400.0], f:[0.0, 3.0, 320.0], p:[-60.0, 3.0, 0.0], s:[60.0, 3.0, 0.0]},
{k:"corvette", a:[0.0, 6.0, -16.5], f:[0.0, 3.0, 16.5], p:[-5.0, 2.0, 0.0], s:[5.0, 2.0, 0.0]},
{k:"cruiser", a:[0.0, 3.0, -120.0], f:[0.0, 3.0, 120.0], p:[-60.0, 3.0, 0.0], s:[60.0, 3.0, 0.0]},
{k:"drone", a:[0.0, 5.0, -6.5], f:[0.0, 3.0, 9.5], p:[-2.5, 2.0, 0.0], s:[2.5, 2.0, 0.0]},
{k:"freighter", a:[0.0, 3.0, -120.0], f:[0.0, 3.0, 120.0], p:[-60.0, 3.0, 0.0], s:[60.0, 3.0, 0.0]},
{k:"frigate", a:[0.0, 30.0, -50.0], f:[0.0, 3.0, 50.0], p:[-30.0, 0.0, 0.0], s:[30.0, 0.0, 0.0]},
{k:"fighter", a:[0.0, 6.0, -16.5], f:[0.0, 3.0, 16.5], p:[-5.0, 2.0, 0.0], s:[5.0, 2.0, 0.0]},
{k:"gunship", a:[0.0, 6.0, -16.5], f:[0.0, 3.0, 16.5], p:[-5.0, 2.0, 0.0], s:[5.0, 2.0, 0.0]},
{k:"miner", a:[0.0, 30.0, -50.0], f:[0.0, 3.0, 50.0], p:[-30.0, 0.0, 0.0], s:[30.0, 0.0, 0.0]},
{k:"runner", a:[0.0, 6.0, -16.5], f:[0.0, 3.0, 16.5], p:[-5.0, 2.0, 0.0], s:[5.0, 2.0, 0.0]},
];
|
Scripts/telescope.js |
"use strict";
this.name = "telescope";
this.author = "Norby";
this.copyright = "2013 Norbert Nagy";
this.licence = "CC BY-NC-SA 4.0";
this.description = "Telescope mark all visible ships, show vitrual model, sniper ring and more.";
//customizable properties
this.$TelescopeAutoScan = true; //check continually for new isVisible isPiloted target and scan if found
this.$TelescopeAutoScanMaxRange = 1000000; //meters, how far targets will be reported
this.$TelescopeAutoLock = 1; //if no target and something in crosshairs with max. this degree diff., 1=lightball size, 0=off
this.$TelescopeFarStatus = false; //red ball reveal pirates over normal scanner if true
this.$TelescopeGravLock = 20; //gravity scanner relock in this degree cone (0-180, 20=about the screen)
this.$TelescopeIdentLock = 180; //if ident pressed or target lost then lock in this degree (0-180, 180=the whole sphere)
this.$TelescopeLargeLightBalls = false; //lightballs are increasing depending on the distance or remains small
this.$TelescopeLightBalls = true; //turn on or off all lightballs, but markes on the scanner will be remain
this.$TelescopeMassLockBorders = true; //coloured circles around ships and planets in green alert
this.$TelescopeBrightMassLockBorders = false; //brighter circles around ships and planets in green alert
this.$TelescopeRedAlertDist = 30000; //show lollipops in red alert within this distance only
this.$TelescopeRedAlertLimiter = false; //a bit more FPS in dogfight if true but show all marks with weapons off only
this.$TelescopeRing = true; //show a ring around the visual target
this.$TelescopeShipLightBalls = true; //turn on or off the lightballs with scanner markers of the ships, but cargo, etc. remain
this.$TelescopeShowVisualQuestionMark = false; //if a ship has no visual model in effecdata.plist show a big "?" model
this.$TelescopeShowVisualStation = true; //show or not show the 3D model of the targeted station
this.$TelescopeShowVisualTarget = true; //show 3D model of target if weapons are on (except stations if VisualStation false)
this.$TelescopeSniperMinRange = 10000; //meters, show sniper ring if the target is over this distance
this.$TelescopeSniperRange = 30000; //meters, if the target is inside then show sniper ring and large lightball
this.$TelescopeSniperRingSize = 2; //size of the sniper ring (between 1 and 5, default: 2)
this.$TelescopeSteering = 2; //auto steering if lock nearest or step in the target list with activate, 1:nearest only
this.$TelescopeTargets = 200; //limitable to reduce FPS drop in systems with many ships, min. 4, max. 200 due to VFCBM0-VFCBM49
this.$TelescopeThargoids = false; //you will get some aliens right after undock to test Telescope
this.$TelescopeVMarkMinDist = 3000; //meters, if target is inside then remove the lightball marker
this.$TelescopeVMarkShipMinDist = 5000; //meters, if target is ship and inside this range then remove the lightball marker
this.$TelescopeVPosHUD = [0, 0, 0]; //position shift for your HUD's built-in visual target screen if any
this.$TelescopeVSize = 4; //size of the visual target with online weapons (between 0 and 10, default: 4)
this.$TelescopeVZoomSize = 6; //zoomed size of the visual target with offline weapons (between 0 and 10, default: 6)
//internal properties, should not touch
this.$TelescopeAttackers = []; //ships attacked player regardless of success
this.$TelescopeAttackeri = 0; //store the sequential number of the last attacker in the target list
this.$TelescopeBuyMsg = true; //flag to show the buy message once
this.$TelescopeCMFD = null; //store the worldScripts pointer of Combart MFD
this.$TelescopeDataKeys77 = ["adder", //dataKeys with 77 suffix in effectdata.plist for Oolite 1.77
"alloy", "anaconda", "arc-detail", "asp", "asp-cloaked", "asteroid", "asteroid-alternative",
"oolite-cinder", "oolite-cinder-alternative", "oolite-cinder-small", "oolite-cinder-small-alternative",
"barrel","boa", "boa-mk2", "boulder", "boulder-alternative", "buoy", "buoy-witchpoint",
"cloaking-device", "cobra3-trader", "cobra3-alternate", "cobra3-pirate", "cobramk1",
"cobramk1-alt", "cobramk1-miner", "constrictor", "coriolis-station", "dock",
"dock-flat", "oolite-dock-virtual", "dodecahedron-station", "ecm-proof-missile",
"escape-capsule", "ferdelance", "gecko", "hermit-docking-slit", "hermitage", "icosahedron-station",
"krait", "mamba", "mamba-escort", "missile", "moray", "morayMED", "oolite-unknown-ship",
"python", "python-blackdog", "python-trader", "qbomb", "rock-hermit", "scarred-alloy",
"shuttle", "sidewinder", "sidewinder-escort", "splinter", "splinter-alternative", "strut",
"tharglet", "thargoid", "transporter", "transporter-miner", "viper", "viper-interceptor",
"viper-pursuit", "worm", "worm-miner", "wreckage-component", "more-wreckage2",
"more-wreckage3", "more-wreckage4", "more-wreckage5", "ballturret"];
this.$TelescopeFixedTel = 0; //cheaply fixed Telescope with drawbacks
this.$TelescopeFixedGS = 0; //cheaply fixed Gravity Scanner with drawbacks
this.$TelescopeFixedSD = 0; //cheaply fixed Small Dish with drawbacks
this.$TelescopeFixedLD = 0; //cheaply fixed Large Dish with drawbacks
this.$TelescopeGSC = 0; //Gravity Scan counter to call aliens
this.$TelescopeGSP = 0; //Gravity Scan percent counter store the progress of the gravity scan
this.$TelescopeIdentUnLock = false; //flag to steering started by ident, next press will unlock
this.$TelescopeList = []; //list of the scanned ships
this.$TelescopeListFar = []; //list of the scanned far ships
this.$TelescopeListFarPos = []; //positions of the scanned far ships at the moment of the scan
this.$TelescopeListGD = []; //gravity scanner maximal detection distances of the scanned ships
this.$TelescopeListPos = []; //positions of the scanned ships at the moment of the scan
this.$TelescopeListi = 0; //sequential number of the currently selected ship in the list
this.$TelescopeMaxRange = 1000000000000000; //10^15m, usable part of double precision for filteredEntities
this.$TelescopeMMarks = []; //visual effects to mark the masslocking fields around NPC ships
this.$TelescopeMRings = []; //mark the border of masslock fields
this.$TelescopeNearestd = this.$TelescopeMaxRange; //store the distance of the nearest ship in the list (updated in TimedVMC)
this.$TelescopeNearesti = 0; //store the sequential number of the nearest ship in the list (updated in TimedVMC)
this.$TelescopePlanetNames = []; //cache of names
this.$TelescopePrevHeading = []; //heading vector of the player ship in the previous frame to detect manual steering
this.$TelescopePrevNewTarget = null; //bugfix against repeated scan if a ship can not get into the list by any reason
this.$TelescopePrevMFDTarget = null; //support for Combat MFD
this.$TelescopePrevTargetAcq = null; //bugfix against repeated scan if a ship can not get into the list by any reason
this.$TelescopePrevWho = null; //bugfix against non-lockable Military Jammer awarded by ShipVersion to avoid repeated scan
this.$TelescopePrevPlanet = null; //bugfix against target switch but name remain old if new planet is within scanner range
this.$TelescopeReds = []; //store red ships detected earlier
this.$TelescopeSoundScan = null; //scan soundsource
this.$TelescopeStaionNearby = true; //store a station is nearby for gravity scanner
this.$TelescopeSteerFCB = null; //auto steering framecallback
//this.$TelescopeSniperRing = null; //if this ring guided around the crosshair then the far target is lined up correctly
this.$TelescopeSVSync = false; //flag to synhronize the visual effect during auto steering
this.$TelescopeTarget = null; //the targeted entity, needed when target is far and player target set to the markership
this.$TelescopeTargetSet = false; //flag scanning to avoid double scan
this.$TelescopeGravLock2 = this.$TelescopeGravLock; //ident press will switch this between 1 and GravLock
this.$TelescopeTimerA = null; //set player target a bit later to avoid relock the ship in crosshair (bugfix)
this.$TelescopeTimerF = null; //delayed launch of FCBs, must after FarPlanets FCB
this.$TelescopeTimerS = null; //AutoScan timer get targets from normal scanner and do scan if new far target in the front view
this.$TelescopeTWS = null; //store the worldScripts pointer of Towbar
//this.$TelescopeV = null; //visual effect to show the selected target
//this.$TelescopeVDataKey = null; //key of the visual effect
this.$TelescopeVFCB = null; //visual model and ring positions updated in these framecallbacks
this.$TelescopeVFCB2 = null; //visual model and ring positions updated in these framecallbacks part 2 to avoid timelimit
this.$TelescopeVFCB3 = null; //visual model and ring positions updated in these framecallbacks part 3 to avoid timelimit
this.$TelescopeVFCBM = []; //visual marker positions updated in these framecallbacks
this.$TelescopeVMark = null; //visual effect to mark the target
this.$TelescopeVMarks = []; //visual effects to mark the non-current targets
//this.$TelescopeVMCC = 0; //counter to make colour of the visual marks, used to do once in a second within a 0.25s timer
this.$TelescopeVMCs = []; //colour of the visual marks
this.$TelescopeVP = { //default view_positions if shiplib.js is missing
aft:[0.0, 7.5, -32.5], forward:[0.0, 7.25, 16.25], port:[-30.0, 4.75, 0.0], starboard:[30.0, 4.75, 0.0]};
this.$TelescopeVPos = null; //position of the visual effect
//this.$TelescopeVRing = null; //a ring around the visual effect target
//this.$TelescopeVShrinkC = 0; //visual effect shrink counter - shrink code is not ready, leave these at 0
//this.$TelescopeVShrinkDelay = 0; //in sec after the larger visual target start shrinkig to normal size (0: instant)
//this.$TelescopeVShrinkLength = 0; //in sec, shrinking faster if smaller (0: instant)
//this.$TelescopeVUp = 0; //visual effect align to top modifier
//this.$TelescopeWps = true; //the previous state of the player weapons
//this.$TelescopeZoom = 1; //store the original maximal zoom level of the visual effect
//world script events
this.startUp = function() {
var h = worldScripts.hudselector;
if( h && h.$HUDSelectorAddMFD ) h.$HUDSelectorAddMFD(this.name);
var ps = player.ship;
if( ps.setMultiFunctionText )
ps.setMultiFunctionText(this.name, "No Telescope Target", false);
this.$TelescopeSoundScan = new SoundSource();
this.$TelescopeSoundScan.sound = "ScanSound.ogg"; //sound of the Gravity Scanner
this.$TelescopeSoundScan.loop = false;
this.$TelescopeSoundScan.repeatCount = 1;
this.$TelescopeBuyMsg = true; //show again after reload
this.$TelescopePlanetNames = []; //cache of names
this.$TelescopeReds = []; //store red ships detected earlier
this.$TelescopeCMFD = worldScripts.combat_MFD; //store the worldScripts pointer of Combart MFD
this.$TelescopeTWS = worldScripts.towbar; //store the worldScripts pointer of Towbar
var subitem = missionVariables.$TelescopeMenuLightballs;
if( subitem > 0 ) this.$Telescope_SetLightballs( subitem );
subitem = missionVariables.$TelescopeMenuSniper;
if( subitem > 0 ) this.$Telescope_SetSniper( subitem );
subitem = missionVariables.$TelescopeMenuSteering;
if( subitem > 0 ) this.$Telescope_SetSteering( subitem );
subitem = missionVariables.$TelescopeMenuTargets;
if( subitem > 0 ) this.$Telescope_SetTargets( subitem );
subitem = missionVariables.$TelescopeMenuVisual;
if( subitem > 0 ) this.$Telescope_SetVisual( subitem );
subitem = missionVariables.$TelescopeMenuVisualSize;
if( subitem > 0 ) this.$Telescope_SetVisualSize( subitem );
var ws = worldScripts.telescope;
ws._FBC_closures();
if( ws.$FBC_closures ) // once done
delete ws._FBC_closures; // remove ability to create a 2nd ones!
else
log('telescope', 'startUp, failed to create $FBC_closures!' );
}
this.$FBC_closures = false;
this._FBC_closures = function() { // create closure & expose functions
var ws = worldScripts.telescope;
ws.$Telescope_TimedS = ws._TimedS_closure();
ws.$Telescope_VFCBVisualTarget = ws._VFCBVisualTarget_closure();
var vc = ws._VFCB_closure();
ws.$Telescope_VClearS = vc.clear;
ws.$Telescope_VShow = vc.show;
ws.$Telescope_VFCB = vc.fcb;
vc = ws._VFCB2_closure();
ws._clearSniperRing = vc.clear;
ws.$Telescope_VFCB2 = vc.fcb;
ws.$FBC_closures = true;
}
this.equipmentDamaged = this.equipmentDestroyed = function(equipment) {
if( equipment === "EQ_TELESCOPE" || equipment === "EQ_GRAVSCANNER"
|| equipment === "EQ_GRAVSCANNER2" || equipment === "EQ_SMALLDISH" || equipment === "EQ_LARGEDISH" )
worldScripts.telescope.$Telescope_NewList(); //remove lost targets, autoscan will scan again
}
this.equipmentRepaired = function(equipment) {
//Do not use "false" in missionVariables! Will return true! Use 0 and 1 instead!
if(equipment === ("EQ_TELESCOPE"))
this.$TelescopeFixedTel = missionVariables.$TelescopeFixedTel = 0;
else if(equipment === ("EQ_GRAVSCANNER"))
this.$TelescopeFixedGS = missionVariables.$TelescopeFixedGS = 0;
else if(equipment === ("EQ_GRAVSCANNER2"))
this.$TelescopeFixedGS = missionVariables.$TelescopeFixedGS = 0;
else if(equipment === ("EQ_SMALLDISH"))
this.$TelescopeFixedLD = missionVariables.$TelescopeFixedSD = 0;
else if(equipment === ("EQ_LARGEDISH"))
this.$TelescopeFixedLD = missionVariables.$TelescopeFixedLD = 0;
}
this.playerBoughtEquipment = function(equipmentKey) {
var ps = player.ship;
if(equipmentKey === ("EQ_TELESCOPE"))
this.$TelescopeFixedTel = missionVariables.$TelescopeFixedTel = 0;
else if(equipmentKey === ("EQ_GRAVSCANNER"))
this.$TelescopeFixedGS = missionVariables.$TelescopeFixedGS = 0;
else if(equipmentKey === ("EQ_GRAVSCANNER2"))
this.$TelescopeFixedGS = missionVariables.$TelescopeFixedGS = 0;
else if(equipmentKey === ("EQ_SMALLDISH"))
this.$TelescopeFixedSD = missionVariables.$TelescopeFixedSD = 0;
else if(equipmentKey === ("EQ_LARGEDISH"))
this.$TelescopeFixedLD = missionVariables.$TelescopeFixedLD = 0;
else if(equipmentKey === ("EQ_TELESCOPE_REPAIR")) {
ps.setEquipmentStatus("EQ_TELESCOPE", "EQUIPMENT_OK");
ps.removeEquipment("EQ_TELESCOPE_REPAIR");
clock.addSeconds("3600");
this.$TelescopeFixedTel = missionVariables.$TelescopeFixedTel = 1; //with drawback (lightballs only)
}
else if(equipmentKey === ("EQ_TELESCOPE_FULLREPAIR")) {
ps.removeEquipment("EQ_TELESCOPE_FULLREPAIR");
clock.addSeconds("3600");
this.$TelescopeFixedTel = missionVariables.$TelescopeFixedTel = 0;
}
else if(equipmentKey === ("EQ_GRAVSCANNER_REPAIR")) {
ps.setEquipmentStatus("EQ_GRAVSCANNER", "EQUIPMENT_OK");
ps.removeEquipment("EQ_GRAVSCANNER_REPAIR");
clock.addSeconds("3600");
this.$TelescopeFixedGS = missionVariables.$TelescopeFixedGS = 1; //with drawback (misjump)
}
else if(equipmentKey === ("EQ_GRAVSCANNER2_REPAIR")) {
ps.setEquipmentStatus("EQ_GRAVSCANNER2", "EQUIPMENT_OK");
ps.removeEquipment("EQ_GRAVSCANNER2_REPAIR");
clock.addSeconds("3600");
this.$TelescopeFixedGS = missionVariables.$TelescopeFixedGS = 1; //with drawback (misjump)
}
else if(equipmentKey === ("EQ_GRAVSCANNER_FULLREPAIR") || equipmentKey === ("EQ_GRAVSCANNER2_FULLREPAIR") ) {
ps.removeEquipment(equipmentKey);
clock.addSeconds("3600");
this.$TelescopeFixedGS = missionVariables.$TelescopeFixedGS = 0;
}
else if(equipmentKey === ("EQ_SMALLDISH_REPAIR")) {
ps.setEquipmentStatus("EQ_SMALLDISH", "EQUIPMENT_OK");
ps.removeEquipment("EQ_SMALLDISH_REPAIR");
clock.addSeconds("3600");
this.$TelescopeFixedSD = missionVariables.$TelescopeFixedSD = 1; //with drawback (break during jump)
}
else if(equipmentKey === ("EQ_LARGEDISH_REPAIR")) {
ps.setEquipmentStatus("EQ_LARGEDISH", "EQUIPMENT_OK");
ps.removeEquipment("EQ_LARGEDISH_REPAIR");
clock.addSeconds("3600");
this.$TelescopeFixedLD = missionVariables.$TelescopeFixedLD = 1; //with drawback (break during jump)
}
else if(equipmentKey === ("EQ_SMALLDISH_FULLREPAIR")) {
ps.removeEquipment("EQ_SMALLDISH_FULLREPAIR");
clock.addSeconds("3600");
this.$TelescopeFixedSD = missionVariables.$TelescopeFixedSD = 0;
}
else if(equipmentKey === ("EQ_LARGEDISH_FULLREPAIR")) {
ps.removeEquipment("EQ_LARGEDISH_FULLREPAIR");
clock.addSeconds("3600");
this.$TelescopeFixedLD = missionVariables.$TelescopeFixedLD = 0;
}
else if( equipmentKey.substr(-7,7) === "_REFUND" ) {
//any eq which end with _REFUND means full refund the eq named before
ps.removeEquipment( equipmentKey ); //remove the "bought" refund eq
var eq = equipmentKey.substr( 0, equipmentKey.length-7 );//the real eq
if( ps.equipmentStatus( eq ) === "EQUIPMENT_OK" )
worldScripts.telescope.$Telescope_RefundEQ( eq );
else if( ps.equipmentStatus( eq ) === "EQUIPMENT_DAMAGED" ) //need check to avoid message at refund
player.consoleMessage("Need repair first"); //do not get full price back for a damaged eq
return;
}
}
this.shipBeingAttacked = function(whom) {
if( whom && whom.isValid ) {
var ws = worldScripts.telescope;
if( ws._index_in_list( whom, ws.$TelescopeAttackers ) === -1 )
ws.$TelescopeAttackers.push(whom); //add
var i = ws._index_in_list( whom, ws.$TelescopeList );
if( i > -1 ) ws.$TelescopeAttackeri = i + 1; //save last attacker
}
}
this.shipBeingAttackedUnsuccessfully = function(whom) {
if( whom && whom.isValid ) {
var ws = worldScripts.telescope;
if( ws._index_in_list( whom, ws.$TelescopeAttackers ) === -1 )
ws.$TelescopeAttackers.push(whom); //add
var ai = ws.$TelescopeAttackeri;
if( ai > 0 ) {
var a = ws.$TelescopeList[ ai - 1 ]; //if previous attacker is destroyed or too far
if( !a || !a.isValid || !a.isVisible ) ai = ws.$TelescopeAttackeri = 0;
}
if( ai === 0 ) {
var i = ws._index_in_list( whom, ws.$TelescopeList );
if( i > -1 ) ws.$TelescopeAttackeri = i + 1; //save attacker
}
}
}
this.shipKilledOther = function(whom /*,damageType*/) {
var ws = worldScripts.telescope;
var i = ws._index_in_list( whom, ws.$TelescopeList );
if( i > -1 ) ws.$Telescope_Scan();//forced rescan to remove from the list
}
this.shipLaunchedFromStation = function() {
var ps = player.ship;
this.$TelescopeFixedTel = missionVariables.$TelescopeFixedTel;
// if(this.$TelescopeFixedTel) log("Telescope", "FixedTel "+this.$TelescopeFixedTel);
this.$TelescopeFixedGS = missionVariables.$TelescopeFixedGS;
// if(this.$TelescopeFixedGS) log("Telescope", "FixedGS "+this.$TelescopeFixedGS);
this.$TelescopeFixedSD = missionVariables.$TelescopeFixedSD;
// if(this.$TelescopeFixedSD) log("Telescope", "FixedSD "+this.$TelescopeFixedSD);
this.$TelescopeFixedLD = missionVariables.$TelescopeFixedLD;
// if(this.$TelescopeFixedLD) log("Telescope", "FixedLD "+this.$TelescopeFixedLD);
this.$TelescopeGSC = missionVariables.$TelescopeGSC; //Gravity Scan counter to call aliens
if( !this.$TelescopeGSC ) this.$TelescopeGSC = 0; //start to count gravity scans
this.$TelescopeGSP = 0; //begin new gravity detection process
var ws = worldScripts.telescope;
ws.$Telescope_NewList();
ws.$TelescopeAttackers = [];
// if( ps.equipmentStatus("EQ_TELESCOPE") == "EQUIPMENT_OK" ) {
// if( ps && ps.weaponsOnline
// && ps.equipmentStatus("EQ_GRAVSCANNER") == "EQUIPMENT_OK" )
// player.consoleMessage("Turn off weapons for Gravity Scan.",10);
//// ws.$Telescope_Scan();//forced rescan
// }
// if( ws.$TelescopeV && ws.$TelescopeV.isValid ) {
//; log("Telescope", "shipLaunchedFromStation V:"+ws.$TelescopeV);//debug
ws.$Telescope_VClear();
// ws.$TelescopeV.remove();
// var i = system.allVisualEffects.indexOf( this.$TelescopeV );
// if( i > -1 ) system.allVisualEffects[i].remove();
// }
if( ps.viewPositionForward ) { //from oolite v1.79
ws.$TelescopeVPos = ps.viewPositionForward;
} else {
var p = new Vector3D(0,0,0);
if( worldScripts.shiplib && worldScripts.shiplib.$ShipLibVP ) {
var l = worldScripts.shiplib.$ShipLibVP; //view_position
var d = 0; //0. line contains the default data
for( var i = 1; i < l.length; i++ )
if( ps.dataKey && l && l[i]
&& ws._index_in_list( l[i].k, ps.dataKey ) > -1 ) {
d = i; //found
i = l.length; //end of for
}
// player.consoleMessage(l[d].f[0]+" "+l[d].f[1]+" "+l[d].f[2]);//debug
p = new Vector3D( l[d].f[0], l[d].f[1], l[d].f[2] );
} else {
var p1 = ws.$TelescopeVP;
p = new Vector3D( p1.forward[0], p1.forward[1], p1.forward[2] );
}
// player.consoleMessage(p,10);//debug
ws.$TelescopeVPos = p; //save corrected position
}
// if( worldScripts["genericHUDswitch - MilHUD.js"] ) { //was in MilHUD 0.9, removed in 0.92
// ws.$TelescopeVPos = ws.$TelescopeVPos.add([20,-25,70]);
// ws.$TelescopeRing = false; //do not show the ring around visual target
// ws.$TelescopeVSize = 1; //zoomed size of the visual target
// ws.$TelescopeVZoomSize = 1; //zoomed size of the visual target
// } else
ws.$TelescopeVPos = ws.$TelescopeVPos.add(ws.$TelescopeVPosHUD); //custom HUD position
ws.$Telescope_Scan(); //need to avoid list all ship name as newship
ws.$Telescope_StartTimer( 0 ); //no delay
}
this.shipScoopedOther = function(whom) {
// var w = worldScripts["telescope"].$TelescopeList [worldScripts["telescope"].$TelescopeListi - 1 ];
// log("Telescope", "Scooped "+w.isValid+w.name+" VMark:"+worldScripts["telescope"].$TelescopeVMark); //debug
var ws = worldScripts.telescope;
if( ws.$TelescopeVMark && whom === ws.$TelescopeList [ ws.$TelescopeListi - 1 ] ) { //remove shadowmarker if targeted
ws.$TelescopeVMark.remove();
ws.$TelescopeVMark = null;
}
}
this.shipSpawned = function(ship) { //detect missile launch immediately
// ship.setScript("oolite-default-ship-script.js");//debug
var ps = player.ship;
if( !ps || !ps.isValid || ps.docked //player died or docked
|| !worldScripts.telescope.$TelescopeTimerS //no timer means in witchspace
|| !ship || !ship.isValid || ship.isVisualEffect //invalid or effect
|| !ship.dataKey || ship.dataKey === "telescopemarker" //planet or marker
|| !ship.isWeapon ) //missile and mine only
return; //means no scan needed
var distance = ps.position.distanceTo( ship.position );
if( distance < ps.scannerRange ) //ship in range
worldScripts.telescope.$Telescope_Scan();//forced rescan to see launched missiles
}
this.shipTargetAcquired = function(target) { //if locked target by hand then set as the actual item in the list
// player.ship.targetSystem = 147;
// player.consoleMessage(target.name+" "+target.isBeacon);//debug
// var a = system.allShips; var s = "";//debug
// for( var i = 0; i < a.length; i++) s+=a[i]+"\n";//debug
//; log("Telescope", a.length+" Ships "+s);//debug
// a = system.allVisualEffects; s = "";//debug
// for( var i = 0; i < a.length; i++) s+=a[i]+"\n";//debug
// log("Telescope", a.length+" VEffs "+s);//debug
// a = system.filteredEntities(this, this.$Telescope_True, player.ship, player.ship.scannerRange); s = "";//debug
// for( var i = 0; i < a.length; i++) { s+=a[i]+"\n"; if(!a[i].isPlayer && !a[i].isStation) a[i].remove(); }//debug
// log("Telescope", a.length+" Nears: "+s);//debug
if(!target || !target.isValid || this.$TelescopeTargetSet === true ) return;
//no target or just set in $Telescope_Show() or list is empty
// log("Telescope", "TargetAcq: "+target);//debug
var i = -1;
var ws = worldScripts.telescope;
if( target && target.dataKey && target.dataKey === "telescopemarker" ) { //planet marker?
i = ws.$TelescopeListi;
ws.$TelescopeTarget = ws.$TelescopeList [ i - 1 ];
} else ws.$TelescopeTarget = target; //save the real target
if( i < 0 && ws.$TelescopeList && ws.$TelescopeList.length > 0 )
i = ws._index_in_list( target, ws.$TelescopeList ); //find target in list
if( i < 0 && target && target.isValid //not found, refresh the list (usually the target spawned after the last scan)
&& target !== ws.$TelescopePrevTargetAcq ) { //Military Jammer bugfix
//; log("Telescope", "ScanTA: "+target+" - "+ws.$TelescopePrevTargetAcq);//debug
ws.$TelescopePrevTargetAcq = target; //store to avoid repeated scan
ws.$Telescope_Scan(); //rescan
// ws.$Telescope_List3(0, true, true); //free refresh from the normal scanner - need fix, removed
i = ws._index_in_list( target, ws.$TelescopeList ); //find target in list
if( i < 0 ) ws.$TelescopeListi = 0; //target not in list
}
if( ( ws.$TelescopeShowVisualTarget || !player.ship.weaponsOnline )
&& ws.$TelescopeFixedTel !== 1 ) {
//player.consoleMessage(i);//debug
if( i >= 0) { //found
ws.$TelescopeListi = i + 1;
ws.$Telescope_Show2( false );
} else {
//; log("Telescope","shipTargetAcquired i:"+i+" ti:"+ws.$TelescopeListi);
ws.$Telescope_VShow();
}
}
}
this.shipTargetLost = function(losttarget) {
//; log("Telescope", "Losttarget: "+losttarget);//debug
var ws = worldScripts.telescope;
ws.$TelescopeTarget = null; //must to clear
if( ws.$TelescopeTargetSet === true //set by script or disabled
|| ws.$TelescopeIdentLock === 0 ) return;
var lostvalid = false; //target destroyed
if( losttarget && losttarget.isValid ) lostvalid = true; //target not destroyed but lost by ident keypress
ws.$Telescope_MostCentered( null, "ident", lostvalid ); //lock-unlock target
}
this.shipWillEnterWitchspace = function() {
var ps = player.ship;
this.$TelescopeReds = []; //store red ships detected earlier
if( this.$TelescopeFixedGS === 1 && Math.random() > 0.5 ) {
ps.scriptedMisjump = true; //meet Thargoids due to the cheap Grav.Sc. repair
player.consoleMessage("Gravity Scanner caused misjump!");
}
if( this.$TelescopeFixedSD === 1 && Math.random() > 0.2 ) {
ps.setEquipmentStatus("EQ_SMALLDISH", "EQUIPMENT_DAMAGED");
player.consoleMessage("Small Dish damaged during hyperjump!", 10);
}
if( this.$TelescopeFixedLD === 1 && Math.random() > 0.2 ) {
ps.setEquipmentStatus("EQ_LARGEDISH", "EQUIPMENT_DAMAGED");
player.consoleMessage("Large Dish damaged during hyperjump!", 10);
}
this.shipWillDockWithStation();
}
this.shipWillDockWithStation = function() {
var ws = worldScripts.telescope;
ws.$Telescope_NewList();
ws.$TelescopeAttackers = [];
ws.$Telescope_VClear();
if( isValidFrameCallback( ws.$TelescopeVFCB ) )
removeFrameCallback( ws.$TelescopeVFCB );
if( isValidFrameCallback( ws.$TelescopeVFCB2 ) )
removeFrameCallback( ws.$TelescopeVFCB2 );
if( isValidFrameCallback( ws.$TelescopeVFCB3 ) )
removeFrameCallback( ws.$TelescopeVFCB3 );
for(var i = 0; i < ws.$TelescopeVFCBM.length; i++) {
if( isValidFrameCallback( ws.$TelescopeVFCBM[i] ) )
removeFrameCallback( ws.$TelescopeVFCBM[i] );
ws.$TelescopeVFCBM[i] = null; //cag: converting to static arrays
}
if( ws.$TelescopeTimerS ) {
ws.$TelescopeTimerS.stop();
ws.$TelescopeTimerS = null;
}
}
this.shipWillExitWitchspace = function() { //use this event due to shipExitedWitchspace is not working in v1.77
var ws = worldScripts.telescope;
ws.$TelescopePlanetNames = []; //cache of names
ws.$TelescopeGSP = 0; //begin new gravity detection process
ws.$Telescope_NewList();
ws.$Telescope_AddShips(); //do not call shipLaunchedFromStation() to aovid a bug
this.$TelescopeTimerF = new Timer(this, ws.$Telescope_TimedF, 1, 0); //1s delay to launch FCBs after FarPlanets FCB!
}
this.shipWillLaunchFromStation = function( /*station*/ ) {
// player.consoleMessage(player.ship.targetSystem+" "+player.ship.galaxyCoordinatesInLY.x+" "+player.ship.galaxyCoordinatesInLY.y);//debug
// player.ship.targetSystem = 147;//debug
var ws = worldScripts.telescope;
ws.$TelescopeStaionNearby = false; //to send gravscanner message after launch
ws.$Telescope_AddShips();
}
this._index_in_list = function( item, list ) { // for arrays only; faster than indexOf
var k = list.length;
while( k-- ) {
if( list[ k ] === item ) return k;
}
return -1;
}
//Telescope methods
this.$Telescope_AddShips = function() {
if( !system.isInterstellarSpace ) { //need check due to called from shipWillExitWitchspace also
system.addShips("shuttle", 1, system.mainStation.position, 50000);//demo visible target
system.addShips("trader", 1, system.mainStation.position, 20000);//demo near target
// system.addShips("asteroid", 10, system.mainStation.position, 20000);//test rock target
// system.addShips("rescue_station", 1, system.mainStation.position, 20000);//test custom station
// system.addShips("rescue_blackbox", 1, system.mainStation.position, 10000);//test custom ship
// system.addShips("rescue_blackbox_generic", 1, system.mainStation.position, 10000);//test custom ship
// system.addShips("stealth_base", 1, system.mainStation.position, 20000);//test custom station
// system.addShips("stealth_barracuda", 1, system.mainStation.position, 10000);//test stealth ship
// system.addShips("stealth_mine", 1, system.mainStation.position, 20000);//test stealth mine
// system.addShips("vector_areidisAlpha", 1, system.mainStation.position, 20000);//test custom station
// system.addShips("vector_arn", 1, system.mainStation.position, 10000);//test custom ship
// system.addShips("griff_NPC_prototype_boa_decals_from_red_channel",
// 1, system.mainStation.position, 10000);//test visual effect shader uniforms, need Griff Boa OXP
if( worldScripts.telescope.$TelescopeThargoids ) { //test Telescope in instant action
system.addShips("tharglet", 4, system.mainStation.position, 30000);
system.addShips("thargoid", 4, system.mainStation.position, 30000);
// system.addShips("police", 4, system.mainStation.position, 30000);
player.ship.scriptedMisjump = true; //meet Thargoids in the next hyperjump also
}
}
}
this.$Telescope_Angle = function( angle ) { //show the side and up viewing angle of the target
var c = 90;
if( angle < 0 ) c = -90;
return( Math.round( angle * 180 / Math.PI - c ) + "°" );
}
this.$Telescope_Attacker = function(lock) { //lock on the last attacker
var ws = worldScripts.telescope;
var ai = ws.$TelescopeAttackeri;
var who = ws.$TelescopeList[ ai - 1 ];
//; log("Telescope", "Attacker ai:"+ai+" who:"+who);//debug
if( who && who.isValid && who.isVisible ) { //remove if destroyed or flyed too far
ws.$TelescopeListi = ai;
if( lock ) ws.$Telescope_Show(); //change player target to the nearest
return( who );
} else {
ws.$TelescopeAttackeri = 0; //clear to get another attacker
return false;
}
}
this.$Telescope_From = function(ship, whomposition) { //direction mark
// log("Telescope_From1", "ship:"+ship+" wp:"+whomposition);//debug
if( !ship || !ship.isValid || !whomposition || !whomposition.dot ) return ("");
var v = ship.position.subtract(whomposition);
var fw = ship.vectorForward.angleTo(v);
var ri = ship.vectorRight.angleTo(v);
var up = ship.vectorUp.angleTo(v);
var s = ""; // refine if out of front 1 degree cone
if( ri < 1.56 ) s += "<";
if( up > 1.58 ) s += "^";
else if( up < 1.56 ) s += "v";
if( ri > 1.58 ) s += ">";
// log("Telescope_From2", "v:"+v+" fw:"+fw+" ri:"+ri+" up:"+up+" s:"+s);//debug
if( s.length > 0 || fw < 1 ) //do not exclude the aft 1 degree cone
s = Math.round( 180 * ( 1 - fw / Math.PI ) ) + "° " + s;
return( s ); //show forward angle in degrees
}
this.$Telescope_GetDetect = function(who) { //read detection from the script_info telescope entry
var good = true; var d;
if( who.scriptInfo || who.isStation ) {//can give custom detection distance to the target ship
if( who.scriptInfo ) d = parseInt( who.scriptInfo.telescope );
if( d === 0 ) good = false;
else if( d > 0 || d < 0 ) good = true; //show custom station
else if( who.isStation && who.primaryRole !== "station" //d is NaN due to undefined scriptInfo key
&& who.primaryRole !== "coriolis"
&& who.primaryRole !== "dodo"
&& who.primaryRole !== "dodec"
&& who.primaryRole !== "dodecahedron"
&& who.primaryRole !== "ico"
&& who.primaryRole !== "icosa"
&& who.primaryRole !== "icosahedron"
&& who.primaryRole !== "rockhermit" ) {
var ps = player.ship;
if(ps && ps.isValid) { //hide custom station over 4x scanner range
var distance = ps.position.distanceTo(who.position);
if( distance > 4 * ps.scannerRange ) good = false;
}
}
}
//stealth ships and non-standard stations detected in normal scanner range only, requested by Svengali
if( good && ( who.dataKey && ( who.dataKey.indexOf("stealth") > -1
|| who.dataKey === "vector_arn" ) //mission ship in Vector OXP
|| who.primaryRole && ( who.primaryRole.indexOf("stealth") > -1
|| who.primaryRole.indexOf("rescue_blackbox") > -1 ) ) ) //mission ships in Rescue Stations OXP
good = false;
return( good );
}
this.$Telescope_GetMass = function(entity) { //read mass from the script_info telescope_mass entry
var em = entity.mass;
if( entity.scriptInfo ) { //can give custom mass to the ship
var e = parseInt(entity.scriptInfo.telescope);
if( e >= 0 ) em = e;
else if( e < 0 ) em += e; //substract the mass instead of overwrite it
//else telescope key not present, return the original mass
//; log("Telescope", "scriptInfo "+entity.name+":"+entity.scriptInfo.telescope+" e:"+e+" mass:"+em);//debug
}
return( em * Math.min( 1, worldScripts.telescope.$TelescopeGSP ) ); //reduce if GS not in full detection yet
}
this.$Telescope_GravOK = function() { //in the range of the Gravity Scanner if installed
if( player.ship && player.ship.equipmentStatus("EQ_GRAVSCANNER") == "EQUIPMENT_OK"
&& worldScripts.telescope.$TelescopeStaionNearby //near a station or baseship
&& !player.ship.weaponsOnline ) return true; //grav scan without weapons only to need force it
return false;
}
this.$Telescope_InRange = function(entity) { //Visible or in normal Scanner means in Telescope range
if( player.ship && player.ship.equipmentStatus("EQ_TELESCOPE") === "EQUIPMENT_OK" &&
( entity.isPlanet || entity.isSun || !entity.isCloaked && !entity.isVisualEffect
&& ( entity.dataKey //sun and planets has no dataKey
&& entity.dataKey !== "telescopemarker" ) //virtual target of far targets
&& ( !entity.isRock || entity.isStation || entity.isPiloted ) && //there are piloted "rocks" in lave.oxp
( ( entity.isVisible && player.ship.equipmentStatus("EQ_TELESCOPEEXT") === "EQUIPMENT_OK" )
|| entity.isBeacon || entity.beaconCode //beacons in the whole system
|| worldScripts.telescope.$Telescope_IsScannerTarget(entity)
|| worldScripts.telescope.$Telescope_InGravRange(entity) ) ) ) //or in grav.scanner
return true;
else return false;
}
this.$Telescope_InRangeFast = function(entity, listi) {
//less check than InRange due to checked before and speed is important
if( entity.isCloaked ) return false;
var ps = player.ship;
if( entity.isVisible && ps.equipmentStatus("EQ_TELESCOPEEXT") === "EQUIPMENT_OK"
|| entity.isBeacon || entity.beaconCode || entity.isPlanet || entity.isSun )
return true;//beacons in the whole system
var distance = ps.position.distanceTo(entity.position);
if( distance < ps.scannerRange ) return true; //target in the normal scanner
var ws = worldScripts.telescope;
if( !ws.$TelescopeListGD[ listi ] ) { //store max. grav. distance to next time check faster
var em = ws.$Telescope_GetMass( entity );
var gd = Math.pow( 100 * em, 1/3 );//reverse calculation of InGravRange
if( ps.equipmentStatus("EQ_LARGEDISH") === "EQUIPMENT_OK" ) {
gd = gd * 2; //large dish double range
var pm = ws.$Telescope_GetMass( ps );
if( pm > 1000000 ) gd = gd * 2; //huge player ship double range another time
if( pm > 100000000 ) gd = gd * 2; //baseship scan double range third time
} else if( ps.equipmentStatus("EQ_SMALLDISH") === "EQUIPMENT_OK" )
gd = gd * 1.33; //small dish 1.33x range
gd = gd * 500; //max. grav. distance of this ship in meters
ws.$TelescopeListGD[ listi ] = gd; //store
//; log("Telescope", "InRangeFast ship:"+entity.name+" em:"+Math.round(em)+"kg gd:"+Math.round(gd)+"m");//debug
}
if( distance < ws.$TelescopeListGD[ listi ] ) return true; //compare with the stored value
return false;
}
this.$Telescope_InGravRange = function(entity) { //in the range of the Gravity Scanner if installed
var ws = worldScripts.telescope;
if( ws.$Telescope_GravOK()
&& entity.isValid && !entity.isCloaked //can not detect if cloaked
&& entity.dataKey && entity.dataKey !== "telescopemarker" //virtual target of far targets
&& ( entity.isPiloted || entity.forwardWeapon ) //need to detect hostile drones from HardShips OXP
&& ( !entity.isRock || entity.isStation )
&& !entity.isVisualEffect ) {
var ps = player.ship;
var distance = ps.position.distanceTo(entity.position);
if( distance < ps.scannerRange ) return false; //near ships listed before
if( entity.isBeacon || entity.beaconCode || entity.isPlanet || entity.isSun )
return true; //beacons in the whole system
var d2 = distance / 500; //in half km, = 2 * distance / 1000, keep it in sync with InRangeFast
if( ps.equipmentStatus("EQ_LARGEDISH") === "EQUIPMENT_OK" ) {
var pm = ws.$Telescope_GetMass( ps );
if( pm.mass > 100000000 ) d2 = d2 / 2; //baseship scan double range
if( pm.mass > 1000000 ) d2 = d2 / 2; //huge player ship
d2 = d2 / 2; //others detected at double range (with huge 4x)
} else if( ps.equipmentStatus("EQ_SMALLDISH") === "EQUIPMENT_OK" )
d2 = d2 / 1.33; //small dish 1.33x range
var em = ws.$Telescope_GetMass( entity );
if( em > d2*d2*d2/100 ) return true; //mass scaled to third power of distance
}
return false;
}
this.$Telescope_IsCargo = function(entity) { //Cargo, Escape Pod, Station in visible range and Beacon anywhere
if( entity && entity.isValid && !entity.isVisualEffect ) {
if( entity.isBeacon || entity.beaconCode ) return true; //beacons identifyed by active radio broadcast
if( !entity.isPiloted && entity.isCargo || entity.isStation
|| entity.primaryRole && entity.primaryRole === "escape-capsule" ) {
if( worldScripts.telescope.$Telescope_IsVisible( entity ) )
return true; //visible
}
}
return false;
}
this.$Telescope_IsHostile = function(entity) {
var ps = player.ship;
var ws = worldScripts.telescope;
if( entity && entity.isValid && !entity.isVisualEffect
&& ( entity.isPiloted || entity.forwardWeapon ) //need to detect hostile drones from HardShips OXP
&& ws.$Telescope_InRange( entity )
&& !entity.isStation && !entity.isCloaked &&
( entity.target && entity.target === ps //target is hostile if targeting back
//or in the defenseTargets
|| ps.defenseTargets && ws._index_in_list( entity, ps.defenseTargets ) > -1
//or this ship in the defenseTargets of the other
|| entity.defenseTargets && ws._index_in_list( ps, entity.defenseTargets ) > -1 )
|| ws._index_in_list( entity, ws.$TelescopeReds ) > -1 ) //pirate or thargoid
return true;
else return false;
}
/* this.$Telescope_IsNonHostileStaion = function(entity) {
if( entity && entity.isValid && entity.isStation && !entity.isVisualEffect && !entity.isCloaked
&& entity.mass > 10000000 //skip ships with docking port (except baseships), rockhermit with 53508t must fit in
&& entity.target !== player.ship //target is hostile if targeting back
//or player is in the defenseTargets
&& ( !entity.defenseTargets || entity.defenseTargets.indexOf(player.ship) === -1 ) )
return true;
else return false;
}
*/
this.$Telescope_IsNotInTList = function(entity) { //asteroids, etc.
var ws = worldScripts.telescope;
if( entity && entity.isValid && !entity.isVisualEffect && !entity.isCloaked //else excluded from this list also
&& !entity.isPiloted && !entity.forwardWeapon && !entity.isCargo //approximately not in list for speedup
&& ws._index_in_list( entity, ws.$TelescopeList ) === -1 ) //surely not in list but slow alone
return( true );
else return( false );
}
this.$Telescope_IsPilotedShip = function(entity) { //non-hostile piloted ships
return( entity.isValid && !entity.isVisualEffect && !entity.isStation && !entity.isPlanet && !entity.isSun
&& ( entity.isPiloted || entity.forwardWeapon ) //need to detect drones from HardShips OXP
&& worldScripts.telescope.$Telescope_InRange( entity )
&& !entity.isCloaked && !this.$Telescope_IsHostile(entity) );
}
/* this.$Telescope_IsPilotedVisible = function(entity) {
if( entity && entity.isValid && !entity.isVisualEffect && !entity.isCloaked
&& ( entity.isPiloted || entity.forwardWeapon ) //need to detect drones from HardShips OXP
// && ( !entity.isRock || entity.isStation ) //too much asteroids, lock only in scannerRange
&& (( worldScripts.telescope.$Telescope_GetDetect( entity )
&& entity.isVisible && player.ship.equipmentStatus("EQ_TELESCOPEEXT") === "EQUIPMENT_OK" )
|| worldScripts.telescope.$Telescope_IsScannerTarget( entity ))
&& ( !entity.dataKey || entity.dataKey !== "telescopemarker" ) )
return true;
return false;
}
*/
// there is now a copy of this inside _TimedS_closure
this.$Telescope_IsScannerTarget = function(entity) { //call to surely detect all small targets in scanner
var ps = player.ship;
if( entity && entity.isValid && !entity.isVisualEffect && entity.dataKey //sun and planets has no dataKey
&& !entity.isCloaked && ps && ps.isValid ) {
var distance = ps.position.distanceTo(entity.position);
if( distance < ps.scannerRange ) return true; //target in the normal scanner
}
return false;
}
this.$Telescope_IsValid = function(entity) { //help to find most centered
if( !entity || !entity.isValid || ( !entity.dataKey && !entity.isPlanet && !entity.isSun ) )
return false; //Sun and Planets has no dataKey
// var angle = player.ship.vectorForward.angleTo(player.ship.position.subtract(entity.position));
// log("Telescope","angle:"+angle+" entity:"+entity.name);//debug
// if( angle < worldScripts.telescope.$TelescopeAutoLockRad ) { //in auto degree
if( !entity.isVisualEffect || entity.dataKey && entity.dataKey.indexOf("telescope-") > -1 )
return true;
// }
return false;
}
this.$Telescope_IsVisible = function(entity) {
if( !entity.isVisualEffect && ( entity.dataKey || entity.isPlanet || entity.isSun ) //sun and planets has no dataKey
&& ( !entity.isRock || entity.isStation ) //too much asteroids, lock only in scannerRange
&& !entity.isCloaked
&& ( ( entity.isVisible && player.ship.equipmentStatus("EQ_TELESCOPEEXT") === "EQUIPMENT_OK" )
|| worldScripts.telescope.$Telescope_IsScannerTarget(entity) ) ) return true;
return false;
}
this.$Telescope_List = function(step) {
//no scan if there are a list already, show again the message only
worldScripts.telescope.$Telescope_List2(step, false);
}
this.$Telescope_List2 = function(step, forcedscan) {
worldScripts.telescope.$Telescope_List3(step, forcedscan, false);
}
this.$Telescope_List3 = function(step, forcedscan, free) {
var ps = player.ship;
if( !ps || !ps.isValid ) return; //if player died
var ws = worldScripts.telescope;
var list = ws.$TelescopeList;
var len = list.length;
var ti = ws.$TelescopeListi;
if(ps.equipmentStatus("EQ_TELESCOPE") === "EQUIPMENT_DAMAGED") {
player.consoleMessage("Telescope damaged");
ws.$Telescope_NewList();
} else if(ps.equipmentStatus("EQ_TELESCOPE") !== "EQUIPMENT_OK") {
if( ws.$TelescopeBuyMsg ) {
player.consoleMessage("Buy Telescope! (x)");
ws.$TelescopeBuyMsg = false;
}
ws.$Telescope_NewList(); //needed when destroyed
//else silent exit (no Telescope when called from shipTargetLost)
} else {
ws.$TelescopeTargetSet = true;
var forcedship = null;
if( ti > 0 )
forcedship = list[ti - 1];
// var who = null;
if(step < 0) ws.$TelescopeListi--; //step backward in list
else if(step > 0) ws.$TelescopeListi++; //step forward in list
ti = ws.$TelescopeListi;
// player.consoleMessage(step+" "+ws.$TelescopeListi);//debug
if( forcedscan || !list
|| ti < 1
|| len < ti ) {
//if forced to scan or no list yet or listed all items then rescan
if(ps.energy < 64)
player.consoleMessage("Not enough energy for Telescope");
else {
ws.$Telescope_NewList();
//detect hostile ships in normal scanner
var st = system.filteredEntities(this, this.$Telescope_IsHostile,
ps, ps.scannerRange);
// var st1 = st.length;
if(st && st[0]) ws.$Telescope_ListAdd(st); //add to the list if any
//detect non-hostile piloted ships in normal scanner
st = system.filteredEntities(this, this.$Telescope_IsPilotedShip,
ps, ps.scannerRange);
// var st2 = st.length;
if(st && st[0]) ws.$Telescope_ListAdd(st); //add to the list if any
//detect visible cargoes, stations and all beacons
st = system.filteredEntities(this, this.$Telescope_IsCargo,
ps, 2*ps.scannerRange);
// var st3 = st.length;
if(st && st[0]) ws.$Telescope_ListAdd(st); //add to the list
var st4 = 0;
if( free ) { //add the previously scanned far ships
ws.$Telescope_VFCBShrinkVMarks();//new far marks needed
ws.$Telescope_ListAdd2(
ws.$TelescopeListFar,
ws.$TelescopeListFarPos ); //old positions
} else {
ps.energy -= 2; //use a little energy to scan the whole sky
var sc = "Telescope";
if( ws.$Telescope_GravOK() ) {
ps.energy -= 6; //need 4x energy with Gravity Scanner
ws.$TelescopeSoundScan.play();//GS scan sound
sc = "Gravity scan";
if( ws.$TelescopeGSP < 1 )
sc += " "+Math.round(ws.$TelescopeGSP*100)
+"% done,";
//Gravity Scan counter to bring aliens
missionVariables.$TelescopeGSC = ++ws.$TelescopeGSC;
var p = 200; //at every 200. scan
if( ws.$TelescopeFixedGS === 1 ) p = 100; //every 100. scan
var g = ws.$TelescopeGSC / p;
if( g === Math.floor( g ) ) {
var n = Math.ceil( Math.pow( player.score, 0.5 ) / 10 );
if( n > 0 ) { //with 0 score do not get any
player.consoleMessage("Aliens detected your Gravity Scan!",10);
system.addShips("thargoid", n, ps.position, 50000);
}
}
}
ws.$Telescope_NewFarList();
//detect ships NOT in normal scanner
st = system.filteredEntities(this, this.$Telescope_InRange, ps,
ws.$TelescopeMaxRange);//to avoid bugs
st4 = st.length;
if(st && st[0]) ws.$Telescope_ListFarAdd(st); //add to the list
//finally planets
st = system.planets;
if(st && st[0]) ws.$Telescope_ListFarAdd(st); //add to the list
if( !system.isInterstellarSpace && system.sun && system.sun.isValid )
ws.$Telescope_ListFarAdd(system.sun); //add sun to the end of the list
//send message about scan
len = ws.$TelescopeList.length;
if( !forcedscan ) {
var msg = "No";
if( len > 0 ) msg = sc+" found "+len;
var s = "";
if( len > 1 ) s = "s";
player.consoleMessage(msg+" target"+s, 5);
}
}
//; log("Telescope", "filteredEntities: "+st1+", "+st2+", "+st3+", "+st4+" list:"+ws.$TelescopeList.length+" allShips:"+system.allShips.length); //debug
ws.$Telescope_TimedVMC(); //make colours to the new list
}
}
if( ps.target && ps.target.isValid ) {
ti = 0;
list = ws.$TelescopeList;
len = list.length;
if( forcedship && ps.target.dataKey
&& ps.target.dataKey === "telescopemarker" ) //far target
ti = ws._index_in_list( forcedship, list ) + 1;
else ti = ws._index_in_list( ps.target, list ) + 1;
if( ti > 0 ) {
if( step < 0 ) {
ti--; //step backward in list
if( ti <= 0 ) ti = len;
} else if( step > 0 ) {
ti++; //step forward in list
if( ti > len ) ti = 1;
}
} else ti = 0;
if( ti > 0 ) {
var who = list[ ti - 1 ];
var limit = len;
while( ws._is_ignored_ship( ws, who ) && limit > 0 ) {
ti += step;
limit--;
if( ti <= 0 ) ti = len;
if( ti > len ) ti = 1;
who = list[ ti - 1 ];
}
if( limit === 0 ) ti = 0;
}
ws.$TelescopeListi = ti;
// if( forcedscan ) ws.$Telescope_Show2( false ); //do not show name - removed due to a target changer bug reported by Bogatyr
if( !forcedscan ) ws.$Telescope_Show(); //target name with list number
} //else leave listi on 0 to do not nock anything, show lightballs only
//; log("Telescope", "List step:"+step+" forcedscan:"+forcedscan+" listi:"+ws.$TelescopeListi+" ship:"+ws.$TelescopeList[ws.$TelescopeListi-1]);//debug
ws.$TelescopeTargetSet = false;
}
}
this.$Telescope_ListAdd = function(newitems) { //add to the main list
worldScripts.telescope.$Telescope_ListAdd2(newitems, null); //with fresh positions
}
this.$Telescope_ListAdd2 = function(newitems, pos) { //can append the old scanned far list to the new free list
var ws = worldScripts.telescope;
for(var i = 0; i < newitems.length && ws.$TelescopeList.length <
ws.$TelescopeTargets; i++) { //limited number of targets to save CPU
var who = newitems[i]; var p;
if( who && who.isValid &&
ws._index_in_list( who, ws.$TelescopeList ) === -1 ) {
if( ws.$Telescope_GetDetect( who )
|| ws.$Telescope_IsScannerTarget( who ) ) {
if( pos ) p = pos[i]; //old saved position
else p = who.position; //fresh position
ws.$TelescopeListPos.push( p );
ws.$TelescopeList.push(who);
}
}
}
}
this.$Telescope_ListFarAdd = function(newitems) { //add to the far and main list also
var ws = worldScripts.telescope;
for(var i = 0; i < newitems.length; i++) {
var who = newitems[i];
if( who && who.isValid &&
ws._index_in_list( who, ws.$TelescopeListFar ) === -1 ) {
ws.$TelescopeListFarPos.push(who.position);
ws.$TelescopeListFar.push(who);
}
}
ws.$Telescope_ListAdd(newitems); //add to the main list also
}
/* this.$Telescope_MFDTarget = function(ws, ps, who) { //helper function for building MFD in TimedS
if( who && who.isValid ) {
var v = ws.$Telescope_ShowName2(who, who.position);
if( v && v.length > 0 && v.indexOf("(Lost ") === -1 ) {
if( who === ps.target || //current target
ps.target && ps.target.dataKey
&& ps.target.dataKey === "telescopemarker" //get the original target
&& who === ws.$TelescopeList[ ws.$TelescopeListi - 1 ] )
v = "[ "+v+" ]"; //mark the current target
return( v+"\n" );
}
}
return false;
}
*/
this.$Telescope_MostCentered = function( skiptarget, mode, lostvalid ) {
var ws = worldScripts.telescope;
//; log("Telescope", "MostCentered "+skiptarget+" "+mode+" "+lostvalid+" "+ws.$TelescopeIdentUnLock);//debug
var mct = null;
var ps = player.ship;
//in red alert find most centered hostile first if not supressed with offline weapons
if( player.alertCondition > 2 && ps.weaponsOnline && mode === "mode" ) {
// mct = ws.$Telescope_Attacker(false); //fallback to last attacker - old method
//; if(mct) log("Telescope", "Ident lock on attacker: "+mct.name);//debug
mct = ws.$Telescope_MostCentered2( skiptarget, mode, true, true );//ships attacking player
// log("Telescope", "mct1:"+mct); //debug
if(!mct) {
mct = ws.$Telescope_MostCentered2( skiptarget, mode, true, false );//ships targeting player
// log("Telescope", "mct2:"+mct); //debug
}
}
//if no hostile then fallback to normal check
if(!mct) mct = ws.$Telescope_MostCentered2( skiptarget, mode, false, false );
if( mct ) {
if( mct.dataKey && mct.dataKey === "telescopemarker" ) {//markership
mct = ws.$TelescopeTarget; //the real target behind the markership
}
var mi = ws._index_in_list( mct, ws.$TelescopeList );
if( mi > -1 ) {
//ident mode do unlock if pressed second time with the same most centered target
if( mode !== "ident" || mi + 1 !== ws.$TelescopeListi ) {
//; log("Telescope", "MostCenteredTarget: "+mct.name+" mi:"+mi);//debug
if( !ps.weaponsOnline && mode === "ident" ) {//restore GravLock if ident lock target
ws.$TelescopeGravLock2 = ws.$TelescopeGravLock;
player.consoleMessage("Panorama targeting turned ON.");
}
if( ws.$TelescopeListi !== mi + 1 ) {
ws.$TelescopeListi = mi + 1;
ws.$Telescope_Show2( false ); //lock target
}
} else {
if( mode === "ident" && ws.$TelescopeIdentUnLock ) { //unlock target after steer (3. ident press)
ws.$TelescopeIdentUnLock = false;
//; log("Telescope", "MCT ident unlock");//debug
if( !ps.weaponsOnline && mode === "ident" && lostvalid ) {
//shrink GravLock if ident unlock target by keypress and not by target destroyed
ws.$TelescopeGravLock2 = ws.$TelescopeAutoLock;
player.consoleMessage("Panorama targeting turned OFF.");
}
ws.$TelescopeListi = 0;
//the following lines cause crash to desktop in 1.77 after some fight when a targeted Tharglet is exploding
// ws.$Telescope_VClear();
if( ps.target ) {
// log("Telescope", "MostCenteredTarget unlock: "+mct.name+" mi:"+mi);//debug
ws.$TelescopeTargetSet = true;//to avoid doubled message
ps.target = null;
ws.$TelescopeTargetSet = false;
}
ws.$TelescopeTarget = null; //clear after(!) player target cleared
} else if( mode === "ident") { //second ident press start steering to the target
ws.$TelescopeIdentUnLock = true; //next time will do unlock
ws.$TelescopeListi = mi + 1;
ws.$Telescope_Show2( false ); //lock target
if( ws.$TelescopeSteering > 0 )
if( ps.velocity.magnitude() < ps.maxSpeed * 1.1 )
//prevent unwanted steer when lost marker at high speeds
ws.$Telescope_Steer();//turn to the target
}
}
}
}
}
this.$Telescope_MostCentered2 = function( skiptarget, mode, red, attacker ) {
var ps = player && player.ship;
if( !ps || !ps.isValid ) return false;
var psp = ps.position;
var ws = worldScripts.telescope;
function closest_to( target_vector ) {
var min_a = rad;
var best = -1; // ie. not init'd
var best_d = ws.$TelescopeMaxRange;
var angle, distance, i;
for( i = 0; i < list.length; i++ ) { //search target near the center
var test = list[ i ];
if( !test || !test.isValid ) continue; // brought $Telescope_MostCenteredCheck inline
if( test === skiptarget ) continue;
if( red && mode === 'ident' && test.target !== ps ) continue;
// in red alert w/ mode 'ident', check only hostiles
angle = target_vector.angleTo( test.position.subtract( psp ) );
if( angle > min_a ) continue;
distance = psp.distanceTo( test.position );
if( min_a === rad ) { // 1st target found
best_d = distance;
min_a = angle;
best = i;
continue;
}
if( Math.abs( angle - min_a ) < Math.PI / 360 ) { // for ships within a half degree, pick the closer one
if( distance > best_d ) continue;
}
best_d = distance;
min_a = angle;
best = i;
}
return best;
}
function find_target() {
var dir = ps.viewDirection;
if( dir === "VIEW_FORWARD" ) return closest_to( ps.vectorForward );
else if( dir === "VIEW_AFT" ) return closest_to( ps.vectorForward.multiply(-1) );
else if( dir === "VIEW_STARBOARD" ) return closest_to( ps.vectorRight );
else if( dir === "VIEW_PORT" ) return closest_to( ps.vectorRight.multiply(-1) );
return -1;
}
var list = ws.$TelescopeList; //search in the list only (stable)
var rad = ws.$TelescopeIdentLock * Math.PI / 180; ///angle in radians
var result = -1;
if( attacker ) {
list = ws.$TelescopeAttackers;
red = false;
} else if( player.alertCondition > 2 && ps.weaponsOnline ) {//in red alert find most centered hostile if not supressed with offline weapons
rad = Math.PI; //in Red Alert lock from the whole sphere who target you
red = true;
}
if( mode === "ident" ) { //button "r" pressed or target lost
if( player.alertCondition < 3 ) { //do not target asteroids before ships in red alert
// log("Telescope", "MCT calling filteredEntities"); //debug
// var list = system.filteredEntities(this, this.$Telescope_IsValid, ps, ps.scannerRange); - cause bug
list = system.filteredEntities(ws, ws.$Telescope_IsNotInTList, ps, ps.scannerRange);
// log("Telescope", "MCT filteredEntities returned "+list.length); //debug
rad = ws.$TelescopeIdentLock * Math.PI / 180; ///angle in radians
result = find_target();
if( result > -1 ) { //found, target it
return( list[ result ] ); //priority to targets not in list but in crosshairs for asteroid hunting
}
} //if no asteroid in crosshairs then do normal ident to a ship in telescope list
list = ws.$TelescopeList;
red = false;
} else if( mode === "auto" ) { //lock in the crosshairs only
if( ws.$TelescopeAutoLock <= 0 ) return false; //if disabled
rad = ws.$TelescopeAutoLock * Math.PI / 180; ///angle in radians
} else if( mode === "grav" ) { //panorama targeting or lock in the crosshairs
rad = ws.$TelescopeGravLock2 * Math.PI / 180; ///angle in radians
} else if( mode === "mode" ) { //button "b" pressed after primed Telescope equipment with Shift+N
if( red ) rad = Math.PI;//in Red Alert lock from the whole sphere who target you
}
//; log("Telescope", "MostCentered2 "+mode+" "+l);//debug
// if( ps && ps.isValid && ps.target ) skiptarget = ps.target; //search another target
result = find_target();
if( result > -1 ) { //found, target it
return( list[ result ] );
}
return false;
}
/* this.$Telescope_Nearest = function() { //lock the nearest target
// var attacker = false;
var ws = worldScripts.telescope;
var ps = player.ship;
var i, nd, nai, who, ni = 0, d = null;
//in Red Alert lock the last attacker if any and weapons are online
if( player.alertCondition > 2 && ps.weaponsOnline ) {
// attacker = ws.$Telescope_Attacker( true ); //last attacker - old method
nd = ws.$TelescopeMaxRange; //reset to max.
nai = -1;
for( i = 0; i < ws.$TelescopeAttackers.length; i++ ) {
who = ws.$TelescopeAttackers[ i ];
ni = ws._index_in_list( who, ws.$TelescopeList );
if( who && who.isValid && ni > -1 && !who.isDerelict ) {
d = ps.position.distanceTo( who.position ); //distance to the attacker
if( d < nd ) { //nearer than the last nearest
nd = d; //save the new nearest distance
nai = ni; //save the index in the main list
}
} else { //remove if destroyed, derelict or not in TelescopeList
ws.$TelescopeAttackers.splice( i, 1 ); //remove from the array
i--; //stay on this position due to the array is shorter
}
}
if( nai > -1 ) { //change player target to the nearest attacker
ws.$TelescopeListi = nai + 1;
ws.$Telescope_Show();
}
} else { //lock the nearest target
// if( !attacker ) {
ni = ws.$TelescopeNearesti;
who = ws.$TelescopeList[ ni - 1 ];
if( ps && ( !who || !who.isValid ) ) {
ws.$Telescope_Scan(); //forced scan
ni = ws.$TelescopeNearesti;
who = ws.$TelescopeList[ ni - 1 ];
}
//; log("Telescope", "Nearest ni:"+ni+" who:"+who);//debug
if( ps && who && who.isValid ) {
ws.$TelescopeListi = ni;
ws.$Telescope_Show(); //change player target to the nearest
}
}
}
*/
this.$Telescope_Nearest = function() { //lock the nearest target
// var attacker = false;
var ws = worldScripts.telescope;
var ps = player.ship;
var i, nd, nai, who, ni = 0, d = null;
function nearest( list ) {
nd = ws.$TelescopeMaxRange; //reset to max.
let near = -1;
let len = list.length;
for( i = 0; i < len; i++ ) {
who = list[ i ];
if( ws._is_ignored_ship( ws, who ) ) continue;
ni = list === ws.$TelescopeList ? i : ws._index_in_list( who, ws.$TelescopeList );
if( who && who.isValid && ni > -1 && !who.isDerelict ) {
d = ps.position.distanceTo( who.position ); //distance to the attacker
if( d < nd ) { //nearer than the last nearest
nd = d; //save the new nearest distance
near = ni; //save the index in the main list
}
} else { //remove if destroyed, derelict or not in TelescopeList
ws.$TelescopeAttackers.splice( i, 1 ); //remove from the array
i--; //stay on this position due to the array is shorter
}
}
return near;
}
//in Red Alert lock the last attacker if any and weapons are online
if( player.alertCondition > 2 && ps.weaponsOnline ) {
// attacker = ws.$Telescope_Attacker( true ); //last attacker - old method
nai = nearest( ws.$TelescopeAttackers );
if( nai > -1 ) { //change player target to the nearest attacker
ws.$TelescopeListi = nai + 1;
ws.$Telescope_Show();
return;
}
}
nai = nearest( ws.$TelescopeList );
if( nai > -1 ) { //change player target to the nearest attacker
ws.$TelescopeListi = nai + 1;
ws.$Telescope_Show();
}
}
this.$Telescope_NewFarList = function() {
// log("Telescope","NewFarList");
var ws = worldScripts.telescope;
ws.$TelescopeListFar = [];
ws.$TelescopeListFarPos = [];
}
this.$Telescope_NewList = function() {
//; log("Telescope","NewList");
var ws = worldScripts.telescope;
ws.$Telescope_NewFarList();
ws.$TelescopeAttackeri = 0;
ws.$TelescopeList = [];
ws.$TelescopeListGD = [];
ws.$TelescopeListPos = [];
ws.$TelescopeListi = 0;
ws.$TelescopeNearestd = ws.$TelescopeMaxRange;
ws.$TelescopeNearesti = 0;
var m = ws.$TelescopeMMarks;
var i = 0;
for( i = 0; i < m.length; i++ ) {
if( m[i] ) m[i].remove();
ws.$TelescopeMMarks[i] = null;
}
ws.$TelescopeMMarks = [];
m = ws.$TelescopeMRings;
for( i = 0; i < m.length; i++ ) {
if( m[i] ) m[i].remove();
ws.$TelescopeMRings[i] = null;
}
ws.$TelescopeMRings = [];
m = ws.$TelescopeVMarks;
for( i = 0; i < m.length; i++ ) {
if( m[i] ) m[i].remove();
ws.$TelescopeVMarks[i] = null;
}
ws.$TelescopeVMarks = [];
ws.$TelescopeVMCs = [];
}
this.$Telescope_PlanetName = function(who) { //cached names
if( !system || !system.planets || system.planets.length < 1 || !who || (!who.isPlanet && !who.isSun ))
return("");
var ws = worldScripts.telescope;
var name = '';
if( who.isSun ) {
name = ws.$TelescopePlanetNames.sun;
if( !name || name.length < 1 ) {
name = ws.$Telescope_PlanetName2(who);
ws.$TelescopePlanetNames.sun = name;
}
} else {
var i = ws._index_in_list( who, system.planets );
if( i === -1 ) return("");
name = ws.$TelescopePlanetNames[i];
if( !name || name.length < 1 ) {
name = ws.$Telescope_PlanetName2(who);
ws.$TelescopePlanetNames[i] = name;
}
}
return( name );
}
this._isNotPlanet = function (entity) {return(!entity.isPlanet);}
this._allPlanets = function (entity) {return entity.isPlanet;}
this.$Telescope_PlanetName2 = function(who) {
var ws = worldScripts.telescope;
var name = "Planet";
var p = null;
if( system && who && who.isValid ) {
if( who.isSun ) return("Sun of "+system.name);
if( !who.isPlanet ) return("Non-Planet");
var wn = worldScripts.planetnames;
if( wn ) {
name = wn.$PlanetNames_GetPlanetName( who );
if( name && name.length > 0 ) return( name );
}
if( worldScripts["planetaryCompass_worldScript.js"] ) {
p = system.filteredEntities(this, this._isNotPlanet, who, 10);
//; log("Telescope","PlanetName2 "+p);
if( p && p[0] && p[0].isValid && p[0].isVisualEffect && p[0].displayName )
return( p[0].displayName );
}
name = system.name;
if( who.isMainPlanet ) name += " Prime (Planet)";
else {
p = system.filteredEntities(this, this._allPlanets, system.sun); //order by distance from sun
if( who.hasAtmosphere ) {
var n = [ "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X",
"XI", "XII", "XIII", "XIV", "XV", "XVI", "XVII", "XVIII", "XIX", "XX" ];
var no = 0;
var i = ws._index_in_list( who, p );
if( i < n.length ) no = n[i];
else no = i;
name += " "+no+" (Planet)";
} else name = "Moon "+(ws._index_in_list( who, p )+1);
}
}
return( name );
}
this.$Telescope_RefundEQ = function( eq ) {
var ws = worldScripts.telescope;
var ps = player.ship;
if( ws._index_in_list( eq, ps.equipment ) ) {
if( ps.equipmentStatus( eq ) === "EQUIPMENT_DAMAGED" )
player.consoleMessage("Need repair first"); //do not get back full price for a damaged eq
else if( ps.equipmentStatus( eq ) === "EQUIPMENT_OK" ) {
ps.removeEquipment( eq );
clock.addSeconds ("3600");
var refund = EquipmentInfo.infoForKey( eq ).price / 10; ///
player.credits += refund;
player.consoleMessage("Refunded "+refund+" credits for "+EquipmentInfo.infoForKey( eq ).name);
return( refund );
}
}
return( 0 );
}
this.$Telescope_Scan = function() {
worldScripts.telescope.$Telescope_List2( 0, true ); //forced to scan
}
this.$Telescope_SetLightballs = function( subitem ) { //set config variables from telescopeeq.js also
var ws = worldScripts.telescope;
// if( subitem == 1 ) { //off
ws.$TelescopeLightBalls = false;
ws.$TelescopeShipLightBalls = false;
ws.$TelescopeMassLockBorders = false;
ws.$TelescopeBrightMassLockBorders = false;
ws.$TelescopeLargeLightBalls = false;
if( subitem >= 2 ) ws.$TelescopeLightBalls = true; //ship off
if( subitem >= 3 ) ws.$TelescopeShipLightBalls = true; //small
if( subitem >= 4 ) ws.$TelescopeMassLockBorders = true; //25.6km but in green alert only
if( subitem >= 5 ) ws.$TelescopeBrightMassLockBorders = true; //use brighter borders
if( subitem >= 6 ) ws.$TelescopeLargeLightBalls = true;//large
}
this.$Telescope_SetSniper = function( subitem ) {
var ws = worldScripts.telescope;
if( subitem === 1 ) { //off
ws.$TelescopeSniperRange = 10000;
ws.$TelescopeSniperMinRange = 10000;
} else {
var minitem = subitem;
if( subitem < 5 ) ws.$TelescopeSniperRange = 25600;
else { minitem = subitem - 3; ws.$TelescopeSniperRange = 30000;}
ws.$TelescopeSniperMinRange = 5000 * (minitem-1); //5, 10 or 15km
}
}
this.$Telescope_SetSteering = function( subitem ) {
worldScripts.telescope.$TelescopeSteering = subitem - 1;
}
this.$Telescope_SetTargets = function( subitem ) {
var ws = worldScripts.telescope;
if( subitem === 1 ) { //20 and limitation in red alert
ws.$TelescopeRedAlertLimiter = true;
ws.$TelescopeTargets = 20;
} else {
ws.$TelescopeRedAlertLimiter = false;
if( subitem === 2 ) ws.$TelescopeTargets = 50;
else if( subitem === 3 ) ws.$TelescopeTargets = 100;
else ws.$TelescopeTargets = 200;
}
}
this.$Telescope_SetVisual = function( subitem ) {
var ws = worldScripts.telescope;
if( subitem === 1 ) {
ws.$TelescopeShowVisualTarget = false; //off
ws.$TelescopeVZoomSize = 0; //off without weapons also
}
if( subitem <= 2 ) ws.$TelescopeShowVisualTarget = false; //weapons off
else ws.$TelescopeShowVisualTarget = true;
if( subitem <= 3 ) {
if( subitem > 1 && ws.$TelescopeRing ) {
ws.$TelescopeRing = false; //no ring
ws.$TelescopeVSize += 3; //due to ring turned off
ws.$TelescopeVZoomSize = ws.$TelescopeVSize;
}
} else {
if( subitem > 1 && !ws.$TelescopeRing ) {
ws.$TelescopeRing = true;
ws.$TelescopeVSize -= 3; //due to ring turned on
ws.$TelescopeVZoomSize = ws.$TelescopeVSize + 3;
}
}
if( subitem <= 4 ) ws.$TelescopeShowVisualStation = false; //no station
else ws.$TelescopeShowVisualStation = true;
if( subitem <= 5 ) ws.$TelescopeShowVisualQuestionMark = false; //no "?"
else ws.$TelescopeShowVisualQuestionMark = true;
}
this.$Telescope_SetVisualSize = function( subitem ) {
var ws = worldScripts.telescope;
if( ws.$TelescopeRing ) ws.$TelescopeVSize = subitem; //1-8
else ws.$TelescopeVSize = subitem + 3; //without ring is equal with zoomed
ws.$TelescopeVZoomSize = subitem + 3; //3-10
}
this.$Telescope_Show = function() { //inputs: $TelescopeList array, $TelescopeListi item index to show
worldScripts.telescope.$Telescope_Show2( true );
}
this.$Telescope_Show2 = function( showname ) { //call with showname=true if eq step pressed
var ws = worldScripts.telescope;
//must use ws.$Telescope* and not this.$Telescope* to do not crash the game
var ti = ws.$TelescopeListi;
if( ws.$TelescopeList && ti > 0
&& ws.$TelescopeList.length >= ti ) {
var who = ws.$TelescopeList[ ti - 1 ];
if( who ) {
if( worldScripts.detectors && who.isValid && who.script && who.script.$Detectors_Origname )
who.displayName = who.script.$Detectors_Origname;
//show short name in automatic lock message
// log("Telescope", "Show pt:"+player.ship.target+" who:"+who+" tt:"+ws.$TelescopeTarget);//debug
if( player.ship.target !== who //to avoid repeated ident lock sound and message
&& ws.$TelescopeTarget !== who) { //far target
if( ws.$TelescopeTimerA ) { //restart timer if already running
ws.$TelescopeTimerA.stop();
ws.$TelescopeTimerA = null;
}
if( showname )
ws.$TelescopeTimerA = new Timer(this, ws.$Telescope_TimedA, 0.05, 0);
//return; //if the wait time of the timer set to 0.01 then buggy on Intel Atom netbook
//but good on i3: if see coriolis then can not step to the next target (relock the base)
//without timer the same bug happen on desktop i3
else ws.$Telescope_TimedA();
//if called from shipTargetLost then must to lock new target instantly to avoid
//ident system active message
}
}
if( showname ) ws.$Telescope_ShowName(ti, who,
ws.$TelescopeListPos[ ti - 1 ] ); //fallback pos if lost target
if( ( ws.$TelescopeShowVisualTarget || !player.ship.weaponsOnline )
&& ws.$TelescopeFixedTel !== 1 ) {//no visual mode if cheaply fixed
//; log("Telescope","Show2 ti:"+ti+" who:"+who);
ws.$Telescope_VShow();
}
}
}
this.$Telescope_ShowName = function(ti, who, position) {
var ws = worldScripts.telescope;
var msg = ws.$Telescope_ShowName2(who, position);
if( !msg || msg.length <= 0 ) return;
var idlast = "";
if( ti > 0 && ws.$TelescopeList.length <= ti ) idlast = " last";
var tis = "";
if( ti ) tis = " ("+ti+"."+idlast+")";
// msg+=" ("+Math.round( ws.$TelescopeZoom )+"x)"; //debug
if( ws.$TelescopeCMFD ) { //show in Combat MFD instead of console
ws.$TelescopePrevMFDTarget = who; //store for MFD
if(msg && msg.length > 0) ws.$TelescopeCMFD.$TelescopeLine = msg;
} else player.consoleMessage( msg+tis, 4.5 ); //fallback to console, showtime matched to ident message
//; log("Telescope", msg+tis); //debug
}
this.$Telescope_ShowName2 = function(who, position) {
var ws = worldScripts.telescope;
var name = "";
if( who && who.isValid ) {
if( who.name && ( who.name === "Railgun Projectile"
|| who.name === "Debris" //do not show launched bullets
|| who.name.indexOf("customshields") > -1 ) ) return; //nor customshields parts
if( ws.$Telescope_InRange( who ) )
position = who.position; //got fresh data from the normal scanner or the telescope
if( who.script && who.script.$Detectors_Origname )
name = who.script.$Detectors_Origname;
else if( who.displayName && who.displayName.length > 0 )
name = who.displayName;
else if( who.isPlanet || who.isSun ) name = ws.$Telescope_PlanetName(who);
else name = who.name;
}
if( name.indexOf("Exhibition]") > -1 ) return; //do not show ships in exhibition of Gallery OXP
if( !name || name.length === 0 ) name = "(Lost target)";
else if( !who || !who.isPlanet && !who.isSun && ( !who.isValid || !ws.$Telescope_InRange( who ) ) )
// name = "(Lost "+name+")";
return;
var direction = ws.$Telescope_From(player.ship, position);
// log(ws.name, name+" d:"+direction+" p:"+position); //debug
var cr = 0;
if( who.collisionRadius > 0) cr = who.collisionRadius;
var rng = Math.floor((player.ship.position.distanceTo(position)-cr) / 1000);
if( rng >= 1000000 ) rng = Math.floor(rng/1000000)+"M";
if( who.isDerelict ) {
if(ws.$TelescopeTWS && who.script) { //Towbar status
if(who.script.$TowbarUsableShip) name = "Usable "+name;
else if(who.script.$TowbarMinedShip) name = "Mined "+name;
if(who.script.$TowbarEmptyShip) name = "Empty "+name;
else name = "Derelict "+name;
} else name = "Derelict "+name;
} else if( who.target === player.ship ) rng = "! "+rng; //hostile
else if( ws._index_in_list( who, ws.$TelescopeReds ) > -1 ) rng = "* "+rng; //pirate
return( rng+"km "+name+" "+direction );
}
this.$Telescope_ShowFoundTargetNumber = function() {
var ws = worldScripts.telescope;
var len = ws.$TelescopeList.length;
var s = "";
if( len > 1 ) s = "s";
var msg = " found "+len+" target"+s;
if( ws.$TelescopeStaionNearby ) {
var p = "";
if( ws.$TelescopeGSP < 1 ) p = Math.round(ws.$TelescopeGSP*100)+"% ";
msg = "Gravity scan"+msg+", "+p+"done"; //need online gravity scanner
} else msg = "Telescope"+msg;
player.consoleMessage( msg, 5 );
}
this.$Telescope_StartTimer = function( delay ) {
if( player.ship.equipmentStatus("EQ_TELESCOPE") === "EQUIPMENT_OK" ) {
var ws = worldScripts.telescope;
if( !isValidFrameCallback( ws.$TelescopeVFCB ) )
ws.$TelescopeVFCB = addFrameCallback( this.$Telescope_VFCB.bind(this) );
if( !isValidFrameCallback( ws.$TelescopeVFCB2 ) )
ws.$TelescopeVFCB2 = addFrameCallback( this.$Telescope_VFCB2.bind(this) );
if( !isValidFrameCallback( ws.$TelescopeVFCB3 ) )
ws.$TelescopeVFCB3 = addFrameCallback( this.$Telescope_VFCBVisualTarget.bind(this) );
for(var i = 0; i < ws.$TelescopeVFCBM.length; i++) {
if( isValidFrameCallback( ws.$TelescopeVFCBM[i] ) )
removeFrameCallback( ws.$TelescopeVFCBM[i] );
ws.$TelescopeVFCBM[i] = null; //cag: converting to static arrays
}
// ws.$TelescopeVFCBM = [];
ws.$TelescopeVFCBM[0] = addFrameCallback( ws.$Telescope_VFCBM0.bind(ws) );
//cag: deleted 49 static FCBs to replace with dynamic ones
//AutoScan timer get targets from normal scanner and do scan if a new target is visible
//need at least 1 sec delay when called from shipWillExitWitchspace to avoid many gray balls
this.$TelescopeTimerS = new Timer(this, ws.$Telescope_TimedS, delay, 0.25);
}
}
this._is_ignored_ship = function( ws, who ) {
var we = worldScripts.escortdeck;
if( who.status === 'STATUS_BEING_SCOOPED' || who.status === 'STATUS_IN_HOLD' )
return true; // a problem when mining!
if( we ) {
let i = ws._index_in_list( who, we.$EscortDeckShip ); //escortdeck oxp is present
if( i >= 0 && we.$EscortDeckShipPos[i] )
return true; //who is on deck so exclude this who from target list
}
var wt = worldScripts.towbar;
if( wt && who === wt.$TowbarShip )
return true; //skip the towed ship
return false;
}
this.$Telescope_Steer = function() {//turn to the target
var ws = worldScripts.telescope;
var ti = ws.$TelescopeListi;
var who = ws.$TelescopeList[ ti - 1 ];
if( ws._is_ignored_ship( ws, who ) ) return;
if( player.ship && who && who.isValid && player.ship.viewDirection === "VIEW_FORWARD" //working in forward view only
&& ws.$TelescopeFixedTel !== 1 //no steering if cheaply fixed
&& !isValidFrameCallback( ws.$TelescopeSteerFCB ) ) {
ws.$TelescopePrevHeading = player.ship.heading;
ws.$TelescopeSteerFCB = addFrameCallback( ws.$Telescope_SteerFCB.bind(ws) );
}
}
/*
(function() {
var ws = worldScripts.telescope;
if( isValidFrameCallback( ws.$TelescopeSteerFCB ) )
removeFrameCallback( ws.$TelescopeSteerFCB );
ws.$TelescopeSteerFCB = addFrameCallback( ws.$Telescope_SteerFCB.bind(ws) );
console.clearConsole();
})()
*/
this.$Telescope_SteerFCB = function( delta ) {
var ws = worldScripts.telescope;
var ps = player.ship;
// sum += delta; log("Telescope", "Time elapsed: " + sum + " (delta: " + delta + ")");
var ti = ws.$TelescopeListi;
var who = ws.$TelescopeList[ ti - 1 ];
if( ps && ps.isValid && who && who.isValid && !ws._is_ignored_ship( ws, who ) ) {
var position = who.position; //got fresh data from the normal scanner or the telescope
if( !ws.$Telescope_InRangeFast( who, ti ) )
position = ws.$TelescopeListPos[ ti - 1 ];
if( !position ) {
if( isValidFrameCallback( ws.$TelescopeSteerFCB ) )
removeFrameCallback( ws.$TelescopeSteerFCB );
} else {
var v = position.subtract( ps.position ).direction();
var angle = ps.heading.angleTo(v);
var ato = ps.heading.angleTo(ws.$TelescopePrevHeading);
if( ato < 0.005 && angle > 0.015 ) { //steer if no manual steering and not in 1 degree
//if the above ato value lower then can not start steering in my intel atom netbook
// player.consoleMessage(ws.$TelescopePrevHeading +" vs "+ ps.heading);
var a = Math.min(ps.maxPitch*delta, angle/12);//half max turn/step and not too accutate
var wstow = ws.$TelescopeTWS; //slowed steering from towbar oxp if there are towed ship
if( wstow && wstow.$TowbarShip && wstow.$TowbarShip.isValid ) {
var ma = Math.min( 2, ps.mass / wstow.$TowbarShip.mass ); ///small ship max. 2x
a = a * ma / 3; // 1/3 of the original rate with same mass, min. 1/5 max. 2/3
// player.consoleMessage("Telescope slow steering with towed ship "+ato);//debug
}
var c = ps.heading.cross(v).direction(); //set the plane where we should rotate in
var q = ps.orientation.rotate( c, -a );
ps.orientation = q;
} else { //end of steering
// player.consoleMessage(ato+" a"+angle+" p"+position);//debug
if( isValidFrameCallback( ws.$TelescopeSteerFCB ) )
removeFrameCallback( ws.$TelescopeSteerFCB );
}
}
ws.$TelescopePrevHeading = ps.heading;
} else { //end of steering
if( isValidFrameCallback( ws.$TelescopeSteerFCB ) )
removeFrameCallback( ws.$TelescopeSteerFCB );
}
if( isValidFrameCallback( ws.$TelescopeVFCB ) ) {
ws.$TelescopeSVSync = true;
ws.$Telescope_VFCB( delta );//must be run surely after the SteerFCB
ws.$TelescopeSVSync = false;
}
}
this.$Telescope_TimedA = function() { //to avoid backstep if a target in the crosshairs
// log("Telescope", "TimedA start");//debug
var ws = worldScripts.telescope;
var ti = ws.$TelescopeListi;
var who = ws.$TelescopeList[ ti - 1 ];
var ps = player.ship;
// log("Telescope", "TimedA ti:"+ti+" who:"+who);//debug
if( ps && ps.isValid && who && who.isValid ) {
var d = ps.position.distanceTo( who.position );
if( d < ps.scannerRange && !who.isVisualEffect && !who.isPlanet && !who.isSun ) {
if( who && who.isValid && ps.target !== who ) {
ws.$TelescopeTargetSet = true;//to avoid doubled list item message
// log("Telescope", "New player target: "+who.displayName+" who:"+who);//debug
if( !who.isPlanet && !who.isSun ) ps.target = who;
if( ps.target !== who && //yes, it is possible! Hohoho showed when a ship jumped!
//bugfix against non-lockable Military Jammer awarded by ShipVersion to avoid repeated scan
ws.$TelescopePrevWho !== who ) {
ws.$TelescopePrevWho = who; //store to scan only once
// player.consoleMessage("Hohoho!");//debug
//; log("Telescope", "ScanTW: "+who+" - "+ws.$TelescopePrevWho);//debug
ws.$Telescope_Scan(); //forced scan to remove the invalid ball
}
ws.$TelescopeTarget = ps.target; //save real target after(!) set
// log("Telescope", "New player target set to "+who.displayName);//debug
ws.$TelescopeTargetSet = false;
}
} else { //far target or planet, lock the marker
var vm = ws.$TelescopeVMark;
// log("Telescope", "ti:"+ti+" pt:"+ps.target+" VMark:"+vm);//debug
if( !ps.target || ps.target !== vm ) {
// log("Telescope", "TimedA pt:"+ps.target+" vm:"+vm);//debug
ws.$Telescope_VFCBVisualTarget(); //get new name
vm = ws.$TelescopeVMark;
// log("Telescope", "TimedA got new target name for vm:"+vm);//debug
if( vm && vm.isValid && !vm.isVisualEffect && ps.target !== vm ) {
// log("Telescope", "TimedA will set displayName:"+vm.displayName);//debug
var vd = vm.displayName;
if( who.isPlanet || who.isSun ) vm.displayName = ws.$Telescope_PlanetName(who);
else vm.displayName = who.displayName; //remove km from ident message
ws.$TelescopeTargetSet = true;//avoid doubled list item message
// log("Telescope", "New player target: "+vm.displayName+" vm:"+vm+" who:"+who);//debug
ps.target = vm;
ws.$TelescopeTarget = who; //save the real target after(!) set
// log("Telescope", "New player target set to "+vm.displayName);//debug
ws.$TelescopeTargetSet = false;
vm.displayName = vd; //restore km
}
}
}
// log("Telescope", "Player target: "+ps.target+" VMark:"+vm);//debug
// ws.$Telescope_ShowName();//removed, show in target box
}
if( ws.$TelescopeTimerA ) {
ws.$TelescopeTimerA.stop();
ws.$TelescopeTimerA = null;
}
// log("Telescope", "TimedA end");//debug
}
this.$Telescope_TimedF = function() { //delayed launch of FCBs, must after FarPlanets FCB
var ws = worldScripts.telescope;
ws.$Telescope_StartTimer( 1 ); //1 sec delay to avoid unwanted gray balls
if( ws.$TelescopeTimerF ) {
ws.$TelescopeTimerF.stop();
ws.$TelescopeTimerF = null;
}
}
// before w/ TelescopeVMCC=0, Total time: 48.901 ms JavaScript: 10.732 ms, native: 38.155 ms
// after w/ TelescopeVMCC=0, Total time: 34.331 ms JavaScript: 9.057 ms, native: 25.257 ms
this._TimedS_closure = function() {
// 'constant' variables
var ws = worldScripts.telescope;
var telescopeAutoScan = ws.$TelescopeAutoScan;
var telescopeAutoScanMaxRange = ws.$TelescopeAutoScanMaxRange;
var telescopeRedAlertLimiter = ws.$TelescopeRedAlertLimiter;
var telescopeAutoLock = ws.$TelescopeAutoLock;
var telescopeGravLock = ws.$TelescopeGravLock;
var telescopeCMFD = ws.$TelescopeCMFD;
// function references
var player_consoleMessage = player.consoleMessage;
var telescope_Scan = ws.$Telescope_Scan;
var telescope_ShowFoundTargetNumber = ws.$Telescope_ShowFoundTargetNumber;
var system_filteredEntities = system.filteredEntities;
var telescope_ShowName = ws.$Telescope_ShowName;
var telescope_ShowName2 = ws.$Telescope_ShowName2;
var telescope_MostCentered = ws.$Telescope_MostCentered;
var telescope_GetDetect = ws.$Telescope_GetDetect;
var telescope_VClear = ws.$Telescope_VClear;
var telescope_TimedVMC = ws.$Telescope_TimedVMC;
var index_in_list = ws._index_in_list;
// local variables
var telescopeVMCC = 0; //counter to make colour of the visual marks, used to do once in a second within a 0.25s timer
var ps, pst, psp, scannerRange, telescopeGSP, telescopeList, telescopeListi, telescopeStaionNearby;
function _IsPilotedVisible(entity) {
if( entity && entity.isValid && !entity.isVisualEffect && !entity.isCloaked
&& ( entity.isPiloted || entity.forwardWeapon ) //need to detect drones from HardShips OXP
// && ( !entity.isRock || entity.isStation ) //too much asteroids, lock only in scannerRange
&& (( telescope_GetDetect( entity )
&& entity.isVisible && ps.equipmentStatus("EQ_TELESCOPEEXT") === "EQUIPMENT_OK" )
|| // brought code inline // ws.$Telescope_IsScannerTarget( entity )
( entity.dataKey && ps && ps.isValid && psp.distanceTo(entity.position) < scannerRange )
)
&& ( !entity.dataKey || entity.dataKey !== "telescopemarker" ) )
return true;
return false;
}
function _IsNonHostileStaion(entity) {
if( entity && entity.isValid && entity.isStation && !entity.isVisualEffect && !entity.isCloaked
&& entity.mass > 10000000 //skip ships with docking port (except baseships), rockhermit with 53508t must fit in
&& entity.target !== ps //target is hostile if targeting back
//or player is in the defenseTargets
&& ( !entity.defenseTargets || ws._index_in_list( ps, entity.defenseTargets ) === -1 ) )
return true;
else return false;
}
function _MFDTarget(ws, ps, who) { //helper function for building MFD in TimedS
if( who && who.isValid ) {
var v = telescope_ShowName2(who, who.position);
if( v && v.length > 0 && v.indexOf("(Lost ") === -1 ) {
if( who === pst || //current target
pst && pst.dataKey
&& pst.dataKey === "telescopemarker" //get the original target
&& who === telescopeList[ telescopeListi - 1 ] )
v = "[ "+v+" ]"; //mark the current target
return( v+"\n" );
}
}
return false;
}
function _TimedS() { //check for most centered 4 times/second, new targets and colour update once/second
// log("Telescope", "TimedS start"); //debug
ps = player.ship;
pst = ps.target;
psp = ps.position;
scannerRange = ps.scannerRange;
telescopeStaionNearby = ws.$TelescopeStaionNearby;
//; if( ps.target === null ) log("Telescope","TimedS notarget1");
if( !ps || !ps.isValid || ps.equipmentStatus("EQ_TELESCOPE") !== "EQUIPMENT_OK" ) {
if(ps.setMultiFunctionText) //clear MFD if Telescope damaged
ps.setMultiFunctionText(this.name, "No Telescope Target", false);
return; //stop scan when damaged
}
// var gravdone = false;
var gravok = false;
if( ps.equipmentStatus("EQ_GRAVSCANNER") === "EQUIPMENT_OK" ) gravok = true;
telescopeGSP = ws.$TelescopeGSP;
if( gravok && telescopeStaionNearby ) {
if( telescopeGSP < 1 ) {
var gsm = 1;//gravity scanner multiplyer
if( ps.speed === 0 ) gsm = 4; //4 times faster if stopped
if( ps.equipmentStatus("EQ_GRAVSCANNER2") === "EQUIPMENT_OK" )
gsm *= 2; //half time with 2 working grav.scanner
ws.$TelescopeGSP = telescopeGSP = telescopeGSP + gsm * 1/960; //normal gravity scan need 4 minutes
if( telescopeGSP >= 1 ) {
ws.$TelescopeGSP = telescopeGSP = 1;
if( ps.weaponsOnline )
player_consoleMessage("Gravity scan done, turn off weapons to see results", 5);
else {
telescope_Scan(); //forced scan to insert new gravity targets
telescope_ShowFoundTargetNumber();
}
}
}
} else if( telescopeGSP > 0 )
ws.$TelescopeGSP = telescopeGSP = telescopeGSP - 1/240; //degrading from 100% to 0% in 2 minute if away from stations
var newtarget = null;
var st = [];
var ascan = false;
var i = 0, j = 0, who = 0, s = '';
telescopeList = ws.$TelescopeList;
telescopeListi = ws.$TelescopeListi;
if( telescopeAutoScan //enabled
&& telescopeVMCC < 1 //and every 4. call
&& telescopeList.length < ws.$TelescopeTargets ) { //and list is not full
ascan = true;
st = system_filteredEntities(this._TimedS_closure, _IsPilotedVisible, ps,
telescopeAutoScanMaxRange); //maybe avoid bugs if maxed
// log("Telescope", "TimedS filteredEntities returned "+st.length); //debug
var mfd = ""; //build Telescope MFD
for( i = 0; i < st.length && j < 10; i++ ) { //list the nearest ships first
s = _MFDTarget(ws, ps, st[i]);
if( s ) { mfd += s; j++; }
}
for( i = 0; i < telescopeList.length && j < 10; i++ ) { //then other targets
who = telescopeList[i];
if( who && ws._index_in_list( who, st ) === -1 ) { //not in the filtered ships array
s = _MFDTarget(ws, ps, who);
if( s ) { mfd += s; j++; }
}
}
if( j < 1 ) mfd = "No Telescope Target";
if(ps.setMultiFunctionText) ps.setMultiFunctionText(this.name, mfd, false);
//check a station is nearby for gravity scanner
if( gravok ) {
if( ps.mass < 100000000 ) { //baseships can perform gravity scan anywhere
var sg = system_filteredEntities(this._TimedS_closure, _IsNonHostileStaion, ps, 5000);
if( !telescopeStaionNearby && sg && sg.length > 0 ) {
// var w = "";
telescopeStaionNearby = true; //store the result
if( ps.weaponsOnline ) //show when arrived near a station
player_consoleMessage("Gravity scan need offline weapons", 5);
else {
telescope_Scan();//forced rescan
telescope_ShowFoundTargetNumber();
}
} else {
if( telescopeStaionNearby && ( !sg || sg.length === 0 ) ) { //too far or become hostile
player_consoleMessage("Gravity scan need friendly station in 5km", 5);
telescopeStaionNearby = false;
telescope_Scan();//forced rescan
}
}
} else telescopeStaionNearby = true;//baseship
} else telescopeStaionNearby = false;
}
for( i = 0; i < st.length; i++ ) { //search new target
if( ws._index_in_list( st[i], telescopeList ) === -1 &&
!st[i].isPlayer ) { //must, bugfix
var p = st[i].position;
telescope_ShowName("", st[i], p);
// var m = Math.round(ps.position.distanceTo( p ));
// var dir = ws.$Telescope_From(ps, p);
// log("Telescope", "New visible: " + m+"m "+dir+" "+st[i]);//debug
// system.addVisualEffect("telescope-whitemarker", p);//debug
newtarget = st[i]; //but do not jump out of the cycle, keep to print all new name
}
}
if( !newtarget && telescopeCMFD ) { //CombatMFD support
var pt = ws.$TelescopePrevMFDTarget;
if( !pt || !pt.isValid || ascan && index_in_list( pt, telescopeList ) === -1 ) {
//need ascan check also, else cause blinking names in CombatMFD
// player.consoleMessage(pt);//debug
ws.$TelescopePrevMFDTarget = null;
telescopeCMFD.$TelescopeLine = ""; //clear the line in MFD
} else telescope_ShowName("", pt, pt.position); //update the direction
}
//; if( ps.target == null ) log("Telescope","TimedS notarget2");
if( newtarget && newtarget !== ws.$TelescopePrevNewTarget
|| pst && !pst.isValid //target jumped or so
&& !pst.isPlanet && !pst.isSun
&& ( !pst.dataKey || pst.dataKey !== "telescopemarker" )) {
//; log("Telescope", "ScanNT: "+newtarget+" - "+ws.$TelescopePrevNewTarget);//debug
ws.$TelescopePrevNewTarget = newtarget; //store to scan only once
telescope_Scan(); //forced scan to insert new one(s)
}
// else ws.$Telescope_List3(0, true, true); //forced free scan to refresh from the normal scanner - need fix, removed
//; if( ps.target == null ) log("Telescope","TimedS notarget3");
if( !isValidFrameCallback( ws.$TelescopeSteerFCB ) ) { //no retarget during autosteering
if( ps.weaponsOnline ) {//in auto mode
if( pst === null //no target and autolock not disabled
&& telescopeAutoLock !== 0 )
telescope_MostCentered( null, "auto", false );
} else if( telescopeGravLock !== 0 ) //in grav mode and not disabled
telescope_MostCentered( null, "grav", false );
}
if( pst === null ) {
//; log("Telescope","TimedS notarget");
var ti = telescopeListi;
who = telescopeList[ ti - 1 ];
if( !who || ( !who.isPlanet && !who.isSun ) ) {
//; log("Telescope","TimedS VClear");
telescope_VClear(); //cleanup needed in some cases
}
}
if( !telescopeRedAlertLimiter //small help to slow computers:
|| telescopeVMCC < 1 ) //update in every 4. call only
telescope_TimedVMC(); //update the colours of the lightball markers
if( telescopeVMCC < 1 ) { //check colour making counter
telescopeVMCC = 3; //do once in a second when reach 0
} else telescopeVMCC--;
// log("Telescope", "TimedS end"); //debug
ws.$TelescopeStaionNearby = telescopeStaionNearby;
}
return _TimedS;
}
this.$Telescope_TimedVMC = function() { //make colours to visual markers, check targets are flyed out of range
if( !player.ship || !player.ship.isValid ) return;
var ws = worldScripts.telescope;
var ps = player.ship;
var ball = null;
var col = null;
var dt = null;
// var dir = null;
// var scr = ps.scannerRange;
var tcr = 0;
var tl = ws.$TelescopeList;
var tfs = ws.$TelescopeFarStatus;
var t = null;
// var v = null;
ws.$TelescopeNearestd = ws.$TelescopeMaxRange; //reset to max.
var prepa = ws.$TelescopeRedAlertLimiter; //run much faster with local variables
var prepb = ws.$TelescopeLightBalls;
var prepc = ws.$TelescopeVMCs;
var prepd = ws.$TelescopeNearestd;
var prepi = ws.$TelescopeNearesti;
var prepl = ws.$TelescopeLargeLightBalls;
var prepm = ws.$TelescopeSniperMinRange;
var prepp = ws.$TelescopeListPos;
var prepr = ws.$TelescopeSniperRange;
var preps = ws.$TelescopeShipLightBalls;
var prept = null; if( ws.$TelescopeTWS ) prept = ws.$TelescopeTWS.$TowbarShip; //skip the towed ship
var prepv = ws.$TelescopeVMarkMinDist;
var prepvs = ws.$TelescopeVMarkShipMinDist;
var reds = ws.$TelescopeReds; //pirate detected earlier
var telescope_InRangeFast = ws.$Telescope_InRangeFast;
var telescopeListPos = ws.$TelescopeListPos;
var psp = ps.position;
var scannerRange = ps.scannerRange;
var tpos, dataKey, isPlanet, isThargoid, isSun, mass;
//following part is very CPU consuming, with 100 ships need 400 cycle/sec, so code wisely
for( var i = 0; i < tl.length; i++ ) {
t = tl[i];
if( !t || !t.isValid ) col = null; //invalid target
else if( !telescope_InRangeFast( t, i ) ) {
//less check than InRange due to checked before and speed is important
col = "gray"; //last known position only
dt = psp.distanceTo( prepp[ i ] );
//distance to the last known position
} else {
tpos = t.position;
dataKey = t.dataKey;
isPlanet = t.isPlanet;
isThargoid = t.isThargoid;
isSun = t.isSun;
mass = t.mass;
dt = psp.distanceTo( tpos ); //distance to the target
telescopeListPos[ i ] = tpos; //update until InRange
if( t.isStation || ( dataKey && dataKey.indexOf("buoy") > -1 ) )
col = "green"; //base or buoy, do not use isBeacon to exclude ships with beaconCode
else if( isPlanet ) col = "lightgray"; //planets
else if( isThargoid && dataKey !== "tharglet" //warship is red but tharglet is pink or white
|| !t.isDerelict && prepc[i] && prepc[i].indexOf("red") > -1 )
col = "red"; //pirate detected earlier
else if( t.isVisible || dt < scannerRange ) {
if( t.isPolice ) col = "purple"; //police
else if( t.isWormhole || t.isDerelict ) col = "blue"; //wormhole from Oolite v1.79
else if( !t.isPiloted && t.forwardWeapon && t.bounty > 0 //active tharglet or drone
// && ( ( t.owner && t.owner.isValid || t.speed > 0 ) //can fire after owner gone until moving
//&& !t.owner.isDerelict - still fire
&& ( isThargoid //will be like a rock when inactive
|| dataKey !== "tharglet" ) ) col = "pink";
else if( t.isCargo || t.primaryRole === "escape-capsule" //cargo, esc.pod, rock or sun
|| isSun || t.isRock || dataKey === "tharglet" ) col = "white";
else if( t.bounty > 0 && ( tfs || dt < scannerRange || isThargoid ) ) {
col = "red"; //pirate in scanner or FarStatus=true or thargoid
if( ws._index_in_list( t, reds ) === -1 ) reds.push(t); //save
}
else if( t.isWeapon ) col = "cyan"; //missile or mine
else if( ws._index_in_list( t, reds ) > -1 ) col = "red"; //pirate detected earlier
else col = "yellow"; //other ship with clean status
} else if( mass >= 130000 ) col = "orange"; //large ship over the visible range
else col = "brown"; //small ship over the visible range
}
if( col ) { //check to avoid invalid target
if( dt < prepd && t !== prept ) { //find the nearest target but skip the towed ship
prepd = dt;
prepi = i + 1; //store the nearest
}
tcr = 0;
if( t && t.isValid && !isPlanet && !isSun ) tcr = t.collisionRadius;
if( prepb && prepl ) {
if( isPlanet && !t.hasAtmosphere ) ball = "moon";
else if( dt < prepm + tcr ) ball = "largeball"; //xl size
else if( dt < prepr + tcr ) ball = "ball"; //large size
else ball = "marker"; //average size
}
if( dt < prepv + tcr //too near
|| ( ( dt < prepvs + tcr ) && col !== "cyan" && col !== "white" && col !== "pink" )
//in red alert show ball marked targets only to save CPU and clean scanner
|| prepa && player.alertCondition > 2 && ps.weaponsOnline && ball !== "ball" )
col = null;
else {
if( !prepb || !preps //if ship lightballs are disabled then show others only
&& col !== "blue" && col !== "cyan" && col !== "green" && col !== "white" )
col = "telescope-"+col+"_flag";//lollipop without lightball
else if( isPlanet || isSun ) {
if( t.hasAtmosphere ) { //only lightrgray has moon in effectdata.plsit
if( t.isVisible && dt < 10000000 )
col = "telescope-lightgray_moonflag"; //no dot
else col = "telescope-lightgray_moon";
} else if( t.isVisible && dt < 10000000 )
col = "telescope-"+col+"_flag"; //no dot
else col = "telescope-"+col+"_dotmarker";
} else if( prepl ) { //large balls
if( dt > 1000000 ) col += "_tiny"; //over 1000km show tiny ball
else if( dt > 100000 ) col += "_small"; //over 100km show smaller ball
col = "telescope-"+col+"_"+ball;
} else if( dt > 1000000 ) col = "telescope-"+col+"_dotmarker"; //over 1000km
else if( mass < 400000 ) col = "telescope-"+col+"_tinymarker"; //escort ship
else col = "telescope-"+col+"_smallmarker"; //large ship (Cobra3 and over)
}
}
ws.$TelescopeVMCs[ i ] = col;
}
ws.$TelescopeNearestd = prepd;
ws.$TelescopeNearesti = prepi;
}
this.$Telescope_True = function(/*target*/) { //system.filteredEntities can get all ship with this
return true;
}
this.$Telescope_VClear = function() { //Clear Visual Effect Ship Model and Visual Marker also
var ws = worldScripts.telescope;
//; log("Telescope","VClear");
ws.$Telescope_VClearM();
ws.$Telescope_VClearS();
}
/*
(function() {
var ws = worldScripts.telescope;
if( isValidFrameCallback( ws.$TelescopeVFCB ) ) removeFrameCallback( ws.$TelescopeVFCB );
var vc = ws._VFCB_closure();
ws.$Telescope_VClearS = vc.clear;
ws.$Telescope_VShow = vc.show;
ws.$Telescope_VFCB = vc.fcb;
if( !isValidFrameCallback( ws.$TelescopeVFCB ) )
ws.$TelescopeVFCB = addFrameCallback( ws.$Telescope_VFCB.bind(ws) );
})()
*/
this._VFCB_closure = function() {
// 'constant' variables
var ws = worldScripts.telescope;
var w_shiplib = worldScripts.shiplib;
var gameWindow = oolite.gameSettings.gameWindow;
// function references
var system_addVisualEffect = system.addVisualEffect;
var telescope_Scan = ws.$Telescope_Scan;
var telescope_ShowFoundTargetNumber = ws.$Telescope_ShowFoundTargetNumber;
var telescope_InRange = ws.$Telescope_InRange;
var telescope_VClear = ws.$Telescope_VClear;
var index_in_list = ws._index_in_list;
// local variables
var weaps = true; //the previous state of the player weapons
var vRing = null; //a ring around the visual effect target
var vShip = null; //visual effect to show the selected target
var vDataKey = null; //key of the visual effect
var vShrinkC = 0; //visual effect shrink counter - shrink code is not ready, leave these at 0
var vShrinkDelay = 0; //in sec after the larger visual target start shrinkig to normal size (0: instant)
var vShrinkLength = 0; //in sec, shrinking faster if smaller (0: instant)
var vAlighUp = 0; //visual effect align to top modifier
var vZoom = 1; //store the original maximal zoom level of the visual effect
var ps, wide;
// function getVShip() { return vShip; }
function setVShip( ship, up, delay, length ) {
vShip = ship;
vAlighUp = up;
vShrinkDelay = delay;
vShrinkLength = length;
vShrinkC = vShrinkDelay + vShrinkLength; //shrink after delay
return ship;
}
function clearVShip() { //Clear Visual Effect Ship Model and large visual ring
if( vShip ) {
//; log("Telescope", "Remove VModel:"+ws.$TelescopeV); //debug
vShip.remove();
// log("Telescope", "Removed VModel."); //debug
vShip = null;
vShrinkC = 0;
vAlighUp = 0;
vDataKey = null;//need to show again when reident
}
if( vRing ) {//remove large visual ring
//; log("Telescope", "Remove VRing:"+vRing); //debug
vRing.remove();
// log("Telescope", "Removed VRing."); //debug
vRing = null;
}
return null;
}
function showVShip() { //Show Visual Effect
ps = player.ship;
if( !ws.$TelescopeShowVisualTarget ) return;
//cag: added to fix bug where loading game or altering its size caused effect to re-appear when turned off
if( !ws.$TelescopeAutoLock && !ps.target ) return;
if( ps.weaponsOnline ) {
if( ws.$TelescopeVSize <= 0 ) return;
} else if( ws.$TelescopeVZoomSize <= 0 ) return;
var ti = ws.$TelescopeListi;
var who = ws.$TelescopeList[ ti - 1 ];
if( !who || !who.isValid && !who.isPlanet && !who.isSun || !telescope_InRange( who ) ) {
//; log("Telescope","VShow ti:"+ti+" who:"+who);
telescope_VClear();
return;
}
var dk = who.dataKey;
var v = vShip;
// log("Telescope","VShow "+dk+" "+v+" "+who.isStation+" "+ws.$TelescopeShowVisualStation);//debug
if( who.isPlanet || who.isSun || who.isStation && !ws.$TelescopeShowVisualStation )
clearVShip();
else if( !v || vDataKey !== dk ) {
vDataKey = dk;
if( v ) v.remove();
v = null;
if( 0 < oolite.compareVersion("1.79") ) { //before Oolite v1.79
if( index_in_list( dk, ws.$TelescopeDataKeys77 ) > -1 ) {
dk += "77"; //use dataKeys with 77 suffix in effectdata.plist
}
}
var p = ps.position;
if( dk ) v = system_addVisualEffect( dk, p );
// log("Telescope","VShow2 "+dk+" "+v);//debug
if( !v ) { //maybe the dataKey contains partially a name from the shiplib
if( w_shiplib && w_shiplib.$ShipLibVP ) {
var l = w_shiplib.$ShipLibVP;
var d = 0; //0. line contains the default data
for( var i = l.length; i >= 0 ; i-- ) //search backward (from orig.ships)
if( dk && l && l[i] && dk.indexOf( l[i].k ) > -1 ) {
d = i; //found
i = -1; //exit from for
}
v = system_addVisualEffect( l[d].k, p );
}
if( !v && ws.$TelescopeShowVisualQuestionMark )
v = system_addVisualEffect("oolite-unknown-ship", p); //fallback
else clearVShip(); //silent fallback
}
// player.consoleMessage(v+" "+dk);//debug
if( v ) { //must to check it (bugfix)
// log("Telescope","VShow3 "+dk+" "+v);//debug
var z = v.collisionRadius / 6; ///
vZoom = z; //save zoom value
if( z > 0 ) v.scale( 1 / z ); //shrink to the largest size
v.scannerDisplayColor1 = null; //hide from the scanner
v.scannerDisplayColor2 = null; //hide from the scanner
// ws.$TelescopeV = v; //save
// ws.$TelescopeVUp = 0;
// ws.$TelescopeVShrinkC = ws.$TelescopeVShrinkDelay + ws.$TelescopeVShrinkLength; //shrink after delay
setVShip( v, 0, 0, 0 ); // vAlighUp, vShrinkDelay, vShrinkLength
if( !isValidFrameCallback( ws.$TelescopeVFCB ) )
ws.$TelescopeVFCB = addFrameCallback( ws.$Telescope_VFCB.bind( ws ) );
if( !isValidFrameCallback( ws.$TelescopeVFCB2 ) )
ws.$TelescopeVFCB2 = addFrameCallback( ws.$Telescope_VFCB2.bind( ws ) );
if( !isValidFrameCallback( ws.$TelescopeVFCB3 ) )
ws.$TelescopeVFCB3 = addFrameCallback( ws.$Telescope_VFCBVisualTarget.bind( ws ) );
}
}
}
function _VFCB( delta ) { //Visual FrameCallBack
// log("Telescope", "VFCB start"); //debug
ps = player.ship
if( !ps || !ps.isValid ) return; //if player died
if( isValidFrameCallback( ws.$TelescopeSteerFCB )
&& !ws.$TelescopeSVSync ) return; //call after Steering
wide = gameWindow.height / gameWindow.width; ///widescreen correction
//full size virtual target (and ring also) if weapons offline
var vsize = ws.$TelescopeVZoomSize / 10; ///
var vsizechanged = false;
if( ps.weaponsOnline ) { //gravity scan if weapons turned off
if( !ws.$TelescopeShowVisualTarget //remove model if weapons changed back to on
&& vShip ) { //and model showing is disabled
vShip.remove();
vShip = null;
}
vsize = ws.$TelescopeVSize / 10; ///
if( !weaps ) { //state changed to on
vsizechanged = true;
vShrinkC = 0; //restart counter to rescale
weaps = true; //save state
telescope_Scan(); //perform visible scan
}
} else if( weaps ) { //state changed to off
vsizechanged = true;
vShrinkC = 0; //restart counter to rescale
weaps = false; //save state
telescope_Scan(); //perform gravity scan
telescope_ShowFoundTargetNumber();
if( ps.target //repaint visual target and ring if show in weapons off mode only
&& ws.$TelescopeFixedTel !== 1 ) {//no visual mode if cheaply fixed
clearVShip();
showVShip();
}
// player.consoleMessage(ps.target);//debug
}
//visual target zoom
var vp = ws.$TelescopeVPos;
var pos = ps.position.add( ps.vectorForward.multiply( 50 + vp.z ) ); //check effectdata.plist if this line give TypeError: vp is null
pos = pos.add( ps.vectorRight.multiply( vp.x ) );
// var srp = pos; //sniper ring position
if( !vShip || !vShip.isValid ) {
if( vShip || vRing ) {
//; log("Telescope","VFCB remove V:"+ws.$TelescopeV);
clearVShip();
}
} else {
var slen = vShrinkLength; //do shrink after delay
if( ( vShrinkC >= 0 || vsizechanged )
&& vShrinkC <= slen ) {
vShrinkC -= delta;
var d = 1;
if( slen > 0 ) d = ( slen - vShrinkC ) / slen;
var z = ( 1 - d * ( 1 - vsize ) ) / vZoom;
if( z > 0 ) vShip.scale( z ); //shrink
vAlighUp = 3 * d * ( 1 - vsize ) * 1.5; //align to top
// player.consoleMessage(vShrinkC+" "+z);//debug
}
var up = 12.5;
if( !ws.$TelescopeRing )
//|| vsize == ws.$TelescopeVZoomSize / 10 ) ///no ring if zoomed - removed since the ring is narrow
up += 1; //a bit more higher if no ring
else up += 1.25 - 2.5 * vsize; //correction with ring
// player.consoleMessage(up);//debug
pos = pos.add( ps.vectorUp.multiply( up - 24 * ( 0.75 - wide ) + vp.y
+ vAlighUp ) );
vShip.position = pos;
}
//orient vship model
var ti = ws.$TelescopeListi;
var who = ws.$TelescopeList[ ti - 1 ];
var wp = null;
if( who && who.isValid && ( who.isPlanet || who.isSun || ws.$Telescope_InRangeFast( who, ti ) ) ) {
wp = who.position;
} else
wp = ws.$TelescopeListPos[ ti - 1 ]; //last known position
if( wp ) {
var vd = wp.subtract( ps.position ).direction(); // unit vector towards wp
if( vShip && vShip.isValid && !vShip.isPlanet && !vShip.isSun ) {
if( who.isVisible ) { //orientation is known only if visible, Grav.Scanner can give position only
let ps_heading = ps.heading;
var a = ps_heading.angleTo(vd);
var c = ps_heading.cross(vd).direction();
var o = who.orientation.rotate( c, -a );
// var v2 = ps.position.subtract(wp);
// var fw = ship.vectorForward.angleTo(v2);
// var ri = ship.vectorRight.angleTo(v2);
// var up = ship.vectorUp.angleTo(v2);
// var o = who.orientation;
// var o = who.orientation.multiply( ps.orientation ); //depends on player ori only
// o = o.rotateZ(fw);
// o = o.rotateY(up);
// o = o.rotateX(ri);
vShip.orientation = o;
// ( who.orientation.rotate( ps.position.subtract( who.position ) )
// ).multiply( ps.orientation );
//who.orientation.multiply( ps.orientation );
} else { //nonvisible, fixed view only
var r = Math.PI / 2 + 0.22; ///ships viewed from top (90 degree plus a bit)
let who_isValid = who.isValid;
if( who_isValid && who.isStation ) r = Math.PI + 0.22; //stations facing
vShip.orientation = ps.orientation.rotate( ps.vectorRight, r );
if( who_isValid && who.isMainStation ) //rotate to horizontal dock position
vShip.orientation = vShip.orientation.rotate( vShip.vectorForward, Math.PI / 2 );
// var cr = who.collisionRadius;
// log("Telescope", "VFCB who:"+who.name+" cr:"+cr);//debug
// if( cr > 0 ) vShip.scale( 2.5 / cr ); //smaller
}
}
}
//large visual target ring
if( vShip && vShip.isValid && ws.$TelescopeRing //if not disabled
&& ws.$TelescopeFixedTel !== 1 //no ring (nor target model) if cheaply fixed
//&& ps.weaponsOnline //and not in zoomed size - removed since the ring is narrow
&& vShrinkC <= 0 ) { //and not zooming
if( !vRing ) {
vRing = system_addVisualEffect("telescope-sniper", pos);
vRing.scale( 0.166 * vsize ); //shrink
// vRing.scaleZ = vRing.scaleZ * 0.1; //make flatter
} else {
vRing.position = pos;
if( vsizechanged ) { //if weapons switched on/off set new size (small/large)
vRing.scale( 0.166 * vsize ); //shrink
// vRing.scaleZ = vRing.scaleZ * 0.1; //make flatter
}
}
vRing.orientation = ps.orientation;//.rotate( ps.vectorRight, 0 );
} else if( vRing ) {
vRing.remove();
vRing = null;
}
// ws.$Telescope_VFCBVisualTarget(); //called from separated FCB to avoid timeLimit
// the following can reach timeLimit if placed here so must be called from separatd FCB
// for(var i = 0; i < ws.$TelescopeList.length; i+=10; )
// ws.$Telescope_VFCBMarks(Math.floor(i/10));
}
return { clear: clearVShip,
show: showVShip,
fcb: _VFCB };
}
this.$Telescope_VClearM = function() { //Clear Visual Marker and small sniper ring
var ws = worldScripts.telescope;
if( ws.$TelescopeVMark ) {
//; log("Telescope", "Remove VMark:"+ws.$TelescopeVMark); //debug
ws.$TelescopeVMark.remove();
// log("Telescope", "Removed VMark."); //debug
ws.$TelescopeVMark = null;
}
ws._clearSniperRing();
}
/*
(function() {
var ws = worldScripts.telescope;
if( isValidFrameCallback( ws.$TelescopeVFCB2 ) ) removeFrameCallback( ws.$TelescopeVFCB2 );
var vc = ws._VFCB2_closure();
ws._clearSniperRing = vc.clear;
ws.$Telescope_VFCB2 = vc.fcb;
if( !isValidFrameCallback( ws.$TelescopeVFCB2 ) )
ws.$TelescopeVFCB2 = addFrameCallback( ws.$Telescope_VFCB2.bind(ws) );
})()
*/
this._VFCB2_closure = function() {
// 'constant' variables
var ws = worldScripts.telescope;
var gameWindow = oolite.gameSettings.gameWindow;
var TelescopeSniperRingSize = ws.$TelescopeSniperRingSize;
// function references
var system_addVisualEffect = system.addVisualEffect;
// local variables
var sniperRing = null; //if this ring guided around the crosshair then the far target is lined up correctly
var ps, wide;
function clearVRing() { //Clear small sniper ring
if( sniperRing ) {//remove the small sniper ring
//; log("Telescope", "Remove SniperRing:"+ws.$TelescopeSniperRing); //debug
sniperRing.remove();
// log("Telescope", "Removed SniperRing."); //debug
sniperRing = null;
}
}
function _VFCB2( /*delta*/ ) { //Visual FrameCallBack for the small sniper ring
ps = player.ship;
var d = 0;
var snipertarget = false;
var psp, psVF, psVR, psVU;
var pst = ps.target;
if( ps && pst && pst.isValid
&& ws.$TelescopeFixedTel !== 1 ) { //no sniper ring if cheaply fixed
if( pst.dataKey && pst.dataKey === "telescopemarker" ) { //get the original target
var ti = ws.$TelescopeListi;
pst = ws.$TelescopeList[ ti - 1 ];
}
if( pst && pst.isValid && !pst.isPlanet && !pst.isSun ) {
psp = ps.position;
d = psp.distanceTo( pst.position );
var tcr = pst.collisionRadius;
if( d - tcr < ws.$TelescopeSniperRange
&& d - tcr > ws.$TelescopeSniperMinRange ) {
var m = psp.subtract( pst.position );
psVF = ps.vectorForward;
if( psVF.angleTo( m ) > 3 ) { //to exclude aft line-up
// player.consoleMessage(ps.vectorForward.angleTo( m ));//debug
var vp = ws.$TelescopeVPos;
var srp = psp.add( psVF.multiply( 50 + vp.z ) ); //check effectdata.plist if this line give TypeError: vp is null
psVR = ps.vectorRight;
psVU = ps.vectorUp;
srp = srp.add( psVR.multiply( vp.x ) );
wide = gameWindow.height / gameWindow.width; ///widescreen correction
//distant and smaller target tracked with larger ring movement
var ax = -2 * d / tcr * ( psVR.angleTo( m ) - Math.PI / 2 );
var ay = -2 * d / tcr * ( psVU.angleTo( m ) - Math.PI / 2 );
// player.consoleMessage(Math.round(ax*100)/100+" "+Math.round(ay*100)/100);//debug
if( Math.abs(ax) < 5 && Math.abs(ay) < 6 * wide ) { //ay<4 if 4:3, <3.4 if 16:9
srp = srp.add( psVU.multiply( vp.y ) );//center of the view_position
srp = srp.add( psVR.multiply( ax ) );//show misalignment
srp = srp.add( psVU.multiply( ay ) );
if( sniperRing ) sniperRing.position = srp;
else {
sniperRing = system_addVisualEffect("telescope-ring", srp);
sniperRing.scale( 0.01 * TelescopeSniperRingSize ); //shrink
}
sniperRing.orientation = ps.orientation;
snipertarget = true;
}
}
}
}
}
if( !snipertarget && sniperRing ) {
sniperRing.remove();
sniperRing = null;
}
}
return { clear: clearVRing,
fcb: _VFCB2 };
}
//call these from separated FCBs to avoid timeLimit
//this.$Telescope_VFCBM0 = function( delta ) { this.$Telescope_VFCBMarks(0); }
//...
this.$Telescope_VFCBM0 = function() { this.$Telescope_VFCBMarks('zero'); }
//cag: deleted 49 static FCB fns to replace with dynamic FCBs
/*
(function() {
var ws = worldScripts.telescope;
for(var i = 1; i < ws.$TelescopeVFCBM.length; i++) {
if( isValidFrameCallback( ws.$TelescopeVFCBM[i] ) )
removeFrameCallback( ws.$TelescopeVFCBM[i] );
ws.$TelescopeVFCBM[i] = null; //cag: converting to static arrays
}
console.clearConsole();
})()
*/
this.$Telescope_fcb_Startfrom = 0;
this.$Telescope_VFCBMarks = function(starting) { //create and update target marker lightballs - new fast code
//cag: implement dynamic FCBs, as unused ones impact framerate significantly.
// var $num_fcbs = 1; // we initiate w/ FCB in [ 0 ] // for *debug msgs* only
var $fcbs_removed = 0;
function _SetUpFCBs() { // count # FCBs needed and adjust list
//cag: implement dynamic FCBs, as unused ones impact framerate significantly
var ws = worldScripts.telescope;
var TelescopeVFCBM = ws.$TelescopeVFCBM;
var Telescope_VFCBMarks = ws.$Telescope_VFCBMarks;
var list = ws.$TelescopeList;
var i = 4; // start checking on 2nd group of 4 from TelescopeList
var fnum = 1; // $Telescope_VFCBMarks() is started w/ an FCB in [ 0 ]
var fcb;
//var chg = false; // to reduce # degug msgs
do {
fcb = TelescopeVFCBM[ fnum ]; // the next FCB in the lists
if( list[ i ] ) { // have at least one more, will need next FCB slot
// if( !isValidFrameCallback( fcb ) ) {
// not good enough, as it can take a number of frames for a callback to become registered (ie. isValidFrameCallback to become true)!!!
if( fnum > TelescopeVFCBM.length - 1 || fcb === null ) {
TelescopeVFCBM[ fnum ] = addFrameCallback( Telescope_VFCBMarks.bind(ws) );
// log('telescope', '_SetUpFCBs adding FCB in slot ' + fnum + ', list.len is ' + list.length ); $num_fcbs++; chg = true;
}
} else if( isValidFrameCallback( fcb ) ) { // have run out of items in TelescopeList, remove any remaining FCBs
removeFrameCallback( fcb );
TelescopeVFCBM[ fnum ] = null;
$fcbs_removed = 5; // takes 5 frames (on my pc) to complete removal
// log('telescope', '_SetUpFCBs removing FCB in slot ' + fnum + ', list.len is ' + list.length ); $num_fcbs--; chg = true;
}
i += 4; // each call of $Telescope_VFCBMarks handles 4 items from list
fnum++; // the # of the next FCB in the array
} while( i < list.length || isValidFrameCallback( fcb ) ); // end of list or have extra FCB to delete
// if( chg ) log('telescope', "# of FCBs: " + $num_fcbs + ', List.len is ' + ws.$TelescopeList.length );
}
// log("Telescope", "VFCBMarks start from "+startfrom); //debug
//need call from FrameCallBack to compensate player movement
var ws = worldScripts.telescope;
var startfrom = starting; // never modify function args
var prept = ws.$TelescopeList; // local
// - insert - ////////////////////////////////////////////////////////
if( startfrom === 'zero' ) { // is 'zero' on 1st call, delta on the rest
_SetUpFCBs();
ws.$Telescope_fcb_Startfrom = 0;
} else {
ws.$Telescope_fcb_Startfrom++;
}
startfrom = ws.$Telescope_fcb_Startfrom;
// - end - ///////////////////////////////////////////////////////////
var co = 4*startfrom, cl = prept.length; // set loop conditions from local instead
// if( co > cl ) return; //early exit over the end of TelescopeList
// - insert - ////////////////////////////////////////////////////////
if( cl && co > cl ) { // happens when decr # of FCBs, as changes are not applied until next frame (or later?) so don't panic
if( $fcbs_removed > 0 ) {
$fcbs_removed--;
} else if( prept.length > ws.$TelescopeVFCBM * 4 ) {
log('telescope', 'do not have enough FCBs!!!!!! List.length: ' + prept.length + ' TelescopeVFCBM: ' + ws.$TelescopeVFCBM );
} else { // ok, now you can panic
log('telescope', 'should never happen anymore!!!!!! co > cl: ' + co + ' > ' + cl );
}
return; //early exit over the end of TelescopeList
}
// - end - ///////////////////////////////////////////////////////////
var ce = co+4; //end of the loop, 4 item only in one FCB to avoid timelimit
var ps = player.ship;
if( !ps || !ps.isValid ) return; //exit if player died
var dir = null, dt = null, md = null, pos = null, tpos = null;
var prepc = ws.$TelescopeVMCs; // local, colour calculated in timer to save CPU
// var prepd = ws.$TelescopeRedAlertDist; //show lollipops in red alert within this distance only
// var prepm = ws.$TelescopeMMarks; // removed
var prepp = ws.$TelescopeListPos; // local
var prepr = ws.$TelescopeMRings; // local
var prepv = ws.$TelescopeVMarks; // local
var pla = player.alertCondition;
var psf = ps.vectorForward; // local
var pso = ps.orientation; //local
var psp = ps.position; //local
var scr = ps.scannerRange; //local
var angle = 0; //thin masslock border outside this angle
var bl = false; //black lollipops in red alert
if( pla > 1 && ps.weaponsOnline ) bl = true;
var bla = [0,0,0]; //the color of black lollipops is black in red alert
if( pla === 2 ) bla = [0.1, 0.1, 0.1]; //and very dark grey in yellow alert
var cm = null, cmf = null, cmt = null; //dataKey holders of normal, far and thin masslock borders
var fardist = 300000; //far masslock border over this distance (station or gravity scanner target)
var farplanet = 30; //far masslock border distance multiplier (an average 5000km planet over 1500km distance)
var mb = ws.$TelescopeMassLockBorders && ( pla === 1 || !ps.weaponsOnline );
var mb2 = "";
if( ws.$TelescopeBrightMassLockBorders ) mb2 = "2";
var mrs = 41.8; //masslock ring scale, used in var rsc and below for planets also
var rsc = scr / mrs; //masslock ring size
var scr2 = 2 * scr; //maximal distance of thin border
var ti = ws.$TelescopeListi - 1; //exclude current target from black lollipops
//following part is very CPU consuming, with 100 ships 60fps need 6000 cycle/sec, so code wisely
for(var i=co; i<cl && i<ce; i++){ //process 5 marker only at once to avoid timeLimit
var t = prept[i], c = prepc[i], r = prepr[i], v = prepv[i]; // local //m = prepm[i],
if( !c || !t || !t.isValid ) {
tpos = null;
if( v ) {
v.remove(); //without this red ball remain after destroyed pirates
prepv[i] = null;
}
if( r ) {
r.remove();
prepr[i] = null;
}
// if( m ) {
// m.remove();
// ws.$TelescopeMMarks[i] = null;
// }
} else if( c.indexOf("gray") > -1 ) tpos = prepp[i]; //last known position only
else tpos = t.position;
if( tpos ) { //check to avoid invalid target and if ListPos[i] is null
dir = tpos.subtract( psp ).direction();
dt = psp.distanceTo( tpos ); //distance to the target (or to last known pos)
if( dt > scr ) { //target is out of scanner range
md = scr - 600; //marker distance
//do not set closer to the range to do not left behind aft markers during torus travel
if( mb && !t.isSun ) { //masslock borders allowed, except for the sun
cm = c.substr(0, c.indexOf("_"))+mb2+"_ml"; //dataKey with colour
cmf = cm+"f"; //dataKey of coloured far masslock border
cmt = cm+"t"; //dataKey of coloured thin masslock border
// log("Telescope", cm );//debug
// var ml = false; //masslock field - removed
if( r && r.dataKey !== cm && r.dataKey !== cmf && r.dataKey !== cmt ) {
r.remove(); //colour changed, forced to recreate
prepr[i] = r = null;
}
//following conditions determine the thickness of ring, need thinner from close
//if( t.isSun ) cm = cmt; //set thin masslock border, the sun always get thin border
//else
if( dt > fardist ) { //change to far
if( t.isPlanet ) {
if( dt > farplanet * t.radius ) {
cm = cmf; //set far masslock border
if( r && r.dataKey.substr(-1) !== "f" ) {
r.remove();
prepr[i] = r = null;
}
} else if( dt < 3 * t.radius ) {
cm = cmt; //set thin masslock border
if( r && r.dataKey.substr(-1) !== "t" ) {
r.remove();
prepr[i] = r = null;
}
} else {
// cm = cm; //set normal masslock border (default)
if( r && r.dataKey.substr(-1) !== "l" ) {
r.remove();
prepr[i] = r = null;
}
}
} else { //is not planet but far
cm = cmf; //set far masslock border
if( r && r.dataKey.substr(-1) !== "f" ) {
r.remove();
prepr[i] = r = null;
}
}
} else { //check for thin border within 2x scanner range
//and over 45 degree mean ship is near and out of sight
//so if ring is in screen then can be close so need thin border
if( dt < scr2 //45 degree = 2.9 radian
&& (angle = psf.angleTo(psp.subtract(tpos))) < 2.9
//and crosshairs points out of ring which is closer
&& Math.sin( angle ) > scr / dt ) {
cm = cmt; //set thin masslock border
if( r && r.dataKey.substr(-1) !== "t" ) {
r.remove();
prepr[i] = r = null;
}
} else {
// cm = cm; //set normal masslock border (default)
if( r && r.dataKey.substr(-1) !== "l" ) {
r.remove();
prepr[i] = r = null;
}
}
}
if( r ) { //move masslock ring
r.position = tpos;
// if( cm == cmt ) {//stop further rotating if crosshairs points outside of ring
// r.orientation = (psp.subtract(tpos)).rotationTo([0, 0, 1]).normalize();
// r.orientation = psp.subtract(tpos).rotationTo(psf, angle).normalize();
// var psu = ps.vectorUp;
// var ua = psu.angleTo(psp.subtract(tpos));//up angle
//var borderangle = Math.asin( scr / dt );
//r.orientation = pso.rotate([1, 1, 0], Math.asin(scr / dt) );
// } else
r.orientation = pso;
} else { //create masslock ring
if( t.isPlanet ) { //|| t.isSun ) {
r = system.addVisualEffect( cm, tpos );
if( r ) r.scale( ( t.radius + Math.max( t.radius, scr ) ) / mrs ); ///
// log("Telescope", "Planet radius: "+t.radius );
} else if( !t.isRock && !t.isDerelict
&& t.scanClass !== "CLASS_BUOY" && t.scanClass !== "CLASS_CARGO"
&& !t.isWormhole && !t.isCloaked ) {
// ml = true; //target
r = system.addVisualEffect( cm, tpos ); //cm is set above
if( r ) r.scale( rsc ); //ring radius=scanner range
}
if( r ) {
r.orientation = pso;
prepr[i] = r;
}
}
// if( m ) m.position = tpos; //huge lightball - replaced with MRings
// else {
// if( ml ) {
// ws.$TelescopeMMarks[i] = //show masslockfield
// system.addVisualEffect( "telescope-masslockfield", tpos );
// } else ml = false;
// }
} else { //masslock borders turned off with primable menu or weapons on and alert is not green
if( r ) {
r.remove();
prepr[i] = null;
}
// if( m ) {
// m.remove();
// ws.$TelescopeMMarks[i] = null;
// }
}
} else { //target is within scanner range (circle is surely out of view)
md = scr + 300; //show the visual marker only without shadow lolipop
if( r ) {
r.remove();
prepr[i] = null;
}
// if( m ) { //remove masslockfield
// m.remove();
// ws.$TelescopeMMarks[i] = null;
// }
}
pos = psp.add( dir.multiply( md - i ) ) //anti-flicker difference
.add( ps.heading.direction().multiply( ps.speed / 25 ) ); ///torus speed need correction
if( !v ) {
ws.$TelescopeVMarks[i] = system.addVisualEffect( c, pos );
// log("Telescope", "VMarks["+i+"]:"+ws.$TelescopeVMarks[i]+" c:"+c+" pos:"+pos); //debug
} else {
if( v.dataKey !== c ) { //colour or size changed
v.remove();
prepv[i] = system.addVisualEffect( c, pos );
} else {
v.position = pos;
}
if( bl && i !== ti ) //black lollipops exccept the current target
v.scannerDisplayColor1 = bla;
else v.scannerDisplayColor1 = null; //original color from effectdata.plist
}
}
}
// log("Telescope", "VFCBMarks end"); //debug
}
this.$Telescope_VFCBMarksOld = function() { //create and update target marker lightballs - old slow code
var ps = player.ship;
if( !ps || !ps.isValid ) return; //exit if player died
var ws = worldScripts.telescope;
var tl = ws.$TelescopeList, i, md, v = 0, ball = '';
//following part is very CPU cunsuming, with 100 ships 60fps need 6000 cycle/sec, so code wisely
for( i = 0; i < tl.length; i++ ) {
var col = "pink"; //invalid target
var tpos = null;
var t = tl[i];
if( !t || !t.isValid || !t.dataKey ) { //sun and planets has no dataKey
v = ws.$TelescopeVMarks[i];
if( v ) {
v.remove(); //without this red ball remain after destroyed pirates
ws.$TelescopeVMarks[i] = null;
}
} else if( !t.isBeacon && //buoy in the whole system, others in range
!ws.$Telescope_InRange( t ) ) {
tpos = ws.$TelescopeListPos[ i ];
col = "gray"; //last known position only
} else {
ws.$TelescopeListPos[ i ] = t.position; //update until InRange
if( t.isStation || t.dataKey.indexOf("buoy") > -1 )
col = "green"; //base or buoy, do not use isBeacon to exclude ships with beaconCode
else if( t.isVisible || ps.position.distanceTo( t.position ) < ps.scannerRange ) {
if( t.isPolice ) col = "purple"; //police
else if( t.isCargo || t.primaryRole === "escape-capsule" //cargo, esc.pod,
|| t.isRock ) col = "white"; //or rock
else if( t.isWormhole || t.isDerelict ) col = "blue"; //wormhole from Oolite v1.79
else if( t.bounty > 0 ) col = "red"; //pirate or thargoid with bounty
else if( t.isWeapon ) col = "cyan"; //missile or mine
else col = "yellow"; //other ship with clean status
} else if( t.mass >= 130000 ) col = "orange"; //large ship over the visible range
else col = "brown"; //small ship over the visible range
if( ws.$TelescopeLightBalls //if ship lightballs are disabled
|| col === "blue" || col === "cyan" || col === "green" || col === "white" )
tpos = t.position; //then show others only
}
if( tpos ) { //check to avoid invalid target and if ListPos[i] is null
var dir = tpos.subtract( ps.position ).direction();
var dt = ps.position.distanceTo( tpos ); //distance to the target (or to last known pos)
if( dt > ps.scannerRange ) md = ps.scannerRange - 100; //marker distance
//do not set closer to the range to do not left behind aft markers during torus travel
else md = ps.scannerRange + 100; //show the visual marker only without shadow lolipop
var pos = ps.position.add( dir.multiply( md + 50 * Math.random() ) ) //anti-flicker randomness
.add( ps.heading.direction().multiply( ps.speed / 60 ) ); ///torus speed need correction
var tcr = 0;
if( t && t.isValid ) tcr = t.collisionRadius;
if( dt < ws.$TelescopeSniperRange + tcr ) ball = "ball"; //large size
else ball = "marker"; //average size
if( dt < ws.$TelescopeVMarkMinDist + tcr
//in red alert show nearest large ball marked targets only to save CPU and clean scanner
|| player.alertCondition > 2 && ps.weaponsOnline && ball !== "ball" ) {
var vmi = ws.$TelescopeVMarks[i];
if( vmi ) vmi.remove();
ws.$TelescopeVMarks[i] = null;
} else {
if( dt > 150000 ) col += "small"; //over 150km show smaller ball
v = ws.$TelescopeVMarks[i];
if( !v ) {
v = ws.$TelescopeVMarks[i] =
system.addVisualEffect("telescope-"+col+ball, pos);
} else if( v.dataKey !== "telescope-"+col+ball ) { //colour or size changed
v.remove();
v = ws.$TelescopeVMarks[i] =
system.addVisualEffect("telescope-"+col+ball, pos);
} else v.position = pos;
}
}
}
// ws.$Telescope_VFCBShrinkVMarks();//should not needed
}
this.$Telescope_VFCBShrinkVMarks = function() {
var ws = worldScripts.telescope;
var i = ws.$TelescopeList.length;
while( i < ws.$TelescopeVMarks.length) { //shrink VMarks to match List
if( ws.$TelescopeVMarks[i] ) ws.$TelescopeVMarks[i].remove();
ws.$TelescopeVMarks[i] = null;
i++;
}
i = ws.$TelescopeList.length;
while( i < ws.$TelescopeMMarks.length) { //shrink VMarks to match List
if( ws.$TelescopeMMarks[i] ) ws.$TelescopeMMarks[i].remove();
ws.$TelescopeMMarks[i] = null;
i++;
}
i = ws.$TelescopeList.length;
while( i < ws.$TelescopeMRings.length) { //shrink VMarks to match List
if( ws.$TelescopeMRings[i] ) ws.$TelescopeMRings[i].remove();
ws.$TelescopeMRings[i] = null;
i++;
}
}
this._VFCBVisualTarget_closure = function() { //orient vship model, make and update shadow and vmarkship
// 'constant' variables
var ws = worldScripts.telescope;
var ps, ps_scannerRange, ps_target, ps_heading, ps_position, who_isPlanet, who_isSun, who_isValid;
var vm, mp, wdn, who;
// function references
var system_addShips = system.addShips;
var system_addVisualEffect = system.addVisualEffect;
var telescope_VClear = ws.$Telescope_VClear;
var telescope_VClearM = ws.$Telescope_VClearM;
var telescope_InRangeFast = ws.$Telescope_InRangeFast;
var telescope_PlanetName = ws.$Telescope_PlanetName;
var telescope_Scan = ws.$Telescope_Scan;
function _VFCBVisualTargetMarker() {
if( vm ) vm.remove();
vm = system_addShips("telescopemarker", 1, mp, 1)[0];
ws.$TelescopeVMark = vm;
if( wdn && vm && vm.isValid ) vm.displayName = wdn;
//; log("Telescope", "VMarkShip:"+vm);//debug
if( vm && vm.isValid && (ps_target === who || who_isPlanet || who_isSun) && ps_target !== vm ) {
// var v = ws.$TelescopeVMarks[ws.$TelescopeListi-1];
// if( v && v.isValid )
vm.scannerDisplayColor1 = vm.scannerDisplayColor2 = [0.2, 0.2, 0.2];
//change the lock to the markership when step over normal scanner range
ws.$TelescopeTargetSet = true;//to avoid doubled list item message
//; log("Telescope", "Vtarget change n:"+n+"km from:"+vm+" to:"+who);//debug
ps.target = ps_target = vm;
ws.$TelescopeTarget = who; //save the real target after(!) set
//; log("Telescope", "Vtarget changed n:"+n+"km from:"+vm+" to:"+who);//debug
ws.$TelescopeTargetSet = false;
}
return(vm);
}
function _VFCBVisualTarget() { // make and update shadow and vmarkship
ps = player.ship; // need this here unless we export a fn to reset value when player changes ship
if( !ps || !ps.isValid ) return; //if player died
ps_scannerRange = ps.scannerRange; // needed in case scannerRange can chg over course of a game (new equipment?)
ps_target = ps.target;
if( !ws.$TelescopeAutoLock && !ps_target ) return;
// ws.$TelescopeV.orientation = ps.orientation;
var ti = ws.$TelescopeListi;
who = ws.$TelescopeList[ ti - 1 ];
var wp = null;
if( !who ) {
//; log("Telescope","VFCBVisualTarget ti:"+ti+" who:"+who);
telescope_VClear();
} else {
who_isPlanet = who.isPlanet;
who_isSun = who.isSun;
who_isValid = who.isValid;
wdn = "";
if( who_isValid && ( who_isPlanet || who_isSun || telescope_InRangeFast( who, ti ) ) ) {
wp = who.position;
if( who_isPlanet || who_isSun ) wdn = telescope_PlanetName(who);
else wdn = who.displayName; //remove km from ident message
} else wp = ws.$TelescopeListPos[ ti - 1 ]; //last known position
if( !wp ) return; //bugfix after jump
ps_heading = ps.heading;
ps_position = ps.position;
var vd = wp.subtract( ps_position ).direction(); //used below for target marker also
//current target marker
var md = ps_scannerRange - 499.6; //shadow lolipop nearer than others to reduce flickering
//do not set nearer to do not left behind aft markers during torus travel
mp = ps_position.add(vd.multiply(md))
.add(ps_heading.direction().multiply(ps.speed/25));
vm = ws.$TelescopeVMark;
var n = ps_position.distanceTo( wp );
if( who_isPlanet || who_isSun ) n -= who.radius;
else n += who.collisionRadius;
if( n < ps_scannerRange ) { //too near, replace the markership with visuall effect shadow lollipop
if( who_isPlanet || who_isSun ) { //stay with marker
mp = ps_position.add(vd.multiply(Math.min(md, n-299.6)
)).add(ps_heading.direction().multiply(ps.speed/25));
if( !vm || !vm.isValid || ws.$TelescopePrevPlanet !== who ) {
ws.$TelescopePrevPlanet = who;
vm = _VFCBVisualTargetMarker();
//; log("Telescope", "Markwho: "+who+" "+n+" m target:"+ps.target+" "+vm);
} else {
vm.position = mp;
}
} else {
if( vm && !ps_target ) //must check player target to remove shadow marker after scooped
telescope_VClearM();
else if( who && who_isValid && vm && ps_target === vm && ps_target !== who ) {
//change the lock to the real target when reached normal scanner range
ws.$TelescopeTargetSet = true;//to avoid doubled list item message
//; log("Telescope", "Vtarget change n:"+n+"km from:"+vm+" to:"+who);//debug
if( !who_isPlanet && !who_isSun ) ps.target = ps_target = who;
if( ps.target !== who && //yes, it is possible! Hohoho showed when a ship jumped!
// player.consoleMessage("Hohoho!");//debug
//bugfix against non-lockable Military Jammer awarded by ShipVersion to avoid repeated scan
ws.$TelescopePrevWho !== who ) {
// player.consoleMessage("Hohoho!");//debug
//; log("Telescope", "ScanV: "+who+" - "+ws.$TelescopePrevWho);//debug
ws.$TelescopePrevWho = who; //store to scan only once
telescope_Scan(); //forced scan to remove the invalid ball
}
ws.$TelescopeTarget = ps_target; //save the real target after(!) set
//; log("Telescope", "Vtarget changed n:"+n+"km from:"+vm+" to:"+who);//debug
ws.$TelescopeTargetSet = false;
}
if( vm && !vm.isVisualEffect ) { vm.remove(); vm = null; } //remove markership
if( !vm && ps_target ) { //check player target to remove shadow marker after scooped
vm = system_addVisualEffect("telescope-shadow", mp);
ws.$TelescopeVMark = vm;
} else if( vm ) vm.position = mp;
}
} else if( !vm || vm.isVisualEffect ) { //markership to can virtually target far ships
vm = _VFCBVisualTargetMarker();
} else vm.position = mp;
if( vm && vm.isValid && !vm.isVisualEffect ) {
if( n >= ps_scannerRange ) {
n -= ps.collisionRadius;
if( !who_isPlanet && !who_isSun ) n -= 2 * who.collisionRadius;
var km = Math.floor( n / 1000 );
if( km < 100 ) {
var m = Math.floor( n - km * 1000 ); //rest after km
var lz = ""; //leading zeros
if( m < 10 ) lz = "00";
else if( m < 100 ) lz = "0";
//ws.$TelescopeVMark.name =
ws.$TelescopeVMark.displayName =
// formatInteger( Math.round( n ) ) + //missing a dot after km
km + "." + lz + m + " km " + wdn;
} else {
if( km < 1000000 ) ws.$TelescopeVMark.displayName = km + " km " + wdn;
else ws.$TelescopeVMark.displayName = Math.floor( km / 1000000 ) + " Mkm " + wdn;
}
} else ws.$TelescopeVMark.displayName = wdn; //clear previous km
ws.$TelescopeVMark.velocity = ps.velocity;//keep target over Torus speeds in FarPlanets OXP
}
}
//; log("Telescope", "VFCB end, target:"+ps.target); //debug
}
return _VFCBVisualTarget;
}
|