Back to Index Page generated: May 8, 2024, 6:16:03 AM

Expansion Asteroid Storm

Content

Warnings

  1. License not specified
  2. Unknown key 'licence' at https://wiki.alioth.net/img_auth.php/2/2a/AsteroidStorm_4.3.oxz!manifest.plist

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description This OXP adds more models and textures for asteroids to the game and as bonus one mission. This OXP adds more models and textures for asteroids to the game and as bonus one mission.
Identifier oolite.oxp.LittleBear.AsteroidStorm oolite.oxp.LittleBear.AsteroidStorm
Title Asteroid Storm Asteroid Storm
Category Ambience Ambience
Author Little Bear, Eric Walch Little Bear, Eric Walch
Version 4.3 4.3
Tags Asteroids, Mission Asteroids, Mission
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
Conflict Expansions
Information URL http://wiki.alioth.net/index.php/Asteroid_Storm n/a
Download URL https://wiki.alioth.net/img_auth.php/2/2a/AsteroidStorm_4.3.oxz n/a
License
File Size n/a
Upload date 1610873257

Documentation

Also read http://wiki.alioth.net/index.php/Asteroid%20Storm

asteroidstorm_readme.txt

			    	  Asteroid Storm OXP - V4.03
			        -----------------------------

			(New Asteroid Models and Textures by "Charlie")
			         (Scripting by "LittleBear")
			    (Further scripting for 3.4+  by "Kaks")
				(Original JS script by "Dajt")
			     (Galatic Police Image by "Wombat")
                            (Retextured all asteroids by "Eric")


With this version all of Charlies asteroids now appear, but in a much improved mesh and with normalmapping.

------------------------------------------------------------------------------------------------

An addon for Oolite by Giles Williams.

Based on "Elite" by Ian Bell and David Braben.

Version 4.03 - compatible with Oolite 1.74 and higher. 


-------------------------------------------------------------------------------------------------

Overview
--------

This OXP adds more models and textures for Asteroids to the game. All the new asteroids were
modeled and textured by "Charlie", based upon asteroids in the Real Life Sol System. Some are
really big and will be marked by your ID computer as a "Large Asteroid"!

In the native game there are only two types of asteroid. If you play with this OXP installed then
there is more variety to the shapes and sizes of the asteroids you encounter as they have 15
different shapes and sizes. The chance and number of boulders formed when an asteroid is
destroyed also varies for each type of asteroid.

The OXP also adds an asteroid related mission, well suited to a novice commander in Galaxy 1.

You are docked at a station near Lave, in a system well known to suffer from asteroid storms.
Sure enough, as you drop off your cargo, you hear the sound of small asteroids glancing off
the Station's shields. Suddenly all hell breaks loose, Commanders running for their ships,
leaving their cargo behind!

A Large Asteroid has been detected approaching the Station. It is so massive that if it strikes,
destruction of the mighty Dodec is certain. Will you stay and help or get out of Dodge?

The mission has three possible endings depending on your actions.

The mission will trigger when you are docked at a certain system within 7 light years of Lave
and are ranked at least "Above Average". I won't tell you the name of the system, but you may
find that checking your F7 screen gives a clue!

This is intended to be a fairly easy mission, but a bit of fun!

Updates from V1.0
-----------------

1) Version 2.0 adds the models and textures for Charlie's asteroids to the game generally.

2) A code optimisation to remove the System's station permanently, if it is destroyed.
   (The station is now removed by setting the System's station to "none".)

Updates from V2.0
-----------------

1) Texture case names fixed. No problem on Windows or Mac, but the old version had case
sensitivity bugs, which caused a problem on Unix.

2) Eric's mission clash prevention code added, to ensure this OXP doesn't clash with any other
OXPs that display mission briefing screens.

3) The "Large Asteroids" added to the Universe generally have a higher energy value, making
them more resilient to laser fire than a small asteroid.

4) The system which "suffers from deadly asteroid storms" now has a higher than average number of
asteroids in the space lanes, and a small (non-dangerous) storm occurs near the station whenever
the system is visited. Displaced asteroids can also be seen whizzing through the spacelanes.

Updates from v.3.0
------------------ 

1) 	Legacy script: reduced number of tests done by the script to 3, improving overall system performance.

2) 	Made the mission slightly tougher.

3) 	Added alternative mission ending: in some cases, the station will be partially hit by the asteroid, with irreversible damage to the station's main reactor.

4) 	Further cleanup of asteroids, including solving more upper/lower case problems with linux & case sensitive macs.

5) 	In case of cowardice, legal status now worsens by 25 points, as opposed to being set at 25.

6) 	1.68 and 1.69: message screen - after loading savegame - explaining how to enable the 1.65 version on their computer.

7) 	1.70: If the player score is 50% higher than the minimum required for the mission, the asteroid will be tougher still.

