Back to Index Page generated: Sep 15, 2026, 9:03:40 PM

Expansion Nexus Missile

Content

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description Provides several multi-warhead, semi-automatically-targetting, missiles. Available for purchase in various locations. Provides several multi-warhead, semi-automatically-targetting, missiles. Available for purchase in various locations.
Identifier oolite.oxp.UK_Eliter.NexusMissile oolite.oxp.UK_Eliter.NexusMissile
Title Nexus Missile Nexus Missile
Category Weapons Weapons
Author UK_Eliter UK_Eliter
Version 3.0 3.0
Tags Weapons Weapons
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
Conflict Expansions
Information URL https://wiki.alioth.net/index.php/Nexus_Missile n/a
Download URL https://wiki.alioth.net/img_auth.php/d/da/Oolite.oxp.UK_Eliter.NexusMissile.oxz http://wiki.alioth.net/img_auth.php/d/da/Oolite.oxp.UK_Eliter.NexusMissile.oxz
License Creative Commons Attribution - Non-Commercial - Share Alike 4.0 license Creative Commons Attribution - Non-Commercial - Share Alike 4.0 license
File Size n/a
Upload date 1789431410

Relationships Diagram

Documentation

Also read http://wiki.alioth.net/index.php/Nexus%20Missile

Readme & License.txt

==========================================
"Nexus missile" OXP
by (the unimaginatively named) 'UK_Eliter'
==========================================

-------------
GENERAL NOTES
-------------

This OXP provides various multi-warhead, semi-automatically-targetting, missiles.

-------
LICENSE
-------

This OXP is released under the Creative Commons Attribution - Non-Commercial - Share Alike 3.0 license.

This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike License. 
To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/2.0/ 
or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. 

You are free: 

� to copy, distribute, display, and perform the work 
� to make derivative works 

Under the following conditions.

� Attribution. You must give the original author credit. 
� Non-commercial. You may not use this work for commercial purposes. 
� Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license materially identical to this one. 

For any reuse or distribution, you must make clear to others the license terms of this work. 
Any of these conditions can be waived if you get permission from the copyright holder. 
Your fair use and other rights are in no way affected by the above.


ACKNOWLEDGEMENTS

The following provided advice and/or materials for this OXP.

- Eric Walch;
- Thargoid;
- Ramirez;
- Rustem.

Equipment

Name Visible Cost [deci-credits] Tech-Level
Nexus Missile yes 10950 8+
Nexus Bug-Off Missile yes 82500 13+
Nexus Bug-Off Missile (naval reject) yes 40000 3+
Nexus Missile (premium version) yes 19000 9+
Nexus Missile (ultimate version) yes 56000 12+

Ships

Name
Nexus warhead (bug-off version)
Nexus missile (basic version)
Nexus bug-off missile
nexus-missile-bugOff-navalReject
Nexus missile (premium version)
Nexus missile (ultimate version)
Nexus warhead
Nexus warhead (premium version)
Nexus warhead (ultimate version)

Models

This expansion declares no models.

Scripts

Path
Scripts/nexus_conditions.js
/*
===================================================================================

This file: 			nexus_conditions.js
Author: 			UK_Eliter
License: 			2017 Creative Commons: attribution, non-commercial, sharealike.

===================================================================================
*/


/*
==============
LINTER OPTIONS
==============
*/

/* jshint esversion: 6 */
/* jshint -W030 */


/*
======
HEADER
======
*/

this.name = 'nexus_conditionsScript';
this.author = 'UK_Eliter';
this.description = 'Conditions script for Nexus missile';
this.copyright = '2014 Creative Commons: attribution, non-commercial, sharealike.';
this.licence = 'CC-NC-SA 3';


/*
--------------
DEBUG SWITCHES
--------------
*/

//this.logging = true; // THIS SHOULD BE COMMENTED OUT WHEN NOT TESTING
//this.dbg = false;



/*
------------------------
JSHINT: start of wrapper
------------------------
*/

