Scripts/swarm_seeker.js |
this.name = "swarm_seeker";
this.author = "Thargoid";
this.copyright = "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description = "Ship script for the Thargoid swarm seeker";
this.version = "1.03";
"use strict";
this.shipSpawned = function()
{
this.spawnedTime = clock.absoluteSeconds;
function targetShips(entity) {return entity.isShip && entity.isValid && entity.isCloaked && !entity.hasRole("thargoid") && entity.scanClass !== "CLASS_THARGOID" && !entity.isThargoid};
this.cloakedShips = system.filteredEntities(this, targetShips, this.ship, 25600);
if(this.cloakedShips.length === 0)
{
this.ship.explode();
return;
}
this.victim = this.cloakedShips[0];
this.callbackID = addFrameCallback(this.trackVictim.bind(this));
};
this.trackVictim = function()
{
if(!this.victim || !this.victim.isValid || (clock.absoluteSeconds - this.spawnedTime > 120))
{
this.stopCallback();
this.ship.explode();
return;
}
var targetVector = this.victim.position.subtract(this.ship.position).direction();
var angle = this.ship.heading.angleTo(targetVector);
var cross = this.ship.heading.cross(targetVector).direction();
this.ship.orientation = this.ship.orientation.rotate(cross, -angle);
this.ship.desiredSpeed = this.ship.maxSpeed;
if(this.ship && this.victim && (this.ship.position.distanceTo(this.victim.position) < 25))
{
if(this.victim && this.victim.isValid && this.victim.equipmentStatus("EQ_CLOAKING_DEVICE", "EQUIPMENT_OK"))
{
if(Math.random() > 0.9)
{ this.victim.setEquipmentStatus("EQ_CLOAKING_DEVICE", "EQUIPMENT_DAMAGED"); }
else
{
this.victim.removeEquipment("EQ_CLOAKING_DEVICE");
this.victim.awardEquipment("EQ_CLOAKING_DEVICE");
}
}
this.stopCallback();
}
};
this.shipDied = this.stopCallback = function()
{
if(this.callbackID && isValidFrameCallback(this.callbackID))
{ removeFrameCallback(this.callbackID); }
delete this.callbackID;
};
this.shipHitByECM = function(pulse)
{
if(Math.random() < ((pulse+1)/100))
{
this.stopCallback();
this.ship.explode();
}
}; |
Scripts/swarm_thargoid.js |
this.name = "swarm_thargoid";
this.author = "Thargoid";
this.copyright = "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description = "Ship script for the Thargoid swarm mothership";
this.version = "1.03";
"use strict";
this.spawnedAsEscort = function()
{ this.ship.switchAI("swarm_thargoidAI.plist"); };
this.shipSpawned = function()
{
if (player.score > 512)
{ this.ship.awardEquipment("EQ_SHIELD_BOOSTER"); }
if (player.score > 1024)
{ this.ship.awardEquipment("EQ_ENERGY_UNIT"); }
if (player.score > 2560)
{ this.ship.awardEquipment("EQ_SHIELD_ENHANCER"); }
if (player.score > 4000)
{ this.ship.awardEquipment("EQ_NAVAL_ENERGY_UNIT"); }
if (player.score > 6399)
{ this.ship.awardEquipment("EQ_NAVAL_SHIELD_BOOSTER"); }
if(this.ship.scriptInfo.missileRole) // missileRole should be defined in shipdata.plist
{ this.missileRole = this.ship.scriptInfo.missileRole; }
else
{ this.missileRole = "EQ_THARGON"; } // default to standard thargon if not
this.ship.awardEquipment("EQ_MISSILE_REMOVAL"); // remove all spawning missiles and restock with selected ones.
var addCounter = 0;
for(addCounter = 0; addCounter < this.ship.missileCapacity;addCounter++)
{ this.ship.awardEquipment(this.missileRole); }
this.swarmGroup = new ShipGroup("Alien Swarm", this.ship);
this.ship.group = this.swarmGroup;
this.swarmGroup.leader = this.ship;
this.lastBlink = 0;
this.lastSeek = 0;
this.seekerCount = 3;
};
this.shipFiredMissile = function(missile, target)
{
if(!this.ship.isValid || this.ship.subEntities.length === 0) { return; } // if we've run out of sub-ents before we run out of missiles, or the ship has been destroyed
var subCounter = this.ship.subEntities.length - 1; // Set counter to number of sub-ents minus 1 (as entity array goes up from zero)
for(subCounter = this.ship.subEntities.length - 1; subCounter >= 0; subCounter--)
{
if(this.ship.subEntities[subCounter].hasRole(missile.primaryRole)) // if the sub-ent is the same as the missile being fired
{
missile.position = this.localToGlobal(this.ship.subEntities[subCounter].position); // move the fired missile to the sub-ent position
missile.orientation = this.ship.subEntities[subCounter].orientation.multiply(this.ship.orientation); // point the missile in the right direction
missile.desiredSpeed = missile.maxSpeed;
missile.group = this.swarmGroup;
this.ship.subEntities[subCounter].remove(); // remove the sub-ent version of the missile
break; // come out of the loop, as we've done our swap
}
}
};
this.localToGlobal = function(position)
{ // sub-ent position is relative to mother, but for swapping we need the absolute global position
let orientation = this.ship.orientation;
return this.ship.position.add(position.rotateBy(orientation));
};
this.shipTakingDamage = function(amount, fromEntity, damageType)
{
if(this.ship.missiles.length === 0 && this.ship.subEntities.length === 0) // if we're all out of missiles and any sub-entities, bail out.
{ return; }
this.missileSubs = 0;
var subCounter = this.ship.subEntities.length - 1; // Set counter to number of sub-ents minus 1 (as entity array goes up from zero)
for(subCounter = this.ship.subEntities.length - 1; subCounter >= 0; subCounter--)
{
if(this.ship.subEntities[subCounter].hasRole(this.missileRole)) // if the sub-ent is a missile, count it
{ this.missileSubs++; }
}
if(this.missileSubs === 0 && this.ship.subEntities.length === 0) // if we're all out of missiles and missile sub-entities, bail out.
{ return; }
if(this.missileSubs < this.ship.missiles.length) // if we've got more missiles than sub-entity missiles
{
this.ship.awardEquipment("EQ_MISSILE_REMOVAL"); // get rid of all missiles
if(this.missileSubs > 0)
{
var missileCounter = 0;
for(missileCounter = 0;missileCounter<this.missileSubs;missileCounter++) // restock with the correct number of selected missile
{ this.ship.awardEquipment(this.missileRole); }
}
return;
}
if(this.missileSubs > this.ship.missiles.length) // if we've got less missiles than sub-entity missiles
{
this.difference = this.missileSubs - this.ship.missiles.length;
var removeCounter = 0;
for(removeCounter = 0;removeCounter<this.difference;removeCounter++) // loop through however many subs we need to remove
{
var subCounter = this.ship.subEntities.length - 1; // Set counter to number of sub-ents minus 1 (as entity array goes up from zero)
for(subCounter = this.ship.subEntities.length - 1; subCounter >= 0; subCounter--)
{
if(this.ship.subEntities[subCounter].hasRole(this.missileRole)) // if the sub-ent is a missile, remove it
{
this.ship.subEntities[subCounter].remove();
break;
}
}
}
return;
}
};
this.shipEnergyIsLow = function()
{
this.starburst();
this.blink();
};
this.shipDied = function()
{ this.ship.commsMessage(expandDescription("[thargoid_curses]")); };
this.starburst = function()
{
if(this.ship.missiles.length === 0) { return; }
var missileCounter = this.ship.missiles.length;
for(missileCounter = this.ship.missiles.length; missileCounter > 0; missileCounter--) // restock with the correct number of selected missile
{ this.ship.fireMissile(); }
};
this.blink = function()
{
if(clock.absoluteSeconds - this.lastBlink < 30) { return; }
this.lastBlink = clock.absoluteSeconds;
var xDistance = ((Math.random() * 2) - 1) * 5000;
var yDistance = ((Math.random() * 2) - 1) * 5000;
var zDistance = ((Math.random() * 2) - 1) * 5000;
this.ship.position = this.ship.position.add([xDistance, yDistance, zDistance]);
};
this.validateTarget = function()
{
if(this.ship.target && !this.ship.target.isThargoid && !this.ship.target.hasRole("thargoid") && !this.ship.target.hasRole("EQ_SWARM_MISSILE"))
{ this.ship.reactToAIMessage("TARGET_VALID"); }
else
{ this.ship.reactToAIMessage("TARGET_INVALID"); }
};
this.scanForTarget = function()
{
if(this.ship.target && this.ship.target.isValid && this.ship.AIState === "ATTACK_SHIP" && Math.random() > 0.1) { return; }
function targetShips(entity) {return entity.isShip && !entity.isCloaked && !entity.hasRole("thargoid") && entity.scanClass !== "CLASS_THARGOID" && !entity.isThargoid};
function primaryShips(entity) {return !entity.isStation && entity.isPiloted};
function secondaryShips(entity) {return !entity.isPiloted || entity.isStation };
let allShips = system.filteredEntities(this, targetShips, this.ship, 25600);
this.primaryArray = allShips.filter(primaryShips);
this.secondaryArray = allShips.filter(secondaryShips);
if(this.primaryArray.length > 0)
{
this.targetNumber = Math.floor(Math.random() * this.primaryArray.length);
if(this.targetNumber > this.primaryArray.length)
{ this.targetNumber = 0; }
this.ship.target = this.primaryArray[this.targetNumber];
this.ship.reactToAIMessage("TARGET_FOUND");
}
else
{
if(this.secondaryArray.length > 0)
{
this.targetNumber = Math.floor(Math.random() * this.secondaryArray.length);
if(this.targetNumber > this.secondaryArray.length)
{ this.targetNumber = 0; }
this.ship.target = this.secondaryArray[this.targetNumber];
this.ship.reactToAIMessage("TARGET_FOUND");
}
else
{ this.ship.reactToAIMessage("NOTHING_FOUND"); }
}
};
this.startWeave = function()
{
if(this.callbackID) { return; }
this.weaveTime = clock.absoluteSeconds;
this.phase = Math.random() * 2 * Math.PI;
this.callbackID = addFrameCallback(this.performWeave.bind(this));
};
this.stopWeave = function()
{
if(this.callbackID && isValidFrameCallback(this.callbackID))
{ removeFrameCallback(this.callbackID); }
delete this.callbackID;
};
this.performWeave = function()
{
if(!this.ship.isValid || this.ship.AIState !== "ATTACK_SHIP")
{
this.stopWeave();
return;
}
var xOffset = (2.5 * this.ship.speed/this.ship.maxSpeed) * Math.sin(clock.absoluteSeconds - this.weaveTime);
var yOffset = (2.5 * this.ship.speed/this.ship.maxSpeed) * Math.sin(this.phase + clock.absoluteSeconds - this.weaveTime);
if(isNaN(xOffset))
{
log(this.name, "Swarm OXP - xOffset is NaN. Please report");
xOffset = (2.5 * ((2 * Math.random()) - 1));
};
if(isNaN(yOffset))
{
log(this.name, "Swarm OXP - yOffset is NaN. Please report");
yOffset = (2.5 * ((2 * Math.random()) - 1));
};
this.ship.position = this.ship.position.add([xOffset, yOffset, 0]);
};
this.shipBeingAttackedByCloaked = function()
{
if(this.seekerCount === 0 || (clock.absoluteSeconds - this.lastSeek < 10)) { return; }
this.lastSeek = clock.absoluteSeconds;
this.seekerCount--;
this.ship.spawnOne("swarm_seeker");
}; |
Scripts/swarm_thargon.js |
this.name = "swarm_tharglet";
this.author = "Thargoid";
this.copyright = "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description = "Ship script for the Thargoid swarm tharglet";
this.version = "1.03";
"use strict";
this.shipSpawned = function()
{
if (player.score > 512)
{ this.ship.awardEquipment("EQ_SHIELD_BOOSTER"); }
if (player.score > 2560)
{ this.ship.awardEquipment("EQ_ENERGY_UNIT"); }
if (player.score > 6399)
{ this.ship.awardEquipment("EQ_SHIELD_ENHANCER"); }
};
this.validateTarget = function()
{
if(this.ship.target && this.ship.target.scanClass != "CLASS_THARGOID" && !this.ship.target.hasRole("thargoid") && !this.ship.target.hasRole("EQ_SWARM_MISSILE"))
{ this.ship.reactToAIMessage("TARGET_VALID"); }
else
{ this.ship.reactToAIMessage("TARGET_INVALID"); }
}; |