Back to Index | Page generated: Dec 20, 2024, 7:22:09 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 | 1647012498 |
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 |