| Back to Index | Page generated: Nov 24, 2025, 1:21:31 AM |
| from Expansion Manager's OXP list | from Expansion Manifest | |
|---|---|---|
| Description | Adds new types of Thargoid, which are to be encountered especially in interstellar space. | Adds new types of Thargoid, which are to be encountered especially in interstellar space. |
| Identifier | oolite.oxp.UK_Eliter.ExtraThargoids | oolite.oxp.UK_Eliter.ExtraThargoids |
| Title | Extra Thargoids | Extra Thargoids |
| Category | Ships | Ships |
| Author | UK_Eliter | UK_Eliter |
| Version | 6.73 | 6.73 |
| Tags | thargoids, ships, system | thargoids, ships, system |
| Required Oolite Version | ||
| Maximum Oolite Version | ||
| Required Expansions | ||
| Optional Expansions |
|
|
| Conflict Expansions | ||
| Information URL | http://aegidian.org/bb/viewtopic.php?t=10154&p=143763 | n/a |
| Download URL | https://wiki.alioth.net/img_auth.php/8/8a/Oolite.oxp.UK_Eliter.Extra_Thargoids.oxz | http://wiki.alioth.net/img_auth.php/8/8a/Oolite.oxp.UK_Eliter.Extra_Thargoids.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 | 1746401291 |
Also read http://wiki.alioth.net/index.php/Extra%20Thargoids
==================================== 'Extra Thargoids' OXP by 'UK_Eliter' ==================================== ------------- GENERAL NOTES ------------- � This OXP adds various types of Thargoid. The most commonly (or least infrequently) encountered of these are (/will be) the 'Gruntbuggly' (which itself comes in various versions), the 'anti-poet' Frigate, the minesweeper. � This OXP works best with the 'Thargorn_Threat' OXP. (I have tested it with Thargorn_Threat version 1.5.) ------- 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. ---------------- ACKNOWLEDGEMENTS ---------------- This OXP derives in considerable part from the Thargoid Threat OXP. That OXP was created by 'Arexack_Heretic' and modified by Eric Walch, who himself in so doing drew upon a version of the 'freaky thargoid shader' by Ahruman. The Thargoid Threat OXP contains this statement: 'Created under Creative Commons Licence, as expansion on Oolite, created by Giles Williams (Aegidian). Look the relevant stuff up at http://oolite.aegidian.org. In short however; anyone is welcome to expand to or use parts of this OXP as long as credit is given where due, and as long as not in any commercial enterprise.' I am happy to give that credit! The 'displacement' code in one of my scripts owes to Thargoid's Armoury OXP. The displacement sound is an OGG conversion of 'stk-DM300_18.wav', which is a sound provided, under the Creative Commons License and via www.freesound.org/, by user 'stk'. Other materials are adapted from stuff built-in to Oolite. For the license for Oolite itself, see the OoliteReadMe.pdf file included with that program. My thanks to the following for help with debugging and for ideas (though probably I omit some people here, by accident): cag; Fleurghber; Milo; Nite Owl; Staer9. ----------------- END -----------------
| Path | |
|---|---|
| Scripts/extraThargoids_buggly.js | /*
========================================================================
extraThargoids_buggly.js
This file is part of the ExtraThargoids expansion pack.
Author: UK_Eliter
License: 2017 Creative Commons: attribution, non-commercial, sharealike.
========================================================================
*/
/*
-------------------
JSLINT: set options
-------------------
*/
/*jshint esversion: 6*/
/*jshint sub:true*/
this.name = "extraThargoids_buggly";
this.author = "UK_Eliter";
this.copyright = "2014 Creative Commons: attribution, non-commercial, sharealike.";
this.licence = "CC-NC-SA 3";
this.description = "Script for the 'Gruntbuggly' Thargon ships";
/*
-----------------------------------------------------------------------
Corresponding AIs:
- extraThargoids_bugglyAI.plist (which sends no messages to script)
- extraThargoids_kamikazeAI
-----------------------------------------------------------------------
*/
/*
------------------
DEBUGGING SWITCHES
------------------
*/
// this.logging = true;
var consoleDebugMessages = false; // do NOT comment this out. Rather, to disable, set to false.
/*
------
SOUNDS
------
*/
var mysound_Warning = new SoundSource();
mysound_Warning.sound = "warning.ogg";
// This sound is built-in to Oolite - and does not need to be declared in the 'customsounds' file.
/*
------------------------
JSHINT: start of wrapper
------------------------
*/
(function() {
"use strict";
/*
--------------
EVENT HANDLERS
--------------
*/
this.shipSpawned = function() {
// set timer to check for stun bomb from Armoury OXP - and give some buggly models missiles
if (worldScripts["armoury_machineScript.js"]) {
this.checkStun = new Timer(this, this.$checkStunTimed, 12, 12);
}
delete this.shipSpawned;
};
this.shipDied = this.entityDestroyed = this.playerWillEnterWitchspace = function() {
this.$deleteTimers();
};
this.shipTakingDamage = function(amount, whom, type) {
if ((amount < 50) && (this.ship.energy > 19)) {
return;
}
var chance;
if (amount > 49) {
if (this.ship.energy < 20) {
chance = 0.5;
} else {
chance = 0.1;
}
} else {
chance = 0.2; // this will mean both (this.ship.energy < 20) AND NOT (amount > 49)
}
if (this.ship.target && this.ship.target.isValid) {
this.distanceToTarget = this.ship.position.distanceTo(this.ship.target);
if (this.distanceToTarget < 650) {
chance += 0.67;
} else {
if (this.distanceToTarget < 1000) {
chance += 0.55;
} else if (this.distanceToTarget < 3000) {
chance += 0.3;
}
}
}
if (Math.random() < chance) {
this.ship.energy += 100 + amount; // stop it blowing up normally
if (whom && whom.isPlayer) {
this.$explode_causedByPlayer();
} else {
this.explode_notCausedByPlayer();
}
}
};
this.shipTargetCloaked = function() {
if (this.decloakTargetTimer && this.decloakTargetTimer.isRunning) {
return;
}
if (this.ship.target.isThargoid) {
return;
}
var r = Math.random();
if (r < 0.16) {
return;
}
if (r > 0.75) {
this.ship.commsMessage(expandDescription("[thargoid_curses]"));
}
this.ship.cloakedTarget = this.ship.target;
var seconds = 0.5 + ~~(Math.random() * 8);
if (this.decloakTargetTimer) {
delete this.decloakTargetTimer;
}
this.decloakTargetTimer = new Timer(this, this.$decloakTargetTimed, seconds);
};
/*
---------------------------------------------------
ROUTINES CALLED BY EVENT HANDLERS
or called by the routines called by event handlers.
---------------------------------------------------
*/
this.explode_notCausedByPlayer = function() {
this.$deleteTimers();
if (!this.ship) {
return;
}
this.explodingShip = this.ship.spawnOne("extraThargoids_exploding_notCausedByPlayer");
this.explodingShip.newBounty = this.ship.bounty;
this.explodingShip.bounty = this.ship.bounty;
this.explodingShip.orientation = this.ship.orientation;
this.explodingShip.position = this.ship.position;
if (Math.random() < 0.4) {
this.ship.commsMessage("We boom your bases!");
}
if (!this.ship) {
return;
}
this.ship.remove(true);
};
this.$explode_causedByPlayer = function() {
this.$deleteTimers();
if (!this.ship) {
return;
}
if (Math.random() < 0.7) {
this.ship.commsMessage("We boom your bases!");
}
this.explodingShip = this.ship.spawnOne("extraThargoids_exploding_causedByPlayer");
this.explodingShip.newBounty = this.ship.bounty;
this.explodingShip.bounty = this.ship.bounty;
this.explodingShip.orientation = this.ship.orientation;
this.explodingShip.position = this.ship.position;
if (!this.ship) {
return;
}
this.ship.remove(true);
};
this.$decloakTargetTimed = function $decloakTargetTimed() {
this.decloakTargetTimer.stop();
if (!this.ship || !this.ship.isValid) {
delete this.decloakTargetTimer;
return;
}
if (!this.ship.cloakedTarget || !this.ship.cloakedTarget.isValid) {
delete this.decloakTargetTimer;
return;
}
if (!this.ship.cloakedTarget.isCloaked) {
delete this.decloakTargetTimer;
return;
}
this.distanceToTarget = this.ship.position.distanceTo(this.ship.cloakedTarget);
if (this.distanceToTarget < 10000) {
mysound_Warning.play();
this.ship.cloakedTarget.lightsActive = true;
if (Math.random() > 0.91) {
this.ship.cloakedTarget.setEquipmentStatus("EQ_CLOAKING_DEVICE", "EQUIPMENT_DAMAGED");
if (this.ship.cloakedTarget.isPlayer && !player.ship) {
delete this.decloakTargetTimer;
return;
}
this.ship.commsMessage("CLOAKING DEVICE DAMAGED!", this.ship.cloakedTarget);
} else {
player.consoleMessage("CLOAKING FAILURE!", 10);
player.ship.isCloaked = false;
this.ship.target = this.ship.cloakedTarget;
this.ship.reactToAIMessage("ATTACK_SHIP");
}
}
if (Math.random() < 0.25) {
this.ship.commsMessage(expandDescription("[thargoid_curses]"));
}
delete this.decloakTargetTimer;
};
this.$checkStunTimed = function $checkStunTimed() {
if (this.ship.AIState == "STUNNED") {
this.ship.exitAI();
this.explode_notCausedByPlayer();
}
};
this.$deleteTimers = function() {
if (this.decloakTargetTimer) {
if (this.decloakTargetTimer.isRunning) {
this.decloakTargetTimer.stop();
}
delete this.decloakTargetTimer;
}
if (this.checkStunTimed) {
if (this.checkStunTimed.isRunning) {
this.checkStunTimed.stop();
}
delete this.checkStunTimed;
}
};
/*
--------------------------------------------------------------------------
CALLED BY AI
These routines are called by this AI:
extraThargoids_kamikazeAI (which itself is invoked, only, by the shipdata)
--------------------------------------------------------------------------
*/
this.$_seekPrimaryTarget = function() {
if (!this.ship) {
return;
}
var primaryTargetsArray = system.shipsWithRole("behemoth", this.ship, 25600);
if (primaryTargetsArray.length > 0) {
this.ship.target = primaryTargetsArray[0];
this.ship.reactToAIMessage("TARGET_FOUND");
return;
}
primaryTargetsArray = system.shipsWithRole("leviathan", this.ship, 25600);
if (primaryTargetsArray.length > 0) {
this.ship.target = primaryTargetsArray[0];
this.ship.reactToAIMessage("TARGET_FOUND");
return;
}
primaryTargetsArray = system.shipsWithRole("patrol-frigate", this.ship, 25600);
if (primaryTargetsArray.length > 0) {
this.ship.target = primaryTargetsArray[0];
this.ship.reactToAIMessage("TARGET_FOUND");
return;
}
primaryTargetsArray = system.shipsWithRole("navy-frigate", this.ship, 25600);
if (primaryTargetsArray.length > 0) {
this.ship.target = primaryTargetsArray[0];
this.ship.reactToAIMessage("TARGET_FOUND");
} else {
this.ship.reactToAIMessage("NO_PRIMARY");
}
};
this.$_rangeAchieved = function() {
if (!this.ship || !this.ship.isValid) {
return;
}
// else
this.explode_notCausedByPlayer();
var explosiveBits = this.ship.spawn("explosive_shrapnel", 5);
};
/*
----------------------
JSLINT: end of wrapper
----------------------
*/
}).call(this);
// EOF |
| Scripts/extraThargoids_exploding_generic.js | /*
========================================================================
extraThargoids_exploding_generic.js
This file is part of the ExtraThargoids expansion pack.
Author: UK_Eliter
License: 2017 Creative Commons: attribution, non-commercial, sharealike.
========================================================================
*/
/*
-------------------
JSLINT: set options
-------------------
*/
/*jshint esversion: 6*/
/*jshint sub:true*/
this.name = "extraThargoids_exploding_generic";
this.author = "UK_Eliter";
this.copyright = "2014 Creative Commons: attribution, non-commercial, sharealike.";
this.licence = "CC-NC-SA 3";
this.description = "Script for exploding 'Gruntbuggly' Thargon ships";
/*
------------------------------------------------------
CORRESPONDING AIs:
- extraThargoids_exploding_causedByPlayerAI.plist
- extraThargoids_exploding_notCausedByPlayerAI.plist
------------------------------------------------------
/*
------------------
DEBUGGING SWITCHES
------------------
*/
// this.logging = true; // THIS SHOULD BE COMMENTED OUT WHEN NOT TESTING
// this.ship.reportAIMessages = true; // if set to true, continuously dumps AI stuff to log - and produces vector lines.
// var consoleDebugMessages = false;
/*
------
SOUNDS
------
*/
this.bigBang = new SoundSource();
this.bigBang.sound = "bigbang.ogg";
this.mediumBang = new SoundSource();
this.mediumBang.sound = "extraThargoids_mediumBang.ogg";
this.quietBang = new SoundSource();
this.quietBang.sound = "extraThargoids_quietBang.ogg";
/*
------------------------
JSLINT: start of wrapper
------------------------
*/
(function() {
"use strict";
/*
--------------
EVENT HANDLERS
--------------
*/
this.shipDied = this.entityDestroyed = function() {
var frags = this.ship.spawn("explosive_shrapnel", 3);
};
/*
-------------
CALLED BY AIs
-------------
*/
this.$_bountyHack = function() {
if (this.ship.isValid && this.ship.newBounty && (this.ship.newBounty > 0)) {
this.ship.bounty = this.ship.newBounty;
}
};
this.$_explode_core = function() {
this.ship.dealEnergyDamage(980, 1750);
// SYNTAX: function dealEnergyDamage(damage : Number, idealRange : Number [, velocityBias : Number])
this.$bangSoundEffect();
};
this.$_explode_notCausedByPlayer = function() {
this.$_explode_core();
};
this.$_explode_causedByPlayer = function() {
var bounty;
this.$_explode_core();
player.score += 1;
if (!this.ship.isValid || !this.ship || this.ship.bounty == 0) {
bounty = 200;
} else {
bounty = this.ship.bounty;
}
var string = "Bounty: " + bounty;
player.consoleMessage(string, 6);
player.credits += bounty;
if (player.ship.isValid && Math.random() < 0.15) {
string = "The navy has awarded a 500 credit bonus!";
player.consoleMessage(string, 8);
player.credits += 500;
}
};
/*
-----
OTHER
-----
*/
this.$bangSoundEffect = function() {
if (!this.ship || !this.ship.position || !player.ship.position) {
return;
}
var ps = player.ship; // for speed, but changes won't affect the original variable
if (this.ship.position.distanceTo(ps.position) < 2000) {
this.bigBang.play(); // this one really is VERY loud, so only use for VERY close
return;
}
if (this.ship.position.distanceTo(ps.position) < 15000) {
this.mediumBang.play();
return;
}
if (this.ship.position.distanceTo(ps.position) < 27000) {
this.quietBang.play();
}
};
/*
-----------------------
JSHINT: end of wrapper
----------------------
*/
}).call(this);
// EOF |
| Scripts/extraThargoids_frigatePoet.js | /*
========================================================================
extraThargoids_frigatePoet.js
This file is part of the ExtraThargoids expansion pack.
Author: UK_Eliter
License: 2017 Creative Commons: attribution, non-commercial, sharealike.
========================================================================
*/
/*
-------------------
JSLINT: set options
-------------------
*/
/*jshint esversion: 6*/
/*jshint sub:true*/
this.name = "extraThargoids_frigatePoet";
this.author = "UK_Eliter";
this.copyright = "2014 Creative Commons: attribution, non-commercial, sharealike.";
this.licence = "CC-NC-SA 3";
this.description = "extraThargoids_frigatePoet";
// NB: There is no special AI - but rather an inbuilt one - corresponding to this script.
/*
-------------
VARIABLES etc
-------------
*/
this.displace = new SoundSource();
this.displace.sound = "extraThargoids_displacement.ogg";
this.quietDisplace = new SoundSource();
this.quietDisplace.sound = "[extraThargods_displacementQuiet.ogg]";
this.warning = new SoundSource();
this.warning.sound = "warning.ogg"; // this sound built-in to Oolite - and does not need to be declared in the 'customsounds' file.
/*
------------------------
JSHINT: start of wrapper
------------------------
*/
(function() {
"use strict";
/*
--------------
EVENT HANDLERS
--------------
*/
this.shipSpawned = function() {
this.canDisplaceCurrently = true;
delete this.shipSpawned;
};
this.shipDied = this.entityDestroyed = this.playerWillEnterWitchspace = function() {
this.$cleanUp();
};
this.shipAttackedWithMissile = function() // run by oolite core itself {
{
if (Math.random() > 0.7) {
return;
}
this.ship.isCloaked = true;
// but if can't cloak . .
if (this.ship.isCloaked === false) {
this.$displace();
}
};
this.shipTargetCloaked = function() {
if (Math.random() > 0.82) {
this.$displace();
}
if (this.ship.target) {
this.ship.target = null;
}
};
this.shipEnergyIsLow = function() {
if (Math.random() > 0.13) {
this.ship.isCloaked = false;
this.$displace();
}
};
/*
-----
OTHER
-----
*/
// Following code includes parts adapted from Thargoid's armoury_displacerMissile.js script in his Armoury OXP.
this.$displace = function() {
if (this.canDisplaceCurrently === false || !this.ship) {
return;
}
if (this.ship.fuel < 4) {
this.canDisplaceCurrently = false;
return;
}
this.canDisplaceCurrently = false;
if (this.timerToReenableDisplace) {
if (this.timerToReenableDisplace.isRunning) {
this.timerToReenableDisplace.stop(); // should never happen
}
delete this.timerToReenableDisplace;
}
if (!player.ship.position) {
return;
}
var ps = player.ship; // for speed, but changes won't affect the original variable
var xDistance = ((Math.random() * 2) - 1) * 8600;
var yDistance = ((Math.random() * 2) - 1) * 8600;
var zDistance = ((Math.random() * 2) - 1) * 8600;
this.ship.position = this.ship.position.add([xDistance, yDistance, zDistance]);
if (Math.random() < 0.7) {
this.ship.commsMessage(expandDescription("[thargoid_curses]"), ps);
}
var shipDistanceToDisplacedShip = this.ship.position.distanceTo(ps.position); // would be good to alter the following to occur to ANY ship within the specified range . .
var displacementChance = 0;
this.ship.position = this.ship.position.add([xDistance, yDistance, zDistance]);
this.ship.isCloaked = false;
if (shipDistanceToDisplacedShip < 1200) {
if (shipDistanceToDisplacedShip < 500) {
displacementChance = 0.5;
} else {
displacementChance = 0.2;
}
}
if (shipDistanceToDisplacedShip < 12000) {
this.displace.play();
} else if (shipDistanceToDisplacedShip < 18000) {
this.quietDisplace.play();
}
this.ship.fuel -= (Math.ceil(Math.random() * 5)); // drain off some fuel to simulate the jump
if (this.ship.target) {
if (Math.random() < 0.5) {
this.ship.target = null;
}
}
if (Math.random() <= displacementChance) {
player.ship.position = player.ship.position.add([xDistance, yDistance, zDistance]);
this.warning.play();
player.consoleMessage("EMERGENCY - position changed by nearby displacement device", 6);
if (Math.random() < 0.1) {
player.ship.scriptedMisjump = true;
player.ship.scriptedMisjumpRange = r;
}
}
var t = 8 + Math.ceil(Math.random() * 6);
this.timerToReenableDisplace = new Timer(this, this.$reenableDisplace, t);
};
this.$reenableDisplace = function $reenableDisplace() {
this.canDisplaceCurrently = true;
};
this.$cleanUp = function() {
this.canDisplaceCurrently = true;
if (this.timerToReenableDisplace) {
if (this.timerToReenableDisplace.isRunning) {
this.timerToReenableDisplace.stop();
}
delete this.timerToReenableDisplace;
}
};
/*
----------------------
JSLINT: end of wrapper
----------------------
*/
}).call(this);
// EOF |
| Scripts/extraThargoids_populator.js | /*
========================================================================
extraThargoids_populator.js
This file is part of the ExtraThargoids expansion pack.
Author: UK_Eliter
License: 2017 Creative Commons: attribution, non-commercial, sharealike.
========================================================================
*/
/*
-------------------
JSLINT: set options
-------------------
*/
/*jshint esversion: 6*/
/*jshint sub:true*/
this.name = "extraThargoids_populator";
this.author = "UK_Eliter";
this.copyright = "2014 Creative Commons: attribution, non-commercial, sharealike.";
this.licence = "CC-NC-SA 3";
this.description = "This script adds some of the 'Extra Thargoids' to the game";
/*
--------
SWITCHES
--------
*/
this.logging = false; // NB: Most log lines are commented out at present.
/*
----------------
GLOBAL VARIABLES
----------------
*/
this.invasionChance = 0.003;
// 0.003. Increased somewhat by player score . . - see this.startUp.
/*
------------------------
JSHINT: start of wrapper
------------------------
*/
(function() {
"use strict";
/*
---------
MAIN CODE
---------
*/
this.startUp = function() {
this.threeG_Installed = (worldScripts.ferdelance3G_populator !== undefined);
var score = player.score;
if (score > 7000) {
if (score > 19200) {
this.invasionChance += 0.0035;
} else {
this.invasionChance += 0.0025;
} // 'Elite' score is 6400.
}
this.invasionExtantInCurrentSystem = false;
// log("Extra Thargoids", "Initialised OK");
};
this.playerWillEnterWitchspace = function() {
if (this.invasionExtantInCurrentSystem || this.invasionChance === 0 || player.score < 1500 || Math.random() > this.invasionChance) {
this.invasionExtantInCurrentSystem = false;
} else {
this.repopulationsCounter = 0;
this.invasionExtantInCurrentSystem = true; // well, will occur in the NEXT system.
this.maxRepopulations = 40 + Math.ceil(Math.random() * 100);
this.repopulationsCounter = 0;
}
// this.invasionExtantInCurrentSystem = true; // TEST
};
this.entityDestroyed = function() {
this.invasionExtantInCurrentSystem = false;
};
this.interstellarSpaceWillPopulate = function() {
// INTERSTELLAR POPULATOR
// Use 'callback: this._myFunction.bind(this)' not callback: this._myFunction' in order to use global variables and functions.
// if two populator entries have same 'priority', Oolite will randomly determine their order.
// if (Math.random() > 0.86) {return;}
// ADD THARGOIDS
system.setPopulator("extraThargs-interstellarThargoids", {
priority: 101,
callback: this._perhapsAddInterstellarThargoids.bind(this)
});
};
this._perhapsAddInterstellarThargoids = function(pos) {
//
// log("extraThargoids_populator.js", "One or more Thargoid(s) added to interstellar space by populator script.");
var n;
if (player.score > 3750) {
n = 36;
} else {
n = 40;
}
var c = Math.ceil(Math.random() * n);
var s;
switch (c) {
case 1:
s = system.addShips("extraThargoid", 1, pos, 27000);
break;
case 2:
s = system.addShips("extraThargoid", 1, pos, 27000);
break;
case 3:
s = system.addShips("extraThargoid", 2, pos, 27000);
break;
case 4:
s = system.addShips("extraThargoid", 3, pos, 30000);
break;
case 5:
s = system.addShips("extraThargoids_buggly3", 3, pos, 15000);
break;
case 6:
s = system.addShips("extraThargoid", 2, pos, 60000);
break;
case 7:
s = system.addShips("extraThargoid", 2, pos, 27000); /* falls through */
case 8:
s = system.addShips("extraThargoids_buggly2", 1, pos, 27000);
break;
case 9:
s = system.addShips("extraThargoids_sweeper", 1, pos, 20000);
break;
case 10:
s = system.addShips("extraThargoids_sweeper", 1, pos, 25000);
break;
case 11:
s = system.addShips("extraThargoids_sweeper", 1, pos, 28000);
break;
case 12:
s = system.addShips("extraThargoids_sweeper", 2, pos, 40000);
break;
default:
}
};
// INTERSTELLAR REPOPULATOR - NONE
/*
this.interstellarSpaceWillRepopulate = function()
{
}
*/
this.systemWillPopulate = function() {
// STELLAR POPULATOR
// LANE_PS, LANE_WP, LANE_WS, STATION_AEGIS, PLANET_ORBIT, OUTER_SYSTEM, OUTER_SYSTEM_OFFPLANE
// INVASION stuff
// Use 'callback: this._myFunction.bind(this)' not callback: this._myFunction' in order to use global variables and functions
if (this.invasionExtantInCurrentSystem === false) {
return;
} // Else - INVASION
// Add thargoids and other ships
system.setPopulator("extraThargs-invasionShips", {
groupCount: 1,
priority: 100,
location: "LANE_WP",
callback: this._addInvasionEntities.bind(this)
});
if (Math.random() > 0.8) {
return;
}
var gc = 1;
if (Math.random() < 0.3) {
gc += 1;
}
system.setPopulator("extraThargs-invasionShips_More", {
groupCount: gc,
priority: 101,
location: "LANE_WPS",
callback: this._addInvasionEntities.bind(this)
});
};
this.shipWillExitWitchspace = function() {
if (!this.invasionExtantInCurrentSystem) {
return;
}
// Under certain conditions, cancel it. (And can't do this earlier, i.e. not initiate in the first place, because of technical problems. .
// Or, rather, because cannot cancel in sense of undo the population function, just try to make sure all ships I've added leave.
if (system.isInterstellarSpace) {
this.invasionExtantInCurrentSystem = false;
return;
// This will not actually cancel anything, because interstellar - rather than stellar - populator will have been called.
}
// Else
if (system.sun.isGoingNova || system.sun.hasGoneNova) {
system.sendAllShipsAway();
this.invasionExtantInCurrentSystem = false;
return;
}
// Else
//
// Remove some existing ships - try to do this as late as possible
this.$removeShipsEtcForInvasion();
};
this.shipExitedWitchspace = function() {
if (this.invasionExtantInCurrentSystem) {
// this.invasionExtantInCurrentSystem will have been set to false if we are in interstellar space.
player.consoleMessage("** POLICE ALERT **: Thargoid invasion!", 300);
}
// var s = system.addShips("extraThargoids_uberBuggly", 1, [0,0,0], 22000); // TEST
};
this.$is_a_targettedNonMainStation = function(e) {
return e.isStation && e.scanClass === "CLASS_STATION" && (e.position.distanceTo(system.mainPlanet.position) < system.mainPlanet.radius * 13);
};
this.$isWitchpointBuoy = function(e) {
return e.isShip && e.scanClass === "CLASS_BUOY" && e.hasRole("buoy-witchpoint") && (e.position.distanceTo(system.mainPlanet.position) < system.mainPlanet.radius * 50);
};
this.$removeShipsEtcForInvasion = function() {
// Some populators might add stuff *after* this, so err on removing too much
var i, l, f, r, s;
// Stations
s = system.filteredEntities(this, this.$is_a_targettedNonMainStation, system.mainStation);
for (i = 0; i < s.length; i++) {
r = Math.random();
if (r < 0.5) {
if (r < 0.4) {
s[i].explode();
} else {
s[i].remove(true); // no death action
}
}
}
// Buoys
s = system.filteredEntities(this, this.$isWitchpointBuoy);
l = s.length;
if (l > 0) {
i = s.length;
while (i--) {
if (Math.random() < 0.6) {
s[i].remove(true);
}
}
}
// Neutral ships
s = system.entitiesWithScanClass("CLASS_NEUTRAL");
l = s.length;
if (l > 9) {
if (Math.random() < 0.6) {
f = 0.9;
} else {
f = 0.75;
}
// NB: The following will run before various (old-style) OXP populators
l = Math.ceil(s.length * f);
i = l;
while (l--) {
if (
(s[i].isValid) &&
s[i].isShip &&
!s[i].isPlayer &&
s[i].primaryRole !== "hunter-medium" &&
s[i].primaryRole !== "hunter-heavy" &&
!s[i].hasRole("ecl_escape_pod_beacon") &&
!s[i].hasRole("escape-capsule") &&
!s[i].hasRole("hiredGuns_escort")
) {
if ((i % 3 === 0) && (s[i].distanceToPlayer > 30000) && (s[i].distanceToPlayer < 3072000)) {
if (s[i].abandonShip === true) {
s[i].energy = (s[i].energy * f) - 100 - i;
} else if (i % 6 === 0) {
s[i].explode();
} else {
s[i].remove(true);
}
}
}
}
}
// Remove some rocks
s = system.entitiesWithScanClass("CLASS_ROCK", player.ship, 3072000);
if (s.length < 1) {
return;
}
l = Math.ceil(s.length * 0.35);
i = l;
while (i--) {
if (s[i].isValid) {
if ((i % 2 === 0) && (s[i].distanceToPlayer > 30000)) {
s[i].explode();
} else {
s[i].remove(true); // no death action
}
}
}
};
this._addInvasionEntities = function(pos) {
var baseThargoidNum, basePoliceNum, i, n, n2, r, s;
// THARGOIDS
if (player.score < 5000) {
baseThargoidNum = 18;
} else {
baseThargoidNum = 23;
}
// log("ET TESTING", "OK");
// Main action - carriers and other ships
if (this.$roleExists("thargoidCarrier") !== undefined && system.mainStation && Math.random() < 0.9) {
n = 1 + Math.ceil(Math.random() * 2);
if (n === 1 && Math.random() < 0.5) {
n++;
}
i = n;
while (i--) {
s = system.addShips("thargoid_carrier", 1, pos, 26000);
s[0].script.targetStation = system.mainStation;
s[0].script.destinationCoordinates = system.mainStation.position;
if (Math.random() < 0.6) {
s = system.addShips("extraThargoids_sweeper", 1, pos, 15000);
}
}
baseThargoidNum -= 5; // if (baseThargoidNum < 10) {baseThargoidNum = 10;}
if (Math.random() < 0.7) {
s = system.addShips("extraThargoids_uberBuggly", 1, pos, 20000); // has sweeper escorts
baseThargoidNum -= 1;
}
} else if (Math.random() < 0.92) {
s = system.addShips("extraThargoids_uberBuggly", 1, pos, 17000); // has sweeper escorts
baseThargoidNum -= 2;
if (Math.random() < 0.57) {
s = system.addShips("extraThargoids_uberBuggly", 1, pos, 20000); // has sweeper escorts
baseThargoidNum -= 1;
}
}
s = system.addShips("thargoid", baseThargoidNum, pos, 20000);
// Witchspace - planet
n = Math.ceil(Math.random() * baseThargoidNum);
s = system.addShipsToRoute("thargoid", baseThargoidNum, Math.random(), "wp");
// POLICE
// Main action - normal ships and carriers
basePoliceNum = baseThargoidNum + 2 + Math.ceil(Math.random() * 4);
if (Math.random() < 0.7) {
n = 1 + Math.ceil(Math.random() * 5);
s = system.addShips("interceptor", n, pos, 23000);
if (s[0] && s[0].isValid) {
basePoliceNum--;
}
}
r = Math.random();
if (r < 0.7) {
s = system.addShips("behemoth", 1, pos, 23000);
if (r < 0.35) {
s = system.addShips("behemoth", 1, pos, 32000);
}
if (s[0] && s[0].isValid) {
basePoliceNum -= 2;
} // have done no check actually are these ships installed
}
if (Math.random() < 0.5) {
s = system.addShips("leviathan", 1, pos, 23000);
basePoliceNum -= 2;
if (s[0] && s[0].isValid) {
basePoliceNum -= 2;
} // have done no check actually are these ships installed
}
if (basePoliceNum > 0) {
s = system.addShips("police", basePoliceNum, pos, 20000);
}
// Witchpoint - planet
if (Math.random() < 0.5) {
n = 1 + Math.ceil(Math.random() * basePoliceNum);
s = system.addShipsToRoute("police", n, Math.random(), "wp");
}
// HUNTERS
r = Math.random();
if (r < 0.25) {
n = 1 + Math.ceil(Math.random() * 2);
s = system.addShips("hunter-medium", n, pos, 35000);
}
if (r < 0.2) {
n = 1 + Math.ceil(Math.random() * 3);
s = system.addShips("hunter-heavy", n, pos, 30000);
}
// WRECKAGE. Note that removal of entities via removeShipsEtcForInvasion will tend to generate some wreckage.
// At the site of the main action
n = 1 + Math.ceil(Math.random() * 4);
s = system.addShips("alloy", n, pos, 45000);
n = 1 + Math.ceil(Math.random() * 9);
s = system.addShips("extraThargoids_tharglet", n, pos, 40000);
// Witchpoint
r = Math.random();
if (r < 0.6) {
n = 1 + Math.ceil(r * 3);
s = system.addShips("alloy", n, [0, 0, 0], 45000);
n = 1 + Math.ceil(r * 13);
s = system.addShips("extraThargoids_tharglet", n, [0, 0, 0], 40000);
if (Math.random() < 0.5) {
n2 = 1 + Math.ceil(Math.random() * 4);
s = system.addShips("cargopod", n2, [0, 0, 0], 4000);
}
}
// Witchpoint - planet
n = 1 + Math.ceil(Math.random() * 7);
i = n;
while (i--) {
n2 = 1 + Math.ceil(Math.random() * 4);
s = system.addShipsToRoute("cargopod", n2, Math.random(), "wp");
}
n = 1 + Math.ceil(Math.random() * 4);
i = n;
while (i--) {
n2 = 1 + Math.ceil(Math.random() * 4);
s = system.addShipsToRoute("extraThargoids_tharglet", n2, Math.random(), "wp");
if (Math.random() < 0.3) {
s = system.addShipsToRoute("alloy", 1, r, "wp");
}
}
s = system.addShipsToRoute("extraThargoids_tharglet", n, Math.random(), "wp");
};
this.systemWillRepopulate = 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.
// 'systemWillRepopulate' does *not* use system.setPopulator
if (this.invasionExtantInCurrentSystem === false) {
return;
}
// THE FOLLOWING ONLY RUNS *WHEN IS AN INVASION*
if (this.repopulationsCounter > this.maxRepopulations) {
return;
}
// Else
this.repopulationsCounter++;
if (Math.random() > 0.04) {
return;
}
// Else
var i, g, n, s, s2;
// Perhaps add police
if (Math.random() < 0.45) {
n = system.countShipsWithRole("police");
if (n > 50) {
return;
}
// Else
n = 3 + Math.ceil(Math.random() * 8);
if (this.threeG_Installed && r < 0.015) {
s = system.addShips("ferdelance3G_interstellar", n);
i = s.length;
while (i--) {
s[i].ai.switchAI("route1patrolAI.plist");
// Need to set AI to stop them trying to go interstellar
}
} else {
s = system.addShips("police", n);
}
return;
}
// perhaps add thargoids
if (Math.random() < 0.35) {
n = system.countShipsWithRole("thargoid");
if (n > 150) {
return;
}
n = 2 + Math.ceil(Math.random() * 30);
s = system.addShips("thargoid", n);
return;
}
// Else, add hunters
s = system.addShips("hunter-heavy", 1);
if (s[0]) {
g = new ShipGroup("hunter group vs invasion", s[0]);
s[0].group = g;
log("ET TESTING", "add hunter-heavy(" + g.name + ") to ...");
// TODO: Set weapons, skill, AI
if (s[0].autoAI) {
s[0].switchAI("oolite-bountyHunterLeaderAI.js");
}
n = 2 + Math.ceil(Math.random() * 5);
s2 = system.addShips("hunter", n);
for (i = 0; i < n; i++) {
s2[i].group = g;
g.addShip(s2[i]);
// s2[i].setAI("oolite-bountyHunterAI.js"); // autoAI
}
// log("ET TESTING", "added "+n+" hunters("+g.name+") to ...");
}
};
this.$roleExists = function(roleString) {
var dummyShips = system.addShips(roleString, 1, [100000, 100000, 100000]);
if (dummyShips == null) {
return false;
}
var exists = (dummyShips.length == 1);
if (exists) dummyShips[0].remove(true);
return exists;
};
/*
----------------------
JSHINT: end of wrapper
----------------------
*/
}).call(this);
// EOF |
| Scripts/extraThargoids_sweeper.js | /*
========================================================================
extraThargoids_sweeper.js
This file is part of the ExtraThargoids expansion pack.
Author: UK_Eliter
License: 2017 Creative Commons: attribution, non-commercial, sharealike.
========================================================================
*/
/*
-------------------
JSLINT: set options
-------------------
*/
/*jshint esversion: 6*/
/*jshint sub:true*/
this.name = "extraThargoids_sweeper";
this.author = "UK_Eliter";
this.copyright = "2014 Creative Commons: attribution, non-commercial, sharealike.";
this.licence = "CC-NC-SA 3";
this.description = "Script for Thargon sweepers";
/*
------------------
DEBUGGING SWITCHES
------------------
*/
//this.logging = true; // THIS SHOULD BE COMMENTED OUT WHEN NOT TESTING
//var consoleDebugMessages = false;
/*
--------------
VARIABLES etc.
--------------
*/
this.sweep = new SoundSource();
this.sweep.sound = "extraThargoids_sweep.ogg";
this.mediumSweep = new SoundSource();
this.mediumSweep.sound = "extraThargoids_mediumSweep.ogg";
this.quietSweep = new SoundSource();
this.quietSweep.sound = "extraThargoids_quietSweep.ogg";
/*
------------------------
JSHINT: start of wrapper
------------------------
*/
(function() {
"use strict";
/*
--------------
EVENT HANDLERS
--------------
*/
this.shipSpawned = function() {
// If the scanTimer does not exist, create it.
// If it does exist, and it is not running, start it.
// Then - as usual - remove the ship object created by this function.
if (!this.$scanTimer) {
this.$scanTimer = new Timer(this, this.$scan, 1, 2.8);
} else if (!this.$scanTimer.isRunning) {
this.$scanTimer.start();
}
delete this.shipSpawned;
};
this.shipDied = this.entityDestroyed = this.playerWillEnterWitchspace = function() {
this.$deleteTimers();
};
/*
------------
CALLED BY AI
------------
*/
this.$_incomingMissile = function() {
// This run (only) by extraThargoids_sweeperAI
if (this.$incomingMissileTimer) {
if (this.$incomingMissileTimer.isRunning) {
return;
} else {
this.$incomingMissileTimer.start();
}
} else {
this.$incomingMissileTimer = new Timer(this, this.$incomingMissileActual, 0.2);
}
};
this.$_validateTarget = function() {
if (this.ship.target && !this.ship.target.isThargoid) {
this.ship.reactToAIMessage("TARGET_VALID");
} else {
this.ship.reactToAIMessage("TARGET_INVALID");
}
};
this.$_sophistatedBeligerentAttackResponse = function() {
// = if has this missile type, fire it, else . .
if (this.ship.fireMissile("EQ_THARGON") == null) {
this.ship.reactToAIMessage("DO_ATTACK");
}
};
this.$_checkForPossiblyFarThargoids = function() {
var s = system.filteredEntities(this, this.$isBug, this.ship, 55000);
if (s.length > 0) {
this.ship.reactToAIMessage("TARGET_FOUND"); // AI does actual SETTING of the target
} else if (s.length > 0) {
this.ship.reactToAIMessage("NOTHING_FOUND");
}
};
/*
-------
FILTERS
-------
*/
this.$poppable = function(e) {
return e.isShip && (e.isMissile || e.isMine);
};
this.$isBug = function(e) {
return (e.isShip && e.isThargoid);
};
this.$isTarget = function(e) {
return e.isShip && (e.isMissile || e.isMine) && e.primaryRole !== "EQ_BUGGLYMISSILE" && e.name !== "Thargoid Projectile";
};
/*
-------
GENERAL
-------
*/
this.$scan = function() {
/*
MASSES:
MM Hardened Missile: 114 (!)M
Nexus premium warhead: 67ish
mini-missile mass: 114
intercept missile mass: 210.3
q-bomb: 135
normal mass: 1324
hardhead mass: 1638
TCAT_claw: 472.5
TCAT_talon: 135
s[c].hasRole("EQ_HARDENED_MISSILE") || s[c].hasRole("armoury_MMHardMissile" || s[c].hasRole("EQ_MISSILE")
*/
if (!this.ship) {
return;
}
if (this.$incomingMissileTimer && this.$incomingMissileTimer.isRunning) {
return;
}
this.ship.lightsActive = false; // turn them off, in case they've been turned on before
if (this.ship.energy < 45) {
return;
}
this.ship.energy -= 1; // merely scanning takes a bit of energy
var s = system.filteredEntities(this, this.$isTarget, this.ship, 26000);
var num = s.length;
if (num === 0) {
return;
}
// What follows starts going through all ordinance at large, and stops when the sweeper detects one of those pieces (or when reaches end of list)
var detected = false;
var chance;
var c = num;
while (c--) {
if (s[c].mass < 125) {
chance = 0.05;
} else {
chance = 0.86;
}
if (this.ship.position.distanceTo(s[c]) < 15000) {
chance += 0.12;
}
if (Math.random() <= chance) {
detected = true;
break;
}
}
// if has been a detection, sweeper fires its special ECM . .
if ((detected) && (this.ship.energy > 14)) {
this.$actualSweep();
}
};
this.$actualSweep = function() {
this.ship.lightsActive = true;
this.ship.energy -= 14; // takes more energy to destroy (or try to destroy, anyway) something
var s = system.filteredEntities(this, this.$poppable, this.ship, 26000);
var num = s.length;
if (num > 0) {
var c = num;
var chance;
while (c--) {
// log("EXTRA", s[c].primaryRole);
switch (s[c].primaryRole) {
case "TCAT_talon":
chance = 0.05;
break;
case "TCAT_claw":
chance = 0.035;
break;
case "EQ_BUGGLYMISSILE":
chance = 0.01;
break;
case "EQ_F3G_ANTISWEEP_MISSILE":
chance = 0.02;
break;
default:
chance = 0.97;
}
if (Math.random() <= chance) {
var damage = 16 + (Math.ceil(Math.random() * 40));
if (s[c].energy <= damage) {
s[c].explode();
} else {
s[c].energy -= damage;
}
}
}
}
if (!this.ship || !player.ship) {
return;
}
var ps = player.ship; // for speed, but changes won't affect the original variable
var distanceToPlayer = this.ship.position.distanceTo(ps);
if (distanceToPlayer < 28000) {
if (distanceToPlayer < 13000) {
this.sweep.play();
if (Math.random() > 0.83) {
this.ship.commsMessage(expandDescription("[thargoid_curses]", ps));
}
} else if (distanceToPlayer < 17500) {
this.mediumSweep.play();
if (Math.random() > 0.9) {
this.ship.commsMessage(expandDescription("[thargoid_curses]", ps));
}
} else {
this.quietSweep.play();
if (Math.random() > 0.95) {
this.ship.commsMessage(expandDescription("[thargoid_curses]", ps));
}
}
}
};
this.$incomingMissileActual = function $incomingMissileActual() {
this.$incomingMissileTimer.stop();
if (this.ship.energy > 14) {
this.$actualSweep();
} else {
this.ship.reactToAIMessage("GO_FLEE");
}
};
/*
-------
CLEANUP
-------
*/
this.$deleteTimers = function() {
this.$deleteIncomingMissileTimer();
this.$deleteScanTimer();
};
this.$deleteIncomingMissileTimer = function() {
if (!this.$incomingMissileTimer) {
return;
}
if (this.$incomingMissileTimer.isRunning) {
this.$incomingMissileTimer.stop();
}
delete this.$incomingMissileTimer;
};
this.$deleteScanTimer = function() {
if (!this.$scanTimer) {
return;
}
if (this.$scanTimer.isRunning) {
this.$scanTimer.stop();
}
delete this.$scanTimer;
};
/*
----------------------
JSHINT: end of wrapper
----------------------
*/
}).call(this);
// EOF |
| Scripts/extraThargoids_uber.js | /*
========================================================================
extraThargoids_uber.js
This file is part of the ExtraThargoids expansion pack.
Author: UK_Eliter
License: 2017 Creative Commons: attribution, non-commercial, sharealike.
========================================================================
*/
/*
-------------------
JSLINT: set options
-------------------
*/
/*jshint esversion: 6*/
/*jshint sub:true*/
this.name = "thargoid_uberbuggly";
this.author = "UK_Eliter";
this.copyright = "2014 Creative Commons: attribution, non-commercial, sharealike.";
this.licence = "CC-NC-SA 3";
this.description = "Script for the 'uberbuggly' Thargon ships";
/*
------------------
DEBUGGING SWITCHES
------------------
*/
// this.logging = true;
var consoleDebugMessages = false; // do NOT comment this out. Rather, to disable, set to false.
/*
------
SOUNDS
------
*/
var mysound_Warning = new SoundSource();
mysound_Warning.sound = "warning.ogg"; // this sound built-in to Oolite - and does not need to be declared in the 'customsounds' file.
/*
------------------------
JSHINT: start of wrapper
------------------------
*/
(function() {
"use strict";
/*
--------------
EVENT HANDLERS
--------------
*/
this.shipTargetCloaked = function() {
var seconds;
if (this.decloakTargetTimer && this.decloakTargetTimer.isRunning) {
return;
}
if (this.ship.target.isThargoid) {
return;
}
if (Math.random() < 0.13) {
return;
}
if (Math.random() > 0.4) {
this.ship.commsMessage(expandDescription("[thargoid_curses]"));
}
this.ship.cloakedTarget = this.ship.target;
seconds = (1 + Math.floor(Math.random() * 6));
if (this.decloakTargetTimer) {
delete this.decloakTargetTimer;
}
this.decloakTargetTimer = new Timer(this, this.$decloakTargetTimed, seconds);
};
this.shipDied = this.entityDestroyed = this.playerWillEnterWitchspace = function() {
this.$_deleteTimers();
};
/*
------------
CALLED BY AI
------------
*/
this.$_deleteTimers = function() {
if (!this.decloakTargetTimer) {
return;
}
if (this.decloakTargetTimer.isRunning) {
this.decloakTargetTimer.stop();
}
delete this.decloakTargetTimer;
};
this.$_deleteTimersAndSetMisJump = function() {
this.ship.scriptedMisjump = true;
this.$_deleteTimers();
};
this.$_curse = function() {
this.ship.commsMessage(expandDescription("[thargoid_curses]"));
};
this.$_possiblyCurse = function() {
if (Math.random() < 0.35) {
this.ship.commsMessage(expandDescription("[thargoid_curses]"));
}
};
this.$_fireQuirium = function() {
this.ship.awardEquipment("EQ_QC_MINE");
this.ship.fireMissile("EQ_QC_MINE");
this.$_possiblyCurse();
this.$_deleteTimers();
};
/*
-----
OTHER
-----
*/
this.$decloakTargetTimed = function() {
this.decloakTargetTimer.stop();
if (!this.ship || !this.ship.isValid) {
delete this.decloakTargetTimer;
return;
}
if (!this.ship.cloakedTarget || !this.ship.cloakedTarget.isValid) {
delete this.decloakTargetTimer;
return;
}
if (!this.ship.cloakedTarget.isCloaked) {
delete this.decloakTargetTimer;
return;
}
this.distanceToTarget = this.ship.position.distanceTo(this.ship.cloakedTarget);
if (this.distanceToTarget < 10000) {
mysound_Warning.play();
this.ship.cloakedTarget.lightsActive = true;
if (Math.random() > 0.9) {
this.ship.cloakedTarget.setEquipmentStatus("EQ_CLOAKING_DEVICE", "EQUIPMENT_DAMAGED");
if (this.ship.cloakedTarget.isPlayer && !player.ship) {
delete this.decloakTargetTimer;
return;
}
this.ship.commsMessage("CLOAKING DEVICE DAMAGED!", this.ship.cloakedTarget);
this.ship.target = this.ship.cloakedTarget;
this.ship.reactToAIMessage("TARGET_REGAINED");
} else {
player.consoleMessage("CLOAKING FAILURE!", 10);
player.ship.isCloaked = false;
this.ship.target = this.ship.cloakedTarget;
this.ship.reactToAIMessage("TARGET_REGAINED");
}
}
if (Math.random() < 0.26) {
this.ship.commsMessage(expandDescription("[thargoid_curses]"));
}
delete this.decloakTargetTimer;
};
/*
----------------------
JSHINT: end of wrapper
----------------------
*/
}).call(this);
// EOF |