| Scripts/jh145_04_world.js | 
this.name        = 'jh145_04_world';
this.author      = 'jh145';
this.copyright   = '(C) 2015 jh145';
this.licence     = 'CC-NC-BY-SA 4.0';
this.description = 'Pre-emptive identification and alerting of new ships on the scanner.';
'use strict';
/* ========================================================================
 * ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 *
 * Equipment capabilities: which alert types to offer and which
 * scan classes to monitor.
 *
 * ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 * ========================================================================
 */
this._capabilities = [
  [ 'alerts',
    [ 'scan+con',  ['scanner','console'] ],
    [ 'scanner',   ['scanner']           ],
    [ 'console',   ['console']           ],
    [ 'none',      []                    ]
  ],
  [ 'ships',
    [ 'civilian',     ['CLASS_NEUTRAL']                                 ],
    [ 'military',     ['CLASS_MILITARY']                                ],
    [ 'police',       ['CLASS_POLICE']                                  ],
    [ 'civ+mil+pol',  ['CLASS_NEUTRAL','CLASS_MILITARY','CLASS_POLICE'] ]
  ],
  [ 'extras',
    [ 'escape pods',      ['escpods']             ],
    [ 'dockable rocks',   ['rockdocks']           ],
    [ 'pods+docks',       ['escpods','rockdocks'] ],
    [ 'none',             []                      ]
  ]
];
/* ========================================================================
 * ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 *
 * Equipment "API"
 *
 * + worldScript functions:
 *   | _SAE_nextSubmenu()       : 'n' key
 *   | _SAE_nextSubmenuItem()   : 'b' key
 *   | _SAE_updateDisplay()     : on timer
 *   | _SAE_rememberOne(target) : on targeting
 *   | _SAE_forgetAll()         : on jumping, docking or equipment failure
 *
 * + worldScript data:
 *   | _SAE_config : capability choices
 *
 * + Ship state induced by this equipment:
 *   | _jh145_04_haveTargeted  : boolean
 *   | _jh145_04_originalSDC   : original lollipop colours (set iff flashing)
 *   | _jh145_04_haveConLogged : boolean
 *
 * ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 * ========================================================================
 */
this._SAE_config = {};    // populated by this.startUp()
this._SAE_nextSubmenu = function() {
  this._capabilities = this._capabilities.slice(1).concat([this._capabilities[0]]);
  var cap = this._capabilities[0];
  player.consoleMessage( '['+cap[0]+':'+cap[1][0]+']', 2 );
}
this._SAE_nextSubmenuItem = function() {
  var cap = this._capabilities[0];
  this._capabilities[0] = [cap[0]].concat(cap.slice(2)).concat([cap[1]]);
  cap = this._capabilities[0];
  player.consoleMessage( '['+cap[0]+':'+cap[1][0]+']', 2 );
  this._SAE_config[cap[0]] = cap[1][1];
}
this._SAE_updateDisplay = function() {
  if (!this._isWorking() || player.ship.docked) return;
  var alertScanClasses = this._SAE_config.ships;
  var alertMayFlash    = (this._SAE_config.alerts.indexOf('scanner') >= 0);
  var alertMayLog      = (this._SAE_config.alerts.indexOf('console') >= 0);
  var extras           = this._SAE_config.extras;
  var ships = player.ship.checkScanner(false);
  for (var i=0; i<ships.length; i++) {
    var ship      = ships[i];
    var alertable = (
      ship._jh145_04_haveTargeted!==true && (
        alertScanClasses.indexOf(ship.scanClass)>=0
        || (extras.indexOf('escpods')>=0 && ship.primaryRole=='escape-capsule')
        || (extras.indexOf('rockdocks')>=0 && ship.scanClass=='CLASS_ROCK' && ship instanceof Station)
      )
    );
    // update lollipops
    var isFlashing = (ship._jh145_04_originalSDC!==undefined);
    var shouldFlash = (alertable && alertMayFlash);
    if (!isFlashing && shouldFlash) {
      ship._jh145_04_originalSDC = [
        ship.scannerDisplayColor1,        ship.displayColor2,
        ship.scannerHostileDisplayColor1, ship.displayColor2,
      ];
      var effectiveSDC = this._actualDisplayedColours(ship);
      this._writeSDC(ship,[effectiveSDC[0],'brownColor',effectiveSDC[2],effectiveSDC[3]]);
    } else if (isFlashing && !shouldFlash) {
      this._writeSDC(ship,ship._jh145_04_originalSDC);
      delete ship._jh145_04_originalSDC;
    }
    // update console log
    var hasLogged = (ship._jh145_04_haveConLogged===true);
    var shouldLog = (alertable && alertMayLog);
    if (!hasLogged && shouldLog) {
      player.consoleMessage('+ '+ship.shipClassName);
      ship._jh145_04_haveConLogged = true;
    }
  }
}
this._SAE_rememberOne = function(target) {
  if (!this._isWorking()) return;
  target._jh145_04_haveTargeted = true;
}
this._SAE_forgetAll = function() {
  for (var i=0; i<system.allShips.length; i++) {
    var target = system.allShips[i];
    if (target._jh145_04_haveTargeted)  delete target._jh145_04_haveTargeted;
    if (target._jh145_04_haveConLogged) delete target._jh145_04_haveConLogged;
    if (target._jh145_04_originalSDC)   delete target._jh145_04_originalSDC;
  }
}
/* ========================================================================
 * ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 *
 * "Internal" functions, most of which are devoted to faffing around with
 * lollipop colour schemes.
 *
 * ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 * ========================================================================
 */