(function () {
	'use strict';


	/*
	---------
	MAIN CODE
	---------
	*/

	this.allowAwardEquipment = function (
		eqKey,
		ship,
		context
	) {

		var prob = 0;

		switch (eqKey) {
		case 'EQ_NEXUS_BASIC_MISSILE':
			prob = 0.9;
			break;
		case 'EQ_NEXUS_PREMIUM_MISSILE':
			prob = 0.8;
			break;
		case 'EQ_NEXUS_ULTIMATE_MISSILE':
			prob = 0.6;
			break;
		case 'EQ_NEXUS_BUG_MISSILE':
			if (player.ship.dockedStation === 'Navy SecCom Station') {
				prob = 0.9;
			} else {
				prob = 0.4;
			}
			break;
		case 'EQ_NEXUS_BUG_R_MISSILE':
			if (player.ship.dockedStation === 'Navy SecCom Station') {
				prob = 0.5;
			} else {
				prob = 0.8;
			}
		}
		if (prob === 0) {
			return false;
		}
		if (Math.random() < 0.9) {
			if (system.scrambledPseudoRandomNumber(5922) < prob) {
				return true;
			}
		} else if (Math.random() < prob) {
			return true;
		}
		return false;

	};


	/*
	----------------------
	JSHINT: end of wrapper
	----------------------
	*/

}).call(this);

// EOF
Scripts/nexus_missile_basicOrPremiumOrUltimate.js
/*
////////////////////////////////////////////////////////////////////////////////
This file:       nexus_missile_basicOrPremiumOrUltimate.js
Associated AI:   nexus_missile_basicOrPremiumOrUltimate.plist
Author:          UK_Eliter
License:         2017 Creative Commons: attribution, non-commercial, sharealike.
////////////////////////////////////////////////////////////////////////////////

*/

/*
==============
LINTER OPTIONS
==============
*/

/* jshint esversion: 6 */
/* jshint -W030 */


/*
======
HEADER
======
*/

this.name = 'nexus_missile_basicOrPremiumOrUltimate.js';
this.author = 'UK_Eliter';
this.description = '';
this.copyright = '2014 Creative Commons: attribution, non-commercial, sharealike.';
this.licence = 'CC-NC-SA 3';


/*
============================
GLOBALS, including debugging
============================
*/

this.dbg = false; // NB
this.missileType = null; // specified later
// this.isSpawning = false; // See this.shipTakingDamage


/*
========================
JSHINT: start of wrapper
========================
*/

