Scripts/AsteroidStorm.js |
"use strict";
this.name = "AsteroidStorm";
this.author = "Dajt, Kaks, LittleBear";
this.copyright = "Creative Commons: attribution, non-commercial, sharealike.";
this.description = "A mission to save a space station, original script.js (Oolite 1.65-js) by Dajt, updated & expanded by Kaks & adapted to Oolite 1.73+ by Eric.";
this.version = "4.03";
// declare working variables
this.badrocks=["badrockI","badrockII","badrockIII"];
this.badrock="";
this.lasthit="";
this.lastPosition = 0;
/*
Materials from the following list are randomly used by the asteroids. You can add your own materials to the list by putting
your new textures in the texture folder and adding the definition to the list below.
Some materials use a seperate specular file, other materials use the diffuse texture as specular and have the
shininess map in the alpha chanel of this file.
*/
this.materials = [
{"asteroid.png":{diffuse_map: {name:"astorm01.png", "repeat_s":true, "repeat_t":true},
normal_map: {name:"astorm01_normal.png", "repeat_s":true, "repeat_t":true},
specular_map: {name:"astorm_specular.png", "repeat_s":true, "repeat_t":true},
shininess: 30}},
{"asteroid.png":{diffuse_map: {name:"astorm02.png", "repeat_s":true, "repeat_t":true},
normal_map: {name:"astorm06_normal.png", "repeat_s":true, "repeat_t":true},
specular_map: {name:"astorm_specular.png", "repeat_s":true, "repeat_t":true},
shininess: 30}},
{"asteroid.png":{diffuse_map: {name:"astorm02.png", "repeat_s":true, "repeat_t":true},
normal_map: {name:"astorm02_normal.png", "repeat_s":true, "repeat_t":true},
specular_map: {name:"astorm_specular.png", "repeat_s":true, "repeat_t":true},
shininess: 30}},
{"asteroid.png":{diffuse_map: {name:"astorm03.png", "repeat_s":true, "repeat_t":true},
normal_map: {name:"astorm03_normal.png", "repeat_s":true, "repeat_t":true},
specular_map: {name:"astorm_specular.png", "repeat_s":true, "repeat_t":true},
shininess: 30}},
{"asteroid.png":{diffuse_map: {name:"astorm05.png", "repeat_s":true, "repeat_t":true},
normal_map: {name:"astorm05_normal.png", "repeat_s":true, "repeat_t":true},
specular_map: {name:"astorm05_specular.png", "repeat_s":true, "repeat_t":true},
shininess: 30}},
{"asteroid.png":{diffuse_map: {name:"astorm05.png", "repeat_s":true, "repeat_t":true},
normal_map: {name:"astorm03_normal.png", "repeat_s":true, "repeat_t":true},
specular_map: {name:"astorm_specular.png", "repeat_s":true, "repeat_t":true},
shininess: 30}},
{"asteroid.png":{diffuse_map: {name:"astorm07.png", "repeat_s":true, "repeat_t":true},
normal_map: {name:"astorm07_normal.png", "repeat_s":true, "repeat_t":true},
specular_map: {name:"astorm_specular.png", "repeat_s":true, "repeat_t":true},
shininess: 30}},
{"asteroid.png":{diffuse_map: {name:"astorm08.png", "repeat_s":true, "repeat_t":true},
normal_map: {name:"astorm04_normal.png", "repeat_s":true, "repeat_t":true},
specular_map: {name:"astorm_specular.png", "repeat_s":true, "repeat_t":true},
shininess: 30}},
{"asteroid.png":{diffuse_map: {name:"astorm08.png", "repeat_s":true, "repeat_t":true},
normal_map: {name:"astorm08_normal.png", "repeat_s":true, "repeat_t":true},
specular_map: {name:"astorm_specular.png", "repeat_s":true, "repeat_t":true},
shininess: 30}},
{"asteroid.png":{diffuse_map: {name:"astorm09.png", "repeat_s":true, "repeat_t":true},
normal_map: {name:"astorm09_normal.png", "repeat_s":true, "repeat_t":true},
specular_map: {name:"astorm_specular.png", "repeat_s":true, "repeat_t":true},
shininess: 30}},
{"asteroid.png":{diffuse_map: {name:"astorm09.png", "repeat_s":true, "repeat_t":true},
normal_map: {name:"astorm03_normal.png", "repeat_s":true, "repeat_t":true},
specular_map: {name:"astorm_specular.png", "repeat_s":true, "repeat_t":true},
shininess: 30}},
{"asteroid.png":{diffuse_map: {name:"astorm09.png", "repeat_s":true, "repeat_t":true},
normal_map: {name:"astorm07_normal.png", "repeat_s":true, "repeat_t":true},
specular_map: {name:"astorm_specular.png", "repeat_s":true, "repeat_t":true},
shininess: 30}},
{"asteroid.png":{diffuse_map: {name:"astorm10.png", "repeat_s":true, "repeat_t":true},
normal_map: {name:"astorm10_normal.png", "repeat_s":true, "repeat_t":true},
specular_map: {name:"astorm_specular.png", "repeat_s":true, "repeat_t":true},
shininess: 30}},
{"asteroid.png":{diffuse_map: {name:"astorm11.png", "repeat_s":true, "repeat_t":true},
normal_map: {name:"astorm11_normal.png", "repeat_s":true, "repeat_t":true},
specular_map: {name:"astorm11.png", "repeat_s":true, "repeat_t":true},
shininess: 30}},
{"asteroid.png":{diffuse_map: {name:"astorm13.png", "repeat_s":true, "repeat_t":true},
normal_map: {name:"astorm02_normal.png", "repeat_s":true, "repeat_t":true},
specular_map: {name:"astorm_specular.png", "repeat_s":true, "repeat_t":true},
shininess: 30}},
{"asteroid.png":{diffuse_map: {name:"astorm13.png", "repeat_s":true, "repeat_t":true},
normal_map: {name:"astorm13_normal.png", "repeat_s":true, "repeat_t":true},
specular_map: {name:"astorm13.png", "repeat_s":true, "repeat_t":true},
shininess: 30}},
{"asteroid.png":{diffuse_map: {name:"astorm14.png", "repeat_s":true, "repeat_t":true},
normal_map: {name:"astorm14_normal.png", "repeat_s":true, "repeat_t":true},
specular_map: {name:"astorm14.png", "repeat_s":true, "repeat_t":true},
shininess: 30}},
{"asteroid.png":{diffuse_map: {name:"astorm15.png", "repeat_s":true, "repeat_t":true},
normal_map: {name:"astorm15_normal.png", "repeat_s":true, "repeat_t":true},
specular_map: {name:"astorm15.png", "repeat_s":true, "repeat_t":true},
shininess: 30}}
];
this.lastMaterial = this.boulderMaterial = this.materials[0];
this.materialCount = this.materials.length;
this.startUp = function (){
if (missionVariables.asteroids === "asteroids_FINISHED") this.cleanup();
};
this.cleanup = function (){
//disable the events - tell them why!
delete this.shipWillLaunchFromStation;
delete this.shipWillEnterWitchspace;
delete this.missionScreenOpportunity;
};
this.anyInt = function (n1,n2){
return Math.round(Math.random()*(n2-n1)+n1);
};
this.changeInfo = function (){
var d="The planet Leesti is reasonably fabled for Zero-G cricket and Leestiian evil juice, but cursed by deadly asteroid storms. Leesti's orbital station was recently destroyed by a large asteroid strike. Ships without planet landing capabilities are therefore advised to avoid this system.";
System.infoForSystem(0, 55).description = d;
System.infoForSystem(0, 55).productivity /= 100;
};
this.wipeStationReally = function (){
this.wipeStation(true);
};
this.wipeStation = function (really) {
missionVariables.asteroids = "asteroids_OVER";
missionVariables.asteroids_statdead =1;
this.byeStation=true;
if (system.mainStation){
system.mainStation.displayName="Damaged Leesti High";
}
if (system.countShipsWithRole("aststat")>0){
this.changeInfo();
if (Math.random()<.25||really){
var pos=system.mainStation.position;
system.mainStation.explode();
system.addShips("alloy", 50, pos, 250);
this.removeAllStations(); //(make sure no other station becomes mainStation)
} else{
system.description=system.description.replace(/was recently destroyed by/,"is currently being evacuated after");
system.mainStation.commsMessage("MAIN REACTOR BREACH, EXPLOSION IMMINENT!");
system.mainStation.energy = 100;
for (var i=0; i<5; i++) system.mainStation.launchShuttle();
this.setBadrockMiner(system.mainStation.launchShipWithRole("miner", true)); // true cancels all dockings.
this.timer=new Timer(this, this.wipeStationReally, this.anyInt(18, 38));
}
} else{
system.legacy_addSystemShips("alloy", 50, 1); //should work even with a missing station.
}
};
this.missionScreenOpportunity = function (){
if (player.ship.docked){
this.missionOffers();
}
};
this.missionOffers = function (){
// Don't offer the missions when showing a mission screen or mission.choice needs processing
// wait until called again via missionScreenEnded, next docking, or missionChoiceWasReset
if (this.myMissionShown) return;
{
if (!player.ship.dockedStation.isMainStation) return;
if (system.ID===55 && galaxyNumber===0){
if ((!missionVariables.asteroids && player.score>63) ||
(missionVariables.asteroids === "asteroids_BRIEFED")){
missionVariables.asteroids = "asteroids_BRIEFED";
this.asteroids_bombremoved =
this.asteroids_rockdead = 0;
mission.runScreen({title: "Asteroid Storm", messageKey: "asteroidsbrief_1",
overlay: "GalCop.png", model: this.badrocks[0], music: "astormSiren.ogg"}) // "son et lumiere" :)
this.hullbang = new Timer(this, this.playHit, 4, 1); // add some ambiance.
this.badrock="";
this.myMissionShown= true;
}
if (missionVariables.asteroids==="asteroids_RUNNING"){
// do we still have a doomsday asteroid?
if (system.shipsWithRole(this.badrock).length>0){
mission.runScreen({title: "Asteroid Storm", messageKey: "asteroidsbrief_2",
overlay: "GalCop.png", music: "astormSiren.ogg"}); //get back out!
this.hullbang = new Timer(this, this.playHit, 4, 1); // add some ambiance.
} else { // inside the station, mission running, but no asteroid. this should never happen
missionVariables.asteroids = "asteroids_OVER";
this.asteroids_rockdead=1;
}
this.myMissionShown= true;
}
}
if (missionVariables.asteroids && missionVariables.asteroids != "asteroids_FINISHED") {
if (missionVariables.asteroids === "asteroids_COWARD"){
player.credits -= 200;
player.bounty += 25;
missionVariables.asteroids = "asteroids_FINISHED";
mission.runScreen({title: "Asteroid Storm", messageKey: "asteroidsbrief_3", overlay: "GalCop.png"});
this.myMissionShown= true;
}
if (missionVariables.asteroids === "asteroids_OVER"){
if (missionVariables.asteroids_statdead===1){ //0 or 1
if (this.byeStation && system.ID==55){ //"damaged leesti"
//inside the damaged station.
if (this.timer) this.timer.stop();
if (this.asteroids_bombremoved>0){
this.addEnergyBomb();
}
mission.runScreen({title: "Asteroid Storm", messageKey: "asteroidsbrief_7", overlay: "GalCop.png"}); //we're doomed!
}else{
// failed. Must be docking in an other system.
mission.runScreen({title: "Asteroid Storm", messageKey: "asteroidsbrief_4", overlay: "GalCop.png"}); //you tried!
}
player.credits += 200;
if (system.ID!=55 || galaxyNumber!=0) //we saw the doomed station, didn't bother to go in
this.changeInfo();
} else if (this.asteroids_rockdead===1){
if (this.badRockKiller==="PLAYER"){
player.credits += 1000;
player.bounty=0;
var addedBomb = this.addEnergyBomb(); // do it always here.
if (addedBomb)
mission.runScreen({title: "Asteroid Storm", messageKey: "asteroidsbrief_5", overlay: "GalCop.png"});//you did it!
else
mission.runScreen({title: "Asteroid Storm", messageKey: "asteroidsbrief_5b", overlay: "GalCop.png"});//you did it!
} else {
player.credits += 350;
mission.runScreen({title: "Asteroid Storm", messageKey: "asteroidsbrief_6", overlay: "GalCop.png"});//you helped doing it!
if (this.asteroids_bombremoved>0){
this.addEnergyBomb();
}
}
}
missionVariables.asteroids = "asteroids_FINISHED";
this.myMissionShown= true;
}
}
}
};
this.addEnergyBomb = function () {
// equipment can be unknown after Oolite 1.76
if (player.ship.equipmentStatus("EQ_ENERGY_BOMB") !== "EQUIPMENT_UNKNOWN")
{
player.ship.awardEquipment("EQ_ENERGY_BOMB");
return true;
}
return false;
}
/*
Credits to Kaks. Below Kaks uses a very complicated method to set properties of the badrock from
within this worldScript. In current Oolite versions one can do this much easier, but Kaks had to use
this complex way to let it work with Oolite 1.70. Part of the complexity I wrote out of it and part I
let in as a tribute to Kaks who left some very nice sample code with it.
All b.xxx become properties of the rock itself and can be used in that ship script.
Without this the objects "missionVariables" and "System" could not be used reliable in oolite 1.70 ship scripts.
Eric Walch
*/
this.doomRocks = function (){
if (!this.trajectory) this.setAsteroidTrajectory();
var rockPosition;
var rockDistance = this.anyInt(4000,20000); // addition range relative to station.
rockPosition = system.mainStation.position.add(this.trajectory.multiply(rockDistance));
missionVariables.asteroids = "asteroids_RUNNING";
var badrock = system.addShips(this.badrock, 1, rockPosition, 10)[0];
if (badrock){
badrock.recharge=(rockDistance/7000)-1; //rough estimate
badrock.scannerDisplayColor1 = [0.0, 0.8, 0.8, 1.0]; // cyan-like
var miner = system.addShips("miner", 4, rockPosition, 10E3);
for (var i=0; i<miner.length; i++) if (miner[i]) this.setBadrockMiner(miner[i]);
log(this.name, "Adding doomsday asteroid at: "+rockDistance+" meters");
}
system.addShips("ast1", 27, rockPosition, 15E3);
};
this.setBadrockMiner = function (ship){
ship.switchAI("LBbadrockMinerAI.plist");
ship.primaryRole = "LBbadrockMiner"; // role needed to interact with badrock.
};
this.shipWillLaunchFromStation = function (){
if (system.ID===55 && galaxyNumber===0){
this.myMissionShown=false;
if (this.byeStation){
this.timer=new Timer(this, this.wipeStationReally, this.anyInt(3,19));
return;
}
var asteroids = system.countShipsWithPrimaryRole("ast1")
if (asteroids<3)
for (var i=0; i<4; i++) this.addAsteroid(3);
if (missionVariables.asteroids === "asteroids_RUNNING"|| missionVariables.asteroids === "asteroids_BRIEFED"){
if (player.ship.equipmentStatus("EQ_ENERGY_BOMB") === "EQUIPMENT_OK"){
player.ship.removeEquipment("EQ_ENERGY_BOMB");
this.asteroids_bombremoved=1;
}
if (this.badrock===""){ // choose once.
if (player.score<96) this.badrock=this.badrocks[0] // weak, easy with 2x beam laser.
else if (player.score<180) this.badrock=this.badrocks[1] // strong
else this.badrock=this.badrocks[2]; // very strong, needs 2x military laser.
}
if (system.countShipsWithRole(this.badrock)===0)
this.doomRocks();
}
}
};
this.shipWillEnterWitchspace = function (){
if (missionVariables.asteroids === "asteroids_RUNNING"){
if (system.countShipsWithRole(this.badrock)===0)
missionVariables.asteroids = "asteroids_OVER";
else{
missionVariables.asteroids = "asteroids_COWARD";
missionVariables.asteroids_statdead=1;
this.changeInfo();
}
}
};
this.shipWillExitWitchspace = function (){
if (system.ID===55 && galaxyNumber===0){
for (var i=0; i<4; i++) this.addAsteroid(3);
system.addShips("asteroid", 3);
if (missionVariables.asteroids_statdead===1){
this.timer = new Timer(this, this.removeAllStations, 0); // make sure it runs after all other oxps.
this.timer2 = new Timer(this, this.removeAllStations, 5); // also remove delayed added ones.
for (var i=0; i<5; i++) this.addAsteroid(4); // add some more rocks during mission
}
}
};
this.removeAllStations = function (){
// Find all stations and dockable items in the system.
var stations = system.filteredEntities(this, function (entity) { return entity.isStation; });
// Blow them all up.
stations.forEach(function (entity) { entity.remove(true); });
};
this.setAsteroidTrajectory = function (){
if (system.mainStation) this.trajectory = system.mainStation.position.subtract(system.mainPlanet.position).direction()
else this.trajectory = new Vector3D(-0.95569, 0.131987, -0.263126);
};
this.addAsteroid = function (count){
if (!this.trajectory) this.setAsteroidTrajectory();
var multiplier = 3 + 10 * Math.random();
var distance = system.mainPlanet.radius * multiplier; // at least 3 radii away (station is at 2 radii)
var pos = system.mainPlanet.position.add(this.trajectory.multiply(distance));
if (Math.random() < 0.3) system.addShips("ast1", 1, pos, 1E3) // on very likely ramming course.
else system.addShips("ast1", 1, pos, 10E3 * multiplier); // spread more widely
// asteroids focus themself at one point on their journey to the planet, so spread them
// furter appart when adding them further away.
if (count > 1) system.addShips("ast1", count-1, pos, 15E3 * multiplier);
};
// function is called by timer.
this.playHit = function (){
if (!player.ship.docked){
this.hullbang.stop();
delete this.hullbang;
return;
}
if (Math.random() < 0.9) return;
this.mySound = new SoundSource;
this.mySound.sound = "hullbang.ogg";
this.mySound.play(1);
};
this.getMaterial = function (pos){
var dif = pos - this.lastPosition;
dif *= dif;
if (dif > 400E6){
// Only switch material for distant asteroids so that we obtain asteroid clusters of similar type.
// for effectifines we only compare the z component of the position.
this.lastPosition = pos;
this.lastMaterial = this.materials[Math.floor(Math.random()*this.materialCount)];
//log(this.name, "Made new material selection. Difference = "+Math.round(Math.sqrt(dif))+" m");
}
return this.lastMaterial;
};
|