this._wasWorking = false;
this._isWorking = function() {
  var isWorking = (player.ship.equipmentStatus('EQ_SCANNER_ALERTING_ENHANCEMENT')=='EQUIPMENT_OK');
  if (this._wasWorking && !isWorking) this._SAE_forgetAll();
  this._wasWorking = isWorking;
  return isWorking;
}
this._actualDisplayedColours = function(target) {
  var sdc1  = target.scannerDisplayColor1;
  var sdc2  = target.scannerDisplayColor2;
  var shdc1 = target.scannerHostileDisplayColor1;
  var shdc2 = target.scannerHostileDisplayColor2;
  var cols  = this._defaultDisplayedColours(target.scanClass);
  var userDefinedSDC = true;
  if (!sdc1 && !sdc2) { sdc1 = cols[0]; sdc2 = cols[1]; userDefinedSDC = false; }
  else if (!sdc1)     { sdc1 = sdc2; }
  else if (!sdc2)     { sdc2 = sdc1; }
  if (!shdc1 && !shdc2) { shdc1 = userDefinedSDC ? sdc1 : cols[2];
                          shdc2 = userDefinedSDC ? sdc2 : cols[3]; }
  else if (!shdc1) { shdc1 = shdc2; }
  else if (!shdc2) { shdc2 = shdc1; }
  return [ sdc1, sdc2, shdc1, shdc2 ];
}
this._defaultDisplayedColours = function(scanClass) {
  var c_cargo    = [ 0.9, 0.9, 0.9, 1.0 ];  // grey
  var c_hostile  = [ 1.0, .25, 0.0, 1.0 ];  // red/orange
  var c_neutral  = [ 1.0, 1.0, 0.0, 1.0 ];  // yellow
  var c_friendly = [ 0.0, 1.0, 0.0, 1.0 ];  // green
  var c_missile  = [ 0.0, 1.0, 1.0, 1.0 ];  // cyan
  var c_police1  = [ 0.5, 0.0, 1.0, 1.0 ];  // purpley-blue
  var c_police2  = [ 1.0, 0.0, 0.5, 1.0 ];  // purpley-red
  switch (scanClass) {
    case 'CLASS_ROCK':
    case 'CLASS_CARGO':
      return [c_cargo,c_cargo,c_cargo,c_cargo];
    case 'CLASS_THARGOID':
      return [c_friendly,c_hostile,c_friendly,c_hostile];
    case 'CLASS_MISSILE':
      return [c_missile,c_missile,c_missile,c_missile];
    case 'CLASS_STATION':
      return [c_friendly,c_friendly,c_friendly,c_friendly];
    case 'CLASS_BUOY':
      return [c_neutral,c_friendly,c_neutral,c_friendly];
    case 'CLASS_POLICE':
    case 'CLASS_MILITARY':
      return [c_police1,c_police1,c_police1,c_police2];  // yes, 1112
    case 'CLASS_MINE':
      return [c_hostile,c_neutral,c_hostile,c_neutral];
  }
  return [c_neutral,c_neutral,c_hostile,c_hostile];
}
this._writeSDC = function(target,colours) {
  var _v = function(x) { return x===undefined ? null : x; }
  target.scannerDisplayColor1        = _v(colours[0]);
  target.scannerDisplayColor2        = _v(colours[1]);
  target.scannerHostileDisplayColor1 = _v(colours[2]);
  target.scannerHostileDisplayColor2 = _v(colours[3]);
}
/* ========================================================================
 * ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 *
 * Methods called by the core game.  Keep at end of script.
 *
 * ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 * ========================================================================
 */
this.startUp = function() {
  this._timer = new Timer(this,this._SAE_updateDisplay,0,1.202056903);
  // 1.202... is just today's favourite number a little bigger than 1.
  for (var i=0; i<this._capabilities.length; i++) {
    var cap = this._capabilities[i];
    this._SAE_config[cap[0]] = cap[1][1];
  }
}
this.shipTargetAcquired = this._SAE_rememberOne;
this.shipWillEnterWitchspace = this.shipDockedWithStation = this._SAE_forgetAll;
 |