(function () {
    'use strict';

    /*
    --------------
    Event handlers
    --------------
    */

    this.shipSpawned = function () {
        this.energyThresholdForDamage = this.ship.maxEnergy * 0.8;
        if (this.ship.hasRole('EQ_NEXUS_BASIC_MISSILE')) {
            this.missileType = 1;
        } else if (this.ship.hasRole('EQ_NEXUS_PREMIUM_MISSILE')) {
            this.missileType = 2;
        } else {
            this.missileType = 3; // 'EQ_NEXUS_ULTIMATE_MISSILE'
        }
        this.dbg && log(this.name, 'shipSpawned - missile type: ' + this.missileType); // TEST
    };

    /*
    // This routine seems to stop the premium or ultimate models - but not the basic model - from spawning, or at least from continuing to exist.
    // EDIT: The problem may have been elsewhere. CONSIDER REINSTATING. TO DO.

        this.shipTakingDamage = function (amount, whom, type) {
            if (this.ship.target) {
                if (
                    (whom == this.ship.target) &&
                    (type === 'scrape damage') &&
                    (amount > this.ship.energy) &&
                    (Math.random() < 0.9)
                ) {
                    this.ship.energy = this.ship.energy + amount; // keep it around long enough to detonate it.
                    this.dbg && log(this.name, 'Detonating, via damage'); // TEST
                    this.$detonate_core();
                    return;
                }
            }
            if (
                (Math.random() > 0.5) ||
                (
                    (amount > 60) &&
                    (this.ship.energy < this.energyThresholdForDamage)
                )
            ) {
                if (!this.isSpawning) {
                    // Keep it around long enough for it to spawn. We can seem to get an infinite loop. Hence the check.
                    this.ship.energy = this.ship.energy + amount;
                    this.dbg && log(this.name, 'Spawning, via damage'); // TEST
                    this.isSpawning = true;
                    this.$spawnWarheads_core();
                }
            }
        };
    */

    /*
    ----------------------
    Functions called by AI
    ----------------------
    */

    this.$_detonate = function () {
        this.$detonate_core();
    };

    this.$_spawnWarheads = function () {
        this.$spawnWarheads_core();
    };


    /*
    -----
    Other
    -----
    */

    this.$detonate_core = function () {
        /*
            `function dealEnergyDamage(damage : Number, idealRange : Number [, velocityBias : Number])`
            The standard Oolite missile uses dealEnergyDamage(170, 32.5, 0.25), has a maximum speed of 0.75LM, and its AI tries to detonate it 25m from its target. [NB: If target within ideal range, takes full damage.]
        */
        switch (this.missileType) {
        case 1:
            this.ship.dealEnergyDamage(330, 50, 0.25);
            break;
        case 2:
            this.ship.dealEnergyDamage(470, 70, 0.25);
            break;
        case 3:
            this.ship.dealEnergyDamage(600, 90, 0.25);
            break;
        default:
            this.dbg && log(this.name, 'Error: bad missileType <' + this.missileType + '> in $detonate_core');
        }
        this.ship.explode();
    };

    // this.$isHostile = function (e) {
    //  // if (this.dbg) {player.consoleMessage('Hostile scan from MISSILE script', 6);}
    //  return e.isShip &&
    //      e.hasHostileTarget &&
    //      (e.target == this.ship.owner);
    // };

    this.$spawnWarheads_core = function () {
        /*
        -------------
        PRELIMINARIES
        -------------
        */
        if (this.dbg) {
            log(this.name, '$spawnWarheads_core - entered');
            log(this.name, '$spawnWarheads_core - missileType: ' + this.missileType);
        }
        if (
            !this.ship ||
            !this.ship.owner
        ) {
            this.dbg && log(this.name, 'bad shap or bad owner');
            return;
        }

        var
            numWarheads,
            submunition_as_role;

        switch (this.missileType) {
        case 1:
            numWarheads = 3;
            submunition_as_role = 'nexus_warhead';
            break;
        case 2:
            numWarheads = 3;
            submunition_as_role = 'nexus-premium-warhead';
            break;
        case 3:
            numWarheads = 4;
            submunition_as_role = 'nexus-ultimate-warhead';
            break;
        default:
            this.dbg && log(this.name, 'Error: bad missileType <' + this.missileType + '> in $spawnWarheads_core');
        }


        /*
        -----------------------------------------------------------------------------------------------------
        Once spawned (which happens later), each head initially will have as its target the missile's target.
        Yet, if there are other potential targets, then we want to distribute them amongst the warheads.

        Here is the main logic of the code below.

        We get a list of ships near the missle.

        We see which are hostile to the player.

        Then, skipping the first warhead, we assign the hostiles (in order found) as targets.
        Insofar as there are more warheads - or warheads-minus-one - than hostiles, some warheads will end
        up, like the first warhead, with the target of the original missile.

        Often the foregoing will result in the original target being targetted by two warheads, even if there
        are multiple hostiles. But that is OK (and allows for relatively simple code).
        -----------------------------------------------------------------------------------------------------
        */


        /*
        --------------------------------------------
        BEGIN TO DETERMINE TARGETS:
        get a list of powered ships near the missile.
        ---------------------------------------------
        */

        const missile = this.ship;
        const shipsNearMissile = missile.checkScanner(true);
        var
            i,
            missileOwner,
            warheadTargets = [],
            warheadTargetsIncludeMissileTarget = false;

        if (missile.owner && missile.owner.isValid) {
            missileOwner = missile.owner;
        } else {
            log(this.name, 'Missile lacks owner!');
        }

        const missileOwned = !!missileOwner; // This JS engine seems to lack the operator 'boolean'.

        if (shipsNearMissile.length > 0) {
            // There is something within scanner range of the missile that is powered (though it might be only the ship that fired the missile!).

            /*
            -----------------------------------------------------------------------------
            CONTINUE TO DETERMINE TARGETS:
            see which if any of the nearby ships are targetting the owner of the missile.
            -----------------------------------------------------------------------------
            */

            if (missileOwned) {
                /*
                If the ship that fired the missile still exists, then populate warheadTargets with those nearby ships that are hostile to the ship.
                And if one of those hostile ships is the missile's target, then record that fact.
                */
                this.dbg && log(this.name, 'Checking hostility of nearby ships:');
                const targetsToSeek = numWarheads - 1; // We leave the first warhead's target - which should be the missile's target - alone.
                var numHostiles = 0;
                for (
                    i = 0; i < shipsNearMissile.length; i++
                ) {
                    this.dbg && log(this.name, '-- ship #' + i); // TEST
                    if (
                        shipsNearMissile[i].hasHostileTarget &&
                        shipsNearMissile[i].target == missileOwner
                    ) {
                        warheadTargets.push(shipsNearMissile[i]);
                        numHostiles++;
                        this.dbg && log(this.name, '---- HOSTILE');
                        if (numHostiles >= targetsToSeek) {
                            this.dbg && log(
                                this.name, '-- breaking loop: ' + targetsToSeek + ' target(s), ' + numWarheads + ' warheads'
                            ); // TEST
                            break;
                        }
                    } else if (this.dbg) {
                        this.dbg && log(this.name, '---- not hostile');
                    }
                }
            } // End of `if (missile.owner && missile.owner.isValid)
        } // End `if (shipsNearMissile.length > 0)`

        /*
        If there was nothing at all within scanner range of the missile (or indeed merely the player), then presumably, when we spawn the warheads, they are going to get an invalid
        target. But try anyway.
        */

        /*
        ----------------------------
        SPAWNING, OWNERSHIP, TARGETS
        ----------------------------
        */

        /*
        Upon spawn, the warheads will have the missile as the owner. That is good in that they inherit the target.
        It is bad in that they lack legal connection to the ship that fired the missile.
        But Oolite's owner property is read-only.
        So, give each warhead an 'urOwner' property.
        Also, store the missile/warhead's original target.
        */
        const missileHasTarget = !!missile.target; // This JS engine seems to lack the operator 'boolean'.

        const
            isOwnedWithTarget = missileOwned && missileHasTarget,
            isOwnedWithoutTarget = missileOwned && !missileHasTarget,
            isUnownedWithTarget = !missileOwned && missileHasTarget,
            unOwnedWithoutTarget = !missileOwned && !missileHasTarget;

        // Spawn the warheads (as late as possible). In so doing, each warheads gets as its target the missile's target.
        const warheads = missile.spawn(
            submunition_as_role,
            numWarheads
        );

        if (warheads.length === 0) {
            this.dbg && log(this.name, 'Failed to spawn warheads');
            // ^ I have had this happen. I am unsure why.
            this.ship.explode();
            return;
        }

        switch (true) {
        case isOwnedWithTarget:
            this.dbg && log(this.name, "Setting ownership and 'old target':");
            for (i = 0; i < numWarheads; i++) {
                this.dbg && log(this.name, '-- warhead #' + i); // TEST
                if (warheads[i] && warheads[i].isValid) {
                    warheads[i].urOwner = missile.owner;
                }
                if (warheads[i] && warheads[i].isValid) {
                    warheads[i].oldTarget = missile.target;
                }
            }
            break;

        case isOwnedWithoutTarget:
            // missileOwned is true; missileHasTarget is false.
            if (this.dbg) {
                log(this.name, 'Missile lacks target!');
                log(this.name, 'Setting ownership:');
            }
            for (i = 0; i < numWarheads; i++) {
                this.dbg && log(this.name, '-- warhead #' + i); // TEST
                if (warheads[i] && warheads[i].isValid) {
                    warheads[i].urOwner = missile.owner;
                }
            }
            break;

        case isUnownedWithTarget:
            // missileOwned is false; missileHasTarget is true.
            if (this.dbg) {
                log(this.name, 'Missile lacks owner!');
                log(this.name, "Setting 'old target':");
            }
            for (i = 0; i < numWarheads; i++) {
                this.dbg && log(this.name, '-- warhead #' + i); // TEST
                if (warheads[i] && warheads[i].isValid) {
                    warheads[i].oldTarget = missile.target;
                }
            }
            break;

        case unOwnedWithoutTarget:
            // missileOwned is false; missileHasTarget is false.
            if (this.dbg) {
                log(this.name, 'Missile lacks target!');
                log(this.name, 'Missile lacks owner!');
            }
        }

        const numTargets = warheadTargets.length;
        if (numTargets < 1) {
            this.dbg && log(this.name, 'No targets to assign');
        } else {
            this.dbg && log(this.name, 'Assigning targets to ' + numTargets + ' warheads:');
            for (i = 0; i < numTargets; i++) {
                this.dbg && log(this.name, '-- warhead #' + i); // TEST
                if (warheads[i] && warheads[i].isValid) {
                    warheads[i].target = warheadTargets[i];
                }
            }
        }

        // TEST:
        if (this.dbg) {
            if (!warheads[0] || !warheads[0].isValid) {
                log(this.name, 'Warhead 0 does not exist');
            } else {
                if (!warheads[0].target) {
                    log(this.name, 'Warhead 0 has no target at all!');
                }
            }
        }

        /*
        ------------------
        REMOVE THE MISSILE
        ------------------
        */
        this.ship.explode();
    };


    /*
    ======================
    JSHINT: end of wrapper
    ======================
    */

}).call(this);

