2013-07-13 11:36:28 +01:00
/ *
2013-08-31 16:21:07 +01:00
oolite - priorityai . js
2013-07-13 11:36:28 +01:00
2013-07-26 18:52:11 +01:00
Priority - based Javascript AI library
2013-07-13 11:36:28 +01:00
2013-07-26 18:52:11 +01:00
Oolite
Copyright © 2004 - 2013 Giles C Williams and contributors
2013-07-13 11:36:28 +01:00
2013-07-26 18:52:11 +01:00
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation ; either version 2
of the License , or ( at your option ) any later version .
2013-07-13 11:36:28 +01:00
2013-07-26 18:52:11 +01:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2013-07-13 11:36:28 +01:00
2013-07-26 18:52:11 +01:00
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston ,
MA 02110 - 1301 , USA .
2013-07-13 11:36:28 +01:00
* /
"use strict" ;
2013-07-12 19:44:14 +01:00
/* AI Library */
this . name = "oolite-libPriorityAI" ;
this . version = "1.79" ;
2013-07-13 11:36:28 +01:00
this . copyright = "© 2008-2013 the Oolite team." ;
this . author = "cim" ;
2013-07-12 19:44:14 +01:00
/* Constructor */
2013-08-31 16:21:07 +01:00
this . PriorityAIController = function ( ship )
2013-07-12 19:44:14 +01:00
{
2013-08-01 22:40:23 +01:00
// the ship property must be read-only
Object . defineProperty ( this , "ship" , {
value : ship ,
writable : false ,
enumerable : true ,
2013-08-04 14:20:20 +01:00
configurable : true
2013-08-01 22:40:23 +01:00
} ) ;
2013-08-07 16:29:24 +01:00
this . _ _cache = { } ; // short-term cache
this . _ _ltcache = { } ; // long-term cache
this . _ _ltcachestart = clock . adjustedSeconds + 60 ;
this . scannerRange = this . ship . scannerRange ; // cached
2013-08-01 22:40:23 +01:00
this . ship . AIScript . oolite _intership = { } ;
this . ship . AIScript . oolite _priorityai = this ;
var activeHandlers = [ ] ;
2013-08-07 10:53:44 +01:00
var handlerCache = { } ;
2013-08-01 22:40:23 +01:00
var priorityList = null ;
var parameters = { } ;
var lastCommSent = 0 ;
var lastCommHeard = 0 ;
var commsRole = "generic" ;
var commsPersonality = "generic" ;
var waypointgenerator = null ;
2013-09-08 17:20:28 +01:00
this . playerRole = this . playerRoleAssessment ( ) ;
2013-08-07 10:53:44 +01:00
/* Cache variables used by utility functions */
var condmet = true ;
2013-08-01 22:40:23 +01:00
/* Private utility functions. Cannot be called from external code */
2013-08-07 10:53:44 +01:00
// event handlers which must not be overridden
function _handlerAIAwoken ( )
{
if ( this . ship )
{
_reconsider . call ( this ) ;
}
}
function _handlerShipDied ( )
{
{
this . cleanup ( ) ;
}
}
2013-08-01 22:40:23 +01:00
/* Considers a priority list, potentially recursively */
function _reconsiderList ( priorities ) {
2013-08-09 13:09:54 +01:00
var logging = this . getParameter ( "oolite_flag_behaviourLogging" ) ;
2013-08-07 16:29:24 +01:00
var pl = priorities . length ;
2013-08-10 08:34:33 +01:00
if ( pl == 0 )
{
log ( this . name , "AI '" + this . ship . AIScript . name + "' for ship " + this . ship + " had a branch with no entries. This may be caused by a template function not being executed during priority set up." ) ;
}
2013-08-08 16:00:20 +01:00
if ( logging )
{
log ( this . ship . name , "Considering branch with " + pl + " entries" ) ;
}
2013-08-07 16:29:24 +01:00
for ( var i = 0 ; i < pl ; i ++ )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
if ( logging )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
if ( priorities [ i ] . label )
2013-08-04 12:29:44 +01:00
{
2013-08-07 10:53:44 +01:00
log ( this . ship . name , "Considering: " + priorities [ i ] . label ) ;
2013-07-12 19:44:14 +01:00
}
2013-08-01 22:40:23 +01:00
else
{
log ( this . ship . name , "Considering: entry " + i ) ;
}
}
// always call the preconfiguration function at this point
// to set up condition parameters
2013-08-07 10:53:44 +01:00
if ( priorities [ i ] . preconfiguration )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
priorities [ i ] . preconfiguration . call ( this ) ;
2013-08-01 22:40:23 +01:00
}
// allow inverted conditions
2013-08-07 10:53:44 +01:00
condmet = true ;
if ( priorities [ i ] . notcondition )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
condmet = ! priorities [ i ] . notcondition . call ( this ) ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
else if ( priorities [ i ] . condition )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
condmet = priorities [ i ] . condition . call ( this ) ;
2013-08-01 22:40:23 +01:00
}
// absent condition is always true
if ( condmet )
{
2013-08-07 10:53:44 +01:00
if ( logging )
2013-07-17 22:44:26 +01:00
{
2013-08-01 22:40:23 +01:00
log ( this . ship . name , "Conditions met" ) ;
2013-07-17 22:44:26 +01:00
}
2013-08-01 22:40:23 +01:00
// always call the configuration function at this point
2013-08-07 10:53:44 +01:00
if ( priorities [ i ] . configuration )
2013-07-13 19:13:30 +01:00
{
2013-08-07 10:53:44 +01:00
priorities [ i ] . configuration . call ( this ) ;
2013-07-13 19:13:30 +01:00
}
2013-08-01 22:40:23 +01:00
// this is what we're doing
2013-08-07 10:53:44 +01:00
if ( priorities [ i ] . behaviour )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
if ( logging )
2013-08-01 22:40:23 +01:00
{
log ( this . ship . name , "Executing behaviour" ) ;
}
2013-08-07 10:53:44 +01:00
if ( priorities [ i ] . reconsider )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
_resetReconsideration . call ( this , priorities [ i ] . reconsider ) ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
return priorities [ i ] . behaviour ;
2013-07-13 19:13:30 +01:00
}
2013-08-01 22:40:23 +01:00
// otherwise this is what we might be doing
2013-08-07 10:53:44 +01:00
if ( priorities [ i ] . truebranch )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
if ( logging )
2013-08-01 22:40:23 +01:00
{
log ( this . ship . name , "Entering truebranch" ) ;
}
2013-07-13 19:13:30 +01:00
2013-08-07 10:53:44 +01:00
var branch = _reconsiderList . call ( this , priorities [ i ] . truebranch ) ;
2013-08-01 22:40:23 +01:00
if ( branch != null )
{
return branch ;
}
// otherwise nothing in the branch was usable, so move on
}
}
else
{
2013-08-07 10:53:44 +01:00
if ( priorities [ i ] . falsebranch )
2013-07-16 22:33:42 +01:00
{
2013-08-07 10:53:44 +01:00
if ( logging )
2013-08-01 22:40:23 +01:00
{
log ( this . ship . name , "Entering falsebranch" ) ;
}
2013-08-07 10:53:44 +01:00
var branch = _reconsiderList . call ( this , priorities [ i ] . falsebranch ) ;
2013-08-01 22:40:23 +01:00
if ( branch != null )
{
return branch ;
}
// otherwise nothing in the branch was usable, so move on
2013-07-16 22:33:42 +01:00
}
2013-08-01 22:40:23 +01:00
}
}
2013-08-07 10:53:44 +01:00
if ( this . getParameter ( logging ) )
2013-08-01 22:40:23 +01:00
{
log ( this . ship . name , "Exiting branch" ) ;
}
return null ; // nothing in the list is usable, so return
} ;
2013-07-13 19:13:30 +01:00
2013-08-07 10:53:44 +01:00
2013-08-01 22:40:23 +01:00
/* Only call this from aiAwoken to avoid loops */
function _reconsider ( ) {
if ( ! this . ship || ! this . ship . isValid || ! this . ship . isInSpace )
{
return ;
}
2013-08-17 20:41:36 +01:00
this . _ _cache = { } ; // clear short-term cache
2013-08-07 16:29:24 +01:00
// maybe clear long-term cache
if ( this . _ _ltcachestart < clock . adjustedSeconds )
{
this . _ _ltcache = { } ;
this . _ _ltcachestart = clock . adjustedSeconds + 60 ;
}
2013-08-17 15:19:25 +01:00
if ( ! this . _ _ltcache . oolite _nearestStation )
2013-08-17 13:26:37 +01:00
{
2013-08-17 15:19:25 +01:00
this . _ _ltcache . oolite _nearestStation = this . ship . findNearestStation ( ) ;
2013-08-17 13:26:37 +01:00
}
2013-08-01 22:40:23 +01:00
var newBehaviour = _reconsiderList . call ( this , priorityList ) ;
if ( newBehaviour == null ) {
log ( this . name , "AI '" + this . ship . AIScript . name + "' for ship " + this . ship + " had all priorities fail. All priority based AIs should end with an unconditional entry." ) ;
return false ;
}
2013-07-13 19:13:30 +01:00
2013-08-01 22:40:23 +01:00
if ( this . getParameter ( "oolite_flag_behaviourLogging" ) )
2013-07-12 19:44:14 +01:00
{
2013-08-01 22:40:23 +01:00
log ( this . ship . name , newBehaviour ) ;
}
newBehaviour . call ( this ) ;
return true ;
} ;
2013-07-12 19:44:14 +01:00
2013-08-07 16:29:24 +01:00
/* Resets the reconsideration timer. (Can't make it later) */
2013-08-01 22:40:23 +01:00
function _resetReconsideration ( delay )
{
2013-08-04 14:49:52 +01:00
if ( this . ship )
{
2013-08-07 16:29:24 +01:00
var newwake = clock . adjustedSeconds + delay ;
if ( this . ship . AIScriptWakeTime > newwake || this . ship . AIScriptWakeTime == 0 )
{
this . ship . AIScriptWakeTime = newwake ;
}
2013-08-04 14:49:52 +01:00
}
2013-08-01 22:40:23 +01:00
} ;
2013-07-12 19:44:14 +01:00
2013-07-27 12:29:59 +01:00
2013-08-01 22:40:23 +01:00
/* ****************** General AI functions. ************** */
/ * T h e s e p r i v i l e g e d f u n c t i o n s i n t e r f a c e w i t h t h e p r i v a t e f u n c t i o n s
* and variables . Do not override them . * /
2013-07-13 19:13:30 +01:00
2013-08-07 10:53:44 +01:00
/ * T h e s i m p l e i m p l e m e n t a t i o n o f t h i s f u n c t i o n r e q u i r e s a l o t o f
* creation and destruction of function objects , which aggravates
* the garbage collector . We avoid this where possible by keeping
* a cache ( pre - binding ) of the handler objects , and only
* replacing those which have changed . This requires the functions
* to be stored where possible as this . variables ( or
* this . prototype . variables ) * /
2013-08-01 22:40:23 +01:00
this . applyHandlers = function ( handlers )
{
/ * T h i s h a n d l e r m u s t a l w a y s e x i s t f o r a p r i o r i t y A I , a n d m u s t
* be set here . * /
2013-08-07 10:53:44 +01:00
handlers . aiAwoken = _handlerAIAwoken ;
2013-08-04 14:20:20 +01:00
/ * T h i s h a n d l e r m u s t a l w a y s e x i s t f o r a p r i o r i t y A I , a n d m u s t
* be set here . * /
2013-08-07 10:53:44 +01:00
handlers . shipDied = _handlerShipDied ;
// step 1: go through activeHandlers, and delete those
// functions from this.ship.AIScript that aren't in the new
// handler list
2013-08-27 22:08:35 +01:00
for ( var i = activeHandlers . length - 1 ; i >= 0 ; i -- )
2013-08-04 14:20:20 +01:00
{
2013-08-07 10:53:44 +01:00
if ( handlerCache [ activeHandlers [ i ] ] != handlers [ activeHandlers [ i ] ] )
{
delete this . ship . AIScript [ activeHandlers [ i ] ] ;
delete handlerCache [ activeHandlers [ i ] ] ;
}
2013-07-12 19:44:14 +01:00
}
2013-08-01 22:40:23 +01:00
// step 2: go through the keys in handlers and put those handlers
// into this.ship.AIScript and the keys into activeHandlers
activeHandlers = Object . keys ( handlers ) ;
2013-08-27 22:08:35 +01:00
for ( var i = activeHandlers . length - 1 ; i >= 0 ; i -- )
2013-07-12 19:44:14 +01:00
{
2013-08-07 10:53:44 +01:00
// unset or not deleted in step 1
if ( ! this . ship . AIScript [ activeHandlers [ i ] ] )
{
handlerCache [ activeHandlers [ i ] ] = handlers [ activeHandlers [ i ] ] ;
if ( handlers [ activeHandlers [ i ] ] )
{
this . ship . AIScript [ activeHandlers [ i ] ] = handlers [ activeHandlers [ i ] ] . bind ( this ) ;
}
else
{
log ( this . name , "AI '" + this . ship . AIScript . name + "' for ship " + this . ship + " had an invalid entry for handler " + activeHandlers [ i ] + ". Skipped." ) ;
}
}
2013-07-12 19:44:14 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-27 12:29:59 +01:00
2013-08-01 22:40:23 +01:00
2013-08-27 22:08:35 +01:00
/* Do not call this directly. It is called automatically on ship death */
2013-08-04 14:20:20 +01:00
this . cleanup = function ( )
{
// break links to disconnect this from GC roots a little sooner
delete this . ship . AIScript . oolite _priorityai ;
2013-08-04 14:49:52 +01:00
this . applyHandlers ( { } ) ;
2013-08-04 14:20:20 +01:00
this . ship . AIScriptWakeTime = 0 ;
delete this . ship . AIScript . aiAwoken ;
Object . defineProperty ( this , "ship" , {
value : ship ,
writable : true ,
enumerable : true ,
configurable : true
} ) ;
delete this . ship ;
delete this . parameters ; // might contain entities
}
2013-08-09 13:09:54 +01:00
this . clearHandlers = function ( )
{
// delete all handlers to allow rebinding
activeHandlers = Object . keys ( handlerCache ) ;
for ( var i = 0 ; i < activeHandlers . length ; i ++ )
{
delete this . ship . AIScript [ activeHandlers [ i ] ] ;
}
handlerCache = { } ;
delete this . ship . AIScript . aiAwoken ;
delete this . ship . AIScript . shipDied ;
}
2013-08-01 22:40:23 +01:00
this . communicate = function ( key , params , priority )
{
if ( priority > 1 )
2013-07-12 19:44:14 +01:00
{
2013-08-01 22:40:23 +01:00
var send = clock . adjustedSeconds - lastCommSent ;
if ( priority == 2 )
{
if ( send < 10 )
{
return ;
}
}
2013-08-02 22:16:54 +01:00
else
2013-08-01 22:40:23 +01:00
{
2013-08-02 22:16:54 +01:00
var recv = clock . adjustedSeconds - lastCommHeard ;
if ( priority == 3 )
2013-08-01 22:40:23 +01:00
{
2013-08-02 22:16:54 +01:00
if ( recv < 10 || send < 10 )
{
return ;
}
2013-08-01 22:40:23 +01:00
}
2013-08-02 22:16:54 +01:00
else
2013-07-12 19:44:14 +01:00
{
2013-08-02 22:16:54 +01:00
if ( recv < 60 || send < 60 )
{
return ;
}
2013-07-12 19:44:14 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-12 19:44:14 +01:00
}
2013-08-01 22:40:23 +01:00
var template = worldScripts [ "oolite-libPriorityAI" ] . _getCommunication ( commsRole , commsPersonality , key ) ;
if ( template != "" )
2013-07-19 20:18:53 +01:00
{
2013-08-12 18:45:09 +01:00
if ( params && params . isShip )
2013-08-07 16:29:24 +01:00
{
params = this . entityCommsParams ( params ) ;
}
2013-08-01 22:40:23 +01:00
var message = expandDescription ( template , params ) ;
if ( message != "" )
{
this . ship . commsMessage ( message ) ;
lastCommSent = clock . adjustedSeconds ;
}
2013-08-02 22:16:54 +01:00
else
{
// this is for debugging: ordinarily this is legitimate
2013-08-04 12:29:44 +01:00
// log(this.name,"Empty message for "+key);
2013-08-02 22:16:54 +01:00
}
2013-07-19 20:18:53 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-19 20:18:53 +01:00
2013-08-01 22:40:23 +01:00
this . getParameter = function ( key )
{
if ( key in parameters )
2013-07-14 21:28:19 +01:00
{
2013-08-01 22:40:23 +01:00
return parameters [ key ] ;
2013-07-12 19:44:14 +01:00
}
2013-08-01 22:40:23 +01:00
return null ;
}
2013-07-12 19:44:14 +01:00
2013-07-13 19:13:30 +01:00
2013-08-01 22:40:23 +01:00
this . getWaypointGenerator = function ( )
{
return waypointgenerator ;
}
2013-07-12 19:44:14 +01:00
2013-07-15 23:14:47 +01:00
2013-08-01 22:40:23 +01:00
this . noteCommsHeard = function ( )
{
lastCommHeard = clock . adjustedSeconds ;
}
2013-07-12 19:44:14 +01:00
2013-08-01 22:40:23 +01:00
/* Requests reconsideration of behaviour ahead of schedule. */
this . reconsiderNow = function ( )
{
2013-08-08 16:00:20 +01:00
_resetReconsideration . call ( this , 0.1 ) ;
2013-08-01 22:40:23 +01:00
}
2013-07-27 12:29:59 +01:00
2013-08-01 22:40:23 +01:00
this . setCommunicationsRole = function ( role )
{
commsRole = role ;
2013-08-09 18:00:18 +01:00
// TODO: if personality is generic, pick a new one from the
// allowed list. If possible use the same as the group leader.
2013-08-01 22:40:23 +01:00
}
this . setCommunicationsPersonality = function ( personality )
{
commsPersonality = personality ;
}
// parameters created by Oolite must always be prefixed oolite_
this . setParameter = function ( key , value )
{
parameters [ key ] = value ;
}
this . setPriorities = function ( priorities )
{
priorityList = priorities ;
2013-08-09 13:09:54 +01:00
this . clearHandlers ( ) ;
2013-08-01 22:40:23 +01:00
this . applyHandlers ( { } ) ;
2013-08-07 17:08:31 +01:00
_resetReconsideration . call ( this , Math . random ( ) ) ;
2013-08-01 22:40:23 +01:00
}
// set the waypoint generator function
this . setWaypointGenerator = function ( value )
{
waypointgenerator = value ;
}
2013-07-13 19:13:30 +01:00
2013-07-27 12:29:59 +01:00
2013-07-26 18:52:11 +01:00
} ; // end object constructor
2013-07-13 19:13:30 +01:00
2013-07-26 18:52:11 +01:00
/* Object prototype */
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . constructor = PriorityAIController ;
PriorityAIController . prototype . name = this . name ;
2013-07-26 18:52:11 +01:00
/* ****************** AI utility functions. ************** */
/ * T h e s e f u n c t i o n s p r o v i d e s t a n d a r d c h e c k s f o r c o n s i s t e n c y i n
* conditions and other functions . * /
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . allied = function ( ship1 , ship2 )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
// ships in same group
2013-08-07 16:29:24 +01:00
var g1 = ship1 . group ;
if ( g1 && g1 . containsShip ( ship2 ) )
2013-08-01 22:40:23 +01:00
{
return true ;
}
2013-08-07 16:29:24 +01:00
if ( g1 && g1 . leader )
2013-08-01 22:40:23 +01:00
{
// ship1 is escort of ship in same group as ship2
2013-08-07 16:29:24 +01:00
if ( g1 . leader . group && g1 . leader . group . containsShip ( ship2 ) )
2013-08-01 22:40:23 +01:00
{
return true ;
}
}
// or in reverse, ship2 is the escort
2013-08-07 16:29:24 +01:00
var g2 = ship2 . group ;
if ( g2 && g2 . leader )
2013-08-01 22:40:23 +01:00
{
// ship2 is escort of ship in same group as ship1
2013-08-07 16:29:24 +01:00
if ( g2 . leader . group && g2 . leader . group . containsShip ( ship1 ) )
2013-08-01 22:40:23 +01:00
{
return true ;
}
}
// ship1 is escort of a ship, ship2 is escort of a ship, both
// those ships are in the same group
2013-08-07 16:29:24 +01:00
if ( g1 && g2 && g1 . leader && g2 . leader && g1 . leader . group && g1 . leader . group . containsShip ( g2 . leader ) )
2013-08-01 22:40:23 +01:00
{
return true ;
}
2013-08-07 16:29:24 +01:00
// all thargoids are allied with each other
// all police are allied with each other
if ( ship1 . scanClass == "CLASS_THARGOID" || ship1 . scanClass == "CLASS_POLICE" )
2013-08-04 12:29:44 +01:00
{
2013-08-07 16:29:24 +01:00
if ( ship1 . scanClass == ship2 . scanClass )
2013-08-04 12:29:44 +01:00
{
return true ;
}
}
2013-08-01 22:40:23 +01:00
// Okay, these ships really do have nothing to do with each other...
return false ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . broadcastDistressMessage = function ( )
2013-08-01 22:40:23 +01:00
{
2013-08-30 21:14:55 +01:00
if ( this . _ _ltcache . oolite _sentDistressMessage )
{
return ;
}
this . _ _ltcache . oolite _sentDistressMessage = true ;
2013-08-01 22:40:23 +01:00
this . ship . broadcastDistressMessage ( ) ;
if ( this . ship . AIPrimaryAggressor )
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_makeDistressCall" , this . ship . AIPrimaryAggressor , 2 ) ;
2013-08-01 22:40:23 +01:00
}
2013-07-26 18:52:11 +01:00
}
2013-07-13 23:18:05 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . checkScannerWithPredicate = function ( predicate )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var scan = this . getParameter ( "oolite_scanResults" ) ;
if ( scan == null || predicate == null )
{
return false ;
}
2013-08-09 18:00:18 +01:00
// if current target matches, use that
if ( this . ship . target && predicate . call ( this , this . ship . target ) )
{
this . setParameter ( "oolite_scanResultSpecific" , this . ship . target ) ;
return true ;
}
2013-08-07 16:29:24 +01:00
var sl = scan . length ;
2013-08-09 18:00:18 +01:00
// use a random offset so if several ships make the same scan
// they don't all pick the same target
var offset = Math . floor ( Math . random ( ) * sl ) ;
2013-08-07 16:29:24 +01:00
for ( var i = 0 ; i < sl ; i ++ )
2013-08-01 22:40:23 +01:00
{
2013-08-09 18:00:18 +01:00
var io = ( i + offset ) % sl ;
if ( predicate . call ( this , scan [ io ] ) )
2013-07-22 21:24:27 +01:00
{
2013-08-09 18:00:18 +01:00
this . setParameter ( "oolite_scanResultSpecific" , scan [ io ] ) ;
2013-08-01 22:40:23 +01:00
return true ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
return false ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . cruiseSpeed = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-17 15:19:25 +01:00
if ( this . _ _ltcache . oolite _cruiseSpeed )
2013-08-07 16:29:24 +01:00
{
2013-08-17 15:19:25 +01:00
return this . _ _ltcache . oolite _cruiseSpeed ;
2013-08-07 16:29:24 +01:00
}
2013-08-01 22:40:23 +01:00
var cruise = this . ship . maxSpeed * 0.8 ;
2013-08-07 16:29:24 +01:00
var ignore = this . ship . maxSpeed / 4 ;
2013-08-08 16:00:20 +01:00
var grouped = false ;
2013-08-01 22:40:23 +01:00
if ( this . ship . group )
{
2013-08-07 16:29:24 +01:00
var gs = this . ship . group . ships ;
2013-08-08 16:00:20 +01:00
if ( gs . length > 1 )
{
grouped = true ;
}
2013-08-07 16:29:24 +01:00
for ( var i = gs . length - 1 ; i >= 0 ; i -- )
2013-07-26 18:52:11 +01:00
{
2013-08-07 16:29:24 +01:00
var spd = gs [ i ] . maxSpeed ;
if ( spd >= ignore && cruise > spd )
{
2013-08-10 08:34:33 +01:00
cruise = spd * 0.95 ;
2013-08-01 22:40:23 +01:00
}
2013-07-22 21:24:27 +01:00
}
2013-08-01 22:40:23 +01:00
}
if ( this . ship . escortGroup )
{
2013-08-07 16:29:24 +01:00
var gs = this . ship . escortGroup . ships ;
2013-08-08 16:00:20 +01:00
if ( gs . length > 1 )
{
grouped = true ;
}
2013-08-07 16:29:24 +01:00
for ( var i = gs . length - 1 ; i >= 0 ; i -- )
2013-07-13 23:18:05 +01:00
{
2013-08-07 16:29:24 +01:00
var spd = gs [ i ] . maxSpeed ;
if ( spd >= ignore && cruise > spd )
2013-08-01 22:40:23 +01:00
{
2013-08-07 16:29:24 +01:00
cruise = spd ;
2013-08-01 22:40:23 +01:00
}
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-08-08 16:00:20 +01:00
if ( ! grouped )
{
// not in a group, so don't need to slow down for others to catch up
cruise = this . ship . maxSpeed ;
}
2013-08-17 15:19:25 +01:00
this . _ _ltcache . oolite _cruiseSpeed = cruise ;
2013-08-01 22:40:23 +01:00
return cruise ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . distance = function ( entity )
2013-08-07 16:29:24 +01:00
{
2013-08-23 21:18:23 +01:00
if ( ! entity )
{
return 0 ;
}
2013-08-17 15:19:25 +01:00
if ( this . _ _cache . oolite _position === undefined )
2013-08-07 16:29:24 +01:00
{
2013-08-17 15:19:25 +01:00
this . _ _cache . oolite _position = this . ship . position ;
2013-08-07 16:29:24 +01:00
}
2013-08-17 15:19:25 +01:00
return this . _ _cache . oolite _position . distanceTo ( entity ) ;
2013-08-07 16:29:24 +01:00
}
2013-08-01 22:40:23 +01:00
// gets a standard comms params object
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . entityCommsParams = function ( entity )
2013-08-01 22:40:23 +01:00
{
var params = { } ;
2013-08-02 22:16:54 +01:00
if ( entity )
2013-08-01 22:40:23 +01:00
{
2013-08-02 22:16:54 +01:00
if ( entity . isShip )
{
// TODO: extend the ship object so more precise names can be
// returned?
2013-08-26 16:17:59 +01:00
params [ "oolite_entityClass" ] = entity . shipClassName ;
if ( entity . shipUniqueName != "" )
{
params [ "oolite_entityName" ] = entity . shipUniqueName ;
}
else
{
params [ "oolite_entityName" ] = entity . displayName ;
}
2013-08-02 22:16:54 +01:00
}
else if ( entity . name )
{
params [ "oolite_entityClass" ] = entity . name ;
params [ "oolite_entityName" ] = entity . name ;
}
2013-08-01 22:40:23 +01:00
}
return params ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . fineThreshold = function ( )
2013-07-27 12:29:59 +01:00
{
2013-08-17 15:19:25 +01:00
if ( ! this . _ _ltcache . oolite _fineThreshold )
2013-08-17 14:39:16 +01:00
{
2013-08-17 15:19:25 +01:00
this . _ _ltcache . oolite _fineThreshold = 50 - ( system . info . government * 6 ) ;
2013-08-17 14:39:16 +01:00
}
2013-08-17 15:19:25 +01:00
return this . _ _ltcache . oolite _fineThreshold ;
2013-07-27 12:29:59 +01:00
}
2013-08-17 14:39:16 +01:00
// May need to move this and hostileStation to native code for efficiency
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . friendlyStation = function ( station )
2013-07-26 18:52:11 +01:00
{
2013-08-17 13:26:37 +01:00
if ( ! station || ! station . isInSpace )
2013-08-07 16:29:24 +01:00
{
return false ;
}
2013-08-27 22:08:35 +01:00
// home station always friendly unless actually shooting at you
if ( station != this . _ _ltcache . oolite _homeStation )
2013-08-01 22:40:23 +01:00
{
2013-08-27 22:08:35 +01:00
var allegiance = this . stationAllegiance ( station ) ;
// thargoid stations unfriendly to non-thargoid and vice versa
if ( allegiance == "thargoid" && this . ship . scanClass != "CLASS_THARGOID" )
{
return false ;
}
if ( allegiance != "thargoid" && this . ship . scanClass == "CLASS_THARGOID" )
{
return false ;
}
// hunter stations attack any ship without bounty
if ( allegiance == "hunter" && this . ship . bounty > 0 )
{
return false ;
}
// galcop stations likely to be hostile to certain ships
if ( allegiance == "galcop" && ( this . ship . bounty > this . fineThreshold ( ) || this . ship . isPirate ) )
{
return false ;
}
// pirate stations hostile to bounty-free ships
2013-09-08 17:20:28 +01:00
if ( allegiance == "pirate" && ( this . ship . bounty == 0 || this . shipInRoleCategory ( this . ship , "oolite-pirate-victim" ) ) )
2013-08-27 22:08:35 +01:00
{
return false ;
}
// pirates won't dock at neutral stations
if ( allegiance == "neutral" && this . ship . isPirate )
{
return false ;
}
// restricted+private stations never count as friendly: AI must use custom routines
if ( allegiance == "restricted" || allegiance == "private" )
{
return false ;
}
2013-08-16 21:44:27 +01:00
}
2013-08-01 22:40:23 +01:00
return ( station . target != this . ship || ! station . hasHostileTarget ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . homeStation = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-17 15:19:25 +01:00
if ( this . _ _ltcache . oolite _homeStation !== undefined )
2013-08-07 16:29:24 +01:00
{
2013-08-17 15:19:25 +01:00
return this . _ _ltcache . oolite _homeStation ;
2013-08-07 16:29:24 +01:00
}
2013-08-01 22:40:23 +01:00
// home station might be the owner of the ship, or might just
// be a group member
if ( this . ship . owner && this . ship . owner . isStation && this . friendlyStation ( this . ship . owner ) )
{
2013-08-17 15:19:25 +01:00
this . _ _ltcache . oolite _homeStation = this . ship . owner ;
2013-08-01 22:40:23 +01:00
return this . ship . owner ;
}
if ( this . ship . group )
{
2013-08-07 16:29:24 +01:00
var gs = this . ship . group . ships ;
for ( var i = gs . length - 1 ; i >= 0 ; i -- )
2013-07-26 18:52:11 +01:00
{
2013-08-07 16:29:24 +01:00
if ( gs [ i ] != this . ship && gs [ i ] . isStation && this . friendlyStation ( gs [ i ] ) )
2013-08-01 22:40:23 +01:00
{
2013-08-17 15:19:25 +01:00
this . _ _ltcache . oolite _homeStation = gs [ i ] ;
2013-08-07 16:29:24 +01:00
return gs [ i ] ;
2013-08-01 22:40:23 +01:00
}
2013-07-13 23:18:05 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-08-17 15:19:25 +01:00
this . _ _ltcache . oolite _homeStation = null ;
2013-08-01 22:40:23 +01:00
return null ;
2013-07-26 18:52:11 +01:00
}
2013-08-16 21:44:27 +01:00
// this is mostly, but not entirely, a mirror of friendlyStation to
// get certain things (e.g. pirates) to work, unfortunately, it can't
// be an exact negation
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . hostileStation = function ( station )
2013-08-16 21:44:27 +01:00
{
2013-08-17 13:26:37 +01:00
if ( ! station || ! station . isInSpace )
2013-08-16 21:44:27 +01:00
{
return false ;
}
2013-08-27 22:08:35 +01:00
// home station not hostile unless actually shooting at you
if ( station != this . _ _ltcache . oolite _homeStation )
2013-08-16 21:44:27 +01:00
{
2013-08-27 22:08:35 +01:00
var allegiance = this . stationAllegiance ( station ) ;
// thargoid stations unfriendly to non-thargoid and vice versa
if ( allegiance == "thargoid" && this . ship . scanClass != "CLASS_THARGOID" )
{
return true ;
}
if ( allegiance != "thargoid" && this . ship . scanClass == "CLASS_THARGOID" )
{
return true ;
}
// hunter stations attack any ship without bounty
if ( allegiance == "hunter" && this . ship . bounty > 0 )
{
return true ;
}
// galcop stations likely to be hostile to certain ships
if ( allegiance == "galcop" && ( this . ship . bounty > this . fineThreshold ( ) || this . ship . isPirate ) )
{
return true ;
}
// pirate stations hostile to bounty-free ships
2013-09-08 17:20:28 +01:00
if ( allegiance == "pirate" && ( this . ship . bounty == 0 || this . shipInRoleGroup ( this . ship , "oolite-pirate-victim" ) ) )
2013-08-27 22:08:35 +01:00
{
return true ;
}
// neutral, chaotic and private stations don't count as unfriendly
// restricted stations should always be considered unfriendly
if ( allegiance == "restricted" )
{
return true ;
}
2013-08-16 21:44:27 +01:00
}
return ( station . target == this . ship && station . hasHostileTarget ) ;
}
2013-09-08 17:20:28 +01:00
PriorityAIController . prototype . ignorePlayerFriendlyFire = function ( )
{
var whom = player . ship ;
if ( whom . target == this . ship )
{
return false ; // was probably intentional
}
2013-09-11 18:29:08 +01:00
if ( this . getParameter ( "oolite_lastAssist" ) == whom )
{
// player has helped this ship in this fight so is probably on the same side.
if ( Math . random ( ) < 0.5 )
{
// don't forgive too often
this . setParameter ( "oolite_lastAssist" , null ) ;
}
return true ;
}
2013-09-08 17:20:28 +01:00
// don't trust ships with opposite legal status
if ( ( this . ship . bounty == 0 ) == ( whom . bounty == 0 ) )
{
// player could have meant to do that
if ( ! this . getParameter ( "oolite_playerFriendlyFireAlready" ) )
{
var friendlyRoles = this . getParameter ( "oolite_friendlyRoles" ) ;
if ( Array . isArray ( friendlyRoles ) )
{
for ( var i = friendlyRoles . length - 1 ; i >= 0 ; i -- )
{
if ( this . shipInRoleCategory ( whom , friendlyRoles [ i ] ) )
{
// only allow one!
this . setParameter ( "oolite_playerFriendlyFireAlready" , true ) ;
return true ;
}
}
}
}
}
return false ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . isAggressive = function ( ship )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( ship && ship . isPlayer )
{
return ! ship . isFleeing ;
}
return ship && ship . hasHostileTarget && ! ship . isFleeing && ! ship . isDerelict ;
2013-07-26 18:52:11 +01:00
}
2013-08-04 12:29:44 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . isEscaping = function ( ship )
2013-08-17 13:26:37 +01:00
{
if ( ai . getParameter ( "oolite_flag_continueUnlikelyPursuits" ) != null )
{
return false ;
}
return ! this . isAggressive ( ship ) && this . distance ( ship ) > 15000 && ship . speed > this . ship . maxSpeed && ship . speed > this . ship . speed ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . isFighting = function ( ship )
2013-07-26 18:52:11 +01:00
{
2013-08-18 19:15:09 +01:00
if ( ship . isPlayer )
2013-08-08 11:47:03 +01:00
{
return ! ship . isFleeing ; // have to assume aggressive
}
2013-08-23 21:18:23 +01:00
return ship && ship . target && ship . hasHostileTarget ;
2013-07-26 18:52:11 +01:00
}
2013-08-04 12:29:44 +01:00
/ * C a l l j u s t b e f o r e s w i t c h i n g t a r g e t t o a m o r e s e r i o u s t h r e a t , w h o m i s
* the more serious threat * /
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . noteDistraction = function ( whom )
2013-08-04 12:29:44 +01:00
{
if ( this . ship . target )
{
if ( this . ship . target . script && this . ship . target . script . shipAttackerDistracted )
{
this . ship . target . script . shipAttackerDistracted ( whom ) ;
}
if ( this . ship . target . AIScript && this . ship . target . AIScript . shipAttackerDistracted )
{
this . ship . target . AIScript . shipAttackerDistracted ( whom ) ;
}
}
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . oddsAssessment = function ( )
2013-08-05 14:14:50 +01:00
{
2013-08-17 15:19:25 +01:00
if ( this . _ _cache . oolite _oddsAssessment )
2013-08-07 12:27:22 +01:00
{
2013-08-17 15:19:25 +01:00
return this . _ _cache . oolite _oddsAssessment ;
2013-08-07 12:27:22 +01:00
}
2013-08-07 16:29:24 +01:00
var target = this . ship . target ;
if ( ! target )
2013-08-05 14:14:50 +01:00
{
return 10 ;
}
var us = 0 ;
var them = 0 ;
var i = 0 ;
var ship ;
us += this . threatAssessment ( this . ship , true )
2013-08-07 16:29:24 +01:00
var group ;
if ( ( group = this . ship . group ) )
2013-08-05 14:14:50 +01:00
{
2013-08-07 16:29:24 +01:00
var gs = group . ships ;
for ( i = gs . length - 1 ; i >= 0 ; i -- )
2013-08-05 14:14:50 +01:00
{
2013-08-07 16:29:24 +01:00
ship = gs [ i ]
if ( ship != this . ship && ship . position . distanceTo ( target ) < this . scannerRange )
2013-08-05 14:14:50 +01:00
{
us += this . threatAssessment ( ship , true ) ;
}
}
2013-08-07 16:29:24 +01:00
if ( group . leader && group . leader . group != group )
2013-08-05 14:14:50 +01:00
{
2013-08-07 16:29:24 +01:00
gs = group . leader . group . ships ;
2013-08-05 14:14:50 +01:00
// don't want escorts running off early
2013-08-07 16:29:24 +01:00
for ( i = gs . length - 1 ; i >= 0 ; i -- )
2013-08-05 14:14:50 +01:00
{
2013-08-07 16:29:24 +01:00
ship = gs [ i ] ;
if ( ship != this . ship && ship . position . distanceTo ( target ) < this . scannerRange )
2013-08-05 14:14:50 +01:00
{
us += this . threatAssessment ( ship , true ) ;
}
}
}
}
2013-08-07 16:29:24 +01:00
var egroup ;
if ( ( egroup = this . ship . escortGroup ) && egroup != this . ship . group )
2013-08-05 14:14:50 +01:00
{
2013-08-07 16:29:24 +01:00
var gs = egroup . ships ;
for ( i = gs . length - 1 ; i >= 0 ; i -- )
2013-08-05 14:14:50 +01:00
{
2013-08-07 16:29:24 +01:00
ship = gs [ i ] ;
if ( ship != this . ship && ship . position . distanceTo ( target ) < this . scannerRange )
2013-08-05 14:14:50 +01:00
{
us += this . threatAssessment ( ship , true ) ;
}
}
}
2013-08-07 16:29:24 +01:00
them += this . threatAssessment ( target , false )
if ( target . group )
2013-08-05 14:14:50 +01:00
{
2013-08-07 16:29:24 +01:00
var gs = target . group . ships ;
for ( i = gs . length - 1 ; i >= 0 ; i -- )
2013-08-05 14:14:50 +01:00
{
2013-08-07 16:29:24 +01:00
ship = gs [ i ]
if ( ship != target && this . distance ( ship ) < this . scannerRange )
2013-08-05 14:14:50 +01:00
{
them += this . threatAssessment ( ship , false ) ;
}
}
}
2013-08-07 16:29:24 +01:00
if ( target . escortGroup && target . escortGroup != target . group )
2013-08-05 14:14:50 +01:00
{
2013-08-07 16:29:24 +01:00
var gs = target . escortGroup . ships ;
for ( i = gs . length - 1 ; i >= 0 ; i -- )
2013-08-05 14:14:50 +01:00
{
2013-08-07 16:29:24 +01:00
ship = gs [ i ]
if ( ship != target && this . distance ( ship ) < this . scannerRange )
2013-08-05 14:14:50 +01:00
{
them += this . threatAssessment ( ship , false ) ;
}
}
}
2013-08-17 15:19:25 +01:00
this . _ _cache . oolite _oddsAssessment = us / them ;
return this . _ _cache . oolite _oddsAssessment ;
2013-08-05 14:14:50 +01:00
}
2013-09-08 17:20:28 +01:00
PriorityAIController . prototype . playerRoleAssessment = function ( )
{
/ * F o r t h e p l a y e r , w e p i c k o n e e n t r y o f t h e i r r o l e a r r a y a t
* random when first asked , then preserve it . Group members
* will take the role their group leader has set , and keep it
* until they get a group leader with different opinions . * /
var role = null ;
// grab role assessment from current group leader
var leader = null ;
if ( this . ship . group && ( leader = this . ship . group . leader ) && leader . AIScript . oolite _intership )
{
// if leader hasn't decided on a role, make them do so
if ( leader . AIScript . oolite _intership . oolite _player _role === undefined )
{
leader . AIScript . oolite _intership . oolite _player _role = player . roleWeights [ Math . floor ( Math . random ( ) * player . roleWeights . length ) ] ;
}
role = leader . AIScript . oolite _intership . oolite _player _role ;
// save leader's decision
this . ship . AIScript . oolite _intership . oolite _player _role = role ;
}
else
// group leader does not exist or does not have useful AI
{
// already decided what the player's role is
if ( this . ship . AIScript . oolite _intership . oolite _player _role !== undefined )
{
role = this . ship . AIScript . oolite _intership . oolite _player _role ;
}
else
{
role = player . roleWeights [ Math . floor ( Math . random ( ) * player . roleWeights . length ) ] ;
this . ship . AIScript . oolite _intership . oolite _player _role = role ; // save decision
}
}
this . playerRole = role ;
}
2013-08-04 12:29:44 +01:00
/* Be very careful with 'passon' parameter to avoid infinite loops */
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . respondToThargoids = function ( whom , passon )
2013-08-04 12:29:44 +01:00
{
if ( this . getParameter ( "oolite_flag_noSpecialThargoidReaction" ) != null )
{
return false ;
}
// non-thargoid being attacked by thargoid
if ( this . ship . target && this . ship . target . scanClass != "CLASS_THARGOID" )
{
if ( passon )
{
this . noteDistraction ( whom ) ;
}
this . ship . target = whom ; // thargoid gets priority
if ( passon )
{
this . ship . requestHelpFromGroup ( ) ; // tell the rest!
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_thargoidAttack" , whom , 2 ) ;
2013-08-04 12:29:44 +01:00
}
}
var dts = this . ship . defenseTargets ;
for ( var i = 0 ; i < dts . length ; i ++ )
{
if ( dts [ i ] . scanClass != "CLASS_THARGOID" && dts [ i ] . scanClass != "CLASS_MISSILE" && dts [ i ] . scanClass != "CLASS_MINE" )
{
// safe: dts is a copy of the real data
this . ship . removeDefenseTarget ( dts [ i ] ) ;
}
}
return true ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . setWitchspaceRouteTo = function ( dest )
2013-08-08 16:00:20 +01:00
{
if ( ! dest )
{
return this . configurationSelectWitchspaceDestination ( ) ;
}
if ( dest == system . ID )
{
this . setParameter ( "oolite_witchspaceDestination" , - 1 ) ;
return ;
}
var info = System . infoForSystem ( galaxyNumber , dest ) ;
if ( system . info . distanceToSystem ( info ) < this . ship . fuel )
{
this . setParameter ( "oolite_witchspaceDestination" , dest ) ;
return ;
}
else
{
var route = system . info . routeToSystem ( info ) ;
if ( ! route )
{
this . setParameter ( "oolite_witchspaceDestination" , - 1 ) ;
return ;
}
var next = route . route [ 1 ] ;
if ( system . info . distanceToSystem ( System . infoForSystem ( galaxyNumber , next ) ) < this . ship . fuel )
{
this . setParameter ( "oolite_witchspaceDestination" , next ) ;
return ;
}
this . setParameter ( "oolite_witchspaceDestination" , null ) ;
}
}
2013-09-08 17:20:28 +01:00
/* Check role category membership allowing for player role assessment */
PriorityAIController . prototype . shipInRoleCategory = function ( ship , category )
{
if ( ship . isPlayer )
{
// recheck every so often in case we change groups
if ( this . _ _ltcache . oolite _shipInRoleCategory === undefined )
{
this . _ _ltcache . oolite _shipInRoleCategory = 1 ;
this . playerRoleAssessment ( ) ;
}
return Ship . roleIsInCategory ( this . playerRole , category ) ;
}
else // NPCs are easier!
{
return Ship . roleIsInCategory ( ship . primaryRole , category ) ;
}
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . stationAllegiance = function ( station )
2013-08-16 21:44:27 +01:00
{
if ( station . allegiance )
{
return station . allegiance ;
}
else
{
var allegiance = "neutral" ;
if ( station . isMainStation )
{
allegiance = "galcop" ;
}
else if ( station . scanClass == "CLASS_THARGOID" )
{
allegiance = "thargoid" ;
}
else if ( station . scanClass == "CLASS_MILITARY" || station . scanClass == "CLASS_POLICE" )
{
allegiance = "hunter" ;
}
else if ( station . bounty > 0 )
{
allegiance = "pirate" ;
}
else
{
var ses = station . subEntities ;
for ( var i = 0 ; i < ses . length ; i ++ )
{
if ( ses [ i ] . isTurret )
{
allegiance = "hunter" ;
break ;
}
}
}
2013-08-17 13:26:37 +01:00
if ( allegiance == "neutral" && system . mainStation . position . distanceTo ( station ) < 51200 )
{
allegiance = "galcop" ; // neutral stations in aegis
}
2013-08-16 21:44:27 +01:00
// cache default value
station . allegiance = allegiance ;
return allegiance ;
}
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . threatAssessment = function ( ship , full )
2013-08-04 12:29:44 +01:00
{
2013-09-01 19:25:45 +01:00
if ( ship . isStation && this . getParameter ( "oolite_flag_fightsNearHostileStations" ) )
{
return 1 ; // mostly ignore stations in assessment
}
2013-08-05 14:14:50 +01:00
return worldScripts [ "oolite-libPriorityAI" ] . _threatAssessment ( ship , full ) ;
2013-08-04 12:29:44 +01:00
}
2013-07-26 18:52:11 +01:00
/* ****************** Condition functions ************** */
/ * C o n d i t i o n s . A n y f u n c t i o n w h i c h r e t u r n s t r u e o r f a l s e c a n b e u s e d a s
* a condition . They do not have to be part of the AI library , but
* several common conditions are provided here . * /
/*** Combat-related conditions ***/
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionCascadeDetected = function ( )
2013-07-27 15:39:23 +01:00
{
2013-08-01 22:40:23 +01:00
var cpos = this . getParameter ( "oolite_cascadeDetected" ) ;
if ( cpos != null )
{
2013-08-07 16:29:24 +01:00
if ( this . distance ( cpos ) < this . scannerRange )
2013-07-27 15:39:23 +01:00
{
2013-08-01 22:40:23 +01:00
return true ;
2013-07-27 15:39:23 +01:00
}
2013-08-01 22:40:23 +01:00
this . setParameter ( "oolite_cascadeDetected" , null ) ;
}
return false ;
2013-07-27 15:39:23 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionCombatOddsTerrible = function ( )
2013-08-05 14:14:50 +01:00
{
2013-08-05 15:42:26 +01:00
if ( this . getParameter ( "oolite_flag_surrendersEarly" ) )
{
return this . oddsAssessment ( ) < 0.75 ;
}
else
{
return this . oddsAssessment ( ) < 0.375 ;
}
2013-08-05 14:14:50 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionCombatOddsBad = function ( )
2013-08-05 14:14:50 +01:00
{
2013-08-05 15:42:26 +01:00
if ( this . getParameter ( "oolite_flag_surrendersLate" ) )
{
return this . oddsAssessment ( ) < 0.375 ;
}
else
{
return this . oddsAssessment ( ) < 0.75 ;
}
2013-08-05 14:14:50 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionCombatOddsGood = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-05 14:14:50 +01:00
return this . oddsAssessment ( ) >= 1.5 ;
}
2013-08-01 22:40:23 +01:00
2013-08-05 14:14:50 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionCombatOddsExcellent = function ( )
2013-08-05 14:14:50 +01:00
{
return this . oddsAssessment ( ) >= 3.0 ;
2013-07-26 18:52:11 +01:00
}
2013-07-13 23:18:05 +01:00
2013-08-09 13:09:54 +01:00
// group has taken too many losses
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionGroupAttritionReached = function ( )
2013-08-09 13:09:54 +01:00
{
var group ;
if ( ! ( group = this . ship . group ) )
{
return false ;
}
var cgp = this . getParameter ( "oolite_groupPower" ) ;
if ( ! cgp )
{
this . setParameter ( "oolite_groupPower" , group . count ) ;
return false ;
}
if ( group . count > cgp )
{
this . setParameter ( "oolite_groupPower" , group . count ) ;
return false ;
}
return group . count < cgp * 0.75 ;
}
2013-09-04 22:25:54 +01:00
PriorityAIController . prototype . conditionGroupSuppliesLow = function ( )
{
var group ;
if ( ! ( group = this . ship . group ) )
{
return this . ship . damageAssessment ( ) > 0 ;
}
var assessment = 0 ;
var gs = group . ships ;
for ( var i = gs . length - 1 ; i >= 0 ; i -- )
{
assessment += gs [ i ] . damageAssessment ( ) ;
}
return ( assessment > gs . length / 2 ) ; // over half ships have low supplies
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionInCombat = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-17 15:19:25 +01:00
if ( this . _ _cache . oolite _conditionInCombat !== undefined )
2013-08-07 12:27:22 +01:00
{
2013-08-17 15:19:25 +01:00
return this . _ _cache . oolite _conditionInCombat ;
2013-08-07 12:27:22 +01:00
}
2013-08-18 19:15:09 +01:00
this . _ _cache . oolite _conditionInCombat = ( this . ship . alertCondition == 3 ) ;
if ( ! this . _ _cache . oolite _conditionInCombat )
{
delete this . ship . AIScript . oolite _intership . cargodemandpaid ;
}
return this . _ _cache . oolite _conditionInCombat ;
/ *
2013-08-01 22:40:23 +01:00
if ( this . isFighting ( this . ship ) )
{
2013-08-17 15:19:25 +01:00
this . _ _cache . oolite _conditionInCombat = true ;
2013-08-01 22:40:23 +01:00
return true ;
}
var dts = this . ship . defenseTargets ;
2013-08-07 12:27:22 +01:00
for ( var i = dts . length - 1 ; i >= 0 ; i -- )
2013-08-01 22:40:23 +01:00
{
2013-08-07 16:29:24 +01:00
if ( this . isFighting ( dts [ i ] ) && this . distance ( dts [ i ] ) < this . scannerRange )
2013-07-15 23:14:47 +01:00
{
2013-08-17 15:19:25 +01:00
this . _ _cache . oolite _conditionInCombat = true ;
2013-08-01 22:40:23 +01:00
return true ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
if ( this . ship . group != null )
{
2013-08-07 12:27:22 +01:00
var gs = this . ship . group . ships ;
for ( var i = gs . length - 1 ; i >= 0 ; i -- )
2013-07-26 18:52:11 +01:00
{
2013-08-07 22:45:31 +01:00
if ( this . isFighting ( gs [ i ] ) && this . distance ( gs [ i ] ) < this . scannerRange )
2013-08-01 22:40:23 +01:00
{
2013-08-17 15:19:25 +01:00
this . _ _cache . oolite _conditionInCombat = true ;
2013-08-01 22:40:23 +01:00
return true ;
}
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
if ( this . ship . escortGroup != null )
{
2013-08-07 12:27:22 +01:00
var gs = this . ship . escortGroup . ships ;
for ( var i = gs . length - 1 ; i >= 0 ; i -- )
2013-07-26 18:52:11 +01:00
{
2013-08-07 22:45:31 +01:00
if ( this . isFighting ( gs [ i ] ) && this . distance ( gs [ i ] ) < this . scannerRange )
2013-08-01 22:40:23 +01:00
{
2013-08-17 15:19:25 +01:00
this . _ _cache . oolite _conditionInCombat = true ;
2013-08-01 22:40:23 +01:00
return true ;
}
2013-07-15 23:14:47 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-08-17 15:19:25 +01:00
this . _ _cache . oolite _conditionInCombat = false ;
2013-08-01 22:40:23 +01:00
delete this . ship . AIScript . oolite _intership . cargodemandpaid ;
return false ;
2013-08-18 19:15:09 +01:00
* /
2013-07-26 18:52:11 +01:00
}
2013-07-15 23:14:47 +01:00
2013-07-26 18:52:11 +01:00
/* Ships being attacked are firing back */
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionInCombatWithHostiles = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( this . isFighting ( this . ship ) && this . isAggressive ( this . ship . target ) )
{
return true ;
}
var dts = this . ship . defenseTargets ;
2013-08-07 12:27:22 +01:00
for ( var i = dts . length - 1 ; i >= 0 ; i -- )
2013-08-01 22:40:23 +01:00
{
2013-08-07 16:29:24 +01:00
if ( this . isAggressive ( dts [ i ] ) && this . distance ( dts [ i ] ) < this . scannerRange )
2013-07-15 23:14:47 +01:00
{
2013-08-01 22:40:23 +01:00
return true ;
2013-07-15 23:14:47 +01:00
}
2013-08-01 22:40:23 +01:00
else
2013-07-20 09:14:58 +01:00
{
2013-08-01 22:40:23 +01:00
// this is safe to do mid-loop as dts is a copy of the
// actual defense target list
this . ship . removeDefenseTarget ( dts [ i ] ) ;
2013-07-20 09:14:58 +01:00
}
2013-08-01 22:40:23 +01:00
}
if ( this . ship . group != null )
{
2013-08-07 12:27:22 +01:00
var gs = this . ship . group . ships ;
for ( var i = gs . length - 1 ; i >= 0 ; i -- )
2013-07-12 19:44:14 +01:00
{
2013-08-07 12:27:22 +01:00
if ( this . isFighting ( gs [ i ] ) && this . isAggressive ( gs [ i ] . target ) )
2013-08-01 22:40:23 +01:00
{
return true ;
}
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
if ( this . ship . escortGroup != null )
{
2013-08-07 12:27:22 +01:00
var gs = this . ship . escortGroup . ships ;
for ( var i = gs . length - 1 ; i >= 0 ; i -- )
2013-07-26 18:52:11 +01:00
{
2013-08-07 12:27:22 +01:00
if ( this . isFighting ( gs [ i ] ) && this . isAggressive ( gs [ i ] . target ) )
2013-08-01 22:40:23 +01:00
{
return true ;
}
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
delete this . ship . AIScript . oolite _intership . cargodemandpaid ;
return false ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionLosingCombat = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var cascade = this . getParameter ( "oolite_cascadeDetected" ) ;
if ( cascade != null )
{
if ( cascade . distanceTo ( this . ship ) < 25600 )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return true ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
else
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
this . setParameter ( "oolite_cascadeDetected" , null ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-08-18 16:36:57 +01:00
if ( ! this . conditionInCombat ( ) )
{
this . setParameter ( "oolite_lastFleeing" , null ) ;
return false ;
}
2013-08-07 12:27:22 +01:00
var en = this . ship . energy ;
var maxen = this . ship . maxEnergy ;
if ( en == maxen )
2013-08-01 22:40:23 +01:00
{
// forget previous defeats
2013-08-05 14:14:50 +01:00
if ( ! this . conditionCombatOddsTerrible ( ) )
{
this . setParameter ( "oolite_lastFleeing" , null ) ;
}
2013-08-01 22:40:23 +01:00
}
2013-08-08 16:00:20 +01:00
if ( this . getParameter ( "oolite_flag_fleesPreemptively" ) && this . ship . fuel > 0 && this . ship . equipmentStatus ( "EQ_FUEL_INJECTION" ) == "EQUIPMENT_OK" )
{
// ships of this behaviour will run away from anything if they
// still have fuel
return true ;
}
2013-09-05 20:12:41 +01:00
2013-08-01 22:40:23 +01:00
var lastThreat = this . getParameter ( "oolite_lastFleeing" ) ;
2013-08-07 16:29:24 +01:00
if ( lastThreat != null && this . distance ( lastThreat ) < 25600 )
2013-08-01 22:40:23 +01:00
{
// the thing that attacked us is still nearby
return true ;
}
2013-08-07 12:27:22 +01:00
if ( en * 4 < maxen )
2013-08-01 22:40:23 +01:00
{
// TODO: adjust threshold based on group odds
return true ; // losing if less than 1/4 energy
}
var dts = this . ship . defenseTargets ;
2013-08-07 12:27:22 +01:00
for ( var i = dts . length - 1 ; i >= 0 ; i -- )
2013-08-01 22:40:23 +01:00
{
if ( dts [ i ] . scanClass == "CLASS_MISSILE" && dts [ i ] . target == this . ship )
{
2013-09-04 22:25:54 +01:00
this . ship . target = dts [ i ] ; // specifically flee the missile
2013-08-01 22:40:23 +01:00
return true ;
}
2013-08-07 16:29:24 +01:00
if ( dts [ i ] . scanClass == "CLASS_MINE" && this . distance ( dts [ i ] ) < this . scannerRange )
2013-08-01 22:40:23 +01:00
{
return true ;
}
}
// if we've dumped cargo or the group leader has, then we're losing
if ( this . ship . AIScript . oolite _intership . cargodemandpaid )
{
return true ;
}
if ( this . ship . group && this . ship . group . leader && this . ship . group . leader . AIScript . oolite _intership && this . ship . group . leader . AIScript . oolite _intership . cargodemandpaid )
{
return true ;
}
2013-08-07 16:29:24 +01:00
if ( en * 2 < maxen )
2013-08-05 14:14:50 +01:00
{
if ( this . conditionCombatOddsBad ( ) )
{
// outnumbered; losing earlier
return true ;
}
}
if ( this . conditionCombatOddsTerrible ( ) )
{
if ( ! this . ship . isFleeing )
{
if ( this . ship . group && this . ship . group . leader && this . ship . group . leader == this . ship )
{
this . communicate ( "oolite_groupIsOutnumbered" , { } , 2 ) ;
}
else
{
this . communicate ( "oolite_groupIsOutnumbered" , { } , 4 ) ;
}
}
// badly outnumbered; losing
return true ;
}
2013-08-17 20:41:36 +01:00
2013-08-17 14:39:16 +01:00
if ( ! this . getParameter ( "oolite_flag_fightsNearHostileStations" ) )
2013-08-16 21:44:27 +01:00
{
2013-08-17 15:19:25 +01:00
if ( this . _ _ltcache . oolite _nearestStation && this . distance ( this . _ _ltcache . oolite _nearestStation ) < 51200 && this . hostileStation ( this . _ _ltcache . oolite _nearestStation ) )
2013-08-17 14:39:16 +01:00
{
// if there is a hostile station nearby, probably best to leave
return true ;
}
2013-08-16 21:44:27 +01:00
}
2013-08-05 14:14:50 +01:00
2013-08-01 22:40:23 +01:00
return false ; // not losing yet
}
2013-08-07 12:27:22 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionMothershipInCombat = function ( )
2013-08-01 22:40:23 +01:00
{
2013-08-07 12:27:22 +01:00
if ( this . ship . group )
2013-08-01 22:40:23 +01:00
{
var leader = this . ship . group . leader ;
2013-08-07 12:27:22 +01:00
if ( leader && leader != this . ship )
2013-07-26 18:52:11 +01:00
{
2013-08-07 16:29:24 +01:00
if ( this . distance ( leader ) > this . scannerRange )
2013-08-07 12:27:22 +01:00
{
return false ; // can't tell
}
if ( this . isFighting ( leader ) )
{
return true ;
}
var ltarget = leader . target ;
if ( ltarget && ltarget . target == leader && ltarget . hasHostileTarget )
2013-08-01 22:40:23 +01:00
{
2013-07-26 18:52:11 +01:00
return true ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 12:27:22 +01:00
var dts = leader . defenseTargets ;
for ( var i = dts . length - 1 ; i >= 0 ; i -- )
{
if ( dts [ i ] . target == leader && dts [ i ] . hasHostileTarget )
{
return true ;
}
}
return false ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-08-07 12:27:22 +01:00
// no mothership
return false ;
2013-07-26 18:52:11 +01:00
}
2013-07-12 19:44:14 +01:00
2013-07-26 18:52:11 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionMothershipIsAttacking = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( this . ship . group && this . ship . group . leader != this . ship )
{
var leader = this . ship . group . leader ;
2013-08-07 16:29:24 +01:00
if ( leader . target && this . isFighting ( leader ) && this . distance ( leader . target ) < this . scannerRange )
2013-07-17 22:44:26 +01:00
{
2013-08-01 22:40:23 +01:00
return true ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
return false ;
2013-07-26 18:52:11 +01:00
}
// as MothershipIsAttacking, but leader.target must be aggressive
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionMothershipIsAttackingHostileTarget = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( this . ship . group && this . ship . group . leader != this . ship )
{
var leader = this . ship . group . leader ;
2013-08-07 16:29:24 +01:00
if ( leader . target && this . isFighting ( leader ) && this . isAggressive ( leader . target ) && this . distance ( leader . target ) < this . scannerRange )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return true ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
return false ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionMothershipUnderAttack = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( this . ship . group && this . ship . group . leader != this . ship )
{
var leader = this . ship . group . leader ;
2013-08-07 16:29:24 +01:00
if ( leader . target && leader . target . target == leader && leader . target . hasHostileTarget && this . distance ( leader . target ) < this . scannerRange )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return true ;
2013-07-17 22:44:26 +01:00
}
2013-08-01 22:40:23 +01:00
var dts = leader . defenseTargets ;
for ( var i = 0 ; i < dts . length ; i ++ )
2013-07-24 21:56:50 +01:00
{
2013-08-07 16:29:24 +01:00
if ( dts [ i ] . target == leader && dts [ i ] . hasHostileTarget && this . distance ( dts [ i ] ) < this . scannerRange )
2013-08-01 22:40:23 +01:00
{
return true ;
}
2013-07-24 21:56:50 +01:00
}
2013-08-01 22:40:23 +01:00
return false ;
}
else
{
return false ;
}
2013-07-26 18:52:11 +01:00
}
2013-07-24 21:56:50 +01:00
2013-09-04 22:25:54 +01:00
PriorityAIController . prototype . conditionSuppliesLow = function ( )
{
if ( this . _ _ltcache . oolite _conditionSuppliesLow !== undefined )
{
return this . _ _ltcache . oolite _conditionSuppliesLow ;
}
this . _ _ltcache . oolite _conditionSuppliesLow = ( this . ship . damageAssessment ( ) > 0 ) ;
return this . _ _ltcache . oolite _conditionSuppliesLow ;
}
2013-07-26 18:52:11 +01:00
/*** Navigation-related conditions ***/
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionCanWitchspaceOnRoute = function ( )
2013-08-08 16:00:20 +01:00
{
if ( ! this . ship . hasHyperspaceMotor )
{
return false ;
}
var dest = this . getParameter ( "oolite_witchspaceDestination" ) ;
if ( dest == null || dest == - 1 )
{
return false ;
}
return ( system . info . distanceToSystem ( System . infoForSystem ( galaxyNumber , dest ) ) <= this . ship . fuel ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionCanWitchspaceOut = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( ! this . ship . hasHyperspaceMotor )
{
return false ;
}
return ( system . info . systemsInRange ( this . ship . fuel ) . length > 0 ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-24 21:56:50 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionFriendlyStationExists = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-17 20:41:36 +01:00
if ( this . _ _cache . oolite _friendlyStationExists !== undefined )
{
return this . _ _cache . oolite _friendlyStationExists ;
}
2013-08-01 22:40:23 +01:00
var stations = system . stations ;
for ( var i = 0 ; i < stations . length ; i ++ )
{
var station = stations [ i ] ;
if ( this . friendlyStation ( station ) )
2013-07-13 23:18:05 +01:00
{
2013-08-17 20:41:36 +01:00
this . _ _cache . oolite _friendlyStationExists = true ;
2013-08-01 22:40:23 +01:00
return true ;
2013-07-13 23:18:05 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-08-17 20:41:36 +01:00
this . _ _cache . oolite _friendlyStationExists = false ;
2013-08-01 22:40:23 +01:00
return false ;
2013-07-26 18:52:11 +01:00
}
2013-07-13 23:18:05 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionFriendlyStationNearby = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-17 15:19:25 +01:00
return this . friendlyStation ( this . _ _ltcache . oolite _nearestStation ) && this . distance ( this . _ _ltcache . oolite _nearestStation ) < 25600 ;
2013-07-26 18:52:11 +01:00
}
2013-07-13 23:18:05 +01:00
2013-07-26 18:52:11 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionGroupIsSeparated = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( ! this . ship . group || ! this . ship . group . leader )
{
return false ;
}
2013-08-07 16:29:24 +01:00
var leader = this . ship . group . leader ;
if ( leader . isStation )
2013-08-01 22:40:23 +01:00
{
// can get 2x as far from station
2013-08-07 16:29:24 +01:00
return ( this . distance ( leader ) > this . scannerRange * 2 ) ;
2013-08-01 22:40:23 +01:00
}
else
{
2013-08-07 16:29:24 +01:00
return ( this . distance ( leader ) > this . scannerRange ) ;
2013-08-01 22:40:23 +01:00
}
2013-07-26 18:52:11 +01:00
}
2013-07-22 23:15:17 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionHasSelectedPlanet = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var planet = this . getParameter ( "oolite_selectedPlanet" ) ;
if ( planet && ( ! planet . isValid || ! planet . isPlanet ) )
{
this . setParameter ( "oolite_selectedPlanet" , null ) ;
return false ;
}
return planet != null ;
2013-07-26 18:52:11 +01:00
}
2013-07-12 19:44:14 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionHasSelectedStation = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var station = this . getParameter ( "oolite_selectedStation" ) ;
if ( station && ( ! station . isValid || ! station . isStation ) )
{
this . setParameter ( "oolite_selectedStation" , null ) ;
return false ;
}
return station != null ;
2013-07-26 18:52:11 +01:00
}
2013-07-13 19:13:30 +01:00
2013-07-14 23:11:25 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionHomeStationExists = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return ( this . homeStation ( ) != null ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionHomeStationNearby = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var home = this . homeStation ( ) ;
if ( home == null )
{
return false ;
}
2013-08-07 16:29:24 +01:00
return this . distance ( home ) < this . scannerRange ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionHostileStationNearby = function ( )
2013-08-16 21:44:27 +01:00
{
2013-08-17 15:19:25 +01:00
return this . hostileStation ( this . _ _ltcache . oolite _nearestStation ) && this . distance ( this . _ _ltcache . oolite _nearestStation ) < 51200 ;
2013-08-16 21:44:27 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionInInterstellarSpace = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return system . isInterstellarSpace ;
2013-07-26 18:52:11 +01:00
}
2013-07-18 23:00:23 +01:00
2013-07-26 18:52:11 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionMainPlanetNearby = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( ! system . mainPlanet )
{
2013-07-26 18:52:11 +01:00
return false ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 16:29:24 +01:00
if ( this . distance ( system . mainPlanet ) < system . mainPlanet . radius * 4 )
2013-08-01 22:40:23 +01:00
{
return true ;
}
return false ;
2013-07-26 18:52:11 +01:00
}
2013-07-21 11:10:47 +01:00
2013-07-26 18:52:11 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionNearDestination = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-07 16:29:24 +01:00
return ( this . distance ( this . ship . destination ) < this . ship . desiredRange ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionPlayerNearby = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-07 16:29:24 +01:00
return this . distance ( player . ship ) < this . scannerRange ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionReadyToSunskim = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-07 16:29:24 +01:00
return ( system . sun && this . distance ( system . sun ) < system . sun . radius * 1.15 ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionSelectedStationNearby = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var station = this . getParameter ( "oolite_selectedStation" ) ;
2013-08-07 16:29:24 +01:00
if ( station && this . distance ( station ) < this . scannerRange )
2013-08-01 22:40:23 +01:00
{
return true ;
}
return false ;
2013-07-26 18:52:11 +01:00
}
2013-07-13 19:13:30 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionSelectedStationNearMainPlanet = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( ! system . mainPlanet )
{
2013-07-26 18:52:11 +01:00
return false ;
2013-08-01 22:40:23 +01:00
}
var station = this . getParameter ( "oolite_selectedStation" ) ;
if ( station && station . position . distanceTo ( system . mainPlanet ) < system . mainPlanet . radius * 4 )
{
return true ;
}
return false ;
2013-07-26 18:52:11 +01:00
}
2013-09-14 13:50:49 +01:00
PriorityAIController . prototype . conditionStationNearby = function ( )
{
return this . distance ( this . _ _ltcache . oolite _nearestStation ) < this . scannerRange * 2 ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionSunskimPossible = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return ( system . sun &&
! system . sun . hasGoneNova &&
! system . sun . isGoingNova &&
this . ship . fuel < 7 &&
this . ship . equipmentStatus ( "EQ_FUEL_SCOOPS" ) == "EQUIPMENT_OK" &&
( this . ship . heatInsulation > 1000 / this . ship . maxSpeed || this . ship . heatInsulation >= 12 ) ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 18:07:17 +01:00
PriorityAIController . prototype . conditionWormholeNearby = function ( )
{
var holes = system . wormholes ;
for ( var i = holes . length - 1 ; i >= 0 ; i -- )
{
var hole = holes [ i ] ;
if ( hole . expiryTime > clock . adjustedSeconds && this . distance ( hole ) < this . scannerRange )
{
this . _ _cache . oolite _wormholeNearby = hole ;
return true ;
}
}
return false ;
}
2013-07-26 18:52:11 +01:00
/*** Pirate conditions ***/
2013-07-22 21:24:27 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionCargoDemandsMet = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( ! this . getParameter ( "oolite_flag_watchForCargo" ) )
{
log ( this . name , "AI '" + this . ship . AIScript . name + "' for ship " + this . ship + " is asking if cargo demands are met but has not set 'oolite_flag_watchForCargo'" ) ;
return true ;
}
var seen = this . getParameter ( "oolite_cargoDropped" ) ;
if ( seen != null )
{
var recorder = null ;
var demand = 0 ;
if ( this . ship . group )
2013-07-13 19:13:30 +01:00
{
2013-08-01 22:40:23 +01:00
if ( this . ship . group . leader && this . ship . group . leader . AIScript . oolite _intership && this . ship . group . leader . AIScript . oolite _intership . cargodemanded > 0 )
{
if ( this . ship . group . leader . AIScript . oolite _intership . cargodemandmet )
2013-07-15 23:14:47 +01:00
{
2013-08-01 22:40:23 +01:00
return true ;
2013-07-13 19:13:30 +01:00
}
2013-08-01 22:40:23 +01:00
recorder = this . ship . group . leader ;
demand = this . ship . group . leader . AIScript . oolite _intership . cargodemanded ;
}
else if ( this . ship . group . ships [ 0 ] . AIScript . oolite _intership && this . ship . group . ships [ 0 ] . AIScript . oolite _intership . cargodemanded > 0 )
2013-07-13 19:13:30 +01:00
2013-08-01 22:40:23 +01:00
{
demand = this . ship . group . ships [ 0 ] . AIScript . oolite _intership . cargodemanded ;
if ( this . ship . group . ships [ 0 ] . AIScript . oolite _intership . cargodemandmet )
2013-07-23 21:21:49 +01:00
{
2013-08-01 22:40:23 +01:00
return true ;
2013-07-13 19:13:30 +01:00
}
2013-08-01 22:40:23 +01:00
recorder = this . ship . group . ships [ 0 ] ;
}
2013-07-13 19:13:30 +01:00
}
2013-08-01 22:40:23 +01:00
else
2013-07-14 19:02:16 +01:00
{
2013-08-01 22:40:23 +01:00
if ( this . ship . AIScript . oolite _intership . cargodemanded > 0 )
{
if ( this . ship . AIScript . oolite _intership . cargodemandmet )
2013-07-14 19:02:16 +01:00
{
2013-08-01 22:40:23 +01:00
return true ;
2013-07-14 19:02:16 +01:00
}
2013-08-01 22:40:23 +01:00
demand = this . ship . AIScript . oolite _intership . cargodemanded ;
recorder = this . ship ;
}
2013-07-14 19:02:16 +01:00
}
2013-08-01 22:40:23 +01:00
if ( demand == 0 )
2013-07-21 23:25:41 +01:00
{
2013-08-01 22:40:23 +01:00
return true ; // no demand made
2013-07-21 23:25:41 +01:00
}
2013-08-01 22:40:23 +01:00
if ( demand <= seen )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
recorder . AIScript . oolite _intership . cargodemandmet = true ;
return true ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
return false ;
2013-07-26 18:52:11 +01:00
}
2013-07-21 23:25:41 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionGroupHasEnoughLoot = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var used = 0 ;
var available = 0 ;
if ( ! this . ship . group )
{
used = this . ship . cargoSpaceUsed ;
if ( this . ship . equipmentStatus ( "EQ_FUEL_SCOOPS" ) == "EQUIPMENT_OK" )
{
available = this . ship . cargoSpaceAvailable ;
}
}
else
{
2013-08-07 12:27:22 +01:00
var gs = this . ship . group . ships ;
for ( var i = gs . length - 1 ; i >= 0 ; i -- )
2013-08-01 22:40:23 +01:00
{
2013-08-07 12:27:22 +01:00
used += gs [ i ] . cargoSpaceUsed ;
if ( gs [ i ] . equipmentStatus ( "EQ_FUEL_SCOOPS" ) == "EQUIPMENT_OK" )
2013-08-01 22:40:23 +01:00
{
2013-08-07 12:27:22 +01:00
available += gs [ i ] . cargoSpaceAvailable ;
2013-08-01 22:40:23 +01:00
}
}
}
2013-09-04 22:25:54 +01:00
var threshold = 0.33 ; // normally retreat at 2/3 hold
if ( this . conditionGroupAttritionReached ( ) )
{
threshold += 0.25 ; // if losing ships, take off a 1/4 of hold space
}
if ( this . conditionGroupSuppliesLow ( ) )
{
threshold += 0.25 ; // if running out of supplies, take off a 1/4 of hold space
}
if ( available < ( available + used ) * threshold || available == 0 )
2013-08-01 22:40:23 +01:00
{
2013-07-26 18:52:11 +01:00
return true ;
2013-08-01 22:40:23 +01:00
}
return false ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionPiratesCanBePaidOff = function ( )
2013-08-01 22:40:23 +01:00
{
if ( this . ship . AIScript . oolite _intership . cargodemandpaid )
{
return false ;
}
// TODO: need some way for the player to set this
if ( ! this . ship . AIScript . oolite _intership . cargodemand )
{
return false ;
}
if ( this . ship . cargoSpaceUsed < this . ship . AIScript . oolite _intership . cargodemand )
{
return false ;
}
return true ;
2013-07-26 18:52:11 +01:00
}
/*** Scanner conditions ***/
2013-09-14 13:50:49 +01:00
PriorityAIController . prototype . conditionScannerContainsAssassinationTarget = function ( )
{
return this . checkScannerWithPredicate ( function ( s ) {
return s . primaryRole == "escape-capsule" ;
} ) ;
}
2013-09-01 19:25:45 +01:00
PriorityAIController . prototype . conditionScannerContainsCleanShip = function ( )
{
return this . checkScannerWithPredicate ( function ( s ) {
return ( s . scanClass == "CLASS_NEUTRAL" || s . scanClass == "CLASS_POLICE" ) && s . bounty == 0 ;
} ) ;
}
2013-09-14 13:50:49 +01:00
PriorityAIController . prototype . conditionScannerContainsCourier = function ( )
{
if ( this . checkScannerWithPredicate ( function ( s ) {
return ( this . shipInRoleCategory ( s , "oolite-courier" ) ) ;
} ) )
{
return true ;
}
// TODO: check for player ship carrying high-risk contracts
return false ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionScannerContainsEscapePods = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-07 12:27:22 +01:00
if ( ! this . conditionCanScoopCargo ( ) )
{
return false ;
}
2013-08-01 22:40:23 +01:00
return this . checkScannerWithPredicate ( function ( s ) {
2013-08-07 12:27:22 +01:00
return s . primaryRole == "escape-capsule" && s . isInSpace && s . scanClass == "CLASS_CARGO" && s . velocity . magnitude ( ) < this . ship . maxSpeed ;
2013-08-01 22:40:23 +01:00
} ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-14 19:02:16 +01:00
2013-07-26 18:52:11 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionScannerContainsFineableOffender = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return this . checkScannerWithPredicate ( function ( s ) {
var threshold = this . fineThreshold ( ) ;
return s . isInSpace && s . bounty <= threshold && s . bounty > 0 && ! s . markedForFines && ( s . scanClass == "CLASS_NEUTRAL" || s . isPlayer ) && ! s . isDerelict ;
} ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionScannerContainsFugitive = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return this . checkScannerWithPredicate ( function ( s ) {
return s . isInSpace && s . bounty > 50 && s . scanClass != "CLASS_CARGO" && s . scanClass != "CLASS_ROCK" ;
} ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionScannerContainsHuntableOffender = function ( )
2013-08-05 15:42:26 +01:00
{
return this . checkScannerWithPredicate ( function ( s ) {
var threshold = this . fineThreshold ( ) / 2 ;
return s . isInSpace && s . bounty > threshold && s . scanClass != "CLASS_CARGO" && s . scanClass != "CLASS_ROCK" ;
} ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionScannerContainsSeriousOffender = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return this . checkScannerWithPredicate ( function ( s ) {
var threshold = this . fineThreshold ( ) ;
return s . isInSpace && s . bounty > threshold && s . scanClass != "CLASS_CARGO" && s . scanClass != "CLASS_ROCK" ;
} ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionScannerContainsHunters = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return this . checkScannerWithPredicate ( function ( s ) {
2013-09-08 17:20:28 +01:00
return ( s . primaryRole && this . shipInRoleCategory ( s , "oolite-bounty-hunter" ) ) || s . scanClass == "CLASS_POLICE" || ( s . isStation && s . isMainStation ) ;
2013-08-01 22:40:23 +01:00
} ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionScannerContainsLoneVictim = function ( )
2013-08-26 17:08:05 +01:00
{
var scan = this . getParameter ( "oolite_scanResults" ) ;
var others = 0 ;
var target = null ;
for ( var i = scan . length - 1 ; i >= 0 ; i -- )
{
2013-09-08 17:20:28 +01:00
if ( ! this . allied ( this . ship , scan [ i ] ) && this . shipInRoleCategory ( scan [ i ] , "oolite-pirate-victim" ) && scan [ i ] . cargoSpaceCapacity > 0 )
2013-08-26 17:08:05 +01:00
{
target = scan [ i ] ;
others ++ ;
}
}
if ( others == 1 )
{
this . setParameter ( "oolite_scanResultSpecific" , target ) ;
return true ;
}
return false ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionScannerContainsMiningOpportunity = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
// if hold full, no
if ( ! this . conditionCanScoopCargo ( ) )
{
return false ;
}
// need a mining laser, and for now a forward one
if ( ! this . ship . forwardWeapon == "EQ_WEAPON_MINING_LASER" )
{
return false ;
}
return this . conditionScannerContainsRocks ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-14 19:02:16 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionScannerContainsNonThargoid = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var prioritytargets = this . checkScannerWithPredicate ( function ( s ) {
return s . scanClass != "CLASS_THARGOID" && s . scanClass != "CLASS_ROCK" && s . scanClass != "CLASS_CARGO" ;
} ) ;
if ( prioritytargets )
{
return true ;
}
return this . checkScannerWithPredicate ( function ( s ) {
return s . scanClass != "CLASS_THARGOID" ;
} ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-22 21:24:27 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionScannerContainsPirateLeader = function ( )
2013-08-09 13:09:54 +01:00
{
return this . checkScannerWithPredicate ( function ( s ) {
2013-09-08 17:20:28 +01:00
return s . group && s . group . leader == s && this . shipInRoleCategory ( s , "oolite-pirate-leader" ) ;
2013-08-09 13:09:54 +01:00
} ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionScannerContainsPirateVictims = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-16 21:44:27 +01:00
var lpv = this . getParameter ( "oolite_lastPirateVictim" ) ;
2013-08-01 22:40:23 +01:00
return this . checkScannerWithPredicate ( function ( s ) {
// is a pirate victim
2013-09-08 21:23:00 +01:00
// can carry cargo
2013-08-01 22:40:23 +01:00
// hasn't already paid up
2013-09-08 21:23:00 +01:00
return s != lpv && this . shipInRoleCategory ( s , "oolite-pirate-victim" ) && s . cargoSpaceCapacity > 0 && ( ! s . AIScript || ! s . AIScript . oolite _intership || ! s . AIScript . oolite _intership . cargodemandpaid ) ;
2013-08-01 22:40:23 +01:00
} ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionScannerContainsReadyThargoidMothership = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return this . checkScannerWithPredicate ( function ( s ) {
return s . hasRole ( "thargoid-mothership" ) && ( ! s . escortGroup || s . escortGroup . count <= 16 ) ;
} ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-22 21:24:27 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionScannerContainsRocks = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var scan1 = this . checkScannerWithPredicate ( function ( s ) {
return s . isInSpace && s . isBoulder ;
} ) ;
if ( scan1 )
{
return true ;
}
// no boulders, what about asteroids?
return this . checkScannerWithPredicate ( function ( s ) {
return s . isInSpace && s . hasRole ( "asteroid" ) ;
} ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionScannerContainsSalvage = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return this . checkScannerWithPredicate ( function ( s ) {
return s . isInSpace && s . scanClass == "CLASS_CARGO" ;
} ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-25 20:09:53 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionScannerContainsSalvageForGroup = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-17 15:19:25 +01:00
if ( ! this . _ _ltcache . oolite _conditionScannerContainsSalvageForGroup )
2013-08-01 22:40:23 +01:00
{
2013-08-07 16:29:24 +01:00
var maxspeed = 0 ;
if ( this . conditionCanScoopCargo ( ) )
2013-07-13 23:18:05 +01:00
{
2013-08-07 16:29:24 +01:00
maxspeed = this . ship . maxSpeed ;
}
if ( this . ship . group )
2013-07-13 23:18:05 +01:00
{
2013-08-07 16:29:24 +01:00
var gs = this . ship . group . ships ;
for ( var i = gs . length - 1 ; i >= 0 ; i -- )
2013-08-01 22:40:23 +01:00
{
2013-08-07 16:29:24 +01:00
if ( gs [ i ] . cargoSpaceAvailable > 0 && gs [ i ] . equipmentStatus ( "EQ_FUEL_SCOOPS" ) == "EQUIPMENT_OK" && gs [ i ] . maxSpeed > maxspeed )
{
maxspeed = gs [ i ] . maxSpeed ;
}
2013-08-01 22:40:23 +01:00
}
2013-07-13 23:18:05 +01:00
}
2013-08-17 15:19:25 +01:00
this . _ _ltcache . oolite _conditionScannerContainsSalvageForGroup = maxspeed ;
2013-08-01 22:40:23 +01:00
}
return this . checkScannerWithPredicate ( function ( s ) {
2013-08-17 15:19:25 +01:00
return s . isInSpace && s . scanClass == "CLASS_CARGO" && s . velocity . magnitude ( ) < this . _ _ltcache . oolite _conditionScannerContainsSalvageForGroup ;
2013-08-01 22:40:23 +01:00
} ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-13 23:18:05 +01:00
2013-07-22 21:24:27 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionScannerContainsSalvageForMe = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( ! this . conditionCanScoopCargo ( ) )
{
return false ;
}
return this . checkScannerWithPredicate ( function ( s ) {
return s . isInSpace && s . scanClass == "CLASS_CARGO" && s . velocity . magnitude ( ) < this . ship . maxSpeed ;
} ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-13 23:18:05 +01:00
2013-07-21 11:10:47 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionScannerContainsShipAttackingPirate = function ( )
2013-08-16 18:00:46 +01:00
{
return this . checkScannerWithPredicate ( function ( s ) {
2013-08-16 21:44:27 +01:00
return s . target && s . hasHostileTarget && s . target . isPirate ;
2013-08-16 18:00:46 +01:00
} ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionScannerContainsShipNeedingEscort = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( this . ship . bounty == 0 )
{
return this . checkScannerWithPredicate ( function ( s ) {
return s . scanClass == this . ship . scanClass && s . bounty == 0 && ( ! s . escortGroup || s . escortGroup . count <= s . maxEscorts ) ;
} ) ;
}
else
{
return this . checkScannerWithPredicate ( function ( s ) {
return s . scanClass == this . ship . scanClass && s . bounty > 0 && ( ! s . escortGroup || s . escortGroup . count <= s . maxEscorts ) ;
} ) ;
}
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionScannerContainsThargoidMothership = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return this . checkScannerWithPredicate ( function ( s ) {
return s . hasRole ( "thargoid-mothership" ) ;
} ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-21 11:10:47 +01:00
2013-09-13 18:54:14 +01:00
PriorityAIController . prototype . conditionScannerContainsUnspreadMissile = function ( )
{
if ( ! this . getParameter ( "oolite_flag_autoSpreadMissiles" ) )
{
return false ;
}
return this . checkScannerWithPredicate ( function ( s ) {
var target = this . ship . target ;
return ( s . scanClass == "CLASS_MISSILE" ) && s . target == target && s . owner == this . ship . owner && this . distance ( s ) < 500 && this . distance ( target ) > s . position . distanceTo ( target ) ;
} ) ;
}
2013-07-26 18:52:11 +01:00
/*** State conditions ***/
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionAllEscortsInFlight = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( ! this . ship . escortGroup )
{
return true ; // there are no escorts not in flight
}
2013-08-07 16:29:24 +01:00
var gs = this . ship . escortGroup . ships ;
for ( var i = gs . length - 1 ; i >= 0 ; i -- )
2013-08-01 22:40:23 +01:00
{
2013-08-07 16:29:24 +01:00
if ( gs [ i ] . status != "STATUS_IN_FLIGHT" )
2013-07-13 23:18:05 +01:00
{
2013-08-01 22:40:23 +01:00
return false ;
2013-07-27 21:40:07 +01:00
}
2013-08-01 22:40:23 +01:00
}
// if just exited witchspace, escorts might not have rejoined escort
// group yet.
if ( ! this . ship . group )
{
return true ;
}
2013-08-07 16:29:24 +01:00
var gs = this . ship . group . ships ;
for ( var i = gs . length - 1 ; i >= 0 ; i -- )
2013-08-01 22:40:23 +01:00
{
2013-08-07 16:29:24 +01:00
if ( gs [ i ] . status != "STATUS_IN_FLIGHT" )
2013-07-27 21:40:07 +01:00
{
2013-08-01 22:40:23 +01:00
return false ;
2013-07-27 21:40:07 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-27 21:40:07 +01:00
2013-08-01 22:40:23 +01:00
return true ;
2013-07-26 18:52:11 +01:00
}
2013-07-13 23:18:05 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionCanScoopCargo = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-17 15:19:25 +01:00
if ( this . _ _cache . oolite _conditionCanScoopCargo !== undefined )
2013-08-07 12:27:22 +01:00
{
2013-08-17 15:19:25 +01:00
return this . _ _cache . oolite _conditionCanScoopCargo ;
2013-08-07 12:27:22 +01:00
}
2013-08-01 22:40:23 +01:00
if ( this . ship . cargoSpaceAvailable == 0 || this . ship . equipmentStatus ( "EQ_FUEL_SCOOPS" ) != "EQUIPMENT_OK" )
{
2013-08-17 15:19:25 +01:00
this . _ _cache . oolite _conditionCanScoopCargo = false ;
2013-08-01 22:40:23 +01:00
return false ;
}
2013-08-17 15:19:25 +01:00
this . _ _cache . oolite _conditionCanScoopCargo = true ;
2013-08-01 22:40:23 +01:00
return true ;
2013-07-26 18:52:11 +01:00
}
2013-07-14 19:02:16 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionCargoIsProfitableHere = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-09 13:09:54 +01:00
// only consider these values if the ship has a route defined
if ( this . ship . homeSystem != this . ship . destinationSystem )
2013-08-06 18:40:15 +01:00
{
2013-08-09 13:09:54 +01:00
// cargo is always considered profitable in the designated
// destination system (assume they have a prepared buyer)
if ( this . ship . destinationSystem && this . ship . destinationSystem == system . ID )
{
return true ;
}
// cargo is never considered profitable in the designated source
// system (or you could get ships launching and immediately
// redocking)
if ( this . ship . homeSystem && this . ship . homeSystem == system . ID )
{
return false ;
}
// and allow ships to be given multi-system trips if wanted
if ( this . getParameter ( "oolite_flag_noDockingUntilDestination" ) )
{
return false ;
}
2013-08-06 18:40:15 +01:00
}
2013-07-27 21:40:07 +01:00
2013-08-01 22:40:23 +01:00
if ( ! system . mainStation )
{
return false ;
}
2013-08-07 16:29:24 +01:00
2013-08-17 15:19:25 +01:00
if ( this . _ _ltcache . oolite _conditionCargoIsProfitableHere == undefined )
2013-08-01 22:40:23 +01:00
{
2013-08-07 16:29:24 +01:00
if ( this . ship . cargoSpaceUsed == 0 )
{
2013-08-17 15:19:25 +01:00
this . _ _ltcache . oolite _conditionCargoIsProfitableHere = false ;
2013-08-07 16:29:24 +01:00
}
else
{
var cargo = this . ship . cargoList ;
var profit = 0 ;
var multiplier = ( system . info . economy <= 3 ) ? - 1 : 1 ;
var market = system . mainStation . market ;
for ( var i = cargo . length - 1 ; i >= 0 ; i -- )
{
var commodity = cargo [ i ] . commodity ;
var quantity = cargo [ i ] . quantity ;
var adjust = market [ commodity ] . marketEcoAdjustPrice * multiplier * quantity / market [ commodity ] . marketMaskPrice ;
profit += adjust ;
}
2013-08-17 15:19:25 +01:00
this . _ _ltcache . oolite _conditionCargoIsProfitableHere = ( profit >= 0 ) ;
2013-08-07 16:29:24 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-08-17 15:19:25 +01:00
return this . _ _ltcache . oolite _conditionCargoIsProfitableHere ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionGroupLeaderIsStation = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return ( this . ship . group && this . ship . group . leader && this . ship . group . leader . isStation ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionHasInterceptCoordinates = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return ( this . getParameter ( "oolite_interceptCoordinates" ) != null ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionHasMothership = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return ( this . ship . group && this . ship . group . leader && this . ship . group . leader != this . ship ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionHasNonThargoidTarget = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return ( this . ship . target && this . ship . target . scanClass != "CLASS_THARGOID" ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-14 19:02:16 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionHasReceivedDistressCall = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var aggressor = this . getParameter ( "oolite_distressAggressor" ) ;
var sender = this . getParameter ( "oolite_distressSender" ) ;
var ts = this . getParameter ( "oolite_distressTimestamp" ) ;
2013-07-26 18:52:11 +01:00
2013-08-07 16:29:24 +01:00
if ( aggressor == null || ! aggressor . isInSpace || sender == null || ! sender . isInSpace || this . distance ( sender ) > this . scannerRange || ts + 30 < clock . adjustedSeconds )
2013-08-01 22:40:23 +01:00
{
// no, or it has expired
this . setParameter ( "oolite_distressAggressor" , null ) ;
this . setParameter ( "oolite_distressSender" , null ) ;
this . setParameter ( "oolite_distressTimestamp" , null ) ;
return false ;
}
return true ;
2013-07-26 18:52:11 +01:00
}
2013-09-14 13:50:49 +01:00
PriorityAIController . prototype . conditionHasRememberedTarget = function ( )
{
var rt = this . getParameter ( "oolite_rememberedTarget" ) ;
if ( rt != null && ( rt . isInSpace || rt . status == "STATUS_ENTERING_WITCHSPACE" ) )
{
return true ;
}
else
{
this . setParameter ( "oolite_rememberedTarget" , null ) ;
return false ;
}
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionHasTarget = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return this . ship . target != null ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionHasWaypoint = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return this . getParameter ( "oolite_waypoint" ) != null ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionIsActiveThargon = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return this . ship . scanClass == "CLASS_THARGOID" && this . ship . hasRole ( "EQ_THARGON" ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-15 23:14:47 +01:00
2013-07-26 18:52:11 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionIsEscorting = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( ! this . ship . group || ! this . ship . group . leader || this . ship . group . leader == this . ship )
{
return false ;
}
2013-08-07 16:29:24 +01:00
var leader = this . ship . group . leader ;
if ( leader . escortGroup && leader . escortGroup . containsShip ( this . ship ) )
2013-08-01 22:40:23 +01:00
{
2013-08-07 16:29:24 +01:00
if ( leader . status == "STATUS_ENTERING_WITCHSPACE" )
2013-08-01 22:40:23 +01:00
{
var hole = this . getParameter ( "oolite_witchspaceWormhole" ) ;
if ( hole == null || hole . expiryTime < clock . seconds )
{
// has been left behind
this . configurationLeaveEscortGroup ( ) ;
this . setParameter ( "oolite_witchspaceWormhole" , false ) ;
2013-07-18 23:00:23 +01:00
return false ;
2013-08-01 22:40:23 +01:00
}
2013-07-18 23:00:23 +01:00
}
2013-08-01 22:40:23 +01:00
return true ;
}
return false ;
2013-07-26 18:52:11 +01:00
}
2013-07-14 19:02:16 +01:00
2013-07-26 18:52:11 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionIsGroupLeader = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( ! this . ship . group )
{
return true ;
}
return ( this . ship . group . leader == this . ship ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionMissileOutOfFuel = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var range = 30000 ; // 30 km default
if ( this . ship . scriptInfo . oolite _missile _range )
{
range = this . ship . scriptInfo . oolite _missile _range ;
}
return range < this . ship . distanceTravelled ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionPatrolIsOver = function ( )
2013-08-08 16:00:20 +01:00
{
2013-09-04 22:25:54 +01:00
return this . ship . distanceTravelled > 200000 || this . conditionSuppliesLow ( ) ;
2013-08-08 16:00:20 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . conditionWitchspaceEntryRequested = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return ( this . getParameter ( "oolite_witchspaceWormhole" ) != null ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-15 23:14:47 +01:00
2013-07-26 18:52:11 +01:00
/* ****************** Behaviour functions ************** */
/ * B e h a v i o u r s . B e h a v i o u r s a r e e f f e c t i v e l y a s t a t e d e f i n i t i o n ,
* defining a set of events and responses . They are aided in this
* by the 'responses' , which mean that the event handlers for the
* behaviour within the definition can itself be templated . * /
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourApproachDestination = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var handlers = { } ;
this . responsesAddStandard ( handlers ) ;
2013-07-26 18:52:11 +01:00
2013-08-07 10:53:44 +01:00
handlers . shipAchievedDesiredRange = this . responseComponent _standard _shipAchievedDesiredRange ;
2013-08-01 22:40:23 +01:00
var waypoints = this . getParameter ( "oolite_waypoints" ) ;
if ( waypoints != null )
{
this . ship . destination = waypoints [ waypoints . length - 1 ] ;
2013-08-11 20:51:46 +01:00
this . ship . desiredRange = 100 ;
2013-08-01 22:40:23 +01:00
}
var blocker = this . ship . checkCourseToDestination ( ) ;
if ( blocker )
{
if ( blocker . isPlanet || blocker . isSun )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
// the selected planet can't block
if ( blocker . isSun || this . getParameter ( "oolite_selectedPlanet" ) != blocker )
{
2013-08-11 20:51:46 +01:00
var dist = this . distance ( blocker ) ;
if ( dist < blocker . radius * 1.3 )
{
if ( waypoints == null )
{
waypoints = [ ] ;
}
waypoints . push ( this . ship . position . subtract ( blocker . position . subtract ( this . ship . position ) ) ) ;
this . ship . destination = waypoints [ waypoints . length - 1 ] ;
this . ship . desiredRange = 100 ;
}
else if ( this . distance ( blocker ) < blocker . radius * 3 )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( waypoints == null )
{
waypoints = [ ] ;
}
waypoints . push ( this . ship . getSafeCourseToDestination ( ) ) ;
this . ship . destination = waypoints [ waypoints . length - 1 ] ;
2013-08-11 20:51:46 +01:00
this . ship . desiredRange = 100 ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
}
else if ( blocker . isShip )
{
2013-08-07 16:29:24 +01:00
if ( this . distance ( blocker ) < 25600 )
2013-08-01 22:40:23 +01:00
{
if ( ! blocker . group || ! blocker . group . leader == this . ship )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
// our own escorts are not a blocker!
if ( waypoints == null )
{
waypoints = [ ] ;
}
waypoints . push ( this . ship . getSafeCourseToDestination ( ) ) ;
this . ship . destination = waypoints [ waypoints . length - 1 ] ;
2013-08-11 20:51:46 +01:00
this . ship . desiredRange = 100 ;
2013-07-14 23:11:25 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-14 23:11:25 +01:00
}
2013-08-01 22:40:23 +01:00
}
this . setParameter ( "oolite_waypoints" , waypoints ) ;
this . applyHandlers ( handlers ) ;
this . ship . performFlyToRangeFromDestination ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-14 23:11:25 +01:00
2013-07-26 18:52:11 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourAvoidCascadeExplosion = function ( )
2013-07-27 15:39:23 +01:00
{
2013-08-01 22:40:23 +01:00
var handlers = { } ;
this . responsesAddStandard ( handlers ) ;
this . applyHandlers ( handlers ) ;
2013-07-27 15:39:23 +01:00
2013-08-01 22:40:23 +01:00
var cascade = this . getParameter ( "oolite_cascadeDetected" ) ;
if ( cascade != null )
{
if ( cascade . distanceTo ( this . ship ) < 25600 )
2013-07-27 15:39:23 +01:00
{
2013-08-01 22:40:23 +01:00
if ( this . ship . defenseTargets . length > 0 && this . ship . defenseTargets [ 0 ] . scanClass == "CLASS_MINE" )
{
// if the mine is still visible, conventional fleeing works
2013-08-02 22:16:54 +01:00
this . communicate ( "oolite_quiriumCascade" , { } , 3 ) ;
2013-08-01 22:40:23 +01:00
this . ship . target = this . ship . defenseTargets [ 0 ] ;
this . ship . desiredRange = 30000 ;
this . ship . performFlee ( ) ;
return ;
}
else
{
if ( this . ship . destination != cascade )
2013-07-27 15:39:23 +01:00
{
2013-08-01 22:40:23 +01:00
this . communicate ( "oolite_quiriumCascade" , { } , 3 ) ;
2013-07-27 15:39:23 +01:00
}
2013-08-01 22:40:23 +01:00
this . ship . destination = cascade ;
this . ship . desiredRange = 30000 ;
this . ship . desiredSpeed = 10 * this . ship . maxSpeed ;
this . ship . performFlyToRangeFromDestination ( ) ;
return ;
}
2013-07-27 15:39:23 +01:00
}
2013-08-01 22:40:23 +01:00
else
{
this . setParameter ( "oolite_cascadeDetected" , null ) ;
}
}
2013-07-27 15:39:23 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourBecomeInactiveThargon = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
this . applyHandlers ( { } ) ;
this . ship . scanClass = "CLASS_CARGO" ;
this . ship . target = null ;
this . ship . clearDefenseTargets ( ) ;
if ( this . ship . group )
{
this . ship . group . removeShip ( this . ship ) ;
this . ship . group = null ;
}
if ( this . ship . escortGroup )
{
this . ship . escortGroup . removeShip ( this . ship ) ;
}
this . ship . desiredSpeed = 0 ;
this . ship . performStop ( ) ;
2013-08-04 12:29:44 +01:00
var nearby = this . ship . checkScanner ( true ) ;
2013-08-01 22:40:23 +01:00
for ( var i = 0 ; i < nearby . length ; i ++ )
{
var ship = nearby [ i ] ;
if ( ship . target == this . ship && ! ship . isPlayer && ship . hasHostileTarget )
{
ship . target = null ;
}
ship . removeDefenseTarget ( this . ship ) ;
}
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourCollectSalvage = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var handlers = { } ;
this . responsesAddStandard ( handlers ) ;
2013-08-07 10:53:44 +01:00
handlers . shipScoopedOther = this . responseComponent _standard _shipScoopedOther ;
2013-08-01 22:40:23 +01:00
this . applyHandlers ( handlers ) ;
this . ship . performCollect ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourDestroyCurrentTarget = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
this . setParameter ( "oolite_witchspaceEntry" , null ) ;
2013-07-14 23:11:25 +01:00
2013-08-01 22:40:23 +01:00
var handlers = { } ;
this . responsesAddStandard ( handlers ) ;
this . applyHandlers ( handlers ) ;
2013-08-04 12:29:44 +01:00
if ( this . getParameter ( "oolite_flag_noSpecialThargoidReaction" ) != null )
{
if ( this . ship . scanClass != "CLASS_THARGOID" && this . ship . target . scanClass != "CLASS_THARGOID" && this . ship . target . target . scanClass == "CLASS_THARGOID" )
{
2013-08-04 14:20:20 +01:00
this . respondToThargoids ( this . ship . target . target , true ) ;
2013-08-04 12:29:44 +01:00
this . ship . performAttack ( ) ;
return ;
}
}
2013-08-17 13:26:37 +01:00
/ * T h i s d o e s n ' t w o r k : s h i p s w h i c h a r e r e m o v e d f r o m t h e l i s t
2013-08-17 15:19:25 +01:00
* because they ' re unreachable then just end up being reselected the
2013-08-17 13:26:37 +01:00
* next time the ship scans for targets . * /
/ *
2013-08-16 21:44:27 +01:00
if ( this . getParameter ( "oolite_flag_continueUnlikelyPursuits" ) == null )
{
if ( this . ship . target )
{
2013-08-17 13:26:37 +01:00
if ( this . isEscaping ( this . ship . target ) )
2013-08-16 21:44:27 +01:00
{
this . ship . removeDefenseTarget ( this . ship . target ) ;
this . ship . target = null ;
}
}
}
2013-08-17 13:26:37 +01:00
* /
2013-08-04 12:29:44 +01:00
2013-08-07 16:29:24 +01:00
if ( this . ship . target )
2013-08-01 22:40:23 +01:00
{
2013-08-07 16:29:24 +01:00
if ( ! this . ship . hasHostileTarget )
{
// entering attack mode
this . communicate ( "oolite_beginningAttack" , this . ship . target , 3 ) ;
}
else
{
this . communicate ( "oolite_continuingAttack" , this . ship . target , 4 ) ;
}
2013-08-01 22:40:23 +01:00
}
this . ship . performAttack ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-16 21:44:27 +01:00
// NOTE: this does not, and should not, check whether the station is friendly
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourDockWithStation = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
// may need to release escorts
if ( this . ship . escortGroup && this . ship . escortGroup . count > 1 )
{
this . ship . dockEscorts ( ) ;
}
var station = this . getParameter ( "oolite_dockingStation" ) ;
this . ship . target = station ;
var handlers = { } ;
this . responsesAddStandard ( handlers ) ;
this . responsesAddDocking ( handlers ) ;
this . ship . requestDockingInstructions ( ) ;
if ( ! this . ship . dockingInstructions )
{
this . ship . performIdle ( ) ;
this . reconsiderNow ( ) ;
return ;
}
switch ( this . ship . dockingInstructions . ai _message )
{
case "TOO_BIG_TO_DOCK" :
case "DOCKING_REFUSED" :
this . ship . setParameter ( "oolite_dockingStation" , null ) ;
this . ship . target = null ;
this . reconsiderNow ( ) ;
break ;
case "TRY_AGAIN_LATER" :
2013-08-23 21:18:23 +01:00
if ( this . distance ( station ) < 10000 )
2013-08-01 22:40:23 +01:00
{
2013-08-23 21:18:23 +01:00
this . ship . destination = station . position ;
2013-08-01 22:40:23 +01:00
this . ship . desiredRange = 12500 ;
this . ship . desiredSpeed = this . cruiseSpeed ( ) ;
this . ship . performFlyToRangeFromDestination ( ) ;
break ;
}
// else fall through
case "HOLD_POSITION" :
2013-08-02 22:16:54 +01:00
this . communicate ( "oolite_dockingWait" , { } , 4 ) ;
2013-08-23 21:18:23 +01:00
this . ship . destination = station . position ;
2013-08-01 22:40:23 +01:00
this . ship . performFaceDestination ( ) ;
// and will reconsider in a little bit
break ;
case "APPROACH" :
case "APPROACH_COORDINATES" :
case "BACK_OFF" :
this . ship . performFlyToRangeFromDestination ( ) ;
break ;
}
this . applyHandlers ( handlers ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-14 23:11:25 +01:00
2013-07-26 18:52:11 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourEnterWitchspace = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var handlers = { } ;
this . responsesAddStandard ( handlers ) ;
var wormhole = this . getParameter ( "oolite_witchspaceWormhole" ) ;
if ( wormhole && wormhole . expiryTime < clock . adjustedSeconds )
{
// the wormhole we were trying for has expired
this . setParameter ( "oolite_witchspaceWormhole" , null ) ;
2013-08-09 13:09:54 +01:00
if ( this . ship . group && this . ship . group . leader && this . ship . group . leader . status == "STATUS_ENTERING_WITCHSPACE" )
{
// left behind, so leave group
this . ship . group . removeShip ( this . ship ) ;
this . ship . group = null ;
}
2013-08-01 22:40:23 +01:00
}
else if ( wormhole )
{
2013-08-07 10:53:44 +01:00
handlers . playerWillEnterWitchspace = this . responseComponent _trackPlayer _playerWillEnterWitchspace ;
2013-08-01 22:40:23 +01:00
this . ship . destination = wormhole . position ;
this . ship . desiredRange = 0 ;
this . ship . desiredSpeed = this . ship . maxSpeed ;
this . ship . performFlyToRangeFromDestination ( ) ;
this . applyHandlers ( handlers ) ;
return ;
}
var destID = this . getParameter ( "oolite_witchspaceDestination" ) ;
if ( destID == null )
{
// look for wormholes out of here
// no systems in range
2013-08-07 10:53:44 +01:00
handlers . playerWillEnterWitchspace = this . responseComponent _trackPlayer _playerWillEnterWitchspace ;
2013-08-01 22:40:23 +01:00
this . applyHandlers ( handlers ) ;
return ;
}
else
{
2013-08-07 10:53:44 +01:00
handlers . shipWitchspaceBlocked = this . responseComponent _standard _shipWitchspaceBlocked ;
2013-08-01 22:40:23 +01:00
// set up the handlers before trying it
this . applyHandlers ( handlers ) ;
var entry = this . getParameter ( "oolite_witchspaceEntry" ) ;
// wait for escorts to launch
if ( ! this . conditionAllEscortsInFlight ( ) )
{
2013-08-11 20:51:46 +01:00
this . ship . destination = this . ship . position . add ( this . ship . vectorForward . multiply ( 30000 ) ) ;
2013-08-01 22:40:23 +01:00
this . ship . desiredRange = 10000 ;
this . ship . desiredSpeed = this . cruiseSpeed ( ) ;
if ( this . ship . checkCourseToDestination ( ) )
{
this . ship . destination = this . ship . getSafeCourseToDestination ( ) ;
}
this . ship . performFlyToRangeFromDestination ( ) ;
}
else if ( entry != null && entry < clock . seconds )
{
// this should work
var result = this . ship . exitSystem ( destID ) ;
// if it doesn't, we'll get blocked
if ( result )
{
2013-08-09 13:09:54 +01:00
this . ship . notifyGroupOfWormhole ( ) ;
2013-08-01 22:40:23 +01:00
this . setParameter ( "oolite_witchspaceEntry" , null ) ;
}
2013-07-14 23:11:25 +01:00
}
2013-07-26 18:52:11 +01:00
else
2013-07-14 23:11:25 +01:00
{
2013-08-01 22:40:23 +01:00
if ( entry == null )
{
this . communicate ( "oolite_engageWitchspaceDrive" , { } , 4 ) ;
this . setParameter ( "oolite_witchspaceEntry" , clock . seconds + 15 ) ;
}
2013-08-11 20:51:46 +01:00
this . ship . destination = this . ship . position . add ( this . ship . vectorForward . multiply ( 30000 ) ) ;
2013-08-01 22:40:23 +01:00
this . ship . desiredRange = 10000 ;
this . ship . desiredSpeed = this . cruiseSpeed ( ) ;
if ( this . ship . checkCourseToDestination ( ) )
{
this . ship . destination = this . ship . getSafeCourseToDestination ( ) ;
}
this . ship . performFlyToRangeFromDestination ( ) ;
2013-07-14 23:11:25 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourEscortMothership = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var handlers = { } ;
2013-08-02 22:16:54 +01:00
if ( this . ship . group . leader )
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_escortFormation" , this . ship . group . leader , 4 ) ;
2013-08-02 22:16:54 +01:00
}
2013-08-01 22:40:23 +01:00
this . responsesAddStandard ( handlers ) ;
this . responsesAddEscort ( handlers ) ;
this . applyHandlers ( handlers ) ;
this . ship . desiredRange = 0 ;
this . ship . performEscort ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-14 23:11:25 +01:00
2013-07-21 11:10:47 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourFineCurrentTarget = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var handlers = { } ;
this . responsesAddStandard ( handlers ) ;
this . applyHandlers ( handlers ) ;
if ( this . ship . scanClass == "CLASS_POLICE" && this . ship . target )
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_markForFines" , this . ship . target , 1 ) ;
2013-07-26 18:52:11 +01:00
2013-08-01 22:40:23 +01:00
this . ship . markTargetForFines ( ) ;
}
2013-07-24 21:56:50 +01:00
2013-08-01 22:40:23 +01:00
this . ship . performIdle ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-12 19:44:14 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourFleeCombat = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var handlers = { } ;
this . responsesAddStandard ( handlers ) ;
this . applyHandlers ( handlers ) ;
2013-07-13 11:36:28 +01:00
2013-08-01 22:40:23 +01:00
var cascade = this . getParameter ( "oolite_cascadeDetected" ) ;
if ( cascade != null )
{
if ( cascade . distanceTo ( this . ship ) < 25600 )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( this . ship . defenseTargets . length > 0 && this . ship . defenseTargets [ 0 ] . scanClass == "CLASS_MINE" )
{
// if the mine is still visible, conventional fleeing works
this . ship . target = this . ship . defenseTargets [ 0 ] ;
this . ship . desiredRange = 30000 ;
this . ship . performFlee ( ) ;
return ;
}
else
{
if ( this . ship . destination != cascade )
2013-07-13 11:36:28 +01:00
{
2013-08-01 22:40:23 +01:00
this . communicate ( "oolite_quiriumCascade" , { } , 4 ) ;
2013-07-13 11:36:28 +01:00
}
2013-08-01 22:40:23 +01:00
this . ship . destination = cascade ;
this . ship . desiredRange = 30000 ;
this . ship . desiredSpeed = 10 * this . ship . maxSpeed ;
this . ship . performFlyToRangeFromDestination ( ) ;
return ;
}
2013-07-12 19:44:14 +01:00
}
2013-08-01 22:40:23 +01:00
else
2013-07-12 19:44:14 +01:00
{
2013-08-01 22:40:23 +01:00
this . setParameter ( "oolite_cascadeDetected" , null ) ;
2013-07-12 19:44:14 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-08-07 16:29:24 +01:00
if ( ! this . ship . target || this . distance ( this . ship . target ) > this . scannerRange )
2013-08-01 22:40:23 +01:00
{
2013-09-13 18:54:14 +01:00
var aggressor = this . ship . AIPrimaryAggressor ;
if ( aggressor && aggressor . isInSpace && this . distance ( aggressor ) < this . scannerRange )
{
this . ship . target = aggressor ;
}
else
2013-08-01 22:40:23 +01:00
{
2013-09-13 18:54:14 +01:00
var dts = this . ship . defenseTargets ;
for ( var i = 0 ; i < dts . length ; i ++ )
2013-08-02 22:16:54 +01:00
{
2013-09-13 18:54:14 +01:00
if ( this . distance ( dts [ i ] ) < this . scannerRange && this . isFighting ( dts [ i ] ) )
{
this . ship . target = dts [ i ] ;
break ;
}
2013-08-02 22:16:54 +01:00
}
2013-08-01 22:40:23 +01:00
}
}
2013-08-02 22:16:54 +01:00
if ( this . getParameter ( "oolite_lastFleeing" ) != null )
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_continueFleeing" , this . ship . target , 4 ) ;
2013-08-02 22:16:54 +01:00
}
2013-08-05 14:14:50 +01:00
else if ( this . ship . energy < this . ship . maxEnergy / 4 )
2013-08-02 22:16:54 +01:00
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_startFleeing" , this . ship . target , 3 ) ;
2013-08-02 22:16:54 +01:00
}
2013-08-05 14:14:50 +01:00
if ( this . ship . target )
{
this . setParameter ( "oolite_lastFleeing" , this . ship . target ) ;
}
2013-08-17 14:39:16 +01:00
2013-08-17 15:19:25 +01:00
if ( ! this . _ _ltcache . oolite _considerWitchspaceFlee )
2013-08-17 14:39:16 +01:00
{
2013-08-18 16:36:57 +01:00
if ( this . getParameter ( "oolite_flag_neverFleeToWitchspace" ) == null )
2013-08-17 14:39:16 +01:00
{
2013-08-18 16:36:57 +01:00
this . _ _ltcache . oolite _considerWitchspaceFlee = ( this . ship . hasHyperspaceMotor && ( ( system . isInterstellarSpace && this . ship . fuel > 0 ) || ( system . ID != this . ship . homeSystem && system . info . systemsInRange ( this . ship . fuel ) . length > 0 ) ) ) ? 1 : - 1 ;
2013-08-17 14:39:16 +01:00
}
else
{
2013-08-17 15:19:25 +01:00
this . _ _ltcache . oolite _considerWitchspaceFlee = - 1 ;
2013-08-17 14:39:16 +01:00
}
}
2013-08-17 15:19:25 +01:00
if ( this . _ _ltcache . oolite _considerWitchspaceFlee == 1 )
2013-08-17 14:39:16 +01:00
{
2013-08-18 16:36:57 +01:00
if ( ! this . _ _ltcache . oolite _witchspaceflee )
2013-08-17 14:39:16 +01:00
{
2013-08-17 15:19:25 +01:00
this . _ _ltcache . oolite _witchspaceflee = clock . seconds + 15 ;
2013-08-17 14:39:16 +01:00
}
2013-08-17 15:19:25 +01:00
if ( this . _ _ltcache . oolite _witchspaceflee < clock . seconds )
2013-08-17 14:39:16 +01:00
{
if ( this . ship . exitSystem ( ) )
{
this . ship . notifyGroupOfWormhole ( ) ;
2013-08-17 15:19:25 +01:00
delete this . _ _ltcache . oolite _witchspaceflee ;
2013-08-17 14:39:16 +01:00
}
}
}
2013-08-18 16:36:57 +01:00
2013-08-07 16:29:24 +01:00
this . ship . desiredRange = this . scannerRange ;
2013-08-01 22:40:23 +01:00
this . ship . performFlee ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-12 19:44:14 +01:00
2013-09-14 13:50:49 +01:00
/* Follow a ship, including to witchspace */
PriorityAIController . prototype . behaviourFollowCurrentTarget = function ( )
{
if ( this . ship . target )
{
var rt = this . ship . target ;
}
else
{
var rt = this . getParameter ( "oolite_rememberedTarget" ) ;
}
this . ship . destination = rt . position ;
if ( rt . status == "STATUS_ENTERING_WITCHSPACE" )
{
var pos = rt . position ;
var ws = system . wormholes ;
// most likely to be most recent
for ( var i = ws . length - 1 ; i >= 0 ; i -- )
{
if ( ws [ i ] . position . distanceTo ( pos ) < 100 )
{
this . setParameter ( "oolite_witchspaceWormhole" , ws [ i ] ) ;
this . setParameter ( "oolite_rememberedTarget" , null ) ;
break ;
}
}
this . ship . desiredRange = 0 ; // use wormhole
}
else
{
this . setParameter ( "oolite_rememberedTarget" , rt ) ;
this . ship . desiredRange = 500 + Math . random ( ) * 1000 ;
}
this . ship . desiredSpeed = this . ship . maxSpeed ;
this . behaviourApproachDestination ( ) ;
}
2013-07-26 18:52:11 +01:00
/* Follow the group leader in a less organised way than escorting them */
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourFollowGroupLeader = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( ! this . ship . group || ! this . ship . group . leader )
{
2013-08-05 14:14:50 +01:00
var handlers = { } ;
this . responsesAddStandard ( handlers ) ;
this . applyHandlers ( handlers ) ;
2013-08-01 22:40:23 +01:00
this . ship . performIdle ( ) ;
}
else
{
this . ship . destination = this . ship . group . leader . position ;
2013-08-11 20:51:46 +01:00
this . ship . desiredRange = 500 + Math . random ( ) * 1000 ;
2013-08-01 22:40:23 +01:00
this . ship . desiredSpeed = this . ship . maxSpeed ;
2013-08-05 14:14:50 +01:00
this . behaviourApproachDestination ( ) ;
2013-08-01 22:40:23 +01:00
}
2013-07-26 18:52:11 +01:00
}
2013-07-13 23:18:05 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourGuardTarget = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( ! this . ship . target )
{
this . ship . destination = this . ship . position ;
}
else
{
this . ship . destination = this . ship . target . position ;
}
this . ship . desiredSpeed = this . cruiseSpeed ( ) ;
this . ship . desiredRange = 2500 ;
2013-08-05 14:14:50 +01:00
this . behaviourApproachDestination ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-18 23:00:23 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourJoinTargetGroup = function ( )
2013-08-09 13:09:54 +01:00
{
if ( this . ship . target && this . ship . target . group )
{
this . ship . target . group . addShip ( this . ship ) ;
this . ship . group = this . ship . target . group ;
}
this . ship . performIdle ( ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourLandOnPlanet = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
this . ship . desiredSpeed = this . ship . maxSpeed / 4 ;
this . ship . performLandOnPlanet ( ) ;
this . ship . AIScriptWakeTime = 0 ; // cancel reconsiderations
this . applyHandlers ( { } ) ; // cancel interruptions
this . communicate ( "oolite_landingOnPlanet" , { } , 4 ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourLeaveVicinityOfDestination = function ( )
2013-08-16 21:44:27 +01:00
{
this . ship . desiredRange = 60000 ;
this . ship . desiredSpeed = this . ship . maxSpeed ;
this . communicate ( "oolite_leaveVicinity" , this . ship . target , 3 ) ;
this . behaviourApproachDestination ( ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourLeaveVicinityOfTarget = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( ! this . ship . target )
{
this . reconsiderNow ( ) ;
return ;
}
this . ship . destination = this . ship . target . position ;
this . ship . desiredRange = 27500 ;
this . ship . desiredSpeed = this . ship . maxSpeed ;
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_leaveVicinity" , this . ship . target , 3 ) ;
2013-08-05 14:14:50 +01:00
this . behaviourApproachDestination ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-22 21:24:27 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourMineTarget = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var handlers = { } ;
this . responsesAddStandard ( handlers ) ;
this . applyHandlers ( handlers ) ;
2013-08-02 22:16:54 +01:00
this . communicate ( "oolite_mining" , { } , 4 ) ;
2013-08-01 22:40:23 +01:00
this . ship . performMining ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourOfferToEscort = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var handlers = { } ;
this . responsesAddStandard ( handlers ) ;
this . applyHandlers ( handlers ) ;
var possible = this . getParameter ( "oolite_scanResultSpecific" ) ;
if ( possible == null )
{
this . reconsiderNow ( ) ;
}
else
{
if ( this . ship . offerToEscort ( possible ) )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
// accepted
this . reconsiderNow ( ) ;
2013-07-13 19:13:30 +01:00
}
2013-08-01 22:40:23 +01:00
// if rejected, wait for next scheduled reconsideration
}
2013-07-26 18:52:11 +01:00
}
2013-07-13 19:13:30 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourPayOffPirates = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
this . ship . dumpCargo ( this . ship . AIScript . oolite _intership . cargodemand ) ;
2013-08-02 22:16:54 +01:00
this . communicate ( "oolite_agreeingToDumpCargo" , { "oolite_demandSize" : this . ship . AIScript . oolite _intership . cargodemand } , 1 ) ;
2013-08-01 22:40:23 +01:00
delete this . ship . AIScript . oolite _intership . cargodemand ;
this . ship . AIScript . oolite _intership . cargodemandpaid = true ;
this . behaviourFleeCombat ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-13 09:53:53 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourReconsider = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var handlers = { } ;
this . responsesAddStandard ( handlers ) ;
this . applyHandlers ( handlers ) ;
this . reconsiderNow ( ) ;
2013-07-26 18:52:11 +01:00
}
// Separate behaviour to EscortMothership in case we want to change it later
// This is the one to catch up with a distant mothership
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourRejoinMothership = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var handlers = { } ;
this . responsesAddStandard ( handlers ) ;
this . responsesAddEscort ( handlers ) ;
this . applyHandlers ( handlers ) ;
// to consider: should this behaviour use injectors if
// possible? so few escorts have them that it's probably not
// worth it.
this . ship . desiredRange = 0 ;
this . ship . performEscort ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourRepelCurrentTarget = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
this . setParameter ( "oolite_witchspaceEntry" , null ) ;
2013-07-26 18:52:11 +01:00
2013-08-01 22:40:23 +01:00
var handlers = { } ;
this . responsesAddStandard ( handlers ) ;
this . applyHandlers ( handlers ) ;
2013-08-07 16:29:24 +01:00
var target = this . ship . target
if ( ! target || ! target . isValid || ! target . isShip )
2013-08-01 22:40:23 +01:00
{
this . reconsiderNow ( ) ;
return ;
}
2013-08-04 12:29:44 +01:00
if ( this . getParameter ( "oolite_flag_noSpecialThargoidReaction" ) != null )
{
2013-08-07 16:29:24 +01:00
if ( this . ship . scanClass != "CLASS_THARGOID" && target . scanClass != "CLASS_THARGOID" && target . target . scanClass == "CLASS_THARGOID" )
2013-08-04 12:29:44 +01:00
{
2013-08-07 16:29:24 +01:00
this . respondToThargoids ( target . target , true ) ;
2013-08-04 12:29:44 +01:00
this . ship . performAttack ( ) ;
return ;
}
}
2013-08-07 16:29:24 +01:00
if ( ! this . isAggressive ( target ) )
2013-08-01 22:40:23 +01:00
{
// repelling succeeded
if ( this . ship . escortGroup )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
// also tell escorts to stop attacking it
for ( var i = 0 ; i < this . ship . escortGroup . ships . length ; i ++ )
{
this . ship . escortGroup . ships [ i ] . removeDefenseTarget ( target ) ;
if ( this . ship . escortGroup . ships [ i ] . target == target )
2013-07-13 09:53:53 +01:00
{
2013-08-01 22:40:23 +01:00
this . ship . escortGroup . ships [ i ] . target = null ;
2013-07-13 09:53:53 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-12 19:44:14 +01:00
}
2013-08-01 22:40:23 +01:00
this . ship . removeDefenseTarget ( target ) ;
this . ship . target = null ;
}
else
{
if ( ! this . ship . hasHostileTarget )
2013-07-12 23:00:39 +01:00
{
2013-08-01 22:40:23 +01:00
// entering attack mode
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_beginningAttack" , target , 3 ) ;
2013-07-12 23:00:39 +01:00
}
2013-08-02 22:16:54 +01:00
else if ( this . ship . target )
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_continuingAttack" , target , 4 ) ;
2013-08-02 22:16:54 +01:00
}
2013-09-05 20:12:41 +01:00
if ( this . ship . energy == this . ship . maxEnergy && this . getParameter ( "oolite_flag_escortsCoverRetreat" ) && this . ship . escortGroup . count > 1 )
{
// if has escorts, and is not yet taking damage, run and let
// the escorts take them on
this . ship . performFlee ( ) ;
return ;
}
2013-08-01 22:40:23 +01:00
this . ship . performAttack ( ) ;
}
2013-07-26 18:52:11 +01:00
}
2013-07-12 19:44:14 +01:00
2013-07-26 18:52:11 +01:00
/ * S t a n d a r d " h e l p t h e i n n o c e n t " d i s t r e s s c a l l r e s p o n s e . P e r h a p s
* there should be a 'blood in the water' response available
* too ... * /
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourRespondToDistressCall = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var aggressor = this . getParameter ( "oolite_distressAggressor" ) ;
var sender = this . getParameter ( "oolite_distressSender" ) ;
if ( aggressor && aggressor . isShip && sender && sender . isShip )
{
if ( sender . bounty > aggressor . bounty )
2013-07-13 19:13:30 +01:00
{
2013-08-01 22:40:23 +01:00
var tmp = sender ;
sender = aggressor ;
aggressor = tmp ;
2013-07-13 19:13:30 +01:00
}
2013-08-07 16:29:24 +01:00
if ( this . distance ( aggressor ) < this . scannerRange )
2013-08-01 22:40:23 +01:00
{
this . ship . target = aggressor ;
this . ship . performAttack ( ) ;
this . reconsiderNow ( ) ;
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_distressResponseAggressor" , aggressor , 2 ) ;
2013-08-01 22:40:23 +01:00
}
else
{ // we can't actually see what's attacking the sender yet
this . ship . destination = sender . position ;
this . ship . desiredRange = 1000 + sender . collisionRadius + this . ship . collisionRadius ;
this . ship . desiredSpeed = 7 * this . ship . maxSpeed ; // use injectors if possible
this . ship . performFlyToRangeFromDestination ( ) ;
// and when we next reconsider, hopefully the aggressor will be on the scanner
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_distressResponseSender" , sender , 2 ) ;
2013-08-01 22:40:23 +01:00
}
}
var handlers = { } ;
this . responsesAddStandard ( handlers ) ;
this . applyHandlers ( handlers ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-13 19:13:30 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourRobTarget = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var demand = null ;
if ( this . ship . group && this . ship . group . leader )
{
if ( this . ship . group . leader . AIScript . oolite _intership && this . ship . group . leader . AIScript . oolite _intership . cargodemanded )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
demand = this . ship . group . leader . AIScript . oolite _intership . cargodemanded ;
2013-07-13 19:13:30 +01:00
}
2013-08-01 22:40:23 +01:00
}
else
{
if ( this . ship . AIScript . oolite _intership . cargodemanded )
2013-07-13 23:18:05 +01:00
{
2013-08-01 22:40:23 +01:00
demand = this . ship . AIScript . oolite _intership . cargodemanded ;
}
}
if ( demand == null )
{
2013-08-16 21:44:27 +01:00
var target = this . ship . target ;
var hascargo = target . cargoSpaceCapacity ; //cargoSpaceUsed?
2013-08-01 22:40:23 +01:00
// blowing them up probably gets ~10%, so how much we feel
// confident in demanding depends on how likely patrols
// are to come along and interfere.
demand = ( hascargo / 20 ) ;
demand = demand * ( 1 + Math . random ( ) + ( 8 - system . info . government ) / 8 ) ;
// between 5% and 15% of cargo
2013-08-22 18:38:01 +01:00
if ( this . conditionCombatOddsExcellent ( ) )
{
// if we have overwhelming force, can get away with demanding more
demand *= 1.5 + Math . random ( ) ;
// between 7.5% and 37.5% of cargo
}
2013-08-01 22:40:23 +01:00
demand = Math . ceil ( demand ) ; // round it up so there's always at least 1
var maxdemand = 0 ;
var gc = 1 ;
if ( ! this . ship . group )
{
if ( this . ship . equipmentStatus ( "EQ_FUEL_SCOOPS" ) == "EQUIPMENT_OK" )
{
maxdemand = this . ship . cargoSpaceAvailable ;
}
2013-07-13 23:18:05 +01:00
}
2013-08-01 22:40:23 +01:00
else
2013-07-13 23:18:05 +01:00
{
2013-08-01 22:40:23 +01:00
gc = this . ship . group . ships . length ;
for ( var i = 0 ; i < gc ; i ++ )
{
var ship = this . ship . group . ships [ i ] ;
if ( ship . equipmentStatus ( "EQ_FUEL_SCOOPS" ) == "EQUIPMENT_OK" )
2013-07-15 23:14:47 +01:00
{
2013-08-01 22:40:23 +01:00
maxdemand += ship . cargoSpaceAvailable ;
2013-07-13 23:18:05 +01:00
}
else
{
2013-08-01 22:40:23 +01:00
gc -- ; // this ship can't help scoop
2013-07-15 23:14:47 +01:00
}
2013-08-01 22:40:23 +01:00
}
}
if ( demand > maxdemand )
{
demand = maxdemand ; // don't ask for more than we can carry
}
while ( demand > gc * 5 )
{
// asking for more than 5TC each probably means there
// won't be time to pick it all up anyway
demand = Math . ceil ( demand / 2 ) ;
}
if ( demand < 2 )
{
demand = 2 ;
}
2013-07-15 23:14:47 +01:00
2013-08-01 22:40:23 +01:00
/* Record our demand with the group leader */
if ( this . ship . group && this . ship . group . leader )
{
this . ship . group . leader . AIScript . oolite _intership . cargodemanded = demand ;
2013-07-21 11:10:47 +01:00
}
2013-08-01 22:40:23 +01:00
else
{
this . ship . AIScript . oolite _intership . cargodemanded = demand ;
}
/* Inform the victim of the demand, if possible */
2013-08-16 21:44:27 +01:00
if ( target . AIScript && target . AIScript . oolite _intership )
2013-08-01 22:40:23 +01:00
{
2013-08-16 21:44:27 +01:00
target . AIScript . oolite _intership . cargodemand = demand ;
2013-08-01 22:40:23 +01:00
}
2013-08-16 21:44:27 +01:00
var commsparams = this . entityCommsParams ( target ) ;
2013-08-01 22:40:23 +01:00
commsparams [ "oolite_demandSize" ] = demand ;
2013-09-02 22:23:06 +01:00
this . ship . performAttack ( ) ; // must be before the comms message
2013-08-01 22:40:23 +01:00
this . communicate ( "oolite_makePirateDemand" , commsparams , 1 ) ;
2013-07-28 12:07:39 +01:00
this . ship . requestHelpFromGroup ( ) ;
2013-08-16 21:44:27 +01:00
// prevents choosing this ship twice in a row
// either it beat us, or we just robbed it
this . setParameter ( "oolite_lastPirateVictim" , target ) ;
2013-08-01 22:40:23 +01:00
/ * }
else
{
log ( this . ship . displayName , "Already asked for " + demand ) ; * /
}
var handlers = { } ;
this . responsesAddStandard ( handlers ) ;
this . applyHandlers ( handlers ) ;
this . ship . performAttack ( ) ;
this . ship . requestHelpFromGroup ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-21 11:10:47 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourSunskim = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var handlers = { } ;
this . responsesAddStandard ( handlers ) ;
this . responsesAddScooping ( handlers ) ;
this . applyHandlers ( handlers ) ;
this . ship . performFlyToRangeFromDestination ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-21 23:25:41 +01:00
2013-07-23 21:21:49 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourTumble = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
this . applyHandlers ( { } ) ;
this . ship . performTumble ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-27 12:29:59 +01:00
/* Missile behaviours: have different standard handler sets */
2013-07-26 18:52:11 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourMissileInterceptTarget = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var handlers = { } ;
this . responsesAddMissile ( handlers ) ;
this . applyHandlers ( handlers ) ;
if ( this . ship . scriptInfo . oolite _missile _proximity )
{
this . ship . desiredRange = this . ship . scriptInfo . oolite _missile _proximity ;
}
else
{
this . ship . desiredRange = 25 ;
}
2013-07-27 12:29:59 +01:00
2013-08-01 22:40:23 +01:00
this . ship . performIntercept ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-23 21:21:49 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourMissileInterceptCoordinates = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var handlers = { } ;
this . responsesAddMissile ( handlers ) ;
this . applyHandlers ( handlers ) ;
if ( this . ship . scriptInfo . oolite _missile _proximity )
{
this . ship . desiredRange = this . ship . scriptInfo . oolite _missile _proximity ;
}
else
{
this . ship . desiredRange = 25 ;
}
var dest = this . getParameter ( "oolite_interceptCoordinates" ) ;
if ( dest == null )
{
return ;
}
this . ship . destination = dest
this . ship . desiredSpeed = this . ship . maxSpeed ;
this . ship . performFlyToRangeFromDestination ( ) ;
// if we have an intercept target, try to restore it
var oldtarget = this . getParameter ( "oolite_interceptTarget" ) ;
if ( oldtarget && ! oldtarget . isCloaked && oldtarget . isInSpace )
{
this . ship . target = oldtarget ;
}
2013-07-27 12:29:59 +01:00
}
2013-07-26 18:52:11 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourMissileSelfDestruct = function ( ) {
2013-08-01 22:40:23 +01:00
this . ship . explode ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-27 12:29:59 +01:00
/* Station behaviours: have different standard handler sets */
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourStationLaunchDefenseShips = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-31 18:07:17 +01:00
if ( system . sun && ( system . sun . isGoingNova || system . sun . hasGoneNova ) )
2013-08-27 22:08:35 +01:00
{
return ;
}
2013-08-01 22:40:23 +01:00
if ( this . ship . target && this . isAggressive ( this . ship . target ) )
{
2013-09-01 19:25:45 +01:00
this . ship . alertCondition = 3 ;
2013-08-01 22:40:23 +01:00
this . ship . launchDefenseShip ( ) ;
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_launchDefenseShips" , this . ship . target , 3 ) ;
2013-08-01 22:40:23 +01:00
this . ship . requestHelpFromGroup ( ) ;
}
2013-09-01 19:25:45 +01:00
else if ( this . ship . alertCondition > 1 )
{
this . ship . alertCondition -- ;
}
2013-08-01 22:40:23 +01:00
var handlers = { } ;
this . responsesAddStation ( handlers ) ;
this . applyHandlers ( handlers ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-23 22:37:07 +01:00
2013-07-27 12:29:59 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourStationLaunchMiner = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-31 18:07:17 +01:00
if ( system . sun && ( system . sun . isGoingNova || system . sun . hasGoneNova ) )
2013-08-27 22:08:35 +01:00
{
return ;
}
2013-09-01 19:25:45 +01:00
if ( this . ship . alertCondition > 1 )
2013-08-01 22:40:23 +01:00
{
2013-09-01 19:25:45 +01:00
this . ship . alertCondition -- ;
2013-08-01 22:40:23 +01:00
}
var handlers = { } ;
this . responsesAddStation ( handlers ) ;
this . applyHandlers ( handlers ) ;
if ( this . ship . group )
{
for ( var i = 0 ; i < this . ship . group . ships . length ; i ++ )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( this . ship . group . ships [ i ] . primaryRole == "miner" )
{
// only one in flight at once
return ;
}
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_launchMiner" , this . ship . target , 3 ) ;
2013-08-01 22:40:23 +01:00
this . ship . launchMiner ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-23 22:37:07 +01:00
2013-07-26 18:52:11 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourStationLaunchPatrol = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-31 18:07:17 +01:00
if ( system . sun && ( system . sun . isGoingNova || system . sun . hasGoneNova ) )
2013-08-27 22:08:35 +01:00
{
return ;
}
2013-09-01 19:25:45 +01:00
if ( this . ship . alertCondition > 1 )
2013-08-01 22:40:23 +01:00
{
2013-09-01 19:25:45 +01:00
this . ship . alertCondition -- ;
2013-08-01 22:40:23 +01:00
}
var handlers = { } ;
this . responsesAddStation ( handlers ) ;
this . applyHandlers ( handlers ) ;
2013-07-23 21:21:49 +01:00
2013-08-01 22:40:23 +01:00
if ( this . ship . group )
{
for ( var i = 0 ; i < this . ship . group . ships . length ; i ++ )
2013-07-23 21:21:49 +01:00
{
2013-08-01 22:40:23 +01:00
if ( this . ship . group . ships [ i ] . primaryRole == this . getParameter ( "oolite_stationPatrolRole" ) )
{
// only one in flight at once
return ;
}
2013-07-23 21:21:49 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_launchPatrol" , this . ship . target , 3 ) ;
2013-08-01 22:40:23 +01:00
this . ship . launchPatrol ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-24 21:56:50 +01:00
2013-07-27 12:29:59 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourStationLaunchSalvager = function ( )
2013-07-27 12:29:59 +01:00
{
2013-08-31 18:07:17 +01:00
if ( system . sun && ( system . sun . isGoingNova || system . sun . hasGoneNova ) )
2013-08-27 22:08:35 +01:00
{
return ;
}
2013-09-01 19:25:45 +01:00
if ( this . ship . alertCondition > 1 )
2013-08-01 22:40:23 +01:00
{
2013-09-01 19:25:45 +01:00
this . ship . alertCondition -- ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_launchSalvager" , this . ship . target , 3 ) ;
2013-08-01 22:40:23 +01:00
this . ship . launchScavenger ( ) ;
var handlers = { } ;
this . responsesAddStation ( handlers ) ;
this . applyHandlers ( handlers ) ;
2013-07-27 12:29:59 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourStationManageTraffic = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var handlers = { } ;
this . responsesAddStation ( handlers ) ;
this . applyHandlers ( handlers ) ;
2013-08-11 22:56:53 +01:00
// does nothing special in this state, just waits around being a station
2013-07-26 18:52:11 +01:00
}
2013-07-24 21:56:50 +01:00
2013-07-26 18:52:11 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . behaviourStationRespondToDistressCall = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-31 18:07:17 +01:00
if ( system . sun && ( system . sun . isGoingNova || system . sun . hasGoneNova ) )
2013-08-27 22:08:35 +01:00
{
return ;
}
2013-08-01 22:40:23 +01:00
var aggressor = this . getParameter ( "oolite_distressAggressor" ) ;
var sender = this . getParameter ( "oolite_distressSender" ) ;
if ( sender . bounty > aggressor . bounty )
{
var tmp = sender ;
sender = aggressor ;
aggressor = tmp ;
}
2013-08-07 16:29:24 +01:00
if ( this . distance ( aggressor ) < this . scannerRange )
2013-08-01 22:40:23 +01:00
{
this . ship . target = aggressor ;
this . ship . alertCondition = 3 ;
this . ship . launchDefenseShip ( ) ;
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_distressResponseAggressor" , aggressor , 2 ) ;
2013-08-01 22:40:23 +01:00
this . ship . requestHelpFromGroup ( ) ;
}
else
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_distressResponseSender" , sender , 3 ) ;
2013-08-01 22:40:23 +01:00
}
2013-07-26 18:52:11 +01:00
2013-08-01 22:40:23 +01:00
var handlers = { } ;
this . responsesAddStation ( handlers ) ;
this . applyHandlers ( handlers ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-24 21:56:50 +01:00
2013-07-23 21:21:49 +01:00
2013-07-26 18:52:11 +01:00
/* ****************** Configuration functions ************** */
2013-07-12 19:44:14 +01:00
2013-07-26 18:52:11 +01:00
/ * C o n f i g u r a t i o n s . C o n f i g u r a t i o n s a r e s e t u p a c t i o n s f o r a b e h a v i o u r
* or behaviours . They can also be used on a fall - through conditional
* to set parameters for later tests * /
2013-07-12 19:44:14 +01:00
2013-07-27 12:29:59 +01:00
/*** Target acquisition configuration ***/
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationAcquireCombatTarget = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-07 12:27:22 +01:00
var target = this . ship . target ;
if ( target && this . allied ( this . ship , target ) )
2013-08-01 22:40:23 +01:00
{
// don't shoot at allies even if they have ended up as a target...
2013-08-07 12:27:22 +01:00
this . ship . removeDefenseTarget ( target ) ;
2013-08-01 22:40:23 +01:00
this . ship . target = null ;
}
2013-08-07 12:27:22 +01:00
if ( target && target . scanClass == "CLASS_CARGO" )
2013-08-01 22:40:23 +01:00
{
this . ship . target = null ;
}
/ * I f f t h e s h i p d o e s n o t c u r r e n t l y h a v e a t a r g e t , s e l e c t a n e w o n e
* from the defense target list . * /
2013-08-07 12:27:22 +01:00
if ( target )
2013-08-01 22:40:23 +01:00
{
2013-08-07 12:27:22 +01:00
if ( target . isInSpace )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return ;
2013-07-26 18:52:11 +01:00
}
2013-08-07 12:27:22 +01:00
this . ship . removeDefenseTarget ( target ) ;
2013-08-01 22:40:23 +01:00
this . ship . target = null ;
}
var dts = this . ship . defenseTargets
2013-08-07 12:27:22 +01:00
var dtsl = dts . length ; // we need to iterate up this time
2013-08-07 16:29:24 +01:00
var scan = this . scannerRange ;
2013-08-07 12:27:22 +01:00
for ( var i = 0 ; i < dtsl ; i ++ )
2013-08-01 22:40:23 +01:00
{
2013-08-07 16:29:24 +01:00
if ( this . distance ( dts [ i ] ) < scan )
2013-07-26 18:52:11 +01:00
{
2013-08-07 16:29:24 +01:00
if ( ! dts [ i ] . isCloaked )
{
this . ship . target = dts [ i ] ;
return ;
}
2013-07-26 18:52:11 +01:00
}
2013-08-07 12:27:22 +01:00
else
{
this . ship . removeDefenseTarget ( dts [ i ] ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
if ( this . ship . group != null )
{
2013-08-07 12:27:22 +01:00
var gs = this . ship . group . ships ;
for ( var i = gs . length - 1 ; i >= 0 ; i -- )
2013-07-26 18:52:11 +01:00
{
2013-08-07 12:27:22 +01:00
if ( gs [ i ] != this . ship )
2013-08-01 22:40:23 +01:00
{
2013-08-19 21:05:56 +01:00
if ( this . isFighting ( gs [ i ] ) && this . distance ( gs [ i ] . target ) < scan && gs [ i ] . target . isShip )
2013-07-13 11:36:28 +01:00
{
2013-08-07 12:27:22 +01:00
this . ship . target = gs [ i ] . target ;
2013-08-01 22:40:23 +01:00
return ;
2013-07-13 11:36:28 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
if ( this . ship . escortGroup != null )
{
2013-08-07 12:27:22 +01:00
var gs = this . ship . escortGroup . ships ;
for ( var i = gs . length - 1 ; i >= 0 ; i -- )
2013-07-26 18:52:11 +01:00
{
2013-08-07 12:27:22 +01:00
if ( gs [ i ] != this . ship )
2013-08-01 22:40:23 +01:00
{
2013-08-19 21:05:56 +01:00
if ( this . isFighting ( gs [ i ] ) && this . distance ( gs [ i ] . target ) < scan && gs [ i ] . target . isShip )
2013-07-13 11:36:28 +01:00
{
2013-08-07 12:27:22 +01:00
this . ship . target = gs [ i ] . target ;
2013-08-01 22:40:23 +01:00
return ;
2013-07-12 19:44:14 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-12 19:44:14 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-26 18:52:11 +01:00
}
2013-07-12 19:44:14 +01:00
2013-07-27 12:29:59 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationAcquireDefensiveEscortTarget = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-23 20:01:38 +01:00
if ( this . ship . target && this . allied ( this . ship , this . ship . target ) )
{
// don't shoot at allies even if they have ended up as a target...
this . ship . removeDefenseTarget ( this . ship . target ) ;
this . ship . target = null ;
}
/ * P r e s e r v e c u r r e n t t a r g e t i f s t i l l f i g h t i n g ( l e a d e r c a n s e n d h e l p
* request if needed ) * /
if ( this . ship . target )
{
if ( this . ship . target . isInSpace && this . isAggressive ( this . ship . target ) )
{
return ;
}
this . ship . removeDefenseTarget ( this . ship . target ) ;
this . ship . target = null ;
}
2013-08-01 22:40:23 +01:00
if ( this . ship . group && this . ship . group . leader )
{
var leader = this . ship . group . leader ;
2013-08-07 16:29:24 +01:00
if ( this . isFighting ( leader ) && leader . target . target == leader && this . distance ( leader . target ) < this . scannerRange )
2013-07-27 12:29:59 +01:00
{
2013-08-01 22:40:23 +01:00
this . ship . target = leader . target ;
}
else
{
var dts = leader . defenseTargets ;
for ( var i = 0 ; i < dts . length ; i ++ )
{
2013-08-07 16:29:24 +01:00
if ( dts [ i ] . target == leader && this . isAggressive ( dts [ i ] ) && this . distance ( dts [ i ] ) < this . scannerRange )
2013-07-27 12:29:59 +01:00
{
2013-08-07 16:29:24 +01:00
if ( ! dts [ i ] . isCloaked )
{
this . ship . target = dts [ i ] ;
}
2013-07-27 12:29:59 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-27 12:29:59 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-27 12:29:59 +01:00
}
// TODO: reuse code from AcquireCombatTarget better
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationAcquireHostileCombatTarget = function ( )
2013-07-27 12:29:59 +01:00
{
2013-08-01 22:40:23 +01:00
if ( this . ship . target && this . allied ( this . ship , this . ship . target ) )
{
// don't shoot at allies even if they have ended up as a target...
this . ship . removeDefenseTarget ( this . ship . target ) ;
this . ship . target = null ;
}
/ * I f f t h e s h i p d o e s n o t c u r r e n t l y h a v e a t a r g e t , s e l e c t a n e w o n e
* from the defense target list . * /
if ( this . ship . target )
{
if ( this . ship . target . isInSpace && this . isAggressive ( this . ship . target ) )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
return ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
this . ship . removeDefenseTarget ( this . ship . target ) ;
this . ship . target = null ;
}
var dts = this . ship . defenseTargets
for ( var i = 0 ; i < dts . length ; i ++ )
{
2013-08-07 16:29:24 +01:00
if ( this . distance ( dts [ i ] ) < this . scannerRange && this . isAggressive ( dts [ i ] ) )
2013-07-26 18:52:11 +01:00
{
2013-08-07 16:29:24 +01:00
if ( ! dts [ i ] . isCloaked )
{
this . ship . target = dts [ 0 ] ;
return ;
}
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
if ( this . ship . group != null )
{
2013-08-07 16:29:24 +01:00
var gs = this . ship . group . ships ;
for ( var i = gs . length - 1 ; i >= 0 ; i -- )
2013-07-26 18:52:11 +01:00
{
2013-08-07 16:29:24 +01:00
if ( gs [ i ] != this . ship )
2013-08-01 22:40:23 +01:00
{
2013-08-07 16:29:24 +01:00
if ( this . isFighting ( gs [ i ] ) && this . distance ( gs [ i ] . target ) < this . scannerRange && this . isAggressive ( gs [ i ] . target ) )
2013-07-15 23:14:47 +01:00
{
2013-08-07 16:29:24 +01:00
this . ship . target = gs [ i ] . target ;
2013-08-01 22:40:23 +01:00
return ;
2013-07-15 23:14:47 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
if ( this . ship . escortGroup != null )
{
2013-08-07 16:29:24 +01:00
var gs = this . ship . escortGroup . ships ;
for ( var i = gs . length - 1 ; i >= 0 ; i -- )
2013-07-26 18:52:11 +01:00
{
2013-08-07 16:29:24 +01:00
if ( gs [ i ] != this . ship )
2013-08-01 22:40:23 +01:00
{
2013-08-07 16:29:24 +01:00
if ( this . isFighting ( gs [ i ] ) && this . distance ( gs [ i ] . target ) < this . scannerRange && this . isAggressive ( gs [ i ] . target ) )
2013-07-15 23:14:47 +01:00
{
2013-08-07 16:29:24 +01:00
this . ship . target = gs [ i ] . target ;
2013-08-01 22:40:23 +01:00
return ;
2013-07-15 23:14:47 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-15 23:14:47 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-26 18:52:11 +01:00
}
2013-07-15 23:14:47 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationAcquireOffensiveEscortTarget = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-23 20:01:38 +01:00
if ( this . ship . target && this . allied ( this . ship , this . ship . target ) )
{
// don't shoot at allies even if they have ended up as a target...
this . ship . removeDefenseTarget ( this . ship . target ) ;
this . ship . target = null ;
}
/* Preserve current target if still fighting */
if ( this . ship . target )
{
if ( this . ship . target . isInSpace && this . isAggressive ( this . ship . target ) )
{
return ;
}
this . ship . removeDefenseTarget ( this . ship . target ) ;
this . ship . target = null ;
}
2013-08-07 16:29:24 +01:00
if ( this . ship . group && this . ship . group . leader )
{
var leader = this . ship . group . leader ;
var lt ;
if ( ( lt = leader . target ) && leader . hasHostileTarget )
2013-07-13 23:18:05 +01:00
{
2013-08-07 16:29:24 +01:00
if ( this . distance ( lt ) < this . scannerRange )
{
if ( ! lt . isCloaked )
{
this . ship . target = lt ;
this . ship . addDefenseTarget ( lt ) ;
}
}
2013-07-13 23:18:05 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-26 18:52:11 +01:00
}
2013-07-13 23:18:05 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationAcquirePlayerAsTarget = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
this . ship . target = player . ship ;
2013-07-26 18:52:11 +01:00
}
2013-07-13 23:18:05 +01:00
2013-07-25 20:09:53 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationAcquireScannedTarget = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
this . ship . target = this . getParameter ( "oolite_scanResultSpecific" ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-25 20:09:53 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationCheckScanner = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-04 12:29:44 +01:00
if ( this . getParameter ( "oolite_flag_scanIgnoresUnpowered" ) != null )
{
this . setParameter ( "oolite_scanResults" , this . ship . checkScanner ( true ) ) ;
}
else
{
this . setParameter ( "oolite_scanResults" , this . ship . checkScanner ( ) ) ;
}
2013-08-01 22:40:23 +01:00
this . setParameter ( "oolite_scanResultSpecific" , null ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-13 19:13:30 +01:00
2013-07-25 20:09:53 +01:00
2013-07-27 12:29:59 +01:00
/*** Navigation configuration ***/
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSelectPlanet = function ( )
2013-08-05 14:14:50 +01:00
{
var possibles = system . planets ;
this . setParameter ( "oolite_selectedPlanet" , possibles [ Math . floor ( Math . random ( ) * possibles . length ) ] ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSelectRandomTradeStation = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var stations = system . stations ;
var chosenStation = null ;
if ( this . ship . bounty == 0 )
{
if ( Math . random ( ) < 0.9 && this . friendlyStation ( system . mainStation ) )
2013-07-27 12:29:59 +01:00
{
2013-08-01 22:40:23 +01:00
this . setParameter ( "oolite_selectedStation" , system . mainStation ) ;
return ;
}
}
else if ( this . ship . bounty <= this . fineThreshold ( ) )
{
if ( Math . random ( ) < 0.5 && this . friendlyStation ( system . mainStation ) )
2013-07-27 12:29:59 +01:00
{
2013-08-01 22:40:23 +01:00
this . setParameter ( "oolite_selectedStation" , system . mainStation ) ;
return ;
2013-07-27 12:29:59 +01:00
}
2013-08-01 22:40:23 +01:00
}
var friendlies = 0 ;
2013-08-07 17:09:47 +01:00
for ( var i = stations . length - 1 ; i >= 0 ; i -- )
2013-08-01 22:40:23 +01:00
{
var station = stations [ i ] ;
if ( this . friendlyStation ( station ) )
2013-07-27 12:29:59 +01:00
{
2013-08-01 22:40:23 +01:00
friendlies ++ ;
// equivalent to filtering the list to only contain
// friendlies, then picking a random element.
if ( Math . random ( ) < 1 / friendlies )
{
chosenStation = station ;
}
2013-07-27 12:29:59 +01:00
}
2013-08-01 22:40:23 +01:00
}
this . setParameter ( "oolite_selectedStation" , chosenStation ) ;
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_selectedStation" , chosenStation , 4 ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-13 19:13:30 +01:00
2013-07-27 12:29:59 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSelectShuttleDestination = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var possibles = system . planets . concat ( system . stations ) ;
var destinations1 = [ ] ;
var destinations2 = [ ] ;
for ( var i = 0 ; i < possibles . length ; i ++ )
{
var possible = possibles [ i ] ;
// travel at least a little way
2013-08-07 16:29:24 +01:00
var distance = this . distance ( possible ) ;
2013-08-01 22:40:23 +01:00
if ( distance > possible . collisionRadius + 10000 )
2013-07-21 23:25:41 +01:00
{
2013-08-01 22:40:23 +01:00
// must be friendly destination and not moving too fast
if ( possible . isPlanet || this . friendlyStation ( possible ) || possible . maxSpeed > this . ship . maxSpeed / 5 )
{
if ( distance > system . mainPlanet . radius * 5 )
2013-07-21 23:25:41 +01:00
{
2013-08-01 22:40:23 +01:00
destinations2 . push ( possible ) ;
2013-07-21 23:25:41 +01:00
}
2013-08-01 22:40:23 +01:00
else
{
destinations1 . push ( possible ) ;
}
}
}
}
// no nearby destinations
if ( destinations1 . length == 0 )
{
destinations1 = destinations2 ;
}
// no destinations
if ( destinations1 . length == 0 )
{
return ;
}
var destination = destinations1 [ Math . floor ( Math . random ( ) * destinations1 . length ) ] ;
if ( destination . isPlanet )
{
this . setParameter ( "oolite_selectedPlanet" , destination ) ;
this . setParameter ( "oolite_selectedStation" , null ) ;
}
else
{
this . setParameter ( "oolite_selectedStation" , destination ) ;
this . setParameter ( "oolite_selectedPlanet" , null ) ;
}
2013-07-26 18:52:11 +01:00
}
2013-07-27 12:29:59 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSelectWitchspaceDestination = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( ! this . ship . hasHyperspaceMotor )
{
this . setParameter ( "oolite_witchspaceDestination" , null ) ;
return ;
}
var preselected = this . getParameter ( "oolite_witchspaceDestination" ) ;
if ( preselected != system . ID && system . info . distanceToSystem ( System . infoForSystem ( galaxyNumber , preselected ) ) <= this . ship . fuel )
{
// we've already got a destination
return ;
}
var possible = system . info . systemsInRange ( this . ship . fuel ) ;
2013-08-09 13:09:54 +01:00
if ( possible . length > 0 )
{
var selected = possible [ Math . floor ( Math . random ( ) * possible . length ) ] ;
this . setParameter ( "oolite_witchspaceDestination" , selected . systemID ) ;
this . communicate ( "oolite_selectedWitchspaceDestination" , { "oolite_witchspaceDestination" : selected . name } , 4 ) ;
}
else
{
this . setParameter ( "oolite_witchspaceDestination" , null ) ;
}
2013-07-27 12:29:59 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSelectWitchspaceDestinationInbound = function ( )
2013-08-08 16:00:20 +01:00
{
2013-08-09 13:09:54 +01:00
if ( this . ship . homeSystem == this . ship . destinationSystem )
{
return this . configurationSelectWitchspaceDestination ( ) ;
}
this . setWitchspaceRouteTo ( this . ship . homeSystem ) ;
2013-08-08 16:00:20 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSelectWitchspaceDestinationOutbound = function ( )
2013-08-08 16:00:20 +01:00
{
2013-08-09 13:09:54 +01:00
if ( this . ship . homeSystem == this . ship . destinationSystem )
{
return this . configurationSelectWitchspaceDestination ( ) ;
}
this . setWitchspaceRouteTo ( this . ship . destinationSystem ) ;
2013-08-08 16:00:20 +01:00
}
2013-07-27 12:29:59 +01:00
/*** Destination configuration ***/
2013-08-17 13:26:37 +01:00
2013-09-13 18:54:14 +01:00
PriorityAIController . prototype . configurationMissileAdjustSpread = function ( )
{
var near = this . getParameter ( "oolite_scanResultSpecific" ) ;
if ( ! near )
{
this . ship . destination = this . ship . target . position ;
this . ship . desiredRange = 100 ;
this . ship . desiredSpeed = this . ship . maxFlightSpeed ;
}
else
{
this . ship . destination = near . position . add ( Vector3D . randomDirection ( 20 ) ) ;
this . ship . desiredRange = 1000 ;
this . ship . desiredSpeed = this . ship . maxFlightSpeed ;
}
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSetDestinationToHomeStation = function ( )
2013-08-17 13:26:37 +01:00
{
var home = this . homeStation ( ) ;
if ( home != null )
{
this . ship . destination = home . position ;
this . ship . desiredRange = 15000 ;
this . ship . desiredSpeed = this . cruiseSpeed ( ) ;
}
else
{
this . ship . destination = this . ship . position ;
this . ship . desiredRange = 0 ;
}
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSetDestinationToGroupLeader = function ( )
2013-08-17 13:26:37 +01:00
{
if ( ! this . ship . group || ! this . ship . group . leader )
{
this . ship . destination = this . ship . position ;
}
else
{
this . ship . destination = this . ship . group . leader . position ;
}
this . ship . desiredRange = 2000 ;
this . ship . desiredSpeed = this . ship . maxSpeed ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSetDestinationToMainPlanet = function ( )
2013-08-17 13:26:37 +01:00
{
if ( system . mainPlanet )
{
this . ship . destination = system . mainPlanet . position ;
this . ship . desiredRange = system . mainPlanet . radius * 3 ;
this . ship . desiredSpeed = this . cruiseSpeed ( ) ;
}
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSetDestinationToMainStation = function ( )
2013-08-17 13:26:37 +01:00
{
this . ship . destination = system . mainStation . position ;
this . ship . desiredRange = 15000 ;
this . ship . desiredSpeed = this . cruiseSpeed ( ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSetDestinationToNearestFriendlyStation = function ( )
2013-07-27 12:29:59 +01:00
{
2013-08-01 22:40:23 +01:00
var stations = system . stations ;
var threshold = 1E16 ;
var chosenStation = null ;
for ( var i = 0 ; i < stations . length ; i ++ )
{
var station = stations [ i ] ;
if ( this . friendlyStation ( station ) )
{
2013-08-07 16:29:24 +01:00
var distance = this . distance ( station ) ;
2013-08-01 22:40:23 +01:00
if ( distance < threshold )
{
threshold = distance ;
chosenStation = station ;
}
}
}
if ( chosenStation == null )
{
this . ship . destination = this . ship . position ;
this . ship . desiredRange = 0 ;
}
else
{
this . ship . destination = chosenStation . position ;
this . ship . desiredRange = 15000 ;
2013-08-16 21:44:27 +01:00
this . ship . desiredSpeed = this . cruiseSpeed ( ) ;
}
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSetDestinationToNearestHostileStation = function ( )
2013-08-16 21:44:27 +01:00
{
var stations = system . stations ;
var threshold = 1E16 ;
var chosenStation = null ;
for ( var i = 0 ; i < stations . length ; i ++ )
{
var station = stations [ i ] ;
if ( this . hostileStation ( station ) )
{
var distance = this . distance ( station ) ;
if ( distance < threshold )
{
threshold = distance ;
chosenStation = station ;
}
}
}
if ( chosenStation == null )
{
this . ship . destination = this . ship . position ;
this . ship . desiredRange = 0 ;
}
else
{
this . ship . destination = chosenStation . position ;
this . ship . desiredRange = 15000 ;
2013-08-01 22:40:23 +01:00
this . ship . desiredSpeed = this . cruiseSpeed ( ) ;
}
2013-07-26 18:52:11 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSetDestinationToNearestStation = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-17 15:19:25 +01:00
if ( this . _ _ltcache . oolite _nearestStation )
2013-08-01 22:40:23 +01:00
{
2013-08-17 15:19:25 +01:00
this . ship . destination = this . _ _ltcache . oolite _nearestStation . position ;
2013-08-01 22:40:23 +01:00
this . ship . desiredRange = 15000 ;
this . ship . desiredSpeed = this . cruiseSpeed ( ) ;
}
else
{
this . ship . destination = this . ship . position ;
this . ship . desiredRange = 0 ;
}
2013-07-26 18:52:11 +01:00
}
2013-08-31 18:07:17 +01:00
PriorityAIController . prototype . configurationSetDestinationToNearestWormhole = function ( )
{
var dist = 1E16 ;
var holes = system . wormholes ;
this . ship . desiredRange = 0 ;
this . ship . desiredSpeed = this . ship . maxSpeed ;
for ( var i = holes . length - 1 ; i >= 0 ; i -- )
{
var hole = holes [ i ] ;
var hdist = this . distance ( hole ) ;
if ( hole . expiryTime > clock . adjustedSeconds && hdist < dist )
{
this . ship . destination = hole . position ;
dist = hdist ;
}
}
if ( dist >= 1E15 )
{
this . ship . destination = this . ship . position ;
this . ship . desiredRange = 1000 ;
}
}
2013-07-26 18:52:11 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSetDestinationToPirateLurk = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var lurk = this . getParameter ( "oolite_pirateLurk" ) ;
if ( lurk != null )
{
this . ship . destination = lurk ;
}
else
{
2013-08-11 20:51:46 +01:00
if ( this . distance ( system . sun ) > system . sun . radius * 3 && this . distance ( system . mainPlanet ) > system . mainPlanet . radius * 3 )
2013-07-14 19:02:16 +01:00
{
2013-08-11 20:51:46 +01:00
var p = this . ship . position ;
// if already on a lane, stay on it
if ( p . z < ( system . mainPlanet . position . z - system . mainPlanet . radius * 2 ) && ( ( p . x * p . x ) + ( p . y * p . y ) ) < this . scannerRange * this . scannerRange * 4 )
{
lurk = p ;
}
else if ( p . subtract ( system . mainPlanet ) . direction ( ) . dot ( p . subtract ( system . sun ) . direction ( ) ) < - 0.9 )
{
lurk = p ;
}
else if ( p . direction ( ) . dot ( system . sun . position . direction ( ) ) > 0.9 )
{
lurk = p ;
}
2013-08-01 22:40:23 +01:00
}
2013-08-11 20:51:46 +01:00
if ( lurk == null )
2013-08-01 22:40:23 +01:00
{
2013-08-11 20:51:46 +01:00
// not on a lane, or too close to a sun/planet
var code ;
2013-08-01 22:40:23 +01:00
var choice = Math . random ( ) ;
2013-08-11 20:51:46 +01:00
if ( choice < 0.7 )
2013-08-01 22:40:23 +01:00
{
code = "LANE_WP" ;
}
2013-08-11 20:51:46 +01:00
else if ( choice < 0.8 )
2013-08-01 22:40:23 +01:00
{
code = "LANE_PS" ;
}
2013-08-11 20:51:46 +01:00
else if ( choice < 0.9 )
{
code = "LANE_WS" ;
}
else
{
code = "WITCHPOINT" ;
}
2013-08-01 22:40:23 +01:00
lurk = system . locationFromCode ( code ) ;
}
this . setParameter ( "oolite_pirateLurk" , lurk ) ;
}
this . ship . desiredRange = 1000 ;
this . ship . desiredSpeed = this . cruiseSpeed ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-15 23:14:47 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSetDestinationToSelectedPlanet = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var planet = this . getParameter ( "oolite_selectedPlanet" ) ;
if ( planet )
{
this . ship . destination = planet . position ;
this . ship . desiredRange = planet . radius + 100 ;
this . ship . desiredSpeed = this . cruiseSpeed ( ) ;
}
2013-07-26 18:52:11 +01:00
}
2013-07-14 19:02:16 +01:00
2013-07-26 18:52:11 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSetDestinationToSelectedStation = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var station = this . getParameter ( "oolite_selectedStation" ) ;
if ( station )
{
this . ship . destination = station . position ;
this . ship . desiredRange = 15000 ;
this . ship . desiredSpeed = this . cruiseSpeed ( ) ;
}
2013-07-26 18:52:11 +01:00
}
2013-07-13 23:18:05 +01:00
2013-07-22 21:24:27 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSetDestinationToSunskimEnd = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( system . sun )
{
var direction = Vector3D . random ( ) . cross ( this . ship . position . subtract ( system . sun . position ) ) ;
// 2km parallel to local sun surface for every LY of fuel
this . ship . destination = this . ship . position . add ( direction . multiply ( 2000 * ( 7 - this . ship . fuel ) ) ) ;
// max sunskim height is sqrt(4/3) radius
this . ship . desiredRange = 0 ;
this . ship . desiredSpeed = this . ship . maxSpeed ;
}
2013-07-26 18:52:11 +01:00
}
2013-07-22 21:24:27 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSetDestinationToSunskimStart = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( system . sun )
{
this . ship . destination = system . sun . position ;
// max sunskim height is sqrt(4/3) radius
this . ship . desiredRange = system . sun . radius * 1.125 ;
this . ship . desiredSpeed = this . cruiseSpeed ( ) ;
}
2013-07-26 18:52:11 +01:00
}
2013-07-13 19:13:30 +01:00
2013-07-27 12:29:59 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSetDestinationToWaypoint = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( this . getParameter ( "oolite_waypoint" ) != null && this . getParameter ( "oolite_waypointRange" ) != null )
{
this . ship . destination = this . getParameter ( "oolite_waypoint" ) ;
this . ship . desiredRange = this . getParameter ( "oolite_waypointRange" ) ;
this . ship . desiredSpeed = this . cruiseSpeed ( ) ;
}
2013-07-26 18:52:11 +01:00
}
2013-07-27 12:29:59 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSetDestinationToWitchpoint = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
this . ship . destination = new Vector3D ( 0 , 0 , 0 ) ;
this . ship . desiredRange = 10000 ;
this . ship . desiredSpeed = this . cruiseSpeed ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-13 19:13:30 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSetWaypoint = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var gen = this . getWaypointGenerator ( ) ;
if ( gen != null )
{
gen . call ( this ) ;
this . configurationSetDestinationToWaypoint ( ) ;
}
2013-07-26 18:52:11 +01:00
}
2013-07-12 19:44:14 +01:00
2013-07-27 12:29:59 +01:00
/*** Docking configurations ***/
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSetNearbyFriendlyStationForDocking = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-17 15:19:25 +01:00
if ( this . friendlyStation ( this . _ _ltcache . oolite _nearestStation ) )
2013-08-01 22:40:23 +01:00
{
2013-08-17 15:19:25 +01:00
if ( this . distance ( this . _ _ltcache . oolite _nearestStation ) < this . scannerRange )
2013-08-01 22:40:23 +01:00
{
2013-08-17 15:19:25 +01:00
this . setParameter ( "oolite_dockingStation" , this . _ _ltcache . oolite _nearestStation )
2013-08-17 13:26:37 +01:00
return ;
2013-07-13 23:18:05 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-26 18:52:11 +01:00
}
2013-07-13 23:18:05 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSetHomeStationForDocking = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-07 16:29:24 +01:00
var station = this . homeStation ( ) ;
if ( station )
2013-08-01 22:40:23 +01:00
{
2013-08-07 16:29:24 +01:00
this . setParameter ( "oolite_dockingStation" , station )
2013-08-01 22:40:23 +01:00
return ;
}
2013-07-26 18:52:11 +01:00
}
2013-07-22 21:24:27 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSetSelectedStationForDocking = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
this . setParameter ( "oolite_dockingStation" , this . getParameter ( "oolite_selectedStation" ) ) ;
2013-07-26 18:52:11 +01:00
}
2013-07-14 19:02:16 +01:00
2013-07-27 12:29:59 +01:00
/*** Miscellaneous configuration ***/
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationAppointGroupLeader = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( this . ship . group && ! this . ship . group . leader )
{
this . ship . group . leader = this . ship . group . ships [ 0 ] ;
for ( var i = 0 ; i < this . ship . group . ships . length ; i ++ )
2013-07-14 23:11:25 +01:00
{
2013-08-01 22:40:23 +01:00
if ( this . ship . group . ships [ i ] . hasHyperspaceMotor )
{
// bias towards jump-capable ships
this . ship . group . leader = this . ship . group . ships [ i ] ;
break ;
}
}
var leadrole = this . getParameter ( "oolite_leaderRole" )
if ( leadrole != null )
{
this . ship . group . leader . primaryRole = leadrole ;
2013-07-14 23:11:25 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-26 18:52:11 +01:00
}
2013-07-14 23:11:25 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationEscortGroupLeader = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( ! this . ship . group || ! this . ship . group . leader || this . ship . group . leader == this . ship )
{
return ;
}
if ( this . ship . group . leader . escortGroup && this . ship . group . leader . escortGroup . containsShip ( this . ship ) )
{
return ;
}
var escrole = this . getParameter ( "oolite_escortRole" )
if ( escrole != null )
{
var oldrole = this . ship . primaryRole ;
this . ship . primaryRole = escrole ;
var accepted = this . ship . offerToEscort ( this . ship . group . leader ) ;
if ( ! accepted )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
this . ship . primaryRole = oldrole ;
2013-07-18 23:00:23 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-26 18:52:11 +01:00
}
2013-07-18 23:00:23 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationForgetCargoDemand = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
/ * i f ( t h i s . s h i p . g r o u p & & t h i s . s h i p . g r o u p . l e a d e r & & t h i s . s h i p . g r o u p . l e a d e r . A I S c r i p t . o o l i t e _ i n t e r s h i p . c a r g o d e m a n d e d )
{
delete this . ship . group . leader . AIScript . oolite _intership . cargodemanded ;
} * / / / not sure about this , maybe not needed
2013-07-15 23:14:47 +01:00
2013-08-01 22:40:23 +01:00
if ( this . ship . AIScript . oolite _intership . cargodemanded )
{
delete this . ship . AIScript . oolite _intership . cargodemanded ;
delete this . ship . AIScript . oolite _intership . cargodemandmet ;
// and make the group lose the cargo count from the last demand
if ( this . ship . group )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
for ( var i = 0 ; i < this . ship . group . ships . length ; i ++ )
{
var ship = this . ship . group . ships [ i ] ;
if ( ship . AIScript && ship . AIScript . oolite _priorityai )
2013-07-15 23:14:47 +01:00
{
2013-08-01 22:40:23 +01:00
ship . AIScript . oolite _priorityai . setParameter ( "oolite_cargoDropped" , 0 ) ;
2013-07-15 23:14:47 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-15 23:14:47 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-26 18:52:11 +01:00
}
2013-07-15 23:14:47 +01:00
2013-07-27 15:39:23 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationLeaveEscortGroup = function ( )
2013-07-27 15:39:23 +01:00
{
2013-08-01 22:40:23 +01:00
if ( this . ship . group && this . ship . group . leader && this . ship . group . leader != this . ship && this . ship . group . leader . escortGroup && this . ship . group . leader . escortGroup . containsShip ( this . ship ) )
{
this . ship . group . leader . escortGroup . removeShip ( this . ship ) ;
if ( this . ship . group )
2013-07-27 15:39:23 +01:00
{
2013-08-01 22:40:23 +01:00
this . ship . group . removeShip ( this . ship ) ;
this . ship . group = null ;
2013-07-27 15:39:23 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-27 15:39:23 +01:00
}
2013-08-27 22:08:35 +01:00
// remote controlled ships get same accuracy as lead ship
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationSetRemoteControl = function ( )
2013-08-27 22:08:35 +01:00
{
var group = this . ship . group ;
if ( group && group . leader )
{
this . ship . accuracy = group . leader . accuracy ;
}
}
2013-07-27 12:29:59 +01:00
/*** Station configuration ***/
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationStationReduceAlertLevel = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( this . ship . alertCondition > 1 )
{
this . ship . alertCondition -- ;
}
2013-07-26 18:52:11 +01:00
}
2013-07-23 21:21:49 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . configurationStationValidateTarget = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
if ( this . ship . target )
{
2013-08-07 16:29:24 +01:00
if ( this . distance ( this . ship . target ) > this . scannerRange )
2013-07-23 21:21:49 +01:00
{
2013-08-01 22:40:23 +01:00
// station behaviour does not generally validate target
this . ship . target = null ;
2013-07-23 21:21:49 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-26 18:52:11 +01:00
}
2013-07-21 11:10:47 +01:00
2013-07-26 18:52:11 +01:00
/* ****************** Response definition functions ************** */
2013-07-12 19:44:14 +01:00
2013-07-26 18:52:11 +01:00
/ * S t a n d a r d s t a t e - m a c h i n e r e s p o n s e s . T h e s e s e t u p a s e t o f s t a n d a r d
* state machine responses where incoming events will cause reasonable
* default behaviour and often force a reconsideration of
* priorities . Many behaviours will need to supplement the standard
* responses with additional definitions . * /
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responsesAddStandard = function ( handlers )
2013-07-26 18:52:11 +01:00
{
2013-08-07 10:53:44 +01:00
handlers . approachingPlanetSurface = this . responseComponent _standard _approachingPlanetSurface ;
handlers . cargoDumpedNearby = this . responseComponent _standard _cargoDumpedNearby ;
handlers . cascadeWeaponDetected = this . responseComponent _standard _cascadeWeaponDetected ;
handlers . commsMessageReceived = this . responseComponent _standard _commsMessageReceived ;
handlers . distressMessageReceived = this . responseComponent _standard _distressMessageReceived ;
handlers . escortAccepted = this . responseComponent _standard _escortAccepted ;
handlers . helpRequestReceived = this . responseComponent _standard _helpRequestReceived ;
handlers . offenceCommittedNearby = this . responseComponent _standard _offenceCommittedNearby ;
handlers . shipAcceptedEscort = this . responseComponent _standard _shipAcceptedEscort ;
handlers . shipAttackedOther = this . responseComponent _standard _shipAttackedOther ;
handlers . shipAttackedWithMissile = this . responseComponent _standard _shipAttackedWithMissile ;
handlers . shipAttackerDistracted = this . responseComponent _standard _shipAttackerDistracted ;
handlers . shipBeingAttacked = this . responseComponent _standard _shipBeingAttacked ;
handlers . shipBeingAttackedUnsuccessfully = this . responseComponent _standard _shipBeingAttackedUnsuccessfully ;
handlers . shipFiredMissile = this . responseComponent _standard _shipFiredMissile ;
handlers . shipKilledOther = this . responseComponent _standard _shipKilledOther ;
handlers . shipLaunchedEscapePod = this . responseComponent _standard _shipLaunchedEscapePod ;
handlers . shipLaunchedFromStation = this . responseComponent _standard _shipLaunchedFromStation ;
handlers . shipWillEnterWormhole = this . responseComponent _standard _shipWillEnterWormhole ;
handlers . wormholeSuggested = this . responseComponent _standard _wormholeSuggested ;
2013-09-14 13:50:49 +01:00
// slightly different settings if pursuing to witchspace expected
if ( ! this . getParameter ( "oolite_flag_witchspacePursuit" ) )
{
handlers . shipTargetLost = this . responseComponent _standard _shipTargetLost ;
handlers . playerWillEnterWitchspace = this . responseComponent _standard _playerWillEnterWitchspace ;
}
else
{
handlers . playerWillEnterWitchspace = this . responseComponent _trackPlayer _playerWillEnterWitchspace ;
handlers . shipTargetLost = this . responseComponent _expectWitchspace _shipTargetLost ;
}
2013-08-07 10:53:44 +01:00
// TODO: more event handlers
}
/* Additional handlers for use while docking */
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responsesAddDocking = function ( handlers )
2013-08-07 10:53:44 +01:00
{
handlers . stationWithdrewDockingClearance = this . responseComponent _docking _stationWithdrewDockingClearance ;
handlers . shipAchievedDesiredRange = this . responseComponent _docking _shipAchievedDesiredRange ;
}
/* Override of standard handlers for use while escorting */
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responsesAddEscort = function ( handlers )
2013-08-07 10:53:44 +01:00
{
handlers . helpRequestReceived = this . responseComponent _escort _helpRequestReceived ;
handlers . escortDock = this . responseComponent _escort _escortDock ;
}
/* Additional handlers for scooping */
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responsesAddScooping = function ( handlers )
2013-08-07 10:53:44 +01:00
{
handlers . shipAchievedDesiredRange = this . responseComponent _scooping _shipAchievedDesiredRange
handlers . shipScoopedFuel = this . responseComponent _scooping _shipScoopedFuel ;
}
// shorter list than before
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responsesAddStation = function ( handlers )
2013-08-07 10:53:44 +01:00
{
handlers . cascadeWeaponDetected = this . responseComponent _station _cascadeWeaponDetected ;
handlers . commsMessageReceived = this . responseComponent _station _commsMessageReceived ;
handlers . distressMessageReceived = this . responseComponent _station _distressMessageReceived ;
handlers . helpRequestReceived = this . responseComponent _station _helpRequestReceived ;
handlers . offenceCommittedNearby = this . responseComponent _station _offenceCommittedNearby ;
handlers . shipAttackedOther = this . responseComponent _station _shipAttackedOther ;
handlers . shipAttackedWithMissile = this . responseComponent _station _shipAttackedWithMissile ;
handlers . shipBeingAttacked = this . responseComponent _station _shipBeingAttacked ;
handlers . shipFiredMissile = this . responseComponent _station _shipFiredMissile ;
handlers . shipKilledOther = this . responseComponent _station _shipKilledOther ;
handlers . shipTargetLost = this . responseComponent _station _shipTargetLost ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responsesAddMissile = function ( handlers ) {
2013-08-07 10:53:44 +01:00
handlers . commsMessageReceived = this . responseComponent _missile _commsMessageReceived ;
handlers . shipHitByECM = this . responseComponent _missile _shipHitByECM ;
handlers . shipTargetCloaked = this . responseComponent _missile _shipTargetCloaked ;
handlers . shipTargetLost = this . responseComponent _missile _shipTargetLost ;
handlers . shipAchievedDesiredRange = this . responseComponent _missile _shipAchievedDesiredRange ;
}
/* ******************* Response components *********************** */
/ * R e s p o n s e c o m p o n e n t s . T h e s e a r e s t a n d a r d r e s p o n s e c o m p o n e n t
* functions which can be passed by reference to save on variable
* destruction / creation * /
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _approachingPlanetSurface = function ( )
2013-08-07 10:53:44 +01:00
{
if ( this . getParameter ( "oolite_flag_allowPlanetaryLanding" ) )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
this . ship . desiredSpeed = this . ship . maxSpeed / 4 ;
this . ship . performLandOnPlanet ( ) ;
this . ship . AIScriptWakeTime = 0 ; // cancel reconsiderations
this . applyHandlers ( { } ) ; // cancel interruptions
this . communicate ( "oolite_landingOnPlanet" , { } , 4 ) ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
else
2013-08-01 22:40:23 +01:00
{
this . reconsiderNow ( ) ;
2013-08-07 10:53:44 +01:00
}
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _cargoDumpedNearby = function ( cargo , ship )
2013-08-07 10:53:44 +01:00
{
if ( this . getParameter ( "oolite_flag_watchForCargo" ) )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
var previously = this . getParameter ( "oolite_cargoDropped" ) ;
if ( previously == null )
2013-07-26 18:52:11 +01:00
{
2013-08-07 10:53:44 +01:00
previously = 0 ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
previously ++ ;
this . setParameter ( "oolite_cargoDropped" , previously ) ;
}
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _cascadeWeaponDetected = function ( weapon )
2013-08-07 10:53:44 +01:00
{
this . ship . clearDefenseTargets ( ) ;
this . ship . addDefenseTarget ( weapon ) ;
this . setParameter ( "oolite_cascadeDetected" , weapon . position ) ;
this . ship . target = weapon ;
this . ship . performFlee ( ) ;
this . reconsiderNow ( ) ;
}
2013-09-02 22:23:06 +01:00
PriorityAIController . prototype . responseComponent _standard _commsMessageReceived = function ( message , sender )
2013-08-07 10:53:44 +01:00
{
2013-09-02 22:23:06 +01:00
/ * I f t h e s e n d e r i s h o s t i l e t o u s , a n d w e ' r e n o t o b v i o u s l y i n
* combat , attack the sender : deals with pirate demand case * /
if ( sender . target == this . ship && ! this . ship . hasHostileTarget && sender . hasHostileTarget )
{
this . ship . target = sender ;
this . ship . performAttack ( ) ;
this . reconsiderNow ( ) ;
}
2013-08-07 10:53:44 +01:00
this . noteCommsHeard ( ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _distressMessageReceived = function ( aggressor , sender )
2013-08-07 10:53:44 +01:00
{
if ( this . getParameter ( "oolite_flag_listenForDistressCall" ) != true )
{
return ;
}
2013-08-30 21:14:55 +01:00
if ( this . ship . scanClass == "CLASS_POLICE" || ( this . ship . isStation && this . ship . allegiance == "galcop" ) )
{
if ( this . distance ( aggressor ) < this . scannerRange )
{
aggressor . bounty |= 8 ;
}
}
2013-08-07 10:53:44 +01:00
this . setParameter ( "oolite_distressAggressor" , aggressor ) ;
this . setParameter ( "oolite_distressSender" , sender ) ;
this . setParameter ( "oolite_distressTimestamp" , clock . adjustedSeconds ) ;
this . reconsiderNow ( ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _escortAccepted = function ( escort )
2013-08-07 10:53:44 +01:00
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_escortAccepted" , escort , 2 ) ;
2013-08-07 10:53:44 +01:00
}
// overridden for escorts
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _helpRequestReceived = function ( ally , enemy )
2013-08-07 10:53:44 +01:00
{
if ( this . allied ( this . ship , enemy ) )
{
return ;
}
this . ship . addDefenseTarget ( enemy ) ;
2013-08-07 16:29:24 +01:00
if ( enemy . scanClass == "CLASS_MISSILE" && this . distance ( enemy ) < this . scannerRange && this . ship . equipmentStatus ( "EQ_ECM" ) == "EQUIPMENT_OK" )
2013-08-07 10:53:44 +01:00
{
this . ship . fireECM ( ) ;
}
if ( enemy . scanClass == "CLASS_THARGOID" && this . ship . scanClass != "CLASS_THARGOID" && ( ! this . ship . target || this . ship . target . scanClass != "CLASS_THARGOID" ) )
{
if ( this . respondToThargoids ( enemy , false ) )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
this . reconsiderNow ( ) ;
2013-08-07 10:53:44 +01:00
return ; // not in a combat mode
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
}
2013-08-04 12:29:44 +01:00
2013-08-07 10:53:44 +01:00
if ( ! this . ship . hasHostileTarget )
{
this . reconsiderNow ( ) ;
return ; // not in a combat mode
}
if ( ally . energy / ally . maxEnergy < this . ship . energy / this . ship . maxEnergy )
2013-08-04 12:29:44 +01:00
{
2013-08-07 10:53:44 +01:00
// not in worse shape than ally
if ( this . ship . target . target != ally && this . ship . target != ally . target )
2013-08-04 12:29:44 +01:00
{
2013-08-07 10:53:44 +01:00
// not already helping, go for it...
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_startHelping" , enemy , 4 ) ;
2013-08-07 10:53:44 +01:00
this . ship . target = enemy ;
this . reconsiderNow ( ) ;
2013-08-04 12:29:44 +01:00
}
2013-08-07 10:53:44 +01:00
}
}
2013-08-04 12:29:44 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _offenceCommittedNearby = function ( attacker , victim )
2013-08-07 10:53:44 +01:00
{
2013-09-08 17:20:28 +01:00
if ( this . ship == victim ) return ; // other handlers can get this one
2013-08-07 10:53:44 +01:00
if ( this . getParameter ( "oolite_flag_markOffenders" ) )
2013-08-01 22:40:23 +01:00
{
2013-09-08 17:20:28 +01:00
if ( ! attacker . isPlayer && attacker . target != victim )
{
// ignore friendly fire if they were aiming at a pirate
if ( attacker . bounty == 0 && attacker . target && this . shipInRoleCategory ( attacker . target , "oolite-pirate" ) )
{
// but we might go after the pirate ourselves in a bit
this . ship . addDefenseTarget ( attacker . target ) ;
return ;
}
}
else if ( attacker . isPlayer && this . ignorePlayerFriendlyFire ( ) )
{
this . communicate ( "oolite_friendlyFire" , attacker , 3 ) ;
return ;
}
2013-08-07 16:40:03 +01:00
if ( attacker . bounty & 7 != 7 )
2013-08-04 12:29:44 +01:00
{
2013-08-07 16:40:03 +01:00
this . communicate ( "oolite_offenceDetected" , attacker , 3 ) ;
2013-08-04 12:29:44 +01:00
}
2013-08-01 22:40:23 +01:00
else
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_offenceDetected" , attacker , 4 ) ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
attacker . setBounty ( attacker . bounty | 7 , "seen by police" ) ;
this . ship . addDefenseTarget ( attacker ) ;
this . reconsiderNow ( ) ;
}
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _playerWillEnterWitchspace = function ( )
2013-08-07 10:53:44 +01:00
{
var wormhole = this . getParameter ( "oolite_witchspaceWormhole" ) ;
if ( wormhole != null && wormhole . isWormhole )
{
this . ship . enterWormhole ( wormhole ) ;
}
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _shipAcceptedEscort = function ( mother )
2013-08-07 10:53:44 +01:00
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_escortMotherAccepted" , mother , 2 ) ;
2013-08-07 10:53:44 +01:00
}
2013-08-04 12:29:44 +01:00
2013-08-07 10:53:44 +01:00
// not always applied
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _shipAchievedDesiredRange = function ( )
2013-08-07 10:53:44 +01:00
{
var waypoints = this . getParameter ( "oolite_waypoints" ) ;
if ( waypoints != null )
2013-08-04 12:29:44 +01:00
{
2013-08-07 10:53:44 +01:00
if ( waypoints . length > 0 )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
waypoints . pop ( ) ;
if ( waypoints . length == 0 )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
waypoints = null ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
this . setParameter ( "oolite_waypoints" , waypoints ) ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
}
else
{
var patrol = this . getParameter ( "oolite_waypoint" ) ;
if ( patrol != null && this . ship . destination . distanceTo ( patrol ) < 1000 + this . getParameter ( "oolite_waypointRange" ) )
2013-07-26 18:52:11 +01:00
{
2013-08-07 10:53:44 +01:00
// finished patrol to waypoint
// clear route
this . communicate ( "oolite_waypointReached" , { } , 3 ) ;
this . setParameter ( "oolite_waypoint" , null ) ;
this . setParameter ( "oolite_waypointRange" , null ) ;
if ( this . getParameter ( "oolite_flag_patrolStation" ) )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
if ( this . ship . group )
2013-07-12 23:00:39 +01:00
{
2013-08-07 10:53:44 +01:00
var station = this . ship . group . leader ;
if ( station != null && station . isStation )
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_patrolReportIn" , station , 4 ) ;
2013-08-07 10:53:44 +01:00
this . ship . patrolReportIn ( station ) ;
}
2013-07-13 11:36:28 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-26 18:52:11 +01:00
}
2013-08-07 10:53:44 +01:00
}
this . reconsiderNow ( ) ;
}
2013-08-01 22:40:23 +01:00
2013-08-07 10:53:44 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _shipAttackedOther = function ( other )
2013-08-07 10:53:44 +01:00
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_hitTarget" , other , 4 ) ;
2013-08-07 10:53:44 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _shipAttackedWithMissile = function ( missile , whom )
2013-08-07 10:53:44 +01:00
{
2013-08-30 21:14:55 +01:00
if ( this . getParameter ( "oolite_flag_sendsDistressCalls" ) )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
this . broadcastDistressMessage ( ) ;
}
if ( this . ship . equipmentStatus ( "EQ_ECM" ) == "EQUIPMENT_OK" )
{
this . ship . fireECM ( ) ;
this . ship . addDefenseTarget ( missile ) ;
this . ship . addDefenseTarget ( whom ) ;
// but don't reconsider immediately, because the ECM will
// probably get it
}
else
2013-08-01 22:40:23 +01:00
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_incomingMissile" , whom , 3 ) ;
2013-08-07 10:53:44 +01:00
this . ship . addDefenseTarget ( missile ) ;
this . ship . addDefenseTarget ( whom ) ;
2013-09-13 18:54:14 +01:00
if ( this . ship . target && this . ship . target . scanClass == "CLASS_MISSILE" )
{
// keep fleeing first missile
var tmp = this . ship . target ;
this . ship . target = missile ;
this . ship . requestHelpFromGroup ( ) ; // anyone got an ECM?
this . ship . target = tmp ;
}
else
{
this . ship . target = missile ;
this . ship . requestHelpFromGroup ( ) ; // anyone got an ECM?
}
2013-08-01 22:40:23 +01:00
this . reconsiderNow ( ) ;
2013-08-07 10:53:44 +01:00
}
}
2013-08-04 12:29:44 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _shipAttackerDistracted = function ( whom )
2013-08-07 10:53:44 +01:00
{
if ( this . ship . scanClass != "CLASS_THARGOID" && whom . scanClass == "CLASS_THARGOID" && ( ! this . ship . target || this . ship . target . scanClass != "CLASS_THARGOID" ) )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
// frying pan, fire
if ( this . respondToThargoids ( whom , false ) )
2013-08-04 12:29:44 +01:00
{
2013-08-07 10:53:44 +01:00
this . reconsiderNow ( ) ;
2013-08-04 12:29:44 +01:00
return ;
}
2013-08-07 10:53:44 +01:00
}
var last = this . getParameter ( "oolite_lastAssist" ) ;
if ( last != whom )
{
2013-08-17 14:39:16 +01:00
if ( whom . isPlayer )
{
this . communicate ( "oolite_thanksForHelp" , whom , 1 ) ;
}
else
{
this . communicate ( "oolite_thanksForHelp" , whom , 3 ) ;
}
2013-08-07 10:53:44 +01:00
if ( this . ship . scanClass == "CLASS_POLICE" )
2013-08-04 12:29:44 +01:00
{
2013-08-07 10:53:44 +01:00
if ( whom . scanClass != "CLASS_POLICE" && whom . scanClass != "CLASS_THARGOID" && whom . bounty > 0 )
2013-08-04 12:29:44 +01:00
{
2013-08-07 10:53:44 +01:00
whom . setBounty ( whom . bounty * 4 / 5 , "assisting police" ) ;
2013-08-04 12:29:44 +01:00
}
}
2013-08-07 10:53:44 +01:00
this . setParameter ( "oolite_lastAssist" , whom ) ;
}
this . reconsiderNow ( ) ;
}
2013-08-04 12:29:44 +01:00
2013-08-07 10:53:44 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _shipBeingAttacked = function ( whom )
2013-08-07 10:53:44 +01:00
{
2013-09-08 17:20:28 +01:00
if ( whom . target != this . ship )
2013-08-07 10:53:44 +01:00
{
2013-09-08 17:20:28 +01:00
if ( ! whom . isPlayer )
2013-07-26 18:52:11 +01:00
{
2013-09-08 17:20:28 +01:00
// was accidental
if ( this . allied ( whom , this . ship ) )
{
this . communicate ( "oolite_friendlyFire" , whom , 3 ) ;
// ignore it
return ;
}
if ( Math . random ( ) > 0.1 )
{
// usually ignore it anyway as we know they didn't mean to
return ;
}
2013-07-26 18:52:11 +01:00
}
2013-09-08 17:20:28 +01:00
// only ignore the player's friendly fire if already in combat
else if ( this . conditionInCombat ( ) && this . ignorePlayerFriendlyFire ( ) )
2013-07-26 18:52:11 +01:00
{
2013-09-11 18:29:08 +01:00
// send warning communication
this . communicate ( "oolite_friendlyFire" , whom , 2 ) ;
2013-08-07 10:53:44 +01:00
return ;
2013-08-01 22:40:23 +01:00
}
}
2013-09-08 17:20:28 +01:00
if ( this . getParameter ( "oolite_flag_markOffenders" ) )
{
if ( this . ship . scanClass == "CLASS_POLICE" )
{
whom . setBounty ( whom . bounty | 15 , "attacked police" ) ;
}
else if ( this . ship == system . mainStation )
{
whom . setBounty ( whom . bounty | 63 , "attacked main station" ) ;
}
}
2013-08-23 21:18:23 +01:00
if ( this . ship . target == this . getParameter ( "oolite_dockingStation" ) )
{
// don't get confused and shoot the station!
this . ship . target = null ;
}
2013-08-30 21:14:55 +01:00
if ( this . getParameter ( "oolite_flag_sendsDistressCalls" ) )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
this . broadcastDistressMessage ( ) ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
if ( this . ship . isFleeing )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
this . communicate ( "oolite_surrender" , { } , 3 ) ;
}
if ( ( whom . scanClass == "CLASS_THARGOID" ) && ( this . ship . scanClass != "CLASS_THARGOID" ) && ( ! this . ship . target || this . ship . target . scanClass != "CLASS_THARGOID" ) )
{
if ( this . respondToThargoids ( whom , true ) )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
this . reconsiderNow ( ) ;
2013-08-04 12:29:44 +01:00
return ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
if ( whom . scanClass != "CLASS_THARGOID" && this . ship . target && this . ship . target . scanClass == "CLASS_THARGOID" )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
// now is not a good time. Everything is friendly fire right now...
return ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
if ( this . ship . defenseTargets . indexOf ( whom ) < 0 )
2013-08-01 22:40:23 +01:00
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_newAssailiant" , whom , 3 ) ;
2013-08-07 10:53:44 +01:00
this . ship . addDefenseTarget ( whom ) ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
else
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
// else we know about this attacker already
if ( this . ship . energy * 4 < this . ship . maxEnergy )
2013-07-26 18:52:11 +01:00
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_attackLowEnergy" , whom , 2 ) ;
2013-08-07 10:53:44 +01:00
// but at low energy still reconsider
this . ship . requestHelpFromGroup ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
if ( this . ship . hasHostileTarget )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
if ( ! this . isAggressive ( this . ship . target ) )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
// if our current target is running away, switch targets
this . noteDistraction ( whom ) ;
this . ship . target = whom ;
}
else if ( this . ship . target . target != this . ship )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
// if our current target isn't aiming at us
if ( Math . random ( ) < 0.2 )
2013-08-02 22:16:54 +01:00
{
2013-08-07 10:53:44 +01:00
// occasionally switch
this . noteDistraction ( whom ) ;
this . ship . target = whom ;
2013-08-02 22:16:54 +01:00
}
2013-08-07 10:53:44 +01:00
}
else
{
// tend to switch to the more dangerous one
if ( this . threatAssessment ( whom , true ) > this . threatAssessment ( this . ship . target , true ) * ( 1 + Math . random ( ) ) )
2013-08-02 22:16:54 +01:00
{
2013-08-07 10:53:44 +01:00
this . noteDistraction ( whom ) ;
this . ship . target = whom ;
2013-08-02 22:16:54 +01:00
}
2013-08-01 22:40:23 +01:00
}
}
2013-09-02 22:23:06 +01:00
// TODO: a rep for not accepting surrenders should have an effect here
else if ( whom . isPlayer && ! this . ship . AIScript . oolite _intership . cargodemand && ! this . ship . AIScript . oolite _intership . cargodemandpaid )
{
// don't need to check here: most AIs won't check if a cargo
// demand exists, so setting it is harmless
this . ship . AIScript . oolite _intership . cargodemand = Math . ceil ( this . ship . cargoSpaceCapacity / 15 ) ;
}
2013-08-07 10:53:44 +01:00
if ( this . ship . escortGroup != null )
2013-08-02 22:16:54 +01:00
{
2013-08-07 10:53:44 +01:00
this . ship . requestHelpFromGroup ( ) ;
2013-08-02 22:16:54 +01:00
}
2013-08-07 10:53:44 +01:00
this . reconsiderNow ( ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _shipBeingAttackedUnsuccessfully = function ( whom )
2013-08-07 10:53:44 +01:00
{
2013-08-30 21:14:55 +01:00
if ( this . getParameter ( "oolite_flag_sendsDistressCalls" ) )
2013-08-02 22:16:54 +01:00
{
2013-08-07 10:53:44 +01:00
this . broadcastDistressMessage ( ) ;
2013-08-02 22:16:54 +01:00
}
2013-08-07 10:53:44 +01:00
if ( this . ship . defenseTargets . indexOf ( whom ) < 0 )
2013-08-02 22:16:54 +01:00
{
2013-08-07 10:53:44 +01:00
this . ship . addDefenseTarget ( whom ) ;
this . reconsiderNow ( ) ;
2013-08-02 22:16:54 +01:00
}
2013-09-02 22:23:06 +01:00
// TODO: a rep for not accepting surrenders should have an effect here
if ( ! this . ship . hasHostileTarget && whom . isPlayer && ! this . ship . AIScript . oolite _intership . cargodemand && ! this . ship . AIScript . oolite _intership . cargodemandpaid )
{
this . ship . AIScript . oolite _intership . cargodemand = Math . ceil ( this . ship . cargoSpaceCapacity / 15 ) ;
}
2013-09-05 20:12:41 +01:00
if ( ! this . ship . hasHostileTarget )
{
this . ship . target = whom ;
this . ship . performAttack ( ) ;
this . ship . requestHelpFromGroup ( ) ;
}
2013-08-07 10:53:44 +01:00
}
2013-08-02 22:16:54 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _shipFiredMissile = function ( missile , target )
2013-08-07 10:53:44 +01:00
{
2013-09-04 22:25:54 +01:00
// spread missiles out between targets
if ( this . ship . defenseTargets . length > 1 )
{
this . ship . removeDefenseTarget ( target ) ;
this . ship . target = null ;
this . reconsiderNow ( ) ;
}
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_firedMissile" , target , 4 ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-07 10:53:44 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _shipKilledOther = function ( other )
2013-07-26 18:52:11 +01:00
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_killedTarget" , other , 3 ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-07 10:53:44 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _shipLaunchedEscapePod = function ( )
2013-08-07 10:53:44 +01:00
{
this . communicate ( "oolite_eject" , { } , 1 ) ;
2013-09-05 20:12:41 +01:00
if ( this . getParameter ( "oolite_selfDestructAbandonedShip" ) == true )
{
if ( ! this . ship . script . _ _oolite _self _destruct )
{
this . ship . script . _ _oolite _self _destruct = new Timer ( this . ship . script , function ( ) { this . ship . explode ( ) } , 10 ) ;
}
}
2013-08-07 10:53:44 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _shipLaunchedFromStation = function ( station )
2013-08-07 10:53:44 +01:00
{
// clear the station
this . ship . destination = station . position ;
this . ship . desiredSpeed = this . cruiseSpeed ( ) ;
this . ship . desiredRange = 15000 ;
this . ship . performFlyToRangeFromDestination ( ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _shipScoopedOther = function ( other )
2013-07-26 18:52:11 +01:00
{
2013-08-07 10:53:44 +01:00
this . communicate ( "oolite_scoopedCargo" , { "oolite_goodsDescription" : displayNameForCommodity ( other . commodity ) } , 4 ) ;
this . setParameter ( "oolite_cargoDropped" , null ) ;
this . reconsiderNow ( ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _shipTargetLost = function ( target )
2013-08-07 10:53:44 +01:00
{
this . reconsiderNow ( ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _shipWillEnterWormhole = function ( )
2013-08-07 10:53:44 +01:00
{
this . setParameter ( "oolite_witchspaceWormhole" , null ) ;
this . applyHandlers ( { } ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _shipWitchspaceBlocked = function ( blocker )
2013-08-07 10:53:44 +01:00
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_witchspaceBlocked" , blocker , 3 ) ;
2013-08-07 10:53:44 +01:00
this . ship . setDestination = blocker . position ;
this . ship . setDesiredRange = 30000 ;
this . ship . setDesiredSpeed = this . cruiseSpeed ( ) ;
this . ship . performFlyToRangeFromDestination ( ) ;
this . setParameter ( "oolite_witchspaceEntry" , null ) ;
// no reconsidering yet
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _standard _wormholeSuggested = function ( hole )
2013-08-07 10:53:44 +01:00
{
this . ship . destination = hole . position ;
this . ship . desiredRange = 0 ;
this . ship . desiredSpeed = this . ship . maxSpeed ;
this . ship . performFlyToRangeFromDestination ( ) ;
this . setParameter ( "oolite_witchspaceWormhole" , hole ) ;
// don't reconsider
}
/* Missile response components */
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _missile _commsMessageReceived = function ( message )
2013-08-07 10:53:44 +01:00
{
this . noteCommsHeard ( ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _missile _shipHitByECM = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-07 10:53:44 +01:00
if ( this . ship . scriptInfo . oolite _missile _ecmResponse )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
var fn = this . ship . scriptInfo . oolite _missile _ecmResponse ;
if ( this . ship . AIScript [ fn ] )
2013-08-04 12:29:44 +01:00
{
2013-08-07 10:53:44 +01:00
this . ship . AIScript [ fn ] ( ) ;
this . reconsiderNow ( ) ;
2013-08-04 12:29:44 +01:00
return ;
}
2013-08-07 10:53:44 +01:00
if ( this . ship . script [ fn ] )
2013-08-04 12:29:44 +01:00
{
2013-08-07 10:53:44 +01:00
this . ship . script [ fn ] ( ) ;
this . reconsiderNow ( ) ;
return ;
2013-08-04 12:29:44 +01:00
}
2013-08-07 10:53:44 +01:00
}
2013-08-04 12:29:44 +01:00
2013-08-07 10:53:44 +01:00
/ * T h i s s e c t i o n f o r t h e h a r d h e a d s s h o u l d b e a n E C M
* response function , and that is used in the default
* shipdata . plist , but for compatibility with older OXPs
* it ' s also hardcoded here for now .
*
* OXPs wanting to overrule this for hardheads can set a
* response function to do so .
* /
if ( this . ship . primaryRole == "EQ_HARDENED_MISSILE" )
{
if ( Math . random ( ) < 0.1 ) //10% chance per pulse
2013-07-26 18:52:11 +01:00
{
2013-08-07 10:53:44 +01:00
if ( Math . random ( ) < 0.5 )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
// 50% chance responds by detonation
this . ship . AIScript . shipAchievedDesiredRange ( ) ;
2013-08-01 22:40:23 +01:00
return ;
}
2013-08-07 10:53:44 +01:00
// otherwise explode as normal below
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
else // 90% chance unaffected
2013-08-02 22:16:54 +01:00
{
return ;
}
2013-08-07 10:53:44 +01:00
}
this . ship . explode ( ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _missile _shipTargetCloaked = function ( )
2013-08-07 10:53:44 +01:00
{
this . setParameter ( "oolite_interceptCoordinates" , this . ship . target . position ) ;
this . setParameter ( "oolite_interceptTarget" , this . ship . target ) ;
// stops performIntercept sending AchievedDesiredRange
this . ship . performIdle ( ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _missile _shipTargetLost = function ( )
2013-08-07 10:53:44 +01:00
{
this . reconsiderNow ( ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _missile _shipAchievedDesiredRange = function ( )
2013-08-07 10:53:44 +01:00
{
if ( this . ship . scriptInfo . oolite _missile _detonation )
{
var fn = this . ship . scriptInfo . oolite _missile _detonation ;
if ( this . ship . AIScript [ fn ] )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
this . ship . AIScript [ fn ] ( ) ;
2013-08-01 22:40:23 +01:00
this . reconsiderNow ( ) ;
2013-08-07 10:53:44 +01:00
return ;
2013-07-26 18:52:11 +01:00
}
2013-08-07 10:53:44 +01:00
if ( this . ship . script [ fn ] )
2013-07-26 18:52:11 +01:00
{
2013-08-07 10:53:44 +01:00
this . ship . script [ fn ] ( ) ;
this . reconsiderNow ( ) ;
return ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
/ * D e f a u l t s t o s t a n d a r d m i s s i l e s e t t i n g s , i n c a s e t h e y ' r e
* not specified in scriptInfo * /
var blastpower = 170 ;
var blastradius = 32.5 ;
var blastshaping = 0.25 ;
if ( this . ship . scriptInfo . oolite _missile _blastPower )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
blastpower = this . ship . scriptInfo . oolite _missile _blastPower ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
if ( this . ship . scriptInfo . oolite _missile _blastRadius )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
blastradius = this . ship . scriptInfo . oolite _missile _blastRadius ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
if ( this . ship . scriptInfo . oolite _missile _blastShaping )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
blastshaping = this . ship . scriptInfo . oolite _missile _blastShaping ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
this . ship . dealEnergyDamage ( blastpower , blastradius , blastshaping ) ;
this . ship . explode ( ) ;
2013-07-26 18:52:11 +01:00
}
2013-08-07 10:53:44 +01:00
/* Station response components */
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _station _commsMessageReceived = function ( message )
2013-07-26 18:52:11 +01:00
{
2013-08-07 10:53:44 +01:00
this . noteCommsHeard ( ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _station _cascadeWeaponDetected = function ( weapon )
2013-08-07 10:53:44 +01:00
{
this . ship . alertCondition = 3 ;
this . reconsiderNow ( ) ;
} ;
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _station _shipAttackedWithMissile = function ( missile , whom )
2013-07-26 18:52:11 +01:00
{
2013-08-07 10:53:44 +01:00
this . ship . alertCondition = 3 ;
if ( this . ship . equipmentStatus ( "EQ_ECM" ) == "EQUIPMENT_OK" )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
this . ship . fireECM ( ) ;
this . ship . addDefenseTarget ( missile ) ;
this . ship . addDefenseTarget ( whom ) ;
// but don't reconsider immediately
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
else
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
this . ship . addDefenseTarget ( missile ) ;
this . ship . addDefenseTarget ( whom ) ;
var tmp = this . ship . target ;
this . ship . target = whom ;
this . ship . requestHelpFromGroup ( ) ;
this . ship . target = tmp ;
2013-08-01 22:40:23 +01:00
this . reconsiderNow ( ) ;
2013-08-07 10:53:44 +01:00
}
} ;
2013-07-26 18:52:11 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _station _shipBeingAttacked = function ( whom )
2013-08-07 10:53:44 +01:00
{
if ( ! whom )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
this . reconsiderNow ( ) ;
return ;
}
2013-09-11 18:29:08 +01:00
if ( whom . target != this . ship )
2013-08-01 22:40:23 +01:00
{
2013-09-11 18:29:08 +01:00
if ( ! whom . isPlayer )
2013-08-01 22:40:23 +01:00
{
2013-09-11 18:29:08 +01:00
// was accidental
if ( this . allied ( whom , this . ship ) )
{
this . communicate ( "oolite_friendlyFire" , whom , 4 ) ;
// ignore it
return ;
}
if ( Math . random ( ) > 0.1 )
{
// usually ignore it anyway
return ;
}
2013-08-01 22:40:23 +01:00
}
2013-09-11 18:29:08 +01:00
else if ( this . ship . alertCondition > 1 && this . ignorePlayerFriendlyFire ( ) )
2013-08-01 22:40:23 +01:00
{
2013-09-11 18:29:08 +01:00
// send warning communication
this . communicate ( "oolite_friendlyFire" , whom , 2 ) ;
2013-08-07 10:53:44 +01:00
return ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
}
this . ship . alertCondition = 3 ;
if ( this . ship . defenseTargets . indexOf ( whom ) < 0 )
{
this . ship . addDefenseTarget ( whom ) ;
this . reconsiderNow ( ) ;
}
else
{
// else we know about this attacker already
if ( this . ship . energy * 4 < this . ship . maxEnergy )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
// but at low energy still reconsider
2013-08-01 22:40:23 +01:00
this . reconsiderNow ( ) ;
2013-08-07 10:53:44 +01:00
this . ship . requestHelpFromGroup ( ) ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
}
if ( this . ship . hasHostileTarget )
{
if ( ! this . isAggressive ( this . ship . target ) )
2013-07-26 18:52:11 +01:00
{
2013-08-07 10:53:44 +01:00
// if our current target is running away, switch targets
this . ship . target = whom ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
else if ( this . ship . target . target != this . ship )
2013-07-26 18:52:11 +01:00
{
2013-08-07 10:53:44 +01:00
// if our current target isn't aiming at us
if ( Math . random ( ) < 0.2 )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
// occasionally switch
2013-08-01 22:40:23 +01:00
this . ship . target = whom ;
}
2013-08-02 22:16:54 +01:00
}
2013-08-07 10:53:44 +01:00
}
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _station _shipAttackedOther = function ( other )
2013-08-07 10:53:44 +01:00
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_hitTarget" , other , 4 ) ;
2013-08-07 10:53:44 +01:00
}
2013-08-01 22:40:23 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _station _shipFiredMissile = function ( missile , target )
2013-08-07 10:53:44 +01:00
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_firedMissile" , target , 4 ) ;
2013-08-07 10:53:44 +01:00
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _station _shipKilledOther = function ( other )
2013-08-07 10:53:44 +01:00
{
2013-08-07 16:29:24 +01:00
this . communicate ( "oolite_killedTarget" , other , 3 ) ;
2013-08-07 10:53:44 +01:00
}
2013-08-01 22:40:23 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _station _shipTargetLost = function ( target )
2013-08-07 10:53:44 +01:00
{
this . reconsiderNow ( ) ;
} ;
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _station _helpRequestReceived = function ( ally , enemy )
2013-08-07 10:53:44 +01:00
{
this . ship . addDefenseTarget ( enemy ) ;
2013-08-07 16:29:24 +01:00
if ( enemy . scanClass == "CLASS_MISSILE" && this . distance ( enemy ) < this . scannerRange && this . ship . equipmentStatus ( "EQ_ECM" ) == "EQUIPMENT_OK" )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
this . ship . fireECM ( ) ;
return ;
}
if ( ! this . ship . alertCondition == 3 )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
this . ship . target = enemy ;
2013-08-01 22:40:23 +01:00
this . reconsiderNow ( ) ;
2013-08-07 10:53:44 +01:00
return ; // not in a combat mode
}
this . ship . target = enemy ;
}
2013-08-01 22:40:23 +01:00
2013-08-07 10:53:44 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _station _distressMessageReceived = function ( aggressor , sender )
2013-08-07 10:53:44 +01:00
{
if ( this . getParameter ( "oolite_flag_listenForDistressCall" ) != true )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
return ;
2013-08-01 22:40:23 +01:00
}
2013-08-30 21:14:55 +01:00
if ( this . ship . scanClass == "CLASS_POLICE" || ( this . ship . isStation && this . ship . allegiance == "galcop" ) )
{
if ( this . distance ( aggressor ) < this . scannerRange )
{
2013-09-08 17:20:28 +01:00
aggressor . setBounty ( aggressor . bounty | 8 , "attacked innocent" ) ;
2013-08-30 21:14:55 +01:00
}
}
2013-08-07 10:53:44 +01:00
this . setParameter ( "oolite_distressAggressor" , aggressor ) ;
this . setParameter ( "oolite_distressSender" , sender ) ;
this . setParameter ( "oolite_distressTimestamp" , clock . adjustedSeconds ) ;
this . reconsiderNow ( ) ;
}
2013-08-01 22:40:23 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _station _offenceCommittedNearby = function ( attacker , victim )
2013-08-07 10:53:44 +01:00
{
2013-09-08 17:20:28 +01:00
if ( this . ship == victim ) return ; // other handlers can get this one
2013-08-07 10:53:44 +01:00
if ( this . getParameter ( "oolite_flag_markOffenders" ) )
2013-08-01 22:40:23 +01:00
{
2013-09-08 17:20:28 +01:00
if ( ! attacker . isPlayer && attacker . target != victim )
{
// ignore friendly fire if they were aiming at a pirate
if ( attacker . bounty == 0 && attacker . target && this . shipInRoleCategory ( attacker . target , "oolite-pirate" ) )
{
// but we might go after the pirate ourselves in a bit
this . ship . addDefenseTarget ( attacker . target ) ;
return ;
}
}
else if ( attacker . isPlayer && this . ignorePlayerFriendlyFire ( ) )
{
this . communicate ( "oolite_friendlyFire" , attacker , 3 ) ;
return ;
}
2013-08-07 10:53:44 +01:00
attacker . setBounty ( attacker . bounty | 7 , "seen by police" ) ;
this . ship . addDefenseTarget ( attacker ) ;
if ( this . ship . alertCondition < 3 )
2013-07-26 18:52:11 +01:00
{
2013-08-07 10:53:44 +01:00
this . ship . alertCondition = 3 ;
this . ship . target = attacker ;
2013-08-01 22:40:23 +01:00
}
this . reconsiderNow ( ) ;
}
2013-08-07 10:53:44 +01:00
}
/* Non-standard response components */
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _docking _shipAchievedDesiredRange = function ( )
2013-08-07 10:53:44 +01:00
{
var message = this . ship . dockingInstructions . ai _message ;
if ( message == "APPROACH" || message == "BACK_OFF" || message == "APPROACH_COORDINATES" )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
this . reconsiderNow ( ) ;
2013-08-01 22:40:23 +01:00
}
2013-07-26 18:52:11 +01:00
}
2013-07-12 19:44:14 +01:00
2013-07-23 21:21:49 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _docking _stationWithdrewDockingClearance = function ( )
2013-08-07 10:53:44 +01:00
{
this . setParameter ( "oolite_dockingStation" , null ) ;
this . reconsiderNow ( ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _escort _escortDock = function ( )
2013-08-07 10:53:44 +01:00
{
this . reconsiderNow ( ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _escort _helpRequestReceived = function ( ally , enemy )
2013-08-07 10:53:44 +01:00
{
if ( this . allied ( this . ship , enemy ) )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
return ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
this . ship . addDefenseTarget ( enemy ) ;
2013-08-07 16:29:24 +01:00
if ( enemy . scanClass == "CLASS_MISSILE" && this . distance ( enemy ) < this . scannerRange && this . ship . equipmentStatus ( "EQ_ECM" ) == "EQUIPMENT_OK" )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
this . ship . fireECM ( ) ;
}
if ( enemy . scanClass == "CLASS_THARGOID" && this . ship . scanClass != "CLASS_THARGOID" && ( ! this . ship . target || this . ship . target . scanClass != "CLASS_THARGOID" ) )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
if ( this . respondToThargoids ( enemy , false ) )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
this . reconsiderNow ( ) ;
return ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
}
2013-07-26 18:52:11 +01:00
2013-08-07 10:53:44 +01:00
// always help the leader
if ( ally == this . ship . group . leader )
{
2013-09-05 20:12:41 +01:00
if ( ! this . ship . target || ! this . ship . hasHostileTarget || this . ship . target . target != ally )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
this . ship . target = enemy ;
this . reconsiderNow ( ) ;
return ;
2013-08-01 22:40:23 +01:00
}
}
2013-08-07 10:53:44 +01:00
this . ship . addDefenseTarget ( enemy ) ;
2013-08-07 16:29:24 +01:00
if ( enemy . scanClass == "CLASS_MISSILE" && this . distance ( enemy ) < this . scannerRange && this . ship . equipmentStatus ( "EQ_ECM" ) == "EQUIPMENT_OK" )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
this . ship . fireECM ( ) ;
return ;
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
if ( ! this . ship . hasHostileTarget )
2013-08-01 22:40:23 +01:00
{
2013-09-05 20:12:41 +01:00
this . ship . target = enemy ;
this . ship . performAttack ( ) ;
2013-08-01 22:40:23 +01:00
this . reconsiderNow ( ) ;
2013-08-07 10:53:44 +01:00
return ; // not in a combat mode
2013-08-01 22:40:23 +01:00
}
2013-08-07 10:53:44 +01:00
if ( ally . energy / ally . maxEnergy < this . ship . energy / this . ship . maxEnergy )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
// not in worse shape than ally
if ( this . ship . target . target != ally && this . ship . target != ally . target )
2013-08-01 22:40:23 +01:00
{
2013-08-07 10:53:44 +01:00
// not already helping, go for it...
this . ship . target = enemy ;
this . reconsiderNow ( ) ;
2013-07-23 21:21:49 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-07-26 18:52:11 +01:00
}
2013-07-23 21:21:49 +01:00
2013-07-24 21:56:50 +01:00
2013-09-14 13:50:49 +01:00
PriorityAIController . prototype . responseComponent _expectWitchspace _shipTargetLost = function ( target )
{
if ( ! target )
{
target = this . getParameter ( "oolite_rememberedTarget" ) ;
}
if ( target ) {
var pos = target . position ;
var ws = system . wormholes ;
// most likely to be most recent
for ( var i = ws . length - 1 ; i >= 0 ; i -- )
{
if ( ws [ i ] . position . distanceTo ( pos ) < 100 )
{
this . setParameter ( "oolite_witchspaceWormhole" , ws [ i ] ) ;
break ;
}
}
}
this . reconsiderNow ( ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _scooping _shipAchievedDesiredRange = function ( )
2013-08-07 10:53:44 +01:00
{
this . reconsiderNow ( ) ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _scooping _shipScoopedFuel = function ( )
2013-08-07 10:53:44 +01:00
{
if ( this . ship . fuel == 7 )
{
this . reconsiderNow ( ) ;
}
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . responseComponent _trackPlayer _playerWillEnterWitchspace = function ( )
2013-08-07 10:53:44 +01:00
{
var wormhole = this . getParameter ( "oolite_witchspaceWormhole" ) ;
if ( wormhole != null )
{
this . ship . enterWormhole ( wormhole ) ;
}
else
{
this . ship . enterWormhole ( ) ;
}
}
2013-08-09 13:09:54 +01:00
/* ******************* Templates *************************** */
2013-08-07 10:53:44 +01:00
2013-08-09 13:09:54 +01:00
/ * T e m p l a t e s . C o m m o n A I p r i o r i t y l i s t f r a g m e n t s w h i c h m a y b e u s e f u l t o
* multiple AIs . These functions take no parameters and return a
* list . This can either be used straightforwardly as a truebranch or
* falsebranch value , or appended to a list using Array . concat ( ) * /
2013-08-07 10:53:44 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . templateLeadHuntingMission = function ( )
2013-08-10 08:34:33 +01:00
{
return [
2013-08-31 18:07:17 +01:00
{
condition : this . conditionInInterstellarSpace ,
truebranch : this . templateWitchspaceJumpAnywhere ( )
} ,
2013-08-10 08:34:33 +01:00
{
condition : this . conditionHasWaypoint ,
configuration : this . configurationSetDestinationToWaypoint ,
behaviour : this . behaviourApproachDestination ,
reconsider : 30
} ,
{
condition : this . conditionHasSelectedStation ,
truebranch : [
{
condition : this . conditionSelectedStationNearby ,
configuration : this . configurationSetSelectedStationForDocking ,
behaviour : this . behaviourDockWithStation ,
reconsider : 30
} ,
{
condition : this . conditionSelectedStationNearMainPlanet ,
truebranch : [
{
notcondition : this . conditionMainPlanetNearby ,
configuration : this . configurationSetDestinationToMainPlanet ,
behaviour : this . behaviourApproachDestination ,
reconsider : 30
}
]
} ,
// either the station isn't near the planet, or we are
{
configuration : this . configurationSetDestinationToSelectedStation ,
behaviour : this . behaviourApproachDestination ,
reconsider : 30
}
]
} ,
{
condition : this . conditionMainPlanetNearby ,
truebranch : [
{
condition : this . conditionPatrolIsOver ,
configuration : this . configurationSelectRandomTradeStation ,
behaviour : this . behaviourReconsider
}
]
} ,
/* No patrol route set up. Make one */
{
configuration : this . configurationSetWaypoint ,
behaviour : this . behaviourApproachDestination ,
reconsider : 30
}
] ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . templateLeadPirateMission = function ( )
2013-08-09 13:09:54 +01:00
{
return [
{
2013-08-09 18:00:18 +01:00
label : "Pirate mission" ,
2013-08-09 13:09:54 +01:00
preconfiguration : this . configurationForgetCargoDemand ,
condition : this . conditionScannerContainsPirateVictims ,
configuration : this . configurationAcquireScannedTarget ,
truebranch : [
{
label : "Check odds" ,
condition : this . conditionCombatOddsGood ,
behaviour : this . behaviourRobTarget ,
reconsider : 5
}
]
} ,
{
/* move to a position on one of the space lanes, preferring lane 1 */
label : "Lurk" ,
configuration : this . configurationSetDestinationToPirateLurk ,
behaviour : this . behaviourApproachDestination ,
reconsider : 30
} ,
] ;
}
2013-08-07 10:53:44 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . templateReturnToBase = function ( )
2013-08-09 13:09:54 +01:00
{
return [
{
2013-08-09 18:00:18 +01:00
label : "Return to base" ,
2013-08-09 13:09:54 +01:00
condition : this . conditionHasSelectedStation ,
truebranch : [
{
condition : this . conditionSelectedStationNearby ,
configuration : this . configurationSetSelectedStationForDocking ,
behaviour : this . behaviourDockWithStation ,
reconsider : 30
} ,
{
condition : this . conditionSelectedStationNearMainPlanet ,
truebranch : [
{
notcondition : this . conditionMainPlanetNearby ,
configuration : this . configurationSetDestinationToMainPlanet ,
behaviour : this . behaviourApproachDestination ,
reconsider : 30
}
]
} ,
// either the station isn't near the planet, or we are
{
configuration : this . configurationSetDestinationToSelectedStation ,
behaviour : this . behaviourApproachDestination ,
reconsider : 30
}
] ,
falsebranch : [
{
2013-08-17 20:41:36 +01:00
condition : this . conditionFriendlyStationExists ,
2013-08-09 13:09:54 +01:00
configuration : this . configurationSelectRandomTradeStation ,
behaviour : this . behaviourReconsider
}
]
}
] ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . templateReturnToBaseOrPlanet = function ( )
2013-08-09 13:09:54 +01:00
{
return [
{
2013-08-09 18:00:18 +01:00
label : "Return to base or planet" ,
2013-08-09 13:09:54 +01:00
condition : this . conditionFriendlyStationNearby ,
configuration : this . configurationSetNearbyFriendlyStationForDocking ,
behaviour : this . behaviourDockWithStation ,
reconsider : 30
} ,
{
condition : this . conditionFriendlyStationExists ,
configuration : this . configurationSetDestinationToNearestFriendlyStation ,
behaviour : this . behaviourApproachDestination ,
reconsider : 30
} ,
{
condition : this . conditionHasSelectedPlanet ,
truebranch : [
{
preconfiguration : this . configurationSetDestinationToSelectedPlanet ,
condition : this . conditionNearDestination ,
behaviour : this . behaviourLandOnPlanet
} ,
{
behaviour : this . behaviourApproachDestination ,
reconsider : 30
}
]
} ,
{
condition : this . conditionPlanetExists ,
configuration : this . configurationSelectPlanet ,
behaviour : this . behaviourReconsider
} ,
{
condition : this . conditionCanWitchspaceOut ,
configuration : this . configurationSelectWitchspaceDestination ,
behaviour : this . behaviourEnterWitchspace ,
reconsider : 20
}
] ;
}
2013-08-31 18:07:17 +01:00
PriorityAIController . prototype . templateWitchspaceJumpAnywhere = function ( )
{
return [
{
label : "Wormhole search" ,
condition : this . conditionWormholeNearby ,
configuration : this . configurationSetDestinationToNearestWormhole ,
behaviour : this . behaviourApproachDestination ,
reconsider : 30
} ,
/* Short reconsiders on next two so wormholes aren't missed */
{
label : "No wormholes nearby" ,
condition : this . conditionCanWitchspaceOut ,
configuration : this . configurationSelectWitchspaceDestination ,
behaviour : this . behaviourEnterWitchspace ,
reconsider : 10
} ,
{
label : "Lurk around witchpoint" ,
configuration : this . configurationSetDestinationToWitchpoint ,
behaviour : this . behaviourApproachDestination ,
reconsider : 10
}
] ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . templateWitchspaceJumpInbound = function ( )
2013-08-09 13:09:54 +01:00
{
return [
{
2013-08-09 18:00:18 +01:00
label : "Jump inbound" ,
2013-08-09 13:09:54 +01:00
preconfiguration : this . configurationSelectWitchspaceDestinationInbound ,
condition : this . conditionCanWitchspaceOnRoute ,
behaviour : this . behaviourEnterWitchspace ,
reconsider : 20
} ,
{
condition : this . conditionReadyToSunskim ,
configuration : this . configurationSetDestinationToSunskimEnd ,
behaviour : this . behaviourSunskim ,
reconsider : 20
} ,
{
condition : this . conditionSunskimPossible ,
configuration : this . configurationSetDestinationToSunskimStart ,
behaviour : this . behaviourApproachDestination ,
reconsider : 30
}
] ;
}
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . templateWitchspaceJumpOutbound = function ( )
2013-08-09 13:09:54 +01:00
{
return [
{
2013-08-09 18:00:18 +01:00
label : "Jump outbound" ,
2013-08-09 13:09:54 +01:00
preconfiguration : this . configurationSelectWitchspaceDestinationOutbound ,
condition : this . conditionCanWitchspaceOnRoute ,
behaviour : this . behaviourEnterWitchspace ,
reconsider : 20
} ,
{
condition : this . conditionReadyToSunskim ,
configuration : this . configurationSetDestinationToSunskimEnd ,
behaviour : this . behaviourSunskim ,
reconsider : 20
} ,
{
condition : this . conditionSunskimPossible ,
configuration : this . configurationSetDestinationToSunskimStart ,
behaviour : this . behaviourApproachDestination ,
reconsider : 30
}
] ;
}
2013-08-07 10:53:44 +01:00
2013-08-31 18:07:17 +01:00
2013-07-26 18:52:11 +01:00
/* ******************* Waypoint generators *********************** */
/ * W a y p o i n t g e n e r a t o r s . W h e n t h e s e a r e c a l l e d , t h e y s h o u l d s e t u p
* the next waypoint for the ship . Ideally ships should either
* reach that waypoint or formally give up on it before asking for
* the next one , but the generator shouldn ' t assume that unless
2013-08-09 13:09:54 +01:00
* it ' s one written specifically for a particular AI . * /
2013-07-24 21:56:50 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . waypointsSpacelanePatrol = function ( )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
var p = this . ship . position ;
var choice = "" ;
if ( p . magnitude ( ) < 10000 )
{
// near witchpoint
if ( Math . random ( ) < 0.9 )
{
// mostly return to planet
choice = "PLANET" ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
else
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
choice = "SUN" ;
2013-07-24 21:56:50 +01:00
}
2013-08-01 22:40:23 +01:00
}
else if ( p . distanceTo ( system . mainPlanet ) < system . mainPlanet . radius * 2 )
{
// near planet
if ( Math . random ( ) < 0.75 )
{
// mostly go to witchpoint
choice = "WITCHPOINT" ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
else
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
choice = "SUN" ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
else if ( p . distanceTo ( system . sun ) < system . sun . radius * 3 )
{
// near sun
if ( Math . random ( ) < 0.9 )
{
// mostly return to planet
choice = "PLANET" ;
}
else
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
choice = "SUN" ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-08-07 16:29:24 +01:00
else if ( p . z < system . mainPlanet . position . z && ( ( p . x * p . x ) + ( p . y * p . y ) ) < this . scannerRange * this . scannerRange * 4 )
2013-08-01 22:40:23 +01:00
{
// on lane 1
if ( Math . random ( ) < 0.5 )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
choice = "PLANET" ;
2013-07-26 18:52:11 +01:00
}
else
{
2013-08-01 22:40:23 +01:00
choice = "WITCHPOINT" ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
else if ( p . subtract ( system . mainPlanet ) . dot ( p . subtract ( system . sun ) ) < - 0.9 )
{
// on lane 2
if ( Math . random ( ) < 0.5 )
2013-07-19 20:18:53 +01:00
{
2013-08-01 22:40:23 +01:00
choice = "PLANET" ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
else
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
choice = "SUN" ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
}
else if ( p . dot ( system . sun . position ) > 0.9 )
{
// on lane 3
if ( Math . random ( ) < 0.5 )
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
choice = "WITCHPOINT" ;
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
else
2013-07-26 18:52:11 +01:00
{
2013-08-01 22:40:23 +01:00
choice = "SUN" ;
}
}
else
{
// we're not on any lane. Return to the planet
choice = "PLANET" ;
}
// having chosen, now set up the next stop on the patrol
switch ( choice ) {
case "WITCHPOINT" :
this . setParameter ( "oolite_waypoint" , new Vector3D ( 0 , 0 , 0 ) ) ;
this . setParameter ( "oolite_waypointRange" , 7500 ) ;
break ;
case "PLANET" :
this . setParameter ( "oolite_waypoint" , system . mainPlanet . position ) ;
this . setParameter ( "oolite_waypointRange" , system . mainPlanet . radius * 2 ) ;
break ;
case "SUN" :
this . setParameter ( "oolite_waypoint" , system . sun . position ) ;
this . setParameter ( "oolite_waypointRange" , system . sun . radius * 2.5 ) ;
break ;
}
2013-07-26 18:52:11 +01:00
}
2013-08-01 22:40:23 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . waypointsStationPatrol = function ( )
2013-08-01 22:40:23 +01:00
{
var station = null ;
2013-09-01 19:25:45 +01:00
if ( this . ship . group && this . ship . group . leader && this . ship . group . leader . isStation )
2013-08-01 22:40:23 +01:00
{
station = this . ship . group . leader ;
}
if ( ! station )
{
station = system . mainStation ;
if ( ! station )
{
this . setParameter ( "oolite_waypoint" , new Vector3D ( 0 , 0 , 0 ) ) ;
this . setParameter ( "oolite_waypointRange" , 7500 ) ;
return ;
}
}
var z = station . vectorForward ;
var tmp = new Vector3D ( 0 , 1 , 0 ) ;
if ( system . sun )
{
tmp = z . cross ( system . sun . position . direction ( ) ) ;
}
var x = z . cross ( tmp ) ;
var y = z . cross ( x ) ;
// x and y now consistent vectors relative to a rotating station
var waypoints = [
station . position . add ( x . multiply ( 25000 ) ) ,
station . position . add ( y . multiply ( 25000 ) ) ,
station . position . add ( x . multiply ( - 25000 ) ) ,
station . position . add ( y . multiply ( - 25000 ) )
] ;
var waypoint = waypoints [ 0 ] ;
for ( var i = 0 ; i <= 3 ; i ++ )
{
2013-08-07 16:29:24 +01:00
if ( this . distance ( waypoints [ i ] ) < 500 )
2013-08-01 22:40:23 +01:00
{
waypoint = waypoints [ ( i + 1 ) % 4 ] ;
break ;
}
}
this . setParameter ( "oolite_waypoint" , waypoint ) ;
this . setParameter ( "oolite_waypointRange" , 100 ) ;
}
2013-08-12 18:45:09 +01:00
2013-08-31 16:21:07 +01:00
PriorityAIController . prototype . waypointsWitchpointPatrol = function ( )
2013-08-12 18:45:09 +01:00
{
if ( this . ship . distanceTravelled > system . mainPlanet . position . z + 200000 )
{
this . setParameter ( "oolite_waypoint" , system . mainStation . position ) ;
this . setParameter ( "oolite_waypointRange" , 10000 ) ;
}
else
{
var waypoints = [
new Vector3D ( 15E3 , 0 , 5E3 ) ,
new Vector3D ( 0 , 15E3 , - 5E3 ) ,
new Vector3D ( - 15E3 , 0 , 5E3 ) ,
new Vector3D ( 0 , - 15E3 , - 5E3 )
] ;
var waypoint = waypoints [ 0 ] ;
for ( var i = 0 ; i <= 3 ; i ++ )
{
if ( this . distance ( waypoints [ i ] ) < 500 )
{
waypoint = waypoints [ ( i + 1 ) % 4 ] ;
break ;
}
}
this . setParameter ( "oolite_waypoint" , waypoint ) ;
this . setParameter ( "oolite_waypointRange" , 100 ) ;
}
}
2013-08-01 22:40:23 +01:00
/* ********** Communications data ****************/
/ * W a r n i n g : O X P s s h o u l d o n l y i n t e r a c t w i t h t h i s t h r o u g h t h e p r o v i d e d
* API functions . The internals of data storage may be changed at any
* time . This data is global . * /
this . startUp = function ( )
{
// initial definition is just essential communications for now
2013-08-03 17:47:43 +01:00
this . $commsSettings = { } ;
this . _setCommunications ( {
2013-08-04 12:29:44 +01:00
generic : {
generic : {
2013-08-05 14:14:50 +01:00
oolite _thanksForHelp : "[oolite-comms-thanksForHelp]" ,
oolite _surrender : "[oolite-comms-surrender]"
2013-08-04 12:29:44 +01:00
}
} ,
2013-08-02 22:16:54 +01:00
trader : {
2013-08-01 22:40:23 +01:00
generic : {
oolite _acceptPirateDemand : "[oolite-comms-acceptPirateDemand]" ,
oolite _makeDistressCall : "[oolite-comms-makeDistressCall]"
}
} ,
police : {
generic : {
2013-08-04 12:29:44 +01:00
oolite _thanksForHelp : "[oolite-comms-police-thanksForHelp]" ,
2013-08-01 22:40:23 +01:00
oolite _markForFines : "[oolite-comms-markForFines]" ,
oolite _distressResponseAggressor : "[oolite-comms-distressResponseAggressor]" ,
oolite _offenceDetected : "[oolite-comms-offenceDetected]" ,
}
2013-08-02 22:16:54 +01:00
} ,
pirate : {
generic : {
oolite _makePirateDemand : "[oolite-comms-makePirateDemand]" ,
}
} ,
2013-09-14 17:39:37 +01:00
assassin : {
generic : {
oolite _beginningAttack : "[oolite-comms-contractAttack]" ,
}
} ,
2013-08-03 14:55:48 +01:00
_thargoid : {
thargoid : {
oolite _continuingAttack : "[thargoid_curses]"
2013-08-02 22:16:54 +01:00
}
2013-08-01 22:40:23 +01:00
}
2013-08-03 17:47:43 +01:00
} ) ;
2013-08-01 22:40:23 +01:00
/* These are temporary for testing. Remove before release... */
this . $commsSettings . generic . generic . oolite _continuingAttack = "I've got the [oolite_entityClass]" ;
2013-08-26 16:17:59 +01:00
this . $commsSettings . generic . generic . oolite _beginningAttack = "Die, [oolite_entityName]!" ;
2013-08-02 22:16:54 +01:00
this . $commsSettings . generic . generic . oolite _hitTarget = "Take that, scum." ;
this . $commsSettings . generic . generic . oolite _killedTarget = "[oolite_entityClass] down!" ;
2013-08-26 16:17:59 +01:00
this . $commsSettings . pirate . generic . oolite _hitTarget = "Where's the cargo, [oolite_entityName]?" ;
this . $commsSettings . generic . generic . oolite _friendlyFire = "Watch where you're shooting, [oolite_entityName]!" ;
2013-08-02 22:16:54 +01:00
this . $commsSettings . generic . generic . oolite _eject = "Condition critical! I'm bailing out..." ;
2013-08-04 12:29:44 +01:00
this . $commsSettings . generic . generic . oolite _thargoidAttack = "%N! A thargoid warship!" ;
2013-08-26 16:17:59 +01:00
this . $commsSettings . generic . generic . oolite _firedMissile = "Dodge this for a bit, [oolite_entityName]." ;
2013-08-02 22:16:54 +01:00
this . $commsSettings . generic . generic . oolite _incomingMissile = "Help! Help! Missile!" ;
this . $commsSettings . generic . generic . oolite _startHelping = "Hold on! I'm on them." ;
this . $commsSettings . generic . generic . oolite _switchTarget = "I'll get the [oolite_entityClass]." ;
this . $commsSettings . generic . generic . oolite _newAssailant = "Where did that [oolite_entityClass] come from?" ;
this . $commsSettings . generic . generic . oolite _startFleeing = "I can't take this much longer! I'm getting out of here." ;
2013-08-05 14:14:50 +01:00
this . $commsSettings . generic . generic . oolite _continueFleeing = "I'm still not clear. Someone please help!" ;
this . $commsSettings . generic . generic . oolite _groupIsOutnumbered = "Please, let us go!" ;
this . $commsSettings . pirate . generic . oolite _groupIsOutnumbered = "Argh! They're tougher than they looked. Break off the attack!" ;
2013-08-02 22:16:54 +01:00
this . $commsSettings . generic . generic . oolite _dockingWait = "Bored now." ;
this . $commsSettings . generic . generic . oolite _quiriumCascade = "Cascade! %N! Get out of here!" ;
this . $commsSettings . pirate . generic . oolite _scoopedCargo = "Ah, [oolite_goodsDescription]. We should have shaken them down for more." ;
2013-09-02 22:23:06 +01:00
this . $commsSettings . generic . generic . oolite _agreeingToDumpCargo = "Have it! But please let us go!" ;
2013-08-01 22:40:23 +01:00
}
/ * S e a r c h t h r o u g h c o m m u n i c a t i o n s f r o m m o s t s p e c i f i c t o l e a s t s p e c i f i c .
* role + personality
* "generic" + personality
* role + "generic"
* "generic" + "generic"
* A return value of "" means no communication is set .
2013-08-02 22:16:54 +01:00
*
2013-08-03 14:55:48 +01:00
* Roles or personalities starting with _ do not fall back to generic
2013-08-01 22:40:23 +01:00
* /
this . _getCommunication = function ( role , personality , key )
{
if ( this . $commsSettings [ role ] && this . $commsSettings [ role ] [ personality ] && this . $commsSettings [ role ] [ personality ] [ key ] && this . $commsSettings [ role ] [ personality ] [ key ] != "" )
{
return this . $commsSettings [ role ] [ personality ] [ key ] ;
}
2013-08-03 14:55:48 +01:00
if ( role . charAt ( 0 ) != "_" )
2013-08-01 22:40:23 +01:00
{
2013-08-03 14:55:48 +01:00
if ( this . $commsSettings [ "generic" ] && this . $commsSettings [ "generic" ] [ personality ] && this . $commsSettings [ "generic" ] [ personality ] [ key ] && this . $commsSettings [ "generic" ] [ personality ] [ key ] != "" )
{
return this . $commsSettings [ "generic" ] [ personality ] [ key ] ;
}
2013-08-01 22:40:23 +01:00
}
2013-08-03 14:55:48 +01:00
if ( personality . charAt ( 0 ) != "_" )
2013-08-01 22:40:23 +01:00
{
2013-08-03 14:55:48 +01:00
if ( this . $commsSettings [ role ] && this . $commsSettings [ role ] [ "generic" ] && this . $commsSettings [ role ] [ "generic" ] [ key ] && this . $commsSettings [ role ] [ "generic" ] [ key ] != "" )
{
return this . $commsSettings [ role ] [ "generic" ] [ key ] ;
}
2013-08-01 22:40:23 +01:00
}
2013-08-03 14:55:48 +01:00
if ( role . charAt ( 0 ) != "_" && personality . charAt ( 0 ) != "_" )
2013-08-01 22:40:23 +01:00
{
2013-08-03 14:55:48 +01:00
if ( this . $commsSettings [ "generic" ] && this . $commsSettings [ "generic" ] [ "generic" ] && this . $commsSettings [ "generic" ] [ "generic" ] [ key ] && this . $commsSettings [ "generic" ] [ "generic" ] [ key ] != "" )
{
return this . $commsSettings [ "generic" ] [ "generic" ] [ key ] ;
}
2013-08-01 22:40:23 +01:00
}
return "" ;
2013-08-03 17:47:43 +01:00
}
/* Returns the available personalities for a particular role */
this . _getCommunicationPersonalities = function ( role )
{
if ( ! this . $commsSettings [ role ] )
{
return [ ] ;
}
else
{
return Object . keys ( this . $commsSettings [ role ] ) ;
}
}
/ * S e t a c o m m u n i c a t i o n f o r t h e s p e c i f i e d r o l e , p e r s o n a l i t y a n d c o m m s
* key . "generic" is used as a fallback role and personality . * /
this . _setCommunication = function ( role , personality , key , value )
{
if ( ! this . $commsSettings [ role ] )
{
this . $commsSettings [ role ] = { } ;
}
if ( ! this . $commsSettings [ role ] [ personality ] )
{
this . $commsSettings [ role ] [ personality ] = { } ;
}
this . $commsSettings [ role ] [ personality ] [ key ] = value ;
}
/* Bulk setting of communications */
this . _setCommunications = function ( obj )
{
var roles = Object . keys ( obj ) ;
for ( var i = 0 ; i < roles . length ; i ++ )
{
var personalities = Object . keys ( obj [ roles [ i ] ] ) ;
for ( var j = 0 ; j < personalities . length ; j ++ )
{
var keys = Object . keys ( obj [ roles [ i ] ] [ personalities [ j ] ] ) ;
for ( var k = 0 ; k < keys . length ; k ++ )
{
var val = obj [ roles [ i ] ] [ personalities [ j ] ] [ keys [ k ] ] ;
this . _setCommunication ( roles [ i ] , personalities [ j ] , keys [ k ] , val ) ;
}
}
}
2013-08-05 14:14:50 +01:00
}
this . _threatAssessment = function ( ship , full )
{
2013-08-07 16:29:24 +01:00
full = full || ship . hasHostileTarget || ( ship . isPlayer && player . alertCondition == 3 ) ;
return ship . threatAssessment ( full ) ;
}