8) 	1.70: If the main station is destroyed, stations added by other OXPs will also be removed from the system.

9) 	1.70: Workaround for 'indestructible stations', With nice station explosion, 30-60 seconds after partial asteroid hit.

10)	1.70: Once mission finishes, run only 1 event handler, improving overall system performance.

11)	1.70: Mission records who destroyed the asteroid, and gives a smaller reward to player if NPCs did it.

12)	1.70: If the player had an energy bomb before the mission and can get back to the station, they get their bomb back.

13)	1.71: The further the asteroid is from the station, the more hits will be needed to destroy it.


v.3.45
------
- Cleanup script bugfixed, large asteroids labelled properly.

v.3.46
------

A role key is added to all asteroids added by this OXP. In the previous version only the Large Asteroids had a role. This
meant that only these appeared in game (oops)! On the old version, only 1 new type of asteroid was added even though the
OXP has the graphics and models to add 12 different types. The new versions now works as intended and you will see a greater
variety to the shapes and sizes of all asteroids in the Ooniverse. Only the graphics are changed, rocks are still rocks!

v.3.50
------
Because of the large scripting changes since Oolite 1.70, some of the special stuff to make it work with 1.70 is removed again and instead code is added to make it work with 1.71+. (1.72.0 has a bug but will generate a warning on screen. You need than to update to at least 1.72.1)
All normal big asteroids now have a script that let them generate additional boulders throughout the asteroid and not just in the centre. 

v.3.51
------
Added ships to "help" the player killing the asteroids.
Several minor bug fixes on 3.50.  

v.3.52
------
Changed role of station-alloy. Anything with station in the role is handled as such. Even as part of a name.

v.3.53
------
Added code so it won't run with Oolite 1.74+. It needs rewriting to work with that Oolite version.

v.3.54
------
Removed the warning.ogg sound from this oxp because it was already part of Oolite since at least Oolite 1.40.
Repaired the meshes of all asteroids (Griff). This gave much z-fighting of the texture. Completely retextured all asteroids with the original textures but now free of defects.

v3.55
------
Added low resolution normal maps to the asteroids for better experience on computers with shader capability.

v.4.00
------
Added the new mission offering for Oolite 1.74. Raised minimum version to 1.74.
Changed the asteroid behaviour in the mission system during the "storm". They now fly a more logical path heading for the planet as centre of gravity.
Recompiled the asteroid models to the new .dat structure with explicit normals.
Added better resolution normal maps to the asteroids to simulate a surface texture on computers with shaders. (256x256 textures)
Randomised textures, so that any asteroid can get any texture so we now have 120 different combinations of asteroids and surface structure.
Disabled Oolite's own asteroids and boulders from appearing. (like_ship copies of them created by other oxp's will still appear)
Made the texture selection less random for asteroids added close to the previous one, resulting in areas of similar textured asteroids.
Added new boulders.

v.4.01
------
Fixed a casing bug that will give errors after Oolite 1.74

v.4.02
------
Changed the texture mapping on the asteroids. Now the same texture repeats a few times around the asteroids to create an effective higher resolution for the texture as seen in play.

v.4.02
------
Updated for Oolite 1.77+ were the energy bomb can be missing.

Known Performance Issues (for old systems like mine!)
----------------------------------------------------

When you launch into the Storm during the mission, Oolite will freeze for a few seconds whilst
it adds all the Asteroids to the Ooniverse. Once the Asteroids are added, the game runs normally.

If the Station is destroyed, Oolite will freeze for a few seconds whilst it adds all the
wreackage that the destroyed station throws out! 
Much of this slowdown is fixed in Oolite versions after Oolite 1.65


LittleBear && Others

Equipment

This expansion declares no equipment. This may be related to warnings.

Ships

Name
ASBoulder
ASBoulder1
ASBoulder10
ASBoulder11
ASBoulder2
ASBoulder3
ASBoulder4
ASBoulder5
ASBoulder6
ASBoulder7
ASBoulder8
ASBoulder9
Asteroid
Casteroid1-demo
Casteroid10
Casteroid10-demo
Casteroid11
Casteroid11-demo
Casteroid12
Casteroid12-demo
Casteroid2
Casteroid2-demo
Casteroid3
Casteroid3-demo
Casteroid4
Casteroid4-demo
Casteroid5
Casteroid5-demo
Casteroid6
Casteroid6-demo
Casteroid7
Casteroid7-demo
Casteroid8
Casteroid8-demo
Casteroid9
Casteroid9-demo
Asteroid
LBasteroid10
LBasteroid2
LBasteroid3
LBasteroid4
LBasteroid5
LBasteroid6
LBasteroid7
LBasteroid8
LBasteroid9
Doomsday Asteroid
LBbadrockI
LBbadrockII
LBbadrockIII
Debris
Leesti High