// EOF
Scripts/nexus_missile_bugOff.js
/*
///////////////////////////////////////////////////////////////////////////////
This file: 		nexus_missile_bugOff.js 
Associated AI: 	nexus_missile_bugOff.plist
Author:         UK_Eliter
License:        2017 Creative Commons: attribution, non-commercial, sharealike.
///////////////////////////////////////////////////////////////////////////////

*/


/*
==============
LINTER OPTIONS
==============
*/

/* jshint esversion: 6 */
/* jshint -W030 */


/*
======
HEADER
======
*/

this.name = 'nexus_missile_bugOff.js';
this.author = 'UK_Eliter';
this.description = 'Script for Nexus BugOff missile';
this.copyright = '2014 Creative Commons: attribution, non-commercial, sharealike.';
this.licence = 'CC-NC-SA 3';


/*
==============
DEBUG SWTICHES
==============
*/

this.dbg = false; // NB


/*
========================
JSHINT: start of wrapper
========================
*/

(function () {
	'use strict';

	/*
	--------------
	Event handlers
	--------------
	*/

	this.shipSpawned = function () {
		this.missileEnergyThreshold = this.ship.maxEnergy * 0.7;
	};

	// Do not spawn warheads if the missile has received a large hit, or if the missile has considerable energy remaining.
	this.shipTakingDamage = function (amount) {
		if (
			amount > 25 ||
			this.ship.energy > this.missileEnergyThreshold
		) {
			return;
		}
		if (Math.random() < 0.9) {
			this.$spawnWarheads_core();
		}
	};


	/*
	----------------------
	Functions called by AI
	----------------------
	*/

	this.$_detonate = function () {
		this.ship.dealEnergyDamage(650, 50, 0.25);
		this.ship.explode();
	};

	this.$_spawnWarheads = function () {
		this.$spawnWarheads_core();
	};


	/*
	-----
	Other
	-----
	*/

	this.$spawnWarheads_core = function () {

		this.dbg && log(this.name, '$spawnWarheads_core - entered'); // TEST

		const
			countAdvertised = 5;
		var
			chanceMalfunction,
			countToSpawn,
			countToSpawnOnMalfunction;

		if (this.ship.hasRole('EQ_NEXUS_BUG_R_MISSILE')) {
			// This is the military reject missile.
			chanceMalfunction = 0.19;
			countToSpawnOnMalfunction = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4][Math.floor(Math.random() * 10)];
			// ^ Number will be between 1 and 4, biased moderately towards the high end of the list.
		} else {
			// This is the normal missile.
			chanceMalfunction = 0.025;
			countToSpawnOnMalfunction = [1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4][Math.floor(Math.random() * 16)];
			// ^ Number will be between 1 and 4, biased heavily towards the high end of the list.
		}

		if (Math.random() > chanceMalfunction) {
			countToSpawn = countAdvertised;
		} else {
			countToSpawn = countToSpawnOnMalfunction;
		}

		this.dbg && log(this.name, '$spawnWarheads_core - spawning ' + countToSpawn + ' warheads'); // TEST

		const warheads = this.ship.spawn('nexus-bug-warhead', countToSpawn);
		if (this.dbg && warheads.length === 0) {
			log(this.name, '$spawnWarheads_core - failed to spawn any warheads'); // TEST
		}
		
		this.ship.explode();

	};


	/*
	======================
	JSHINT: end of wrapper
	======================
	*/

}).call(this);


