I'm pretty new to oolite but a coder from the dark ages (pre-web) and got the itch to tinker. There's nothing wrong w/ FTS but I found it slow to respond sometimes; turns out I was loading too many oxp's. Before I figured that out, I optimized some of your code and got 15-40% faster, depending on how full my scanner was. I only just recently figured out how to benchmark it and on my rig, we're only talking a dozen or so msec. Rather than toss it, I figured every little bit helps, esp. on slower rigs, so here goes. I modified 2 variable declarations at the top and everything from lookForTarget() to eof:
Code: Select all
... line 23
this._index = -1; // position of players selected target in array
//this._sortRequired = false; // indicates whether the scan data array needs to be sorted
//cag: no longer used
... line 31
this._ignoreRoles = ["btd_dummy_entity"]; // ship roles that will be ignored (ie they won't be selected)
//cag: increasing the length of _ignoreRoles requires chg's to $findNPCShips()
this._active = false; // flag to indicate the FTS is in operation
... line 221
this.$lookForTarget = function(direction) {
var currNPC = null;
var ps = player.ship;
var valid = false;
this.$refreshArray();
if (this._npc && this._npc.length > 0) {
var lc = 0;
do {
this._index += direction;
// select the next/previous index value, based on the direction
if (this._index < 0)
// if we get to the beginning of the array, go back to the end
this._index = this._npc.length - 1;
else if (this._index > this._npc.length - 1)
// if we get to the end of the array, go back to the beginning
this._index = 0;
currNPC = this._npc[this._index];
valid = currNPC && currNPC.isValid === true && currNPC.isJamming === false
&& currNPC.isCloaked === false;
if (valid && ps.position.distanceTo(currNPC) < 25600) {
// if the item is valid, make it the player's target
ps.target = currNPC;
break;
}
lc += 1;
} while ( valid && lc < this._npc.length );
// if we didn't get a target, keep looping until we do
}
}
this.$refreshArray = function() {
// get the array of ships
if ((global.clock.adjustedSeconds - this._dataAge) > 1) { // limit to once/sec
this._npc = this.$findNPCShips();
this._dataAge = global.clock.adjustedSeconds;
}
}
this.$findNPCShips = function() {
function _isNPC(entity) {
var wF = worldScripts.FastTargetSelector;
if( !entity.isShip ) return false;
if( entity.isPlayer ) return false;
if( entity.displayName === "Wreckage" ) return false;
if (wF._trueCondition === 3 && wF._scanMode === 0) {
// during red alert, only target thargoids, missiles and enemy ships
if( entity.isThargoid === true && entity.isCargo === false ) return true;
if( entity.target === player.ship && entity.hasHostileTarget ) return true;
if( entity.isMine ) return true;
if( entity.isWeapon ) return true;
return false;
}
if( entity.isVisualEffect ) return false ;
if( entity.docked ) return false; //cag: to exclude ships on escortdeck
// if( wF._ignoreRoles.indexOf(entity.primaryRole) === -1 ) return false; // list has only 1 entry & indexOf is slow!
if( entity.primaryRole === wF._ignoreRoles[0] ) return false;
return true;
}
return system.filteredEntities(this, _isNPC, player.ship, 25600);
}
Basically, I did 3 things:
- moved the trap for wreckage up into _isNPC (removing that loop)
- removed sortArray, as filteredEntities' return is sorted if you give it a 3rd arg (which you did)
- re-wrote _isNPC to be explicit
That last one probably didn't do much speed wise but statements like your original return statements in _isNPC are like fingernails on a chalk board to me. I should point out that those were logically flawless and will execute as you intended, but...
<pompous lecturing commencing>
There's so much going on they're hard to debug. And an interpreter can 'optimize' them in unexpected ways, if you don't get the brackets just right. What happens is, if it sees either:
<expression is true> || ...
<expression is false> && ...
it quits processing and ignores the rest of the code in the brackets or statement, if not bounded by brackets.
If you inadvertently combine contradictory expressions, the rest of the expressions *never* get evaluated (been there, done that, wasted hours using a primitive debugger [I did say dark ages, didn't I?] ).
If they get long and/or convoluted, you can end up evaluating expressions unnecessarily, which becomes obvious when written explicitly. (This last one was not aimed at you but someone in the audience; no names).
Another perk of being explicit is you can easily play around to speed things up, just by reordering the (equivalent value) lines. E.g. if you hadn't tested for Thargoid's before regular hostiles, I'd have moved that line up, as I'll take any edge I can get when they swarm!
<lecture ends; humble apologies>
"Better to be thought a fool, boy, than to open your trap and remove all doubt." - Grandma [over time, just "Shut your trap... fool"]
"The only stupid questions are the ones you fail to ask." - Dad
How do I...? Nevermind.