| Scripts/nexus_missile_basicOrPremiumOrUltimate.js |
/*
////////////////////////////////////////////////////////////////////////////////
This file: nexus_missile_basicOrPremiumOrUltimate.js
Associated AI: nexus_missile_basicOrPremiumOrUltimate.plist
Author: UK_Eliter
License: 2017 Creative Commons: attribution, non-commercial, sharealike.
////////////////////////////////////////////////////////////////////////////////
*/
/*
==============
LINTER OPTIONS
==============
*/
/* jshint esversion: 6 */
/* jshint -W030 */
/*
======
HEADER
======
*/
this.name = 'nexus_missile_basicOrPremiumOrUltimate.js';
this.author = 'UK_Eliter';
this.description = '';
this.copyright = '2014 Creative Commons: attribution, non-commercial, sharealike.';
this.licence = 'CC-NC-SA 3';
/*
============================
GLOBALS, including debugging
============================
*/
this.dbg = false; // NB
this.missileType = null; // specified later
// this.isSpawning = false; // See this.shipTakingDamage
/*
========================
JSHINT: start of wrapper
========================
*/
(function () {
'use strict';
/*
--------------
Event handlers
--------------
*/
this.shipSpawned = function () {
this.energyThresholdForDamage = this.ship.maxEnergy * 0.8;
if (this.ship.hasRole('EQ_NEXUS_BASIC_MISSILE')) {
this.missileType = 1;
} else if (this.ship.hasRole('EQ_NEXUS_PREMIUM_MISSILE')) {
this.missileType = 2;
} else {
this.missileType = 3; // 'EQ_NEXUS_ULTIMATE_MISSILE'
}
this.dbg && log(this.name, 'shipSpawned - missile type: ' + this.missileType); // TEST
};
/*
// This routine seems to stop the premium or ultimate models - but not the basic model - from spawning, or at least from continuing to exist.
// EDIT: The problem may have been elsewhere. CONSIDER REINSTATING. TO DO.
this.shipTakingDamage = function (amount, whom, type) {
if (this.ship.target) {
if (
(whom == this.ship.target) &&
(type === 'scrape damage') &&
(amount > this.ship.energy) &&
(Math.random() < 0.9)
) {
this.ship.energy = this.ship.energy + amount; // keep it around long enough to detonate it.
this.dbg && log(this.name, 'Detonating, via damage'); // TEST
this.$detonate_core();
return;
}
}
if (
(Math.random() > 0.5) ||
(
(amount > 60) &&
(this.ship.energy < this.energyThresholdForDamage)
)
) {
if (!this.isSpawning) {
// Keep it around long enough for it to spawn. We can seem to get an infinite loop. Hence the check.
this.ship.energy = this.ship.energy + amount;
this.dbg && log(this.name, 'Spawning, via damage'); // TEST
this.isSpawning = true;
this.$spawnWarheads_core();
}
}
};
*/
/*
----------------------
Functions called by AI
----------------------
*/
this.$_detonate = function () {
this.$detonate_core();
};
this.$_spawnWarheads = function () {
this.$spawnWarheads_core();
};
/*
-----
Other
-----
*/
this.$detonate_core = function () {
/*
`function dealEnergyDamage(damage : Number, idealRange : Number [, velocityBias : Number])`
The standard Oolite missile uses dealEnergyDamage(170, 32.5, 0.25), has a maximum speed of 0.75LM, and its AI tries to detonate it 25m from its target. [NB: If target within ideal range, takes full damage.]
*/
switch (this.missileType) {
case 1:
this.ship.dealEnergyDamage(330, 50, 0.25);
break;
case 2:
this.ship.dealEnergyDamage(470, 70, 0.25);
break;
case 3:
this.ship.dealEnergyDamage(600, 90, 0.25);
break;
default:
this.dbg && log(this.name, 'Error: bad missileType <' + this.missileType + '> in $detonate_core');
}
this.ship.explode();
};
// this.$isHostile = function (e) {
// // if (this.dbg) {player.consoleMessage('Hostile scan from MISSILE script', 6);}
// return e.isShip &&
// e.hasHostileTarget &&
// (e.target == this.ship.owner);
// };
this.$spawnWarheads_core = function () {
/*
-------------
PRELIMINARIES
-------------
*/
if (this.dbg) {
log(this.name, '$spawnWarheads_core - entered');
log(this.name, '$spawnWarheads_core - missileType: ' + this.missileType);
}
if (
!this.ship ||
!this.ship.owner
) {
this.dbg && log(this.name, 'bad shap or bad owner');
return;
}
var
numWarheads,
submunition_as_role;
switch (this.missileType) {
case 1:
numWarheads = 3;
submunition_as_role = 'nexus_warhead';
break;
case 2:
numWarheads = 3;
submunition_as_role = 'nexus-premium-warhead';
break;
case 3:
numWarheads = 4;
submunition_as_role = 'nexus-ultimate-warhead';
break;
default:
this.dbg && log(this.name, 'Error: bad missileType <' + this.missileType + '> in $spawnWarheads_core');
}
/*
-----------------------------------------------------------------------------------------------------
Once spawned (which happens later), each head initially will have as its target the missile's target.
Yet, if there are other potential targets, then we want to distribute them amongst the warheads.
Here is the main logic of the code below.
We get a list of ships near the missle.
We see which are hostile to the player.
Then, skipping the first warhead, we assign the hostiles (in order found) as targets.
Insofar as there are more warheads - or warheads-minus-one - than hostiles, some warheads will end
up, like the first warhead, with the target of the original missile.
Often the foregoing will result in the original target being targetted by two warheads, even if there
are multiple hostiles. But that is OK (and allows for relatively simple code).
-----------------------------------------------------------------------------------------------------
*/
/*
--------------------------------------------
BEGIN TO DETERMINE TARGETS:
get a list of powered ships near the missile.
---------------------------------------------
*/
const missile = this.ship;
const shipsNearMissile = missile.checkScanner(true);
var
i,
missileOwner,
warheadTargets = [],
warheadTargetsIncludeMissileTarget = false;
if (missile.owner && missile.owner.isValid) {
missileOwner = missile.owner;
} else {
log(this.name, 'Missile lacks owner!');
}
const missileOwned = !!missileOwner; // This JS engine seems to lack the operator 'boolean'.
if (shipsNearMissile.length > 0) {
// There is something within scanner range of the missile that is powered (though it might be only the ship that fired the missile!).
/*
-----------------------------------------------------------------------------
CONTINUE TO DETERMINE TARGETS:
see which if any of the nearby ships are targetting the owner of the missile.
-----------------------------------------------------------------------------
*/
if (missileOwned) {
/*
If the ship that fired the missile still exists, then populate warheadTargets with those nearby ships that are hostile to the ship.
And if one of those hostile ships is the missile's target, then record that fact.
*/
this.dbg && log(this.name, 'Checking hostility of nearby ships:');
const targetsToSeek = numWarheads - 1; // We leave the first warhead's target - which should be the missile's target - alone.
var numHostiles = 0;
for (
i = 0; i < shipsNearMissile.length; i++
) {
this.dbg && log(this.name, '-- ship #' + i); // TEST
if (
shipsNearMissile[i].hasHostileTarget &&
shipsNearMissile[i].target == missileOwner
) {
warheadTargets.push(shipsNearMissile[i]);
numHostiles++;
this.dbg && log(this.name, '---- HOSTILE');
if (numHostiles >= targetsToSeek) {
this.dbg && log(
this.name, '-- breaking loop: ' + targetsToSeek + ' target(s), ' + numWarheads + ' warheads'
); // TEST
break;
}
} else if (this.dbg) {
this.dbg && log(this.name, '---- not hostile');
}
}
} // End of `if (missile.owner && missile.owner.isValid)
} // End `if (shipsNearMissile.length > 0)`
/*
If there was nothing at all within scanner range of the missile (or indeed merely the player), then presumably, when we spawn the warheads, they are going to get an invalid
target. But try anyway.
*/
/*
----------------------------
SPAWNING, OWNERSHIP, TARGETS
----------------------------
*/
/*
Upon spawn, the warheads will have the missile as the owner. That is good in that they inherit the target.
It is bad in that they lack legal connection to the ship that fired the missile.
But Oolite's owner property is read-only.
So, give each warhead an 'urOwner' property.
Also, store the missile/warhead's original target.
*/
const missileHasTarget = !!missile.target; // This JS engine seems to lack the operator 'boolean'.
const
isOwnedWithTarget = missileOwned && missileHasTarget,
isOwnedWithoutTarget = missileOwned && !missileHasTarget,
isUnownedWithTarget = !missileOwned && missileHasTarget,
unOwnedWithoutTarget = !missileOwned && !missileHasTarget;
// Spawn the warheads (as late as possible). In so doing, each warheads gets as its target the missile's target.
const warheads = missile.spawn(
submunition_as_role,
numWarheads
);
if (warheads.length === 0) {
this.dbg && log(this.name, 'Failed to spawn warheads');
// ^ I have had this happen. I am unsure why.
this.ship.explode();
return;
}
switch (true) {
case isOwnedWithTarget:
this.dbg && log(this.name, "Setting ownership and 'old target':");
for (i = 0; i < numWarheads; i++) {
this.dbg && log(this.name, '-- warhead #' + i); // TEST
if (warheads[i] && warheads[i].isValid) {
warheads[i].urOwner = missile.owner;
}
if (warheads[i] && warheads[i].isValid) {
warheads[i].oldTarget = missile.target;
}
}
break;
case isOwnedWithoutTarget:
// missileOwned is true; missileHasTarget is false.
if (this.dbg) {
log(this.name, 'Missile lacks target!');
log(this.name, 'Setting ownership:');
}
for (i = 0; i < numWarheads; i++) {
this.dbg && log(this.name, '-- warhead #' + i); // TEST
if (warheads[i] && warheads[i].isValid) {
warheads[i].urOwner = missile.owner;
}
}
break;
case isUnownedWithTarget:
// missileOwned is false; missileHasTarget is true.
if (this.dbg) {
log(this.name, 'Missile lacks owner!');
log(this.name, "Setting 'old target':");
}
for (i = 0; i < numWarheads; i++) {
this.dbg && log(this.name, '-- warhead #' + i); // TEST
if (warheads[i] && warheads[i].isValid) {
warheads[i].oldTarget = missile.target;
}
}
break;
case unOwnedWithoutTarget:
// missileOwned is false; missileHasTarget is false.
if (this.dbg) {
log(this.name, 'Missile lacks target!');
log(this.name, 'Missile lacks owner!');
}
}
const numTargets = warheadTargets.length;
if (numTargets < 1) {
this.dbg && log(this.name, 'No targets to assign');
} else {
this.dbg && log(this.name, 'Assigning targets to ' + numTargets + ' warheads:');
for (i = 0; i < numTargets; i++) {
this.dbg && log(this.name, '-- warhead #' + i); // TEST
if (warheads[i] && warheads[i].isValid) {
warheads[i].target = warheadTargets[i];
}
}
}
// TEST:
if (this.dbg) {
if (!warheads[0] || !warheads[0].isValid) {
log(this.name, 'Warhead 0 does not exist');
} else {
if (!warheads[0].target) {
log(this.name, 'Warhead 0 has no target at all!');
}
}
}
/*
------------------
REMOVE THE MISSILE
------------------
*/
this.ship.explode();
};
/*
======================
JSHINT: end of wrapper
======================
*/
}).call(this);
// EOF |
| Scripts/nexus_missile_bugOff.js |
/*
///////////////////////////////////////////////////////////////////////////////
This file: nexus_missile_bugOff.js
Associated AI: nexus_missile_bugOff.plist
Author: UK_Eliter
License: 2017 Creative Commons: attribution, non-commercial, sharealike.
///////////////////////////////////////////////////////////////////////////////
*/
/*
==============
LINTER OPTIONS
==============
*/
/* jshint esversion: 6 */
/* jshint -W030 */
/*
======
HEADER
======
*/
this.name = 'nexus_missile_bugOff.js';
this.author = 'UK_Eliter';
this.description = 'Script for Nexus BugOff missile';
this.copyright = '2014 Creative Commons: attribution, non-commercial, sharealike.';
this.licence = 'CC-NC-SA 3';
/*
==============
DEBUG SWTICHES
==============
*/
this.dbg = false; // NB
/*
========================
JSHINT: start of wrapper
========================
*/
(function () {
'use strict';
/*
--------------
Event handlers
--------------
*/
this.shipSpawned = function () {
this.missileEnergyThreshold = this.ship.maxEnergy * 0.7;
};
// Do not spawn warheads if the missile has received a large hit, or if the missile has considerable energy remaining.
this.shipTakingDamage = function (amount) {
if (
amount > 25 ||
this.ship.energy > this.missileEnergyThreshold
) {
return;
}
if (Math.random() < 0.9) {
this.$spawnWarheads_core();
}
};
/*
----------------------
Functions called by AI
----------------------
*/
this.$_detonate = function () {
this.ship.dealEnergyDamage(650, 50, 0.25);
this.ship.explode();
};
this.$_spawnWarheads = function () {
this.$spawnWarheads_core();
};
/*
-----
Other
-----
*/
this.$spawnWarheads_core = function () {
this.dbg && log(this.name, '$spawnWarheads_core - entered'); // TEST
const
countAdvertised = 5;
var
chanceMalfunction,
countToSpawn,
countToSpawnOnMalfunction;
if (this.ship.hasRole('EQ_NEXUS_BUG_R_MISSILE')) {
// This is the military reject missile.
chanceMalfunction = 0.19;
countToSpawnOnMalfunction = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4][Math.floor(Math.random() * 10)];
// ^ Number will be between 1 and 4, biased moderately towards the high end of the list.
} else {
// This is the normal missile.
chanceMalfunction = 0.025;
countToSpawnOnMalfunction = [1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4][Math.floor(Math.random() * 16)];
// ^ Number will be between 1 and 4, biased heavily towards the high end of the list.
}
if (Math.random() > chanceMalfunction) {
countToSpawn = countAdvertised;
} else {
countToSpawn = countToSpawnOnMalfunction;
}
this.dbg && log(this.name, '$spawnWarheads_core - spawning ' + countToSpawn + ' warheads'); // TEST
const warheads = this.ship.spawn('nexus-bug-warhead', countToSpawn);
if (this.dbg && warheads.length === 0) {
log(this.name, '$spawnWarheads_core - failed to spawn any warheads'); // TEST
}
this.ship.explode();
};
/*
======================
JSHINT: end of wrapper
======================
*/
}).call(this);
// EOF |
| Scripts/nexus_warhead_basicOrPremiumOrUltimate.js |
/*
///////////////////////////////////////////////////////////////////////////////
This file: nexus_warhead_basicOrPremiumOrUltimate.js
Associated AI: nexus_warhead_basicOrPremiumOrUltimate.plist
Author: UK_Eliter
License: 2017 Creative Commons: attribution, non-commercial, sharealike.
///////////////////////////////////////////////////////////////////////////////
/*
==============
LINTER OPTIONS
==============
*/
/* jshint esversion: 6 */
/* jshint -W030 */
/*
======
HEADER
======
*/
this.name = 'nexus_warhead_basicPremiumOrUltimate.js';
this.author = 'UK_Eliter';
this.description = 'Script for Nexus missile warheads';
this.copyright = '2014 Creative Commons: attribution, non-commercial, sharealike.';
this.licence = 'CC-NC-SA 3';
/*
============================
GLOBALS, including debugging
============================
*/
this.dbg = false; // NB
this.warheadType = null; // This gets set to something meaningful below.
// this.ship.oldTarget is set, initially, by the _missile_ script and also by this script - once this script finds a target.
/*
========================
JSLINT: start of wrapper
========================
*/
(function () {
'use strict';
/*
--------------
EVENT HANDLERS
--------------
*/
this.shipSpawned = function () {
// this.dbg && log(this.name, 'SPAWNED');
if (this.ship.primaryRole === 'nexus_warhead') {
this.warheadType = 1; // 1 = basic
} else if (this.ship.primaryRole === 'nexus-premium-warhead') {
this.warheadType = 2; // 2 = premium
} else {
this.warheadType = 3; // 3 = ultimate
}
this.dbg && log(this.name, 'shipSpawned - warhead type: ' + this.warheadType); // TEST
};
// this.shipTakingDamage = function (amount, whom, type) {
// this.dbg && log(this.name, 'Taking damage:' + amount); // TEST
// if (amount > 14 || Math.random() > 0.2) return;
// this.ship.energy = this.ship.energy + amount; // keep it around long enough to detonate it.
// this.$detonate_core();
// };
/*
------------------------------------
ROUTINES CALLED BY AI and only by AI
------------------------------------
*/
this.$_scanForTargets = function () {
this.dbg && log(this.name, 'Scanning for targets'); // TEST
/*
Here we use the 'urOwner' of the warhead.
The script that spawned the warhead creates that property and sets it to the ship that fired the original missile.
*/
const
nearShips = this.ship.checkScanner(true),
warhead = this.ship;
var i = nearShips.length;
if (i > 0) {
if (warhead.urOwner && warhead.urOwner.isValid) {
while (i--) {
if (
nearShips[i].isValid &&
nearShips[i].hasHostileTarget &&
(nearShips[i].target === warhead.urOwner)
) {
warhead.target = nearShips[i];
warhead.oldTarget = nearShips[i];
warhead.reactToAIMessage('SCRIPT_TARGET');
this.dbg && log(this.name, '-- found one'); // TEST
return;
}
} // End 'while'
} else {
this.dbg && log(this.name, '-- urOwner bad'); // Happens when launching ship is gone // TEST
}
} else {
this.dbg && log(this.name, '-- nothing nearby'); // TEST
}
this.dbg && log(this.name, '-- none found'); // TEST
// We found no target. Can we revert to an old target?
if (
this.oldTarget &&
this.oldTarget.isValid
) {
this.dbg && log(this.name, '-- reverting to old target'); // TEST
warhead.target = this.oldTarget;
warhead.reactToAIMessage('SCRIPT_TARGET');
return;
}
this.dbg && log(this.name, '-- found no old target'); // TEST
warhead.reactToAIMessage('SCRIPT_NO_TARGET');
};
/*
-----
OTHER
-----
*/
this.$detonate_core = function () {
/*
`function dealEnergyDamage(damage : Number, idealRange : Number [, velocityBias : Number])`
The standard Oolite missile uses dealEnergyDamage(170, 32.5, 0.25), has a maximum speed of 0.75LM, and its AI tries to detonate it 25m from its target. [NB: If target within ideal range, takes full damage.]
1 = basic; 2 = premium; 3 = ultimate.
*/
switch (this.warheadType) {
case 1:
this.ship.dealEnergyDamage(110, 27, 0.25);
break;
case 2:
this.ship.dealEnergyDamage(150, 31, 0.22);
break;
case 3:
this.ship.dealEnergyDamage(195, 36, 0.15);
break;
default:
this.dbg && log(this.name, 'Error: bad warheadType <' + this.warheadType + '> in $detonate_core');
}
this.ship.explode();
};
/*
======================
JSHINT: end of wrapper
======================
*/
}).call(this);
// EOF |
| Scripts/nexus_warhead_bugOff.js |
/*
///////////////////////////////////////////////////////////////////////////////
This file: nexus_warhead_bugOff.js
Associated AI: nexus_warhead_bugOff.plist
Part of: Nexus Missile OXP
Author: UK_Eliter
License: 2017 Creative Commons: attribution, non-commercial, sharealike.
///////////////////////////////////////////////////////////////////////////////
*/
/*
==============
LINTER OPTIONS
==============
*/
/* jshint esversion: 6 */
/* jshint -W030 */
/*
======
HEADER
======
*/
this.name = 'nexus_warhead_bugOff.js';
this.author = 'UK_Eliter';
this.description = 'Script for Nexus BugOff warhead';
this.copyright = '2014 Creative Commons: attribution, non-commercial, sharealike.';
this.licence = 'CC-NC-SA 3';
/*
==============================
GLOBALS, including debugging
But debugging currently unused
==============================
*/
// this.dbg = true;
/*
========================
JSHINT: start of wrapper
========================
*/
(function () {
'use strict';
/*
-----------------
Code called by AI
-----------------
*/
this.$_detonate = function () {
// One should make the range values fit well with the desiredRanges set in the AIs.
const
damage_anyShip = 35,
damage_anyShip_velocityBias = 0.25,
damage_thargoidExtra = 135,
range_ideal_anyShip = 20,
range_total_thargoid = 60;
this.ship.dealEnergyDamage(
range_ideal_anyShip,
damage_anyShip,
damage_anyShip_velocityBias
);
/*
The standard Oolite missile uses dealEnergyDamage(170, 32.5, 0.25), has a maximum speed of 0.75LM (which is the same for our warhead, except that our warhead is fuel injected), and its AI tries to detonate it 25m from its target. (NB: If target within ideal range, takes full damage.) The anti-thargoid missile in Missiles & Bombs (rmb-thargoid-warhead-script.js) is: 170, 25.0, 0.25 and has four warheads.
Tharglet energy: 150.
*/
/*
Deal additional damage to anything nearby that is thargoid.
Our method is crude, but: implementing a more sophisticated method is hard to achievel; players are unlikely to notice the crudity.
*/
const s = system.filteredEntities(
this,
this.$isBug,
this.ship,
range_total_thargoid
);
var i = s.length;
while (i--) {
s[i].energy -= range_total_thargoid;
}
this.ship.explode(); // Explode the warhead entity (harmlessly, I think).
};
/*
-----
Other
-----
*/
this.$isBug = function (e) {
return e.isShip && e.isThargoid;
};
/*
======================
JSHINT: end of wrapper
======================
*/
}).call(this);
// EOF |