Back to Index Page generated: May 8, 2024, 6:16:03 AM

Expansion Fer-de-Lance 3G

Content

Warnings

  1. Replaced equipment 'EQ_F3G_ANTISWEEP_MISSILE'
  2. Replaced equipment 'EQ_F3G_ANTISWEEP_MISSILE'
  3. Unresolved dependency reference to oolite.oxp.Ferdelance_3G:0
  4. No version in dependency reference to oolite.oxp.UK_Eliter.Ferdelance_3G:null
  5. No version in dependency reference to oolite.oxp.Ferdelance_3G:null
  6. Conflict Expansions mismatch between OXP Manifest and Expansion Manager at character position 0068 (DIGIT ZERO vs LATIN SMALL LETTER N)
  7. Unknown key 'upload_date' at https://wiki.alioth.net/img_auth.php/d/da/Oolite.oxp.UK_Eliter.Ferdelance_3G.oxz!manifest.plist

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description Adds a line of Fer-de-Lance ships. Player buyable. Adds a line of Fer-de-Lance ships. Player buyable.
Identifier oolite.oxp.UK_Eliter.Ferdelance_3G oolite.oxp.UK_Eliter.Ferdelance_3G
Title Fer-de-Lance 3G Fer-de-Lance 3G
Category Ships Ships
Author UK_Eliter UK_Eliter
Version 6.63 6.63
Tags ships ships
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
  • oolite.oxp.UK_Eliter.ExtraThargoids:6.5
  • oolite.oxp.UK_Eliter.InterstellarTweaks:5.1
  • oolite.oxp.UK_Eliter.ExtraThargoids:6.5
  • oolite.oxp.UK_Eliter.InterstellarTweaks:5.1
  • Conflict Expansions
  • oolite.oxp.UK_Eliter.Ferdelance_3G:0
  • oolite.oxp.Ferdelance_3G:0
  • oolite.oxp.UK_Eliter.Ferdelance_3G:
  • oolite.oxp.Ferdelance_3G:
  • Information URL http://aegidian.org/bb/viewtopic.php?f=4&t=9415 n/a
    Download URL https://wiki.alioth.net/img_auth.php/d/da/Oolite.oxp.UK_Eliter.Ferdelance_3G.oxz http://wiki.alioth.net/img_auth.php/d/da/Oolite.oxp.UK_Eliter.Ferdelance_3G.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 1646067123

    Documentation

    Also read http://wiki.alioth.net/index.php/Fer-de-Lance%203G

    Ferdelance3G Readme & License.txt

    ==========================================
    'Fer-de-Lance 3G' OXP by (the unimaginatively named) 'UK_Eliter'
    ==========================================
    
    --------------------------
    GENERAL NOTES
    --------------------------
    
    � This OXP does not depend on any other OXP. Yet, it does work better when various other OXPs are installed, including these ones: Armoury; Missiles & Bombs; Nexus Missile; Thargoid Carrier.
    
    � For details of (most of . .) the ships, please see the accompanying PDF brochure.
    
    � This ship needs Oolite version >= 1.82.
    
    
    � PLEASE DELETE OLD VERSION OF THE OXP FROM YOUR ADDONS FOLDER BEFORE COPYING-IN THIS ONE.
    
    ---------------------------
    ACKNOWLEDGEMENTS
    ---------------------------
    
    The graphics in this OXP are adapted from the ferdelance model built into Oolite.
    
    My thanks to the following for help with this OXP.
    
    'cim'
    'Commander McLane' (from whose Anarchies OXP I have somewhat adapted some message descriptions)
    'Diziet Sma'
    'Eric Walch' (who provided some javascript routines)
    'fronclynne'
    'Killer Wolf'
    'Rustem'
    'Smivs' (for help with graphics)
    'Svengali'
    'Thargoid' (from whose 'Vortex' OXP the turrets in this my OXP are adapted - and adapted, indeed, mainly *by* Thargoid; I've borrowed some material from his Aquatics and Armoury OXPs too)
    
    
    ---------------------------
    GENERAL INFO
    ---------------------------
    
    The 'Config' folder contains a script that can be used to see - in form of non-player-characters - some of the ships contained in this OXP. See within that folder itself for further instructions.
    
    Please see the PDF for the specifications of the '3G' ships.
    
    ---------------------------
    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. 
    
    But only under the following conditions.
    
    � Attribution: you must give the original author credit. 
    � Non-commercial use: 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. 
    
    Your fair use right and other rights are in no way affected by the above.
    
    ----------------- END ----------------- 
    

    Equipment

    Name Visible Cost [deci-credits] Tech-Level
    Sweeper-resistant navy missile yes 14000 13+

    Ships

    Name
    ferdelance3-player
    ferdelance3-playerPlusModel
    ferdelance3-playerPlusModelWithTurrets
    ferdelance3-playerPlusModelWithTurretsPoliceDecomissioned
    ferdelance3-playerVariant
    Fer-de-Lance 3G+(t)
    ferdelance3G_+(t)TemplateNPC
    ferdelance3G_+HardPirate
    ferdelance3G_+T_HardPirate
    ferdelance3G_+T_HardPiratePoliceDecomissioned
    Fer-de-Lance 3G+
    ferdelance3G_+TemplateNPC
    Sweeper-resistant navy missile
    ferdelance3G_escort1
    ferdelance3G_escort2
    ferdelance3G_escort3
    ferdelance3G_escort4
    ferdelance3G_escort5
    ferdelance3G_escort6
    ferdelance3G_escort7
    ferdelance3G_escort8
    ferdelance3G_hardHunter
    ferdelance3G_hardPirate
    ferdelance3G_hardPirateAlt
    ferdelance3G_hardTrader
    ferdelance3G_hardTrader3G+
    ferdelance3G_hardTrader3G+Escorted
    ferdelance3G_hardTrader3G+EscortedVariant
    ferdelance3G_hardTraderEscorted
    ferdelance3G_hardTraderEscortedVariant
    ferdelance3G_hardTraderEscortedVariant2
    ferdelance3G_hardTraderVariant
    ferdelance3G_hardestHunter
    ferdelance3G_hardestHunterEscorted
    ferdelance3G_hardestHunterPoliceDecomissioned
    ferdelance3G_hunter
    ferdelance3G_hunterVariant
    Fer-de-Lance 3G+(t) (military interstellar)
    Fer-de-Lance 3G+(t) (military Bugblatter)
    ferdelance3G_interstellarTurret
    ferdelance3G_interstellarTurret2
    ferdelance3G_pirate
    ferdelance3G_pirateAlt
    Fer-de-Lance 3G+(t) (Pirate King)
    ferdelance3G_player
    ferdelance3G_playerPlusModel
    ferdelance3G_playerPlusModelWithTurrets
    ferdelance3G_playerPlusModelWithTurretsPoliceDecomissioned
    Fer-de-Lance 3G (Delux-o-Tank variant)
    ferdelance3G_playerVariant
    ferdelance3G_polTurret
    Fer-de-Lance 3G+(t) (police)
    Fer-de-Lance 3G+(t) (ex-police)
    Fer-de-Lance 3G
    ferdelance3G_templateNPC
    ferdelance3G_trader
    ferdelance3G_traderVariant
    3G Turret
    Fer-de-Lance 3G
    ferdelance3G_variantTemplateNPC

    Models

    This expansion declares no models. This may be related to warnings.

    Scripts

    Path
    Scripts/ferdelance3G_antiSweeper.js
    /*
    ========================================================================
    ferdelance3G_antiSweeper.js
    This file is part of the 'Ferdelance 3G' expansion pack.
    Author: UK_Eliter
    License: 2017 Creative Commons: attribution, non-commercial, sharealike.
    ========================================================================
    */
    
    
    /*
    ====================
    JSLINT: set options
    ====================
    */
    
    /*jshint esversion: 6*/
    /*jshint sub:true*/
    
    this.name = "ferdelance3G_antiSweeper";
    this.author = "UK_Eliter";
    this.copyright = "";
    this.description = "Script for anti-Sweeper missile ";
    this.license = "CC-by-nc-sa 3.0";
    
    
    
    /*
    ------------------
    DEBUGGING SWITCHES
    ------------------
    */
    
    // this.logging = true;
    var consoleDebugMessages = false; // do NOT comment this out. Rather, to disable, set to false.
    
    
    /*
    ------------------------
    JSLINT: start of wrapper
    ------------------------
    */
    
    (function() {
    	"use strict";
    
    
    	/*
    	--------------------
    	ROUTINE CALLED BY AI
    	The second parameter of dealEnergyDamage is the 'ideal range'; it should match the desiredRange in the AI.
    	See: http://wiki.alioth.net/index.php/Oolite_JavaScript_Reference:_Ship#dealEnergyDamage
    	--------------------
    	*/
    
    	this.$_detonate = function() {
    		if (this.ship.target && this.ship.target.isThargoid) {
    			this.ship.dealEnergyDamage(660, 35, 0.1);
    		} else {
    			this.ship.dealEnergyDamage(300, 35, 0.15);
    		}
    		this.ship.explode();
    	};
    
    
    	/*
    	----------------------
    	JSLINT: end of wrapper
    	----------------------
    	*/
    
    }).call(this);
    
    
    // EOF
    Scripts/ferdelance3G_conditions.js
    /*
    ========================================================================
    ferdelance3G_conditions.js
    This file is part of the 'Ferdelance 3G' expansion pack.
    Author: UK_Eliter
    License: 2017 Creative Commons: attribution, non-commercial, sharealike.
    ========================================================================
    */
    
    
    /*
    ====================
    JSLINT: set options
    ====================
    */
    
    /*jshint esversion: 6*/
    /*jshint sub:true*/
    
    
    this.name = "ferdelance3G_conditionsScript";
    this.author = "UK_Eliter";
    this.description = "ferdelance3G_conditionsScript.js";
    this.copyright = "2014 Creative Commons: attribution, non-commercial, sharealike.";
    this.licence = "CC-NC-SA 3";
    
    
    /*
    ====--------------
    DEBUGGING SWITCHES
    ------------------
    */
    
    var consoleDebugMessages = false; // do NOT comment this out. Rather, to disable, set to false.
    //this.logging = true; // THIS SHOULD BE COMMENTED OUT WHEN NOT TESTING
    //this.debug = false;
    
    
    /*
    ------------------------
    JSLINT: start of wrapper
    ------------------------
    */
    
    (function() {
    	"use strict";
    
    
    	/*
    	------------------
    	CONDITION ROUTINES
    	------------------
    	*/
    
    	this.allowAwardEquipment = function(eqKey, ship, context) {
    		var chance = 0;
    		switch (eqKey) {
    			case "EQ_F3G_ANTISWEEP_MISSILE":
    				if (player.ship.dockedStation === "Navy SecCom Station") {
    					chance = 0.87;
    				} else if (system.techLevel > 10) {
    					chance = 0.7;
    				} else {
    					if (system.techLevel > 8) {
    						chance = 0.45;
    					}
    				}
    		}
    		if (chance === 0) {
    			return;
    		}
    		if (Math.random() < 0.9 && system.scrambledPseudoRandomNumber(6921) < chance) {
    			return true;
    		}
    		if (Math.random() < chance) {
    			return true;
    		}
    		return false;
    	};
    
    	this.updateEquipmentPrice = function(eqKey, currentPrice) {
    		var myPrice;
    		switch (eqKey) {
    			case "EQ_F3G_ANTISWEEP_MISSILE":
    				if (player.ship.dockedStation === "Navy SecCom Station") {
    					myPrice = 1000;
    					return (myPrice);
    				}
    				// Otherwise
    				if (system.techLevel > 10) {
    					if (Math.random() < 0.95) {
    						myPrice = 13000 + ((Math.ceil(system.scrambledPseudoRandomNumber(3420) * 10)) * 1000);
    					} else {
    						myPrice = 13000 + ((Math.ceil(Math.random() * 10)) * 1000);
    					}
    					return (myPrice);
    				}
    				// Otherwise
    				if (system.techLevel > 8) {
    					if (Math.random() < 0.95) {
    						myPrice = 10000 + ((Math.ceil(system.scrambledPseudoRandomNumber(3420) * 18)) * 1000);
    					} else {
    						myPrice = 10000 + ((Math.ceil(Math.random() * 18)) * 1000);
    					}
    					return (myPrice);
    				}
    		}
    	};
    
    
    	/*
    	----------------------
    	JSLINT: end of wrapper
    	----------------------
    	*/
    
    }).call(this);
    
    
    // EOF
    Scripts/ferdelance3G_hunter.js
    /*
    ========================================================================
    ferdelance3G_hunter.js
    This file is part of the 'Ferdelance 3G' expansion pack.
    Author: UK_Eliter
    License: 2017 Creative Commons: attribution, non-commercial, sharealike.
    ========================================================================
    */
    
    /*
    ====================
    JSLINT: set options
    ====================
    */
    
    /*jshint esversion: 6*/
    /*jshint sub:true*/
    
    this.name = "ferdelance3G_hunter";
    this.author = "UK_Eliter";
    this.copyright = "";
    this.description = "ferdelance3G_hunter.js (for NPCs)";
    this.license = "2014 CC-by-nc-sa 3.0";
    
    
    /*
    ------------------
    DEBUGGING SWITCHES
    ------------------
    */
    
    // this.logging = true;
    var consoleDebugMessages = false; // do NOT comment this out. Rather, to disable, set to false.
    this.debug = false;
    
    if (this.debug) {
    	this.ship.reportAIMessages = true;
    }
    
    
    /*
    ------------------------
    JSLINT: start of wrapper
    ------------------------
    */
    
    (function() {
    	"use strict";
    
    	/*
    	--------------
    	EVENT HANDLERS
    	--------------
    	*/
    
    	this.shipSpawned = function() {
    		var r = Math.random();
    		if (r > 0.45) {
    			// ** Special ORDINANCE **
    			// 1st level ordinance: possibility of some hardheads; 2nd level: more serious stuff; 3rd: q-bomb..
    			var capacity;
    			var chanceThirdLevelOrdinance = 0.11;
    			var giveSecondLevelOrdinance = false;
    			var i;
    			var ordinanceAvailable;
    			var ordinanceCount;
    
    			ordinanceAvailable = ["EQ_MISSILE", "EQ_MISSILE", "EQ_MISSILE"]; // Hard-heads added to the list, below
    			if (this.ship.hasRole("ferdelance3G_+T")) {
    				giveSecondLevelOrdinance = true;
    				chanceThirdLevelOrdinance = 0.15;
    			} else if (r > 0.7) {
    				giveSecondLevelOrdinance = true;
    			}
    			if (giveSecondLevelOrdinance) {
    				if (worldScripts["Missiles & Bombs"]) {
    					ordinanceAvailable.push("EQ_RMB_FRAG_MISSILE", "EQ_RMB_OVERRIDE_MISSILE", "EQ_RMB_LAW_MISSILE", "EQ_RMB_INTERCEPT_MISSILE", "EQ_RMB_INTERCEPT_MISSILE", "EQ_RMB_INTERCEPT_MISSILE");
    				}
    				if (EquipmentInfo.infoForKey("EQ_TORPEDO_MISSILE")) {
    					ordinanceAvailable.push("EQ_TORPEDO_MISSILE");
    				}
    				if (EquipmentInfo.infoForKey("EQ_HARPOON_NUKE1_MISSILE")) {
    					ordinanceAvailable.push("EQ_HARPOON_NUKE1_MISSILE");
    				}
    				if (worldScripts["armoury_trackerWorldScript.js"]) {
    					ordinanceAvailable.push("EQ_ARMOURY_STUNBOMB_MINE");
    					if (this.ship.equipmentStatus("EQ_CLOAKING_DEVICE") != "EQUIPMENT_OK") {
    						ordinanceAvailable.push("EQ_KDRONE_LAUNCHER_MINE", "EQ_CDRONE_LAUNCHER_MINE");
    					}
    				}
    				if (EquipmentInfo.infoForKey("EQ_NEXUS_BUG_MISSILE")) {
    					ordinanceAvailable.push("EQ_NEXUS_PREMIUM_MISSILE");
    					if (r > 0.9) {
    						ordinanceAvailable.push("EQ_NEXUS_PREMIUM_MISSILE");
    					} else {
    						ordinanceAvailable.push("EQ_NEXUS_BASIC_MISSILE");
    					}
    				}
    				capacity = this.ship.missileCapacity;
    				// LEVEL THREE
    				if (Math.random() <= chanceThirdLevelOrdinance) {
    					this.ship.awardEquipment("EQ_QC_MINE"); // NB: actually award
    					--capacity;
    				}
    			}
    			ordinanceCount = ordinanceAvailable.length;
    			i = ordinanceCount;
    			while (i--) {
    				ordinanceAvailable.push("EQ_HARDENED_MISSILE");
    			} // add one of these for every existing missile in the list
    			// Load ordinance to ship
    			ordinanceCount = ordinanceAvailable.length; // this will have changed
    			i = capacity - 1;
    			do {
    				this.ship.awardEquipment(ordinanceAvailable[~~(Math.random() * ordinanceCount)]);
    			}
    			while (i--);
    		}
    		/*
    		**	BOUNTY **
    			NB: This script is used not only for hunters but also for assassins.
    		*/
    		var r2 = Math.random(); // Threshold is 0.7. *Does* need to be r*2*.
    		if (r2 > 0.7) {
    			if (r2 < 0.9) {
    				this.ship.bounty += (Math.ceil(r * 32));
    				// sic - 'r', not 'r2'.
    			} else {
    				this.ship.bounty += 2 + (Math.ceil(r * 120));
    				// sic - 'r', not 'r2'.
    			}
    		}
    		// **CLEAN-UP **
    		delete this.shipSpawned;
    	};
    
    
    
    	/*
    	----------------------
    	JSLINT: end of wrapper
    	----------------------
    	*/
    
    }).call(this);
    
    
    // EOF
    Scripts/ferdelance3G_milInterstellar.js
    /*
    ========================================================================
    ferdelance3G_milInterstellar.js
    This file is part of the 'Ferdelance 3G' expansion pack.
    Author: UK_Eliter
    License: 2017 Creative Commons: attribution, non-commercial, sharealike.
    ========================================================================
    */
    
    
    /*
    ====================
    JSLINT: set options
    ====================
    */
    
    /*jshint esversion: 6*/
    /*jshint sub:true*/
    
    
    this.name = "ferdelance3G_milInterstellar.js";
    this.author = "UK_Eliter";
    this.copyright = "";
    this.description = "ferdelance3G-mainScript.js (for NPCs)";
    this.license = "CC-by-nc-sa 3.0";
    
    
    /*
    ------------------
    DEBUGGING SWITCHES
    ------------------
    */
    
    this.debug = false;
    
    if (this.debug) {
    	this.ship.reportAIMessages = true;
    }
    
    
    /*
    ------------------------
    JSLINT: start of wrapper
    ------------------------
    */
    
    (function() {
    	"use strict";
    
    
    	/*
    	--------------
    	EVENT HANDLERS
    	--------------
    	*/
    
    	this.shipSpawned = function() {
    		// Record presence/absence of some OXPs or weapons for multiple use within THIS function.
    
    		var OXPInstalled_extraBugs;
    		if (worldScripts["extraThargoids_populator.js"]) {
    			OXPInstalled_extraBugs = true;
    		} else {
    			OXPInstalled_extraBugs = false;
    		}
    
    		var OXPInstalled_missilesAndBombs;
    		if (worldScripts["Missiles & Bombs"]) {
    			OXPInstalled_missilesAndBombs = true;
    		} else {
    			OXPInstalled_missilesAndBombs = false;
    		}
    
    		var OXPInstalled_nexus;
    		if (!EquipmentInfo.infoForKey("EQ_NEXUS_BUG_MISSILE")) {
    			OXPInstalled_nexus = true;
    		} else {
    			OXPInstalled_nexus = false;
    		}
    
    		// Create weighted list of available ordinance - varying with ship type
    		var ordinanceAvailable;
    		if (this.ship.hasRole("ferdelance3Bugblatter")) {
    			// BUGBLATTER
    			ordinanceAvailable = ["EQ_F3G_ANTISWEEP_MISSILE", "EQ_F3G_ANTISWEEP_MISSILE", "EQ_HARDENED_MISSILE"];
    			if (OXPInstalled_nexus === true) {
    				ordinanceAvailable.push("EQ_NEXUS_BUG_MISSILE", "EQ_NEXUS_BUG_MISSILE");
    			} else if (OXPInstalled_missilesAndBombs) {
    				ordinanceAvailable.push("EQ_RMB_THARGOID_MISSILE", "EQ_RMB_THARGOID_MISSILE");
    			}
    			if (worldScripts["armoury_trackerWorldScript.js"]) {
    				ordinanceAvailable.push("EQ_ARMOURY_SCREAMER_MINE");
    			}
    			if ((worldScripts.TCAT_masterScript != undefined)) {
    				ordinanceAvailable.push("EQ_TCAT_JAMMER_MINE");
    			}
    			if (EquipmentInfo.infoForKey("EQ_TORPEDO_MISSILE")) {
    				ordinanceAvailable.push("EQ_TORPEDO_MISSILE");
    			}
    		} else {
    			// NORMAL
    			ordinanceAvailable = ["EQ_F3G_ANTISWEEP_MISSILE", "EQ_F3G_ANTISWEEP_MISSILE", "EQ_HARDENED_MISSILE", "EQ_HARDENED_MISSILE"];
    			if (OXPInstalled_extraBugs) {
    				ordinanceAvailable.push("EQ_F3G_ANTISWEEP_MISSILE");
    			}
    			if (OXPInstalled_nexus === true) {
    				ordinanceAvailable.push("EQ_NEXUS_BUG_MISSILE", "EQ_NEXUS_BUG_MISSILE");
    				if (OXPInstalled_missilesAndBombs) {
    					ordinanceAvailable.push("EQ_RMB_THARGOID_MISSILE");
    				}
    			} else if (OXPInstalled_missilesAndBombs) {
    				ordinanceAvailable.push("EQ_RMB_THARGOID_MISSILE", "EQ_RMB_THARGOID_MISSILE");
    			} else if (EquipmentInfo.infoForKey("EQ_MILITARY_MISSILE")) {
    				ordinanceAvailable.push("EQ_MILITARY_MISSILE", "EQ_MILITARY_MISSILE", "EQ_MILITARY_MISSILE");
    			}
    		}
    		var ordinance_shipSlots = this.ship.missileordinance_shipSlots;
    		var ordinance_availableArray_length = ordinanceAvailable.length;
    		var i = ordinance_shipSlots - 1;
    		do {
    			this.ship.awardEquipment(ordinanceAvailable[~~(Math.random() * ordinance_availableArray_length)]);
    		}
    		while (i--);
    		//
    		delete this.shipSpawned;
    	};
    
    
    	/*
    	--------
    	SCANNING
    	--------
    	*/
    
    	this.$isSweeper = function(e) {
    		return e.isShip && e.isThargoid && e.hasRole("extraThargoids_sweeper");
    	};
    
    	this.$isBigBug = function(e) {
    		return e.isShip && e.isThargoid && e.mass > 900000;
    	};
    
    	this.$isVeryBigBug = function(e) {
    		return e.isShip && e.isThargoid && e.mass > 4600000;
    	};
    
    	this.$scanForPrimaryTarget = function() {
    		if (!this.ship || !this.ship.isPiloted) {
    			return;
    		}
    		// if ( this.debug ) {player.consoleMessage("3G - SEEKING", 5);}
    		// Look for sweepers
    		var bigBugs;
    		var sweepers = system.filteredEntities(this, this.$isSweeper, this.ship, 25600);
    		if (sweepers.length > 0) {
    			// See whether target a sweeper or instead look for a big bug
    			bigBugs = system.filteredEntities(this, this.$isVeryBigBug, this.ship, 75000); // note range
    			if (bigBugs.length === 0) {
    				// Is at least one sweeper, are no (very) big bugs - so, go for a sweeper.
    				// So -if is more than one sweeper, decide which one to target.
    				if (sweepers.length === 1 || Math.random() < 0.65) {
    					this.ship.target = sweepers[0];
    				} else {
    					this.ship.target = sweepers[1];
    				}
    				this.ship.reactToAIMessage("TARGET_FOUND");
    			} else {
    				// Is at least one sweeper and at least one (very) big bug. So decide which type to go for.
    				var r = Math.random();
    				if (r < 0.85) {
    					// Target a sweeper.
    					if (sweepers.length === 1 || r < 0.6) {
    						this.ship.target = sweepers[0];
    					} else {
    						this.ship.target = sweepers[1];
    					}
    					this.ship.reactToAIMessage("TARGET_FOUND");
    				} else {
    					// Target a (very) bigbug.
    					// Now decide which bigbug, if more than one.
    					if (bigBugs.length === 1 || Math.random() < 0.6) {
    						this.ship.target = bigBugs[0];
    					} else {
    						this.ship.target = bigBugs[1];
    					}
    					this.ship.reactToAIMessage("TARGET_FOUND");
    				}
    			}
    		} else {
    			// Are no sweepers. So look for (very) big bugs.
    			bigBugs = system.filteredEntities(this, $isVeryBigBug, this.ship, 25600); // note range
    			if (bigBugs.length > 0) {
    				if (bigBugs.length === 1 || Math.random() < 0.55) {
    					this.ship.target = bigBugs[0];
    				} else {
    					this.ship.target = bigBugs[1];
    				}
    				this.ship.reactToAIMessage("TARGET_FOUND");
    			} else {
    				// Found no sweeper nor any very big bug - so look, up to just outside scanner range, for fairly big bugs.
    				bigBugs = system.filteredEntities(this, this.$isBigBug, this.ship, 25600);
    				if (bigBugs.length > 0) {
    					if (bigBugs.length === 1 || Math.random() < 0.6) {
    						this.ship.target = bigBugs[0];
    					} else {
    						this.ship.target = bigBugs[1];
    					}
    					this.ship.reactToAIMessage("TARGET_FOUND");
    				} else {
    					this.ship.reactToAIMessage("NOTHING_FOUND"); // Do need always to end with this or $doInterceptOfThargoid.
    				}
    			}
    		}
    	};
    
    	this.$isSuitableTarget = function(e) {
    		return e.isShip && e.isThargoid && e.mass > 500000 && e.primaryRole !== "thargoidRebel";
    	};
    
    	this.$scanForSecondaryTarget = function() {
    		if (!this.ship || !this.ship.isPiloted) {
    			return;
    		}
    		// if ( this.debug ) {player.consoleMessage("3G - SEEKING", 5);}
    
    		// Tharglet mass: 7829.43
    		// Frigate mass: 110048
    		// Warship mass: 899378
    		var targetArray = system.filteredEntities(this, this.$isSuitableTarget, this.ship, 25600);
    		if (targetArray.length === 0) {
    			this.ship.reactToAIMessage("NOTHING_FOUND");
    			return;
    		}
    		// else
    		if ((targetArray.length === 1) || (Math.random() < 0.7)) {
    			this.ship.target = targetArray[0];
    		} else {
    			this.ship.target = targetArray[1];
    		}
    		// player.consoleMessage("3G - OK!", 5);
    		this.ship.reactToAIMessage("TARGET_FOUND");
    	};
    
    	this.$isSuitableNavy = function(e) {
    		return e.isShip && (e.mass > 20000000) && (e.isPolice || e.scanClass === "CLASS_MILITARY");
    	};
    
    	this.$findNavy = function() {
    		var navalArray;
    
    		navalArray = system.filteredEntities(this, this.$isSuitableNavy, this.ship, 50000);
    		if (navalArray.length > 0) {
    			if ((navalArray.length === 1) || (Math.random() < 0.7)) {
    				this.ship.target = navalArray[0];
    			} else {
    				this.ship.target = navalArray[1];
    			}
    			this.ship.reactToAIMessage("TARGET_FOUND");
    		} else {
    			this.ship.reactToAIMessage("NOTHING_FOUND");
    		}
    	};
    
    
    	/*
    	---------------------
    	ATTACK ROUTINES & co.
    	---------------------
    	*/
    
    	this.$considerRespondingToAttack = function() {
    		if (!this.ship || !this.ship.isPiloted) {
    			return;
    		}
    		if (!this.ship.target || !this.ship.target.isValid) {
    			return;
    		}
    		if (this.ship.target.isThargoid) {
    			this.ship.reactToAIMessage("RESPOND_TO_ATTACK");
    			return;
    		}
    		// else
    		if (this.ship.target.scanClass === "CLASS_MILITARY" || this.ship.target.scanClass === "CLASS_POLICE") {
    			if (Math.random() < 0.02) {
    				this.ship.reactToAIMessage("RESPOND_TO_ATTACK");
    			} else {
    				this.ship.reactToAIMessage("POOTLE_IN_RESPONSE_TO_ATTACK");
    			}
    		} else {
    			if (Math.random() < 0.2) {
    				this.ship.reactToAIMessage("RESPOND_TO_ATTACK");
    			} else {
    				this.ship.reactToAIMessage("POOTLE_IN_RESPONSE_TO_ATTACK");
    			}
    		}
    	};
    
    	this.$considerRespondingToAttackWhenInterceptingNavy = function() {
    		if (!this.ship || !this.ship.isPiloted) {
    			return;
    		}
    		if (!this.ship.target || !this.ship.target.isValid) {
    			return;
    		}
    		if (
    			this.ship.target.isPlayer ||
    			(!this.ship.target.isThargoid && (this.ship.target.scanClass !== "CLASS_MILITARY") && (this.ship.target.scanClass !== "CLASS_POLICE"))
    		) {
    			if (Math.random() < 0.27) {
    				this.ship.reactToAIMessage("RESPOND_TO_ATTACK");
    			} else {
    				this.ship.reactToAIMessage("DO_NOT_RESPOND_TO_ATTACK");
    			}
    		} else {
    			this.ship.reactToAIMessage("RESPOND_TO_ATTACK");
    		}
    	};
    
    	this.$setMisjump = function() {
    		var r = Math.random();
    		this.ship.scriptedMisjump = true;
    		if (r < 0.4) {
    			this.ship.scriptedMisjumpRange = r * 2;
    		}
    	};
    
    
    	/*
    	---------
    	DEBUGGING
    	---------
    	*/
    
    	//this.messagePlayerIfPlayerWithinScannerRangeOfShip = function(text)
    	//{
    	//	if (!this.ship) {return;}
    	//	if (!this.ship.position) {return;}
    	//	if (!player.ship) {return;}
    	//	if (!player.ship.isValid) {return;}
    	//	if ( this.ship.position.distanceTo(player.ship.position) < 23000 ) {player.consoleMessage(text, 6);}
    	//}
    	//
    	//
    	//this.message = function(text) {player.consoleMessage(text, 6);}
    
    
    	/*
    	----------------------
    	JSLINT: end of wrapper
    	----------------------
    	*/
    
    }).call(this);
    
    
    // EOF
    Scripts/ferdelance3G_pirate.js
    /*
    ========================================================================
    ferdelance3G_pirate.js
    This file is part of the 'Ferdelance 3G' expansion pack.
    Author: UK_Eliter
    License: 2017 Creative Commons: attribution, non-commercial, sharealike.
    ========================================================================
    */
    
    
    /*
    ====================
    JSLINT: set options
    ====================
    */
    
    /*jshint esversion: 6*/
    /*jshint sub:true*/
    
    
    this.name = "ferdelance3G_pirate";
    this.author = "UK_Eliter";
    this.copyright = "";
    this.description = "ferdelance3G_pirate.js (for NPCs)";
    this.license = "CC-by-nc-sa 3.0";
    
    /*
    ------------------
    DEBUGGING SWITCHES
    ------------------
    */
    
    
    // this.logging = true;
    
    this.debug = false;
    
    if (this.debug) {
    	this.ship.reportAIMessages = true;
    }
    
    
    /*
    ------------------------
    JSLINT: start of wrapper
    ------------------------
    */
    
    (function() {
    	"use strict";
    
    
    	/*
    	--------------
    	EVENT HANDLERS
    	---------------
    	*/
    
    	this.shipSpawned = function() // For BOUNTY and ALLOCATING MISSILES
    	{
    		var l;
    		/*jshint -W009 */
    		var ordinance_available = new Array();
    		/*jshint +W009 */
    		var ordinance_available_level_two;
    		var ordinance_available_level_three_chance;
    		var ordinance_capacity;
    		var ordinanceCount;
    		var ordinance_available_length;
    
    		ordinance_available_level_two = false;
    		ordinance_available_level_three_chance = 0.11;
    		ordinance_capacity = this.shipSpawned.missileCapacity;
    
    		if (this.ship.hasRole("ferdelance3G_+T")) {
    			ordinance_available_level_two = true;
    			if (this.ship.hasRole("ferdelance3G_pirateKing")) {
    				this.ship.bounty += 50 + ~~((Math.random() * 120) + 1);
    				ordinance_available_level_three_chance = 0.8;
    			}
    		} else if (Math.random() > 0.6) {
    			ordinance_available_level_two = true;
    		}
    
    		if (ordinance_available_level_two) {
    			if (worldScripts["Missiles & Bombs"]) {
    				ordinance_available.push("EQ_RMB_FRAG_MISSILE", "EQ_RMB_OVERRIDE_MISSILE", "EQ_RMB_INTERCEPT_MISSILE", "EQ_RMB_INTERCEPT_MISSILE");
    			}
    
    			if (worldScripts["armoury_trackerWorldScript.js"]) {
    				ordinance_available.push("EQ_ARMOURY_STUNBOMB_MINE");
    				if (this.ship.equipmentStatus("EQ_CLOAKING_DEVICE") != "EQUIPMENT_OK") {
    					ordinance_available.push("EQ_KDRONE_LAUNCHER_MINE", "EQ_CDRONE_LAUNCHER_MINE");
    				}
    			}
    
    			if (EquipmentInfo.infoForKey("EQ_TORPEDO_MISSILE")) {
    				ordinance_available.push("EQ_TORPEDO_MISSILE");
    			}
    
    			if (EquipmentInfo.infoForKey("EQ_HARPOON_NUKE1_MISSILE")) {
    				ordinance_available.push("EQ_HARPOON_NUKE1_MISSILE");
    			}
    
    			if (EquipmentInfo.infoForKey("EQ_NEXUS_BUG_MISSILE")) {
    				if (Math.random() > 0.25) {
    					ordinance_available.push("EQ_NEXUS_BASIC_MISSILE");
    				} else {
    					ordinance_available.push("EQ_NEXUS_PREMIUM_MISSILE");
    				}
    			}
    
    			if (Math.random() < ordinance_available_level_three_chance) {
    				this.ship.awardEquipment("EQ_QC_MINE"); // NB: actually award
    				--ordinance_capacity;
    			}
    		}
    
    		// Ensure there is at least one item in the ordinance list (so that can triple the list and not get zero).
    		ordinance_available.push("EQ_HARDENED_MISSILE");
    
    		// Triple the size of ordinance_available by adding, for every entry present already, a normal missile and a hardhead. 
    		ordinance_available_length = ordinance_available.length;
    		l = ordinance_available_length;
    		while (l--) {
    			ordinance_available.push("EQ_MISSILE");
    			ordinance_available.push("EQ_HARDENED_MISSILE");
    		}
    
    		// Load the ordinance (save for Q-Mine, which may have been loaded above).
    		ordinance_available_length = ordinance_available.length; // The latter has changed, so set the former again.
    		l = ordinance_capacity;
    		do {
    			this.ship.awardEquipment(ordinance_available[~~(Math.random() * ordinance_available_length)]);
    		}
    		while (l--);
    		delete this.shipSpawned;
    	};
    
    
    	/*
    	=======================
    	JSHINT: end of wrapper
    	=======================
    	*/
    
    }).call(this);
    
    // EOF
    Scripts/ferdelance3G_populator.js
    /*
    ========================================================================
    ferdelance3G_populator.js
    This file is part of the 'Ferdelance 3G' expansion pack.
    Author: UK_Eliter
    License: 2017 Creative Commons: attribution, non-commercial, sharealike.
    ========================================================================
    */
    
    
    /*
    ====================
    JSLINT: set options
    ====================
    */
    
    /*jshint esversion: 6*/
    /*jshint sub:true*/
    
    
    this.name = "ferdelance3G_populator";
    this.author = "UK_Eliter";
    this.copyright = "2014 Creative Commons: attribution, non-commercial, sharealike.";
    this.licence = "CC-NC-SA 4";
    this.description = "Fer-de-Lance 3G populator script";
    
    
    /*
    ------------------
    DEBUGGING SWITCHES
    ------------------
    */
    
    // this.logging = true;
    this.consoleDebugMessages = false; // to disable this, set it to false. DO NOT comment it out.
    
    
    /*
    ------------------------
    JSLINT: start of wrapper
    ------------------------
    */
    
    (function() {
    	"use strict";
    
    
    	/*
    	-----------------------
    	INTERSTELLAR population
    	-----------------------
    	*/
    
    	this.interstellarSpaceWillPopulate = function() {
    		if (Math.random() < 0.94) {
    			return;
    		} // NB: 0.94
    		// Otherwise
    		system.setPopulator("ferdelance3G_interstellar", {
    			priority: 300,
    			callback: this._addinterstellar3Gs.bind(this)
    		});
    	};
    
    	this._addinterstellar3Gs = function(pos) {
    		var threeG_number = ~~(1 + (Math.random() * 8));
    		this.$addShips_ringless("ferdelance3G_interstellar", threeG_number, [0, 0, 0], 22000);
    	};
    
    	this.$isBug = function(e) {
    		return e.isThargoid;
    	};
    
    	this.interstellarSpaceWillRepopulate = function() {
    		// It is important for smooth gameplay that this function runs very quickly. If calculations are needed, run as many as possible in the populator function to save the result.
    		// 'interstellarSpaceWillRepopulate' does *not* use system.setPopulator 
    		//
    		// Note re Interstellar Tweaks OXP: that function will stop this routine being called, except in 'modified' scenarios. For 'new' scenarios, InterstellarTweaks can itself spawn 3Gs.
    
    		if (!player.ship || !player.ship.position) {
    			return;
    		}
    
    		if (this.threeG_addNoMore === true) {
    			return;
    		}
    
    		var bugs = system.filteredEntities(this, this.$isBug);
    		if (bugs.length < 5) {
    			return;
    		}
    
    		var police_num = system.countShipsWithRole("police");
    		if (police_num >= bugs.length) {
    			return;
    		}
    
    		var threeG_chanceAdd;
    		if (police_num < 15) {
    			threeG_chanceAdd = 0.02;
    		} else {
    			threeG_chanceAdd = 0.05;
    		}
    		var numCarriers = system.countShipsWithRole("thargoid_carrier");
    		if (numCarriers > 2) {
    			threeG_chanceAdd = threeG_chanceAdd * (numCarriers - 1);
    			// "threeG_chanceAdd* = (numCarriers-1)" throws exception
    		}
    		if (threeG_chanceAdd > 0.4) {
    			threeG_chanceAdd = 0.4;
    		}
    		if (Math.random() > threeG_chanceAdd) {
    			return;
    		}
    
    		// Else
    		var threeG_number = 3 + ~~((Math.random() * 6) + 1);
    		system.addGroup("ferdelance3G_interstellar", threeG_number, [0, 0, 0], 875);
    		if (Math.random() < 0.6) {
    			this.threeG_addNoMore = true;
    		}
    	};
    
    
    	/*
    	------------------
    	STELLAR population
    	------------------
    	*/
    
    	this.systemWillPopulate = function() {
    		/* STELLAR POPULATOR
    		LANE_PS, LANE_WP, LANE_WS, STATION_AEGIS, PLANET_ORBIT, OUTER_SYSTEM, OUTER_SYSTEM_OFFPLANE
    		Use 'callback: this._myFunction.bind(this)' not callback: this._myFunction' in order to use global variables and functions
    		*/
    
    		// log("3G - DEBUG", "entered populator"); // TEST
    
    		if (!((system.government < 3) && (Math.random() < 0.2))) {
    			return;
    		}
    
    		var place = ~~(1 + (Math.random() * 8));
    
    		// log("3G - DEBUG", "place is <" + place + ">"); // TEST
    
    		switch (place) {
    			case 1:
    				system.setPopulator("ferDeLance3G-huntersPO", {
    					groupCount: 1,
    					priority: 150,
    					location: "PLANET_ORBIT",
    					callback: this._addHunter.bind(this)
    				});
    				break;
    			case 2:
    				system.setPopulator("ferDeLance3G-huntersLWP", {
    					groupCount: 1,
    					priority: 111,
    					location: "LANE_WP",
    					callback: this._addHunter.bind(this)
    				});
    				break;
    			case 3:
    				system.setPopulator("ferDeLance3G-huntersOS", {
    					groupCount: 1,
    					priority: 150,
    					location: "OUTER_SYSTEM",
    					callback: this._addHunter.bind(this)
    				});
    				break;
    			case 4:
    				system.setPopulator("ferDeLance3G-huntersSA", {
    					groupCount: 1,
    					priority: 150,
    					location: "STATION_AEGIS",
    					callback: this._addHunter.bind(this)
    				});
    				break;
    			case 5:
    				system.setPopulator("ferDeLance3G-huntersWP", {
    					groupCount: 1,
    					priority: 110,
    					location: "WITCHPOINT",
    					callback: this._addHunter.bind(this)
    				});
    				break;
    			case 6:
    				system.setPopulator("ferDeLance3G-huntersSOL", {
    					groupCount: 1,
    					priority: 150,
    					location: "STAR_ORBIT_LOW",
    					callback: this._addHunter.bind(this)
    				});
    				break;
    			default:
    				system.setPopulator("ferDeLance3G-huntersLWPS", {
    					groupCount: 1,
    					priority: 111,
    					location: "LANE_WPS",
    					callback: this._addHunter.bind(this)
    				});
    		}
    	};
    
    	this._addHunter = function(pos) {
    		var s = system.addShips("ferdelance3G_hunter", 1, pos, 35000);
    		// function addShips(role : String, count : Number [, position: vectorExpression] [, radius: Number]) : Array
    		// log("3G TESTING", "Added stellar hunter");
    	};
    
    
    	/*
    	-----
    	OTHER
    	-----
    	*/
    
    	this.playerWillEnterWitchspace = function() {
    		this.threeG_addNoMore = false;
    	};
    
    	this.$addShips_ringless = function(role, count, position, radius) {
    		var i, offset, ships;
    		offset = new Vector3D(0, 50000, 0);
    		if (count < 1) {
    			this.$error("Bad count argument <" + count + "> for function addShips_ringless");
    			count = 1; // fix the problem.
    		}
    		ships = system.addShips(role, count, offset, radius);
    		offset = new Vector3D(position).subtract(offset);
    		i = ships.length;
    		while (i--) {
    			ships[i].position = ships[i].position.add(offset);
    		}
    		return ships;
    	};
    
    	// For TESTING
    	/*
    	this.shipWillLaunchFromStation = function()
    	{
    		// this.$addShips_ringless("ferdelance3G_trader", 4, player.ship.position, 25000);
    		// this.$addShips_ringless("ferdelance3G_pirate", 4, player.ship.position, 25000);
    		this.$addShips_ringless("ferdelance3G_pirateKing", 2, player.ship.position, 25000);
    		// this.$addShips_ringless("ferdelance3G_hunter", 4, player.ship.position, 25000);
    		// this.$addShips_ringless("ferdelance3G_police", 3, player.ship.position, 25000);
    		//this.$addShips_ringless("ferdelance3G_interstellar", 4, player.ship.position, 25000);
    		this.$addShips_ringless("ferdelance3G_hardPiratePoliceDecomissioned", 1, player.ship.position, 25000);
    		this.$addShips_ringless("ferdelance3G_hardestHunterPoliceDecomissioned", 1, player.ship.position, 25000);
    	}
    	*/
    
    
    	/*
    	----------------------
    	JSLINT: end of wrapper
    	----------------------
    	*/
    
    }).call(this);
    
    
    // EOF
    Scripts/ferdelance3G_trader.js
    /*
    ========================================================================
    ferdelance3G_trader.js
    This file is part of the 'Ferdelance 3G' expansion pack.
    Author: UK_Eliter
    License: 2017 Creative Commons: attribution, non-commercial, sharealike.
    ========================================================================
    */
    
    
    /*
    ====================
    JSLINT: set options
    ====================
    */
    
    /*jshint esversion: 6*/
    /*jshint sub:true*/
    
    
    this.name = "ferdelance3G_trader";
    this.author = "UK_Eliter";
    this.copyright = "";
    this.description = "ferdelance3G_hunter.js (for NPCs)";
    this.license = "CC-by-nc-sa 3.0";
    
    
    /*
    ------------------
    DEBUGGING SWITCHES
    ------------------
    */
    
    // this.logging = true;
    
    this.debug = false;
    
    if (this.debug) {
    	this.ship.reportAIMessages = true;
    }
    
    
    /*
    ------------------------
    JSLINT: start of wrapper
    ------------------------
    */
    
    (function() {
    	"use strict";
    
    
    	/*
    	-------------------------
    	EVENT HANDLERS
    	(except incoming missile)
    	-------------------------
    	*/
    
    	this.shipSpawned = function() // For ALLOCATING MISSILES
    	{
    		var capacity;
    		var chanceForSeriousBomb = 0.1;
    		var giveSeriousOrdinance = false;
    		var i;
    		var ordinanceAvailable;
    		var ordinanceCount;
    		var startTime;
    
    		//Build list of available ordinance.
    		ordinanceAvailable = ["EQ_MISSILE", "EQ_MISSILE", "EQ_MISSILE", "EQ_HARDENED_MISSILE", "EQ_HARDENED_MISSILE"];
    		if (this.ship.hasRole("ferdelance3G_+T")) {
    			giveSeriousOrdinance = true;
    			chanceForSeriousBomb = 0.17;
    		} else if (Math.random() > 0.8) {
    			giveSeriousOrdinance = true;
    		}
    		if (giveSeriousOrdinance) {
    			if (worldScripts["Missiles & Bombs"]) {
    				ordinanceAvailable.push("EQ_RMB_FRAG_MISSILE", "EQ_RMB_OVERRIDE_MISSILE", "EQ_RMB_LAW_MISSILE", "EQ_RMB_INTERCEPT_MISSILE", "EQ_RMB_INTERCEPT_MISSILE", "EQ_RMB_INTERCEPT_MISSILE");
    			}
    			if (EquipmentInfo.infoForKey("EQ_TORPEDO_MISSILE")) {
    				ordinanceAvailable.push("EQ_TORPEDO_MISSILE");
    			}
    			if (EquipmentInfo.infoForKey("EQ_HARPOON_NUKE1_MISSILE")) {
    				ordinanceAvailable.push("EQ_HARPOON_NUKE1_MISSILE");
    			}
    			if (worldScripts["armoury_trackerWorldScript.js"]) {
    				ordinanceAvailable.push("EQ_ARMOURY_STUNBOMB_MINE");
    				if (this.ship.equipmentStatus("EQ_CLOAKING_DEVICE") != "EQUIPMENT_OK") {
    					ordinanceAvailable.push("EQ_KDRONE_LAUNCHER_MINE", "EQ_CDRONE_LAUNCHER_MINE");
    				}
    			}
    			if (EquipmentInfo.infoForKey("EQ_NEXUS_BUG_MISSILE")) {
    				ordinanceAvailable.push("EQ_NEXUS_PREMIUM_MISSILE");
    				if (Math.random() > 0.2) {
    					ordinanceAvailable.push("EQ_NEXUS_BASIC_MISSILE");
    				} else {
    					ordinanceAvailable.push("EQ_NEXUS_PREMIUM_MISSILE");
    				}
    			}
    			capacity = this.ship.missileCapacity;
    			if (Math.random() <= chanceForSeriousBomb) {
    				this.ship.awardEquipment("EQ_QC_MINE"); // NB: actually award
    				--capacity;
    			}
    		}
    		// Load ordinance to ship
    		ordinanceCount = ordinanceAvailable.length;
    		i = capacity - 1;
    		do {
    			this.ship.awardEquipment(ordinanceAvailable[~~(Math.random() * ordinanceCount)]);
    		}
    		while (i--);
    		delete this.shipSpawned;
    	};
    
    
    	/*
    	----------------------
    	JSLINT: end of wrapper
    	----------------------
    	*/
    
    }).call(this);
    
    
    // EOF