Models

This expansion declares no models. This may be related to warnings.

Scripts

Path
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;
};
Scripts/AsteroidStormAsteroid.js
"use strict";
this.name      = "AsteroidStormAsteroid"; 
this.author    = "eric walch"; 
this.copyright = "� 2008 eric walch."; 
this.description = "Code for an self colouring asteroid"; 
this.version   = "1.2";

this.shipSpawned = function(){ 
    this.ship.primaryRole = "asteroid";
    if (this.ship.isBoulder){ // created by one of the very big asteroids.
        this.ship.displayName = "Big boulder";
        this.ship.isBoulder = false;
    }
    this.material = worldScripts.AsteroidStorm.getMaterial(this.ship.position.z); // remember this.
    this.ship.setMaterials(this.material);
};

this.shipDied = function (){
    // store the used material in the worldScript, so the created boulders can
    // retreive it there. We have no direct reference to the created boulders.
    worldScripts.AsteroidStorm.boulderMaterial = this.material;
};
Scripts/AsteroidStormBoulder.js
"use strict";
this.name      = "AsteroidStormBoulder"; 
this.author    = "eric walch"; 
this.copyright = "� 2008 eric walch."; 
this.description = "Code for an self colouring boulder"; 
this.version   = "1.2";

this.shipSpawned = function (miner){ 
    this.ship.setMaterials(worldScripts.AsteroidStorm.boulderMaterial);
};
Scripts/LBasteroid.js
"use strict";
this.name      = "LBAsteroid"; 
this.author    = "eric walch"; 
this.copyright = "� 2008 eric walch."; 
this.description = "Code for regeneration of special asteroid"; 
this.version   = "1.00";

this.shipSpawned = function (){
    this.ship.savedCoordinates = system.mainPlanet.position;
    delete this.shipSpawned;
}

this.shipDied = function(ship){ 
    worldScripts.AsteroidStorm.addAsteroid(1);
    if (ship && ship.isStation && this.ship.position.distanceTo(player.ship) < 7E3) this.playHit();

	delete this.shipDied; // make sure it is not called again.
}

this.playHit = function (){
    this.mySound = new SoundSource;
    this.mySound.sound = player.ship.docked ? "hullbang.ogg" : "hit.ogg";
    this.mySound.play(1);
};
Scripts/LBbadrock.js
"use strict";
this.name = "LBbadrock";
this.author = "LittleBear,Kaks";
this.copyright = "Jan/Feb 2008 - But do what you like with it in your OXPs!";
this.description = "who shot the asteroid last?"
this.version = "1.18";

this.lastEnergy = this.ship.energy;
this.lasthit = "";

this.shipDied = function (who, why){
	log(this.name, "Rock killed by: "+who+", by means of "+why)
	missionVariables.asteroids = 'asteroids_OVER';
	worldScripts["AsteroidStorm"].asteroids_rockdead = 1;
    var bigExplosion = (this.lastEnergy > this.ship.maxEnergy * 0.5); // player cheats with super weapon.
    var stationPosition = system.mainStation.position;
	if (who && who.isStation || bigExplosion || why === "cascade weapon") worldScripts["AsteroidStorm"].wipeStation(false);
    if (bigExplosion){
        var rocks = this.ship.spawn("ast1", 20);
        var vel = stationPosition.subtract(this.ship.position).direction();
        for (var i=0; i < 13; i++) rocks[i].velocity = vel.multiply(500 + Math.random()*1000); // throw some rocks in direction of station.
    }
	// Collided with station or player used Q-bomb or similar super weapon.
	if ((who && who.isPlayer) || this.lasthit === "PLAYER")
		worldScripts["AsteroidStorm"].badRockKiller = "PLAYER"
    else
		worldScripts["AsteroidStorm"].badRockKiller = "NPC"; // this line only happens when the 2 last shots were not the plaer!
	delete this.shipDied; // make sure it is not called again.
	// in 1.72 becomeExplosion is not triggering the shipDied event. 1.71 and probably 1.73 will. (Edit: only fixed since 1.75.4)
}

this.shipBeingAttacked = function (who){

    this.lasthit = (who && who.isPlayer) ? "PLAYER" : "NPC";
	if (who && who.primaryRole === "LBbadrockMiner") this.ship.energy = this.lastEnergy; // don't count the mining hits
	if (this.ship.recharge>=0){
		this.ship.recharge-=(this.ship.maxEnergy-this.ship.energy)/this.ship.maxEnergy;
		this.ship.energy=this.ship.maxEnergy;
		}
	this.lastEnergy = this.ship.energy;
}

this.wipeStation = function (){
	this.shipDied(system.mainStation, "scriptMessage")  //In oolite 1.72 the shipDied() is not executed for ships dying with an AI "becomeExplosion" command.
}