Scripts/variablemasslock.js |
"use strict";
this.name = "variablemasslock";
this.author = "Norby";
this.copyright = "2015 Norby";
this.description= "Variable masslocks based on object masses";
this.licence = "CC BY-NC-SA 4.0";
//internal properties, should not touch
this.$VMActive = false; //there is at least a ship with changed scanClass to prevent masslock
this.$VMFCB = null; //FrameCallBack pointer
this.$VMRocks = []; //store asteroids, bouys and cargo boxes with changed scanClass
this.$VMShips = []; //store ships with changed scanClass and its original scanClass
this.$VMTimer = null; //Timer for detect new ships
//worldscript events
this.startUp = function() {
// this.$WSED = worldScripts.escortdeck;
}
this.alertConditionChanged = function(newCondition, oldCondition) {
var w = this;
if( newCondition == 1 ) { //green alert
if( !isValidFrameCallback( w.$VMFCB ) )
w.$VMFCB = addFrameCallback( w.$VM_FCB.bind(w) );
} else { //other than green alert
w.$VMActive = false;
if( isValidFrameCallback( w.$VMFCB ) )
removeFrameCallback( w.$VMFCB );
w.$VM_Restore(w);
if( newCondition == 2 ) w.$VM_Timed.bind(w);
}
}
this.shipDockedWithStation = function() {
this.$VM_StopTimer(this);
}
this.shipWillLaunchFromStation = function() {
this.$VM_StartTimer(this);
}
//VariableMasslock methods
this.$Range = function(mass) { //callable from other scripts
return( mass * 0.02 + 17000 ); //small masslock radius of this ship
}
this.$VM_FCB = function() { //FrameCallBack in green alert
//detect if a ship with changed scanClass is arrived within the shortened masslock range
//and restore scanClasses to go out from green alert
var p = player.ship;
var w = this;
if( !w.$VMActive || !p || !p.isValid ) return;
var s = w.$VMShips;
if( s ) for( var i = 0; i < s.length; i++ ) {
var si = s[i];
if( si ) {
var t = si[0];
if( t && t.isValid && si[2] > t.position.distanceTo( p.position ) ) {
t.scanClass = si[1]; //end of green alert within radius
t.scannerDisplayColor1 = null; //restore default color
}
}
}
}
this.$VM_Restore = function(w) { //restore scanClasses of changed ships to its original scanClass
var s = w.$VMShips;
if( s ) for( var i = 0; i < s.length; i++ ) {
var si = s[i];
if( si ) {
var t = si[0];
if( t && t.isValid ) {
t.scanClass = si[1]; //restore original scanClass
t.scannerDisplayColor1 = null; //restore default color
}
}
}
w.$VMShips = [];
}
this.$VM_Rocks = function(w) {
var p = player.ship;
for( var i = 0; i < w.$VMRocks.length; i++ ) {
var r = w.$VMRocks[i]; //restore changed asteroids
if( r ) {
var t = r[0]; //Asteroids do not masslock over the given distance
if( t && t.isValid ) {
var dist = t.position.distanceTo( p.position );
var angle = p.heading.angleTo( t.position.subtract(p.position) );
if( dist >= p.speed || angle >= 0.1 ) {
// log( w.name, t.name+" "+t.scanClass+" "+dist+"m "+angle+"rad" ); //debug
t.scanClass = r[1];
t.scannerDisplayColor1 = null; //restore default color
w.$VMRocks[i] = false; //remove from the array
}
}
}
}
}
this.$VM_StartTimer = function(w) {
this.$VMRocks = []; //store asteroids with changed scanClass
if( !w.$VMTimer ) w.$VMTimer = new Timer(w, w.$VM_Timed.bind(w), 1, 0.31);
}
this.$VM_StopTimer = function(w) {
w.$VM_Restore(w); //restore ship scanClasses in variable masslock range
for( var i = 0; i < w.$VMRocks.length; i++ ) {
var r = w.$VMRocks[i]; //restore changed asteroids
if( r && r.isValid ) {
var t = r[0]; //restore changed asteroids
if( t && t.isValid ) {
t.scanClass = r[1];
t.scannerDisplayColor1 = null; //restore default color
}
}
}
w.$VMRocks = [];
if( w.$VMTimer ) {
w.$VMTimer.stop();
delete w.$VMTimer;
}
}
this.$VM_Timed = function() { //detect if there is a ship on scanner over the shortened
// masslock range and change scanClass to do not masslock
var p = player.ship;
if( !p || !p.isValid ) return;
var w = this;
w.$VM_Restore(w); //restore ship scanClasses in variable masslock range
w.$VM_Rocks(w); //restore asteroids over given range
if( player.alertCondition > 2 ) return; //no check in red alert
var s = p.checkScanner(false);//much faster than filteredEntities
// var s = system.filteredEntities(w, w._isShip, p, p.scannerRange); //slow
var vm = true; //variable masslock active
if( s ) for( var i = 0; vm && i < s.length; i++ ) {
var t = s[i];
if( t && t.isValid ) {
var dist = t.position.distanceTo( p.position );
// log( w.name, t.name+" "+t.scanClass+" "+dist+"m"); //debug
var rock = false;
var c = t.scanClass;
if( c == "CLASS_BUOY" || c == "CLASS_CARGO" || c == "CLASS_MINE" ||
c == "CLASS_NO_DRAW" || c == "CLASS_ROCK" )
rock = true;
if( rock && dist < p.speed
&& p.heading.angleTo( t.position.subtract(p.position) ) < 0.1 ) {
w.$VMRocks.push( [t, c] ); //save
t.scanClass = "CLASS_STATION"; //Asteroids, buoys, etc. do masslock
t.scannerDisplayColor1 = [0.9, 0.9, 0.9]; //keep at gray
} else if( !rock ) {
var r = w.$Range( t.mass ); //small masslock radius of this ship
if( r < dist ) {
w.$VMShips.push( [t, t.scanClass, r] ); //save r for FCB
} else vm = false; //there is a ship within small radius
}
}
}
var v = w.$VMShips;
if( vm && v && v.length > 0 ) {
//change scanClasses only if all ships are out of radius, cause green alert
w.$VMActive = true;
for( var i = 0; i < v.length; i++ ) {
var t = v[i][0];
if( t && t.isValid ) {
var c = t.scanClass, d;
if( c == "CLASS_MILITARY" || c == "CLASS_POLICE" )
d = [0.5, 0.0, 0.5]; //purple
else if( c == "CLASS_MISSILE" )
d = [0.0, 0.9, 0.9]; //darker cyan
else if( c == "CLASS_STATION" )
d = [0.0, 0.9, 0.0]; //darker green
else if( c == "CLASS_THARGOID" )
d = [0.9, 0.0, 0.0]; //darker red
else d = [0.7, 0.7, 0]; //darker yellow
t.scanClass = "CLASS_BUOY";
t.scannerDisplayColor1 = d;
}
}
// log(w.name, v); //debug
} else {
w.$VMActive = false;
w.$VMShips = [];
}
}
/* http://wiki.alioth.net/index.php/Shipdata.plist#scan_class
Will alter the model's appearance on the IFF system. If this line is omitted, it will usually become by default a standard ship entity (CLASS_NEUTRAL), appearing as a yellow flag on the radar (red if hostile to the player), but may be given a different scan class if added with other roles. There are other options.
! CLASS_BUOY - green/yellow on scanner, will rotate in idle state, does not masslock
! CLASS_CARGO - white on scanner, can be scooped, does not masslock
CLASS_MILITARY - purple on scanner, better pilots, will not attack other military ships, flashes purple/magenta if hostile to player
CLASS_MISSILE - cyan on scanner, will not avoid collisions
CLASS_POLICE - purple on scanner, will not attack other police ships, legal penalties for attacking, never has bounty, flashes purple/magenta if hostile to player
! CLASS_ROCK - white on scanner, launched defense ships do not inherit scan class, does not masslock
CLASS_STATION - green on scanner, launched defense ships do not inherit scan class
CLASS_THARGOID - green/red on scanner, considered hostile to any non-thargoid ship
! CLASS_NO_DRAW - invisible on scanner, cannot be targeted by missiles, does not masslock
! CLASS_MINE - red/yellow on scanner, automatically set on mines launched by player to override existing scan class, does not masslock
(This property was called "scanClass" before Oolite 1.74.) Scan classes marked as "does not masslock" will masslock the player anyway if they are hostile to the player (as condition will be Red)
Scripts can define custom colours for ships on the IFF system so ships may have a scanner appearance different to the default for their scan class.
Example:
"scan_class" = "CLASS_ROCK";
Developer Note
Oolite uses scan_class internally to determine the behaviour of some ships (particularly with regard to who may shoot whom without incurring legal penalties). Bear this in mind and don't allocate CLASS_POLICE or CLASS_THARGOID to ships lightly!
*/
|