// EOF
Scripts/nexus_warhead_basicOrPremiumOrUltimate.js
/*
///////////////////////////////////////////////////////////////////////////////
This file: 		nexus_warhead_basicOrPremiumOrUltimate.js 
Associated AI: 	nexus_warhead_basicOrPremiumOrUltimate.plist
Author: 		UK_Eliter
License: 		2017 Creative Commons: attribution, non-commercial, sharealike.
///////////////////////////////////////////////////////////////////////////////


/*
==============
LINTER OPTIONS
==============
*/

/* jshint esversion: 6 */
/* jshint -W030 */


/*
======
HEADER
======
*/

this.name = 'nexus_warhead_basicPremiumOrUltimate.js';
this.author = 'UK_Eliter';
this.description = 'Script for Nexus missile warheads';
this.copyright = '2014 Creative Commons: attribution, non-commercial, sharealike.';
this.licence = 'CC-NC-SA 3';


/*
============================
GLOBALS, including debugging
============================
*/

this.dbg = false; // NB

this.warheadType = null; // This gets set to something meaningful below.

// this.ship.oldTarget is set, initially, by the _missile_ script and also by this script - once this script finds a target.

/*
========================
JSLINT: start of wrapper
========================
*/

(function () {
	'use strict';


	/*
	--------------
	EVENT HANDLERS
	--------------
	*/

	this.shipSpawned = function () {
		// this.dbg && log(this.name, 'SPAWNED');
		if (this.ship.primaryRole === 'nexus_warhead') {
			this.warheadType = 1; // 1 = basic
		} else if (this.ship.primaryRole === 'nexus-premium-warhead') {
			this.warheadType = 2; // 2 = premium
		} else {
			this.warheadType = 3; // 3 = ultimate
		}
		this.dbg && log(this.name, 'shipSpawned - warhead type: ' + this.warheadType); // TEST
	};

	// this.shipTakingDamage = function (amount, whom, type) {
	// 	this.dbg && log(this.name, 'Taking damage:' + amount); // TEST
	// 	if (amount > 14 || Math.random() > 0.2) return;
	// 	this.ship.energy = this.ship.energy + amount; // keep it around long enough to detonate it.
	// 	this.$detonate_core();
	// };

	/*
	------------------------------------
	ROUTINES CALLED BY AI and only by AI
	------------------------------------
	*/

	this.$_scanForTargets = function () {
		this.dbg && log(this.name, 'Scanning for targets'); // TEST
		/*
		Here we use the 'urOwner' of the warhead.
		The script that spawned the warhead creates that property and sets it to the ship that fired the original missile. 
		*/
		const
			nearShips = this.ship.checkScanner(true),
			warhead = this.ship;
			
		var i = nearShips.length;
		if (i > 0) {
			if (warhead.urOwner && warhead.urOwner.isValid) {
				while (i--) {
					if (
						nearShips[i].isValid &&
						nearShips[i].hasHostileTarget &&
						(nearShips[i].target === warhead.urOwner)
					) {
						warhead.target = nearShips[i];
						warhead.oldTarget = nearShips[i];
						warhead.reactToAIMessage('SCRIPT_TARGET');
						this.dbg && log(this.name, '-- found one'); // TEST
						return;
					}
				} // End 'while'
			} else {
				this.dbg && log(this.name, '-- urOwner bad'); // Happens when launching ship is gone // TEST
			}
		} else {
			this.dbg && log(this.name, '-- nothing nearby'); // TEST
		}

		this.dbg && log(this.name, '-- none found'); // TEST
		// We found no target. Can we revert to an old target?
		if (
			this.oldTarget &&
			this.oldTarget.isValid
		) {
			this.dbg && log(this.name, '-- reverting to old target'); // TEST
			warhead.target = this.oldTarget;
			warhead.reactToAIMessage('SCRIPT_TARGET');
			return;
		}
		this.dbg && log(this.name, '-- found no old target'); // TEST
		warhead.reactToAIMessage('SCRIPT_NO_TARGET');
	};


	/*
	-----
	OTHER
	-----
	*/

	this.$detonate_core = function () {
		/*
			`function dealEnergyDamage(damage : Number, idealRange : Number [, velocityBias : Number])`
			The standard Oolite missile uses dealEnergyDamage(170, 32.5, 0.25), has a maximum speed of 0.75LM, and its AI tries to detonate it 25m from its target. [NB: If target within ideal range, takes full damage.]
			
			1 = basic; 2 = premium; 3 = ultimate.
		*/
		switch (this.warheadType) {
		case 1:
			this.ship.dealEnergyDamage(110, 27, 0.25);
			break;
		case 2:
			this.ship.dealEnergyDamage(150, 31, 0.22);
			break;
		case 3:
			this.ship.dealEnergyDamage(195, 36, 0.15);
			break;
		default:
			this.dbg && log(this.name, 'Error: bad warheadType <' + this.warheadType + '> in $detonate_core');
		}
		this.ship.explode();
	};


	/*
	======================
	JSHINT: end of wrapper
	======================
	*/


}).call(this);

// EOF
Scripts/nexus_warhead_bugOff.js
/*
///////////////////////////////////////////////////////////////////////////////
This file:		nexus_warhead_bugOff.js
Associated AI: 	nexus_warhead_bugOff.plist
Part of: 		Nexus Missile OXP
Author: 		UK_Eliter
License: 		2017 Creative Commons: attribution, non-commercial, sharealike.
///////////////////////////////////////////////////////////////////////////////
*/


/*
==============
LINTER OPTIONS
==============
*/

/* jshint esversion: 6 */
/* jshint -W030 */


/*
======
HEADER
======
*/

this.name = 'nexus_warhead_bugOff.js';
this.author = 'UK_Eliter';
this.description = 'Script for Nexus BugOff warhead';
this.copyright = '2014 Creative Commons: attribution, non-commercial, sharealike.';
this.licence = 'CC-NC-SA 3';



/*
==============================
GLOBALS, including debugging
But debugging currently unused
==============================
*/

// this.dbg = true;


/*
========================
JSHINT: start of wrapper
========================
*/

(function () {
	'use strict';

	/*
	-----------------
	Code called by AI
	-----------------
	*/

	this.$_detonate = function () {
		// One should make the range values fit well with the desiredRanges set in the AIs.
		const
			damage_anyShip = 35,
			damage_anyShip_velocityBias = 0.25,
			damage_thargoidExtra = 135,
			range_ideal_anyShip = 20,
			range_total_thargoid = 60;

		this.ship.dealEnergyDamage(
			range_ideal_anyShip,
			damage_anyShip,
			damage_anyShip_velocityBias
		);
		/*
		The standard Oolite missile uses dealEnergyDamage(170, 32.5, 0.25), has a maximum speed of 0.75LM (which is the same for our warhead, except that our warhead is fuel injected), and its AI tries to detonate it 25m from its target. (NB: If target within ideal range, takes full damage.) The anti-thargoid missile in Missiles & Bombs (rmb-thargoid-warhead-script.js) is: 170, 25.0, 0.25 and has four warheads.
		Tharglet energy: 150.
		*/

		/*
		Deal additional damage to anything nearby that is thargoid.
		Our method is crude, but: implementing a more sophisticated method is hard to achievel; players are unlikely to notice the crudity.
		*/
		const s = system.filteredEntities(
			this,
			this.$isBug,
			this.ship,
			range_total_thargoid
		);

		var i = s.length;
		while (i--) {
			s[i].energy -= range_total_thargoid;
		}
		this.ship.explode(); // Explode the warhead entity (harmlessly, I think).
	};


	/*
	-----
	Other
	-----
	*/

	this.$isBug = function (e) {
		return e.isShip && e.isThargoid;
	};

	/*
	======================
	JSHINT: end of wrapper
	======================
	*/

}).call(this);


// EOF