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

Expansion Buoy Repair

Content

Warnings

  1. License not specified
  2. Unknown key 'licence' at https://wiki.alioth.net/img_auth.php/6/66/BuoyRepair_1.3.4.oxz!manifest.plist

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description Adds a buoy repair facility to selected systems. Adds a buoy repair facility to selected systems.
Identifier oolite.oxp.Svengali.Eric.BuoyRepair oolite.oxp.Svengali.Eric.BuoyRepair
Title Buoy Repair Buoy Repair
Category Ambience Ambience
Author Eric Walch & Svengali Eric Walch & Svengali
Version 1.3.4 1.3.4
Tags Station, Buoy Station, Buoy
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
Conflict Expansions
Information URL http://wiki.alioth.net/index.php/BuoyRepair n/a
Download URL https://wiki.alioth.net/img_auth.php/6/66/BuoyRepair_1.3.4.oxz n/a
License
File Size n/a
Upload date 1610873320

Documentation

Also read http://wiki.alioth.net/index.php/Buoy%20Repair

BuoyRepair1.3.4 readMe.rtf

{\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;\red0\green0\blue255;}
\paperw11900\paperh16840\vieww21900\viewh14520\viewkind0
\deftab720
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720

\f0\b\fs36 \cf0 Repair Buoy\

\b0\fs24 Authors: Svengali (models+shaders), Eric Walch (scripting)\
version 1.3.4, June 2015\
\

\fs28 Introduction
\fs26 \
\pard\pardeftab720

\fs24 \cf0 \
Trading goods between worlds is an extremely dangerous and hard job, and most trading companies are losing\
ships through accidents, pirate ambushes and thargoid attacks. In 2084003 GCT (Galactic Coordinated Time) /\
3135 MGMT (Modern Galactic Mean Time) a number of traders\'92 guilds decided to counteract to the increasing\
number of accidents by establishing the space buoys as a marker for safe space lanes.\
\
But systems are always slow in replacing destroyed navigation buoys. It is very frustrating when you are at the\
main station and have to meet a ship on the way to the witchpoint when the witchpoint buoy is destroyed. It is\
almost impossible to orient yourself in this situation. The authors (Cmdrs. Walch and Svengali) found this very\
annoying and made a little investigation of the reasons. The main reason seemed to be a systemwide shortage\
of buoys, so it always took much time to bring in a new buoy from far away and install it.\
\
In most cases the pilot was already in an other system when the replacement arrived.\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720
\cf0 \

\fs28 Buoy Factories.
\fs26 \

\fs24 \
Both authors looked for systems that were prepared to build buoys for a reasonable price. These were found\
with industrial systems with a medium technical level. Systems of low technical level didn\'92t have the skills\
to build the buoys and those of high level found it to inferior work to do. Another selection criterium was the\
availability of metal ore on the planet so alloys could be extracted from it. The buoys themselves are not strong\
enough to lift off a planet\'92s surface, so they have to be assembled in space.\
\
Cmdr. Svengali designed a whole assembly station for this purpose. Parts for the buoys are pre-fabricated\
on the planet surface and then flown in to the assembly station with shuttles. Those factories are in a constant\
need of alloys and will also buy alloys flown in from other systems.\
\
The assembly stations have a technologically advanced docking bay sealing: A force-field that keeps the air\
inside and still allows for a ship to pass trough. This makes it possible to load / unload ships with normal clothing\
instead of using pressurised suits. The disadvantage is that an approaching pilot has no visible view of the landing bay\
and has to use special guiding technology to find the right flight path (or use his docking computer).\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720
\cf2 \
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardeftab720

\fs28 \cf0 Buoy Transport vehicles.
\fs26 \

\fs24 \
Buoys are of the size of a medium ship like a Cobra. This means they don\'92t fit in the cargo bay of a normal ship.\
It would need a spaceship carrier to transport them. This was rejected as too expensive, so we choose for the lower-cost\
solution of towing the buoys. For this job Cmdr. Svengali designed a powerful tugship that is capable of delivering\
the cargo at a reasonable speed.\

\fs26 \

\fs28 Distribution System
\b .
\b0\fs26 \

\fs24 \
Meanwhile Cmdr. Walch built a distribution system to send newly-assembled buoys from the factory to other systems\
before they are actually needed. Once docked in another system, the replacement buoys are stored in a safe place\
in the main stations. Now, when a buoy gets destroyed, a new one can be brought into place without much delay.\
\
When the main station buoy needs to be replaced, a new one can be retrieved directly from the station. When a\
witchpoint beacon is destroyed a new one will be brought in by hyperspace jumping with a buoy from an adjacent system.\
\

\fs28 Large Traders and fuel ships
\fs24 \
\
The GRS station has facilities to accommodate large traders that are to big to dock at a regular station. They can dock at\
one of the two external docking bays. From here on normal sized traders can deliver the goods to the local main station\
or a station in an adjacent system.\
\
GRS also has build some large fuel ships that scoop plasma from the sun, transform it into quirium and deliver this fuel\
to the GRS station for further distribution throughout the galaxy.\
\

\fs28 Instalation.
\b\fs24 \

\b0 \
Take the file "buoyRepair.OXP" and put it in Oolite\'92s AddOns folder. After a restart the new factories are in place\
and the distribution of the replacement buoys will start. Now, when a buoy gets defect, a replacement sequence\
is started within 2 minutes. Sometimes replacement takes longer when traffic around stations is too busy, but this\
is dependent on the local station manager\'92s ability to schedule dockings and launches.\
\

\fs28 Version requirement
\b .
\b0\fs26 \

\fs24 \
This OXP needs Oolite 1.75.1 to work.\
No dependencies, but...\
  if Transports.oxp is installed the Woma will be used too.\
  if Aquatics.oxp is installed the Hawksbill and ManOWar will be used too.\
  if BGS-A or BGS-M is installed a music file will be used when docked at a buoyRepair Facility.\
\
Version history\
1.3.4 Added the shaders that were lost in version 1.3.3\
1.3.3 Added old Anaconda & Boa texture that were removed from Oolite 1.80\
1.3.2 Minor fixes.\
1.3.1 External dockers changed, shader fix and buoy (un)folding.\
1.3 New station to reduce shader swapping and music.\
1.02.8 Fix to avoid running startUp twice when OXPConfig is used.\
1.02.7 Tweaks for Oolite v1.75.\
1.02.6 Workaround for ATI's cards and cleanups.\
1,02.5 Fix in shipyard. Previous versions can crash on Oolite 1.73.\
1.02.4 Minor fixes. Fully tested the Oolite 1.73 release.\
1.02.3 Minor fixes. Prepared for the Oolite 1.73 release. Removed incompatibilities with oxps that change Oolite core ships (e.g. neolite.oxp).\
1.02.2 Minor fixes. Recognises now bigShips.oxp.\
1.02	Added big fuel ships and big traders.\
1.01	Bug fixes and improved station.\
1.00	First release.\
\
----------\
A special thanks to Zieman for his help to find solutions for ATI users.\
\pard\pardeftab720
\cf0 Thanks to Murgh for the low cost idea of towing other ships instead of storing them in a cargo bay.\
(see his tugs.OXP, 1 march 2006)\
}

Equipment

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

Ships

Name
GRS Buoy Factory
grs-womasilo
Screen
Bay
Anaconda
Boa Class Cruiser
grs_big_woma
Navigation Buoy Segment
grs_cobra3_redux1
GRS Controller
GRS Controller Turret
Dock
GRS Guanako
grs_guanako_trader
grs_hawksbill
Living
Glow
grs_manOWar
Platforms
Reactor
Navigation Buoy
repaired-buoy-factory
GRS Shuttle
GRS Shuttle
Tug Jaw
Tug Line
repaired-buoy-witchpoint
repaired-buoyViper
GRS Armadillo
repaired-buoytuggerE
repaired-buoytuggerG
repaired-buoytuggerN
repaired-buoytuggerW

Models

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

Scripts

Path
Scripts/buoyRepair.js
"use strict";
this.name      = "buoyRepair";
this.author    = "eric walch (script), Svengali (artwork)";
this.copyright = "(C)2008-2011 the autors.";
this.description = "This script adds buoy repairships when one of the two main navigation buoys gets destroyed";
this.version   = "1.3.3";

this.oxpcLookup = function()
{
	this.oxpcSettings = {
		Info: {
			Name:this.name,
			MinVersion:"1.02.7",
			Display:"BuoyRepair",
			EarlyCall:true,
			EarlySet:true,
			InfoB:"logging: Extended logging for added ships and grs station.\nextraA: Add the GRS station in all average- and high economic systems + more testships."
		},
		Bool0: {Name:"logging",Def:false,Desc:"Logging functions."},
		Bool1: {Name:"extraA",Def:false,Desc:"Add stations in high eco systems."}
	};
	delete this.oxpcLookup;
}

this.startUp = function ()
{
	delete this.startUp;
	if (worldScripts.transportSchedule || worldScripts.transportschedule !== undefined) this.external_fuelship = "buoy_repair_woma_fuelship";
	else this.external_fuelship = "buoy_repair_fuelship";
	this.grsStation = false;
	this.logging = false; // "this.logging" must be "false" for a release.
	this.extraA = false; // Must also be false for a release version.
	/* for OXP-Config:
	logging - Switch on extended loging for the oxp added ships and the grs station.
	extraA - Add the GRS station in all average- and high economic systems + more testships round the station."
	*/
	this.resetTimer = new Timer(this, this.addStation, 0.1); // already add station before first launch
	// a delay greater than 0 is needed to get OXP-Config a chance to change the settings.

}

this.statusCheck = function ()
{
	if (player.ship.docked)
    {
        this.buoyStatusTimer.stop();
    }
	else
    {
		// check for role, not primary role because the replacement has a different role.
        if (!system.isInterstellarSpace && system.countShipsWithRole("buoy-witchpoint") == 0 && (!this.repairBuoyTuggerW || !this.repairBuoyTuggerW.isValid))
        {
            this.repairBuoyTuggerW = system.addShips("repairBuoyTuggerW", 1)[0];
        }
		if (system.mainStation && (!this.repairBuoyTuggerN || !this.repairBuoyTuggerN.isValid) && system.countShipsWithRole("buoy", system.mainStation, 15000) == 0)
        {
            // this.repairBuoyTuggerN = system.mainStation.launchShipWithRole("repairBuoyTugger", true);
            this.repairBuoyTuggerN = system.mainStation.launchShipWithRole("repairBuoyTuggerN", true);
            this.repairBuoyTuggerN.script.replaceBuoy = true; // sets the task for the launching ship.
			if (this.logging) log("buoyRepair", "adding repairBuoyTuggerN to launch queue");
        }
    }
}

this.shipLaunchedFromStation = function ()
{
	if (this.buoyStatusTimer) this.buoyStatusTimer.start()
	else this.buoyStatusTimer = new Timer(this, this.statusCheck, 15, (this.extraA ? 15 : 120));
}

this.shipWillExitWitchspace = function ()
{
	this.grsStation = false;
}

this.shipExitedWitchspace = function ()
{
	if (system.isInterstellarSpace) return;
	this.addStation();
}

this.addStation = function ()
{
	if (system.economy < 2 && ((system.government > 3 && system.techLevel < 11 && system.techLevel > 4) || this.extraA) && !system.gonenova)
    {
		this.grsVector = new Vector3D([system.ID, system.ID, system.ID-256]).direction();
		this.grsStation = system.addShips("repaired-buoy-station", 1, system.mainPlanet.position.add(this.grsVector.multiply(system.mainPlanet.radius * 2)), 1)[0];
        var quaternion = new Quaternion(1,0,0,0); // identityQuaternion
		var upVector = new Vector3D(0,1,0); // vectorUp of identityQuaternion;
		var angle = upVector.angleTo(this.grsVector);
		var cross = upVector.cross(this.grsVector);
		quaternion = quaternion.rotate(cross, -angle); // align the upVector to the this.grsvector

		// set up alignment towards main station
		var mainStatVector = system.mainStation.position.subtract(this.grsStation.position).direction();
		cross = quaternion.vectorUp().cross(mainStatVector);
		angle = quaternion.vectorRight().angleTo(cross);
		var angle2 = quaternion.vectorRight().angleTo(mainStatVector);
		if (angle2 < 0.5*Math.PI) angle=-angle;
		quaternion = quaternion.rotate(quaternion.vectorUp(), angle + 0.07); // docking bay roughly towards main station. (0.07 rad or 4 degr. off for a better look)
		if (system.economy == 1) // tilt the station dock towards the planet in average industrial
			quaternion = quaternion.rotate(quaternion.vectorRight(), -1.1); // good values are -1.05 till -1.15
		this.grsStation.orientation = quaternion;// within a system the station now has always the same orientation

		// store a launch site, used by ship scripts.
		this.launchSite = system.mainPlanet.position.add(this.grsVector.multiply(system.mainPlanet.radius + 500));
		this.addShips();
	}
}

this.addShips = function ()
{
	// add rising shuttles
	this.shuttle = 2;
	system.addShips("buoy_repair_shuttle_u", 2, this.launchSite, 20);

	// add returning armandillos
	this.tugger = 0;
	if (Math.random()< 0.65) {system.addShipsToRoute("repairBuoyTugger", 1, 0.25, "pw"); ++this.tugger};
	if (Math.random()< 0.40) {system.addShipsToRoute("repairBuoyTugger", 1, 0.50, "pw"); ++this.tugger};
	if (Math.random()< 0.25) {system.addShipsToRoute("repairBuoyTugger", 1, 0.75, "pw"); ++this.tugger};

	// add big traders
	if (Math.random()< 0.4) system.addShipsToRoute("buoy_repair_big_trader", 1, Math.random(), "pw");
	if (Math.random()< 0.4) system.addShipsToRoute("buoy_repair_big_trader", 1, Math.random(), "pw");

	var sunVector = system.sun.position.subtract(this.grsStation.position).direction();

	// add repeating dockers
    this.docker = 2;
	system.addShips("buoy_repair_docker", 1, this.grsStation.position.add(sunVector.multiply(40E3)), 1E4);
	system.addShips("buoy_repair_docker", 1, this.grsStation.position.add(sunVector.multiply(80E3)), 1E4);

	// add fuel ships
	if (this.extraA || Math.random()>0.5) this.addFuelShip(this.grsStation.position.add(sunVector.multiply(50E3)));
	if (this.extraA || Math.random()>0.5) this.addFuelShip(this.grsStation.position.add(sunVector.multiply(100E3)));
	if (this.extraA || Math.random()>0.25) this.addFuelShip(this.grsStation.position.add(sunVector.multiply(250E3)));
	if (this.extraA || Math.random()>0.25) this.addFuelShip(this.grsStation.position.add(sunVector.multiply(350E3)));
	this.controller = 0;
	this.tuggerE = 0;
}

this.addFuelShip = function (position)
{
	if (Math.random() > 0.4) system.addShips("buoy_repair_fuelship", 1, position, 1E4)
    else system.addShips(this.external_fuelship, 1, position, 1E4);
}

// below is code used only by ship scripts.
this.addShipnumber = function (name)
{
	var list = ["NL", "DG", "RF", "PH", "TZ"];
	return name + " " + list[Math.floor(Math.random() * list.length)] + Math.ceil(Math.random()*127);
}

this.switch = function (oldShip, buoyName, buoyRole, newAIState)
{
	var subentities = oldShip.subEntities;
	for (var i=0; i<subentities.length; i++)
	{
		if (subentities[i].name == buoyName)
		{
			var newShip = oldShip.spawnOne("switchedRepairBuoyTugger"); // add replacement ship to system.
			var buoy = oldShip.spawnOne(buoyRole);
			buoy.AIState = "LIGHTS_OFF";
			var target = player.ship.target;
			var oldOrientation = oldShip.orientation;
			var oldPosition = oldShip.position;
			var oldVector = oldShip.heading; //vector with lenght 1 meter
			newShip.displayName = oldShip.displayName;
			oldShip.position = oldShip.position.multiply(100); // to deep space
			newShip.orientation = oldOrientation;
			buoy.orientation = oldOrientation;
			newShip.position = oldPosition;
			buoy.position = oldPosition.add(oldVector.multiply(subentities[i].position.z));
			if (target == oldShip) newShip.script.playerTarget = true;
			newShip.primaryRole = "repairBuoyTugger"; // in case there are more switchings going on.
			newShip.AIState = newAIState;
			oldShip.AIState = "DISAPPEAR";
			if (this.logging) log("buoyRepair", "Replaced: " + buoyRole);
            break; // exit the for-loop
		}
	}
}

// routes for control ship

// Next two positions are within the bounding box and regularly lead to random collisions
this.positions1 = [
	new Vector3D(-200, 100, 5000), //nav1
	new Vector3D(-200, 1200, 3500), //stationapproach
	new Vector3D(-200, 1200, 1000), //basement
	new Vector3D(200, 700, 800), //above bay
	new Vector3D(450, 1250, 625), // above arch high
	new Vector3D(800, 1150, 500), // above arch low
	new Vector3D(600, 600, -800), // behind arch
	new Vector3D(500, 0, -1100), // behind station
	new Vector3D(600, -450, -300), // under station
	new Vector3D(1100, -150, 1500) // bolow rescue kit
];
this.positions2 = [
	new Vector3D(-200, 100, 5000), //nav1
	new Vector3D(-200, 1200, 3500), //stationapproach
	new Vector3D(-200, 1200, 1000), //basement
	new Vector3D(200, 600, 800), //above bay
	new Vector3D(400, 575, 400), // below arch
	new Vector3D(500, 550,-800), // behind arch
	new Vector3D(-100, 700, -400), // above explosives
	new Vector3D(-400, 1000, 100), // between poles
	new Vector3D(-900, 500, 900), // above grs logo
	new Vector3D(-900, 100, 1200), // in front of grs logo
	new Vector3D(-950, -400, 500), // heading to clamp 2
	new Vector3D(-950, -500, 0), // below clamp 2
	new Vector3D(-100, -700, -300), // below station back
	new Vector3D(700, -700, -200), // below station back
	new Vector3D(800, -600, 800) // below station front
];
this.positions3 = [
	new Vector3D(-200, 100, 5000), //nav1
	new Vector3D(-200, 1200, 3500), //stationapproach
	new Vector3D(-1700, -1000, 1700),
	new Vector3D(-1700, 500, -1700),
	new Vector3D(1700, 1000, -1700),
	new Vector3D(1700, 500, 1700),
	new Vector3D(-1700, 500, 1700),
	new Vector3D(-1700, 1700, 1700),
	new Vector3D(0, 1700, 0),
	new Vector3D(1700, 1700, 1700),
	new Vector3D(1700, -1700, 1700),
	new Vector3D(0, -1700, 0),
	new Vector3D(-500, -1700, 2000)
];
this.routes = [this.positions1, this.positions2, this.positions3]
// worldScripts.buoyRepair.routes[0][0]=new Vector3D(00,00,00)
Scripts/buoyRepairBuoy.js
"use strict";
this.name      = "buoyRepairBuoy";
this.author    = "eric walch";
this.copyright = "(C)2008-2011 the autors.";
this.description = "Buoy script for calling help";
this.version   = "1.3.3";

this.shipBeingAttacked = function (whom) {
	// add police to system
	if (!this.count || this.count > 10){
		this.count = 1
		if (whom.scanClass != "CLASS_THARGOID" || this.ship.position.distanceTo(player.ship) > 25000){
			if (this.ship.primaryRole == "repaired-grs-buoy-witchpoint") system.addShips("police", 2);
			if (this.ship.primaryRole == "grs-factory-buoy") {
				system.addShips("buoy_repair_viper", 2, worldScripts.buoyRepair.launchSite, 20);
				worldScripts.buoyRepair.viperTarget = whom;
            }
        }
    } else {
        this.count++;
    }
};

this.shipDied = function () {
    var station = worldScripts.buoyRepair.grsStation;
	if (this.ship.primaryRole == "grs-factory-buoy" && station) {
        var repairBuoyTuggerG = station.launchShipWithRole("repairBuoyTuggerG", true);
        repairBuoyTuggerG.savedCoordinates = station.position.add(station.heading.multiply(10E3));
    }
	if (worldScripts.buoyRepair.logging) log("buoyRepair", "A buoy with name: " + this.ship.displayName +" with role " + this.ship.primaryRole + " died");
};
Scripts/buoyRepairCable.js
"use strict";

this.name      = "buoyRepairCable";
this.author    = "eric walch";
this.copyright = "� 2011 the autors.";
this.description = "Make sure that when the cable explodes, no other towing stuff survives";
this.version   = "1.3.3";

this.shipDied = function ()
{
    var subs = this.ship.owner.subEntities;
    
    for (var i=subs.length-1; i>=0; i--)
    {
        if (subs[i].isValid && subs[i].scriptInfo && subs[i].scriptInfo.can_explode) subs[i].explode();
        /* 
        just releasing would be nicer than exploding the buoy, but the chance
        of hitting the line with a buoy still present is small. It is not worth the 
        trouble checking which buoy is towed and spawn that one in space. The script is
        mainly mend to avoid having a dangling clamp in space while the cable was already 
        shot away.
        We could also just explode all subentities without testing, but one does not know
        what new subentities will be added in future to the ship that should stay intact.
        */
    }
}
Scripts/buoyRepairControl.js
"use strict";

this.name      = "buoyRepairController";
this.author    = "eric walch";
this.copyright = "� 2008 the autors.";
this.description = "Station control vessel";
this.version   = "1.3.3";

this.shipSpawned = function ()
{
	if (worldScripts.buoyRepair.logging) log(this.name,this.name+" Spawned Controller");
	this.routes = worldScripts.buoyRepair.routes;
	this.positionCounter = 0;
	if (this.ship.displayName == this.ship.name) this.ship.displayName = worldScripts.buoyRepair.addShipnumber(this.ship.displayName);
	if (this.hasValidStation()) this.grsStation = worldScripts.buoyRepair.grsStation;
	this.route = this.routes[Math.floor(Math.random()*this.routes.length)]; // select a random route.

	if (this.ship.primaryRole == "defense_ship" && this.ship.target)
    {
        this.ship.setAI("interceptAI.plist"); // target was set on launch by station when launches as defense ship.
    }
}

this.shipExitedWormhole = function ()
{
	if (this.hasValidStation()) this.grsStation = worldScripts.buoyRepair.grsStation;
	else this.grsStation = false;
}

this.shipDied = function (whom, why)
{
	if (worldScripts.buoyRepair.logging) log("buoyRepair", this.ship.displayName + " was killed by a " + (whom&&whom.isShip?whom.displayName:whom) + ", because of " + why);
	if (this.hasValidStation()) worldScripts.buoyRepair.controller--;
}

this.shipCollided = function (whom)
{
	if (worldScripts.buoyRepair.logging) log("buoyRepair", this.ship.displayName + " collided with " + (whom&&whom.isShip?whom.displayName:whom));
	if (this.ship.energy < this.ship.maxEnergy) this.ship.reactToAIMessage("STOP");
}

this.shipDockedWithStation = function (station)
{
	if (this.hasValidStation()) worldScripts.buoyRepair.controller--;
}

this.nextPosition = function ()
{
	if (this.positionCounter<this.route.length)
    {
		this.setApproach(this.route[this.positionCounter]);
		if (worldScripts.buoyRepair.logging) log("buoyRepair", this.ship.displayName + " gets coordinate set nr. "+ this.positionCounter +": "+this.route[this.positionCounter]);
		this.positionCounter++;
		this.ship.reactToAIMessage("APPROACH_COORDINATES");
    }
	else this.ship.reactToAIMessage("END_CONTROL");

	if (this.ship.position.distanceTo(player.ship) > 30E3) this.ship.reactToAIMessage("END_CONTROL");
}

this.setApproach = function (position)
{
	if (this.hasValidStation())
    {
        if (0 < oolite.compareVersion("1.75")) this.ship.savedCoordinates = this.grsStation.position.add(this.rotateBy(position, this.grsStation.orientation))
        else this.ship.savedCoordinates = this.grsStation.position.add(position.rotateBy(this.grsStation.orientation));
    }
    else
    {
        this.ship.reactToAIMessage("NO_GRS_STATION"); // q-bombed?
    }
}

this.hasValidStation = function ()
{
    return (worldScripts.buoyRepair.grsStation && worldScripts.buoyRepair.grsStation.isValid);
}

this.findGRSStation = function ()
{
	if (this.hasValidStation()) this.ship.target = this.grsStation
	else this.ship.reactToAIMessage("NO_GRS_STATION");
}

this.rotateBy = function (position, orientation)
{
	// Only used by Oolite 1.74. Can be removed for a 1.75+ version
    var t2, t3, t4, t5, t6, t7, t8, t9, t10;
	var result = new Vector3D();
	t2 =  -orientation.w * orientation.x;
	t3 =  -orientation.w * orientation.y;
	t4 =  -orientation.w * orientation.z;
	t5 =  -orientation.x * orientation.x;
	t6 =   orientation.x * orientation.y;
	t7 =   orientation.x * orientation.z;
	t8 =  -orientation.y * orientation.y;
	t9 =   orientation.y * orientation.z;
	t10 = -orientation.z * orientation.z;
	result.x = 2*((t8 + t10)*position.x + (t6 - t4)*position.y + (t3 + t7)*position.z) + position.x;
	result.y = 2*((t4 + t6)*position.x + (t5 + t10)*position.y + (t9 - t2)*position.z) + position.y;
	result.z = 2*((t7 - t3)*position.x + (t2 + t9)*position.y + (t5 + t8)*position.z) + position.z;
	return result;
}
Scripts/buoyRepairDocker.js
"use strict";

this.name      = "buoyRepairDocker";
this.author    = "eric walch";
this.copyright = "� 2008 eric walch.";
this.description = "Clamp Docking";
this.version   = "1.3.3";

this.shipSpawned = function ()
{
	if (this.ship.displayName == this.ship.name)
		this.ship.displayName = worldScripts.buoyRepair.addShipnumber(this.ship.displayName);
	this.AI = this.ship.AI;  // backup old AI
	if (this.hasValidStation()) this.grsStation = worldScripts.buoyRepair.grsStation;
	this.clamp = false;
	this.goingReverse = false;
	this.dockings = 0;
}

this.shipExitedWormhole = function ()
{
	if (this.hasValidStation()) this.grsStation = worldScripts.buoyRepair.grsStation
	else this.grsStation = false;
	this.cleanup();
	if (this.AI != this.ship.AI)  this.ship.switchAI(this.AI); // reset old AI in case there is a GRS station.
}

this.shipDied = function (whom, why)
{
	if (this.clamp) {
		if (worldScripts.buoyRepair.logging)
        {
            log("buoyRepair", this.ship.displayName + " was killed by a " + (whom&&whom.isShip?whom.displayName:whom) +
                ", because of " + why+ (whom&&whom.isStation?" at clamp "+(this.clamp?this.clamp:"none."):""));
        }
		this.dockEscorts();
    }
	this.resetClamp();
	this.cleanup();
	if (whom != this.grsStation && this.ship.isTrader) this.ship.spawn("cargopod", Math.ceil(Math.random()*15));
}

this.shipCollided = function (whom)
{
	if (worldScripts.buoyRepair.logging)
    {
        log("buoyRepair", this.ship.displayName + " collided with " + (whom.isShip?whom.displayName:whom)+", Remaining energy: "+
            Math.round(this.ship.energy) +" out of "+this.ship.maxEnergy+
            (whom.isStation ? " At clamp "+(this.clamp ? this.clamp : "none.") : ""));
    }
}

this.shipDockedWithStation = function (station)
{
	this.cleanup();
}

this.cleanup = function ()
{
	if (this.hasValidStation() && this.ship.primaryRole == "buoy_repair_docker") worldScripts.buoyRepair.docker--;
}

this.requestClamp = function ()
{
	if (!this.hasValidStation()) {this.ship.reactToAIMessage("GRS_NO_FREE_CLAMP"); return;};
	this.clamp = this.grsStation.script.requestFreeClamp();
	if (this.clamp == 0)
    {
		this.clamp = false;
		this.ship.reactToAIMessage("GRS_NO_FREE_CLAMP");
    }
	else
    {
		this.grsStation.script.clampOn(this.clamp);
		this.ship.reactToAIMessage("GRS_FREE_CLAMP");
    }
}

this.resetClamp = function ()
{
	if (!this.hasValidStation()) return; // blown up by q-bomb.
    
    if (this.clamp) this.grsStation.script.clampOff(this.clamp);
	this.clamp = false;
}

this.setApproachA = function ()
{
	this.setApproach(7000);  // far away
}

this.setApproachB = function ()
{
	this.setApproach(2300); // lining up point, 700m before the clamp.
}

this.setApproachC = function ()
{
	this.setApproach(1500); // immediately before the clamp.
}

this.setApproachD = function ()
{
    this.setApproach(parseFloat(this.ship.scriptInfo.grs_dockinglength));  // endpoint for stopping. Can be different for each ship.
	if (this.hasValidStation()) this.grsStation.script.raiseLightning(this.clamp);
}

this.setApproachE = function ()
{
	this.setApproach(7000);  // far away
	if (this.hasValidStation()) this.grsStation.script.lowerLightning(this.clamp);
}

this.setApproach = function (distance)
{
	if (!this.clamp || !this.hasValidStation())
    {
        this.ship.reactToAIMessage("GRS_NO_FREE_CLAMP");
        return;
    }

    var position = this.grsStation.position;

	if (this.clamp == 2) position = position.subtract(this.grsStation.orientation.vectorRight().multiply(distance))
	else position = position.subtract(this.grsStation.heading.multiply(distance));

	this.ship.savedCoordinates = position.subtract(this.grsStation.orientation.vectorUp().multiply(60)); // a little bit lower.
}

this.checkPlayerDistance = function ()
{
	if (this.ship.position.distanceTo(player.ship) < 30E3)
    {
        this.ship.reactToAIMessage("PLAYER_CLOSE");
    }
	else
    {
        this.ship.reactToAIMessage("PLAYER_FAR_AWAY");
        if (worldScripts.buoyRepair.logging) log("BuoyRepair", this.ship.displayName + " terminated clamp docking because player is to far away.");
    }
	/* Remark: when a ship is further away than Math.sqrt(1E9) (=31622.7766 meters) from the player, there is only a rough
	collision detection and the ship will collide at the outher hull of the station at about 2040 meters from the station core.
	Oolite does not try anymore to detect local collision with any part of the clamps.
	*/
}

this.hasValidStation = function ()
{
    return (worldScripts.buoyRepair.grsStation && worldScripts.buoyRepair.grsStation.isValid);
}

this.findGRSStation = function ()
{
	if (this.hasValidStation()) 
    {
        this.ship.target = worldScripts.buoyRepair.grsStation;
    }
	else if (worldScripts["bigShips_populator"])  
    {
        this.ship.switchAI("bigShips_route1BigTraderAI.plist");
    }
	else 
    {
        this.ship.reactToAIMessage("NO_GRS_STATION");
    }
}

this.reverse = function ()
{
	if (this.goingReverse) return;
	if (worldScripts.buoyRepair.logging) log("BuoyRepair", this.ship.displayName + " at clamp "+this.clamp+", docked succesful " + (++this.dockings) +" times.");

	if (this.hasValidStation() && this.clamp) 
    {
        var orientation = worldScripts.buoyRepair.grsStation.orientation;
        var direction = (this.clamp == 1) ? orientation.vectorForward() : orientation.vectorRight();
        direction.x *= -1; // we need te opposite direction.
        direction.y *= -1;
        direction.z *= -1;            
        
        this.ship.thrust = 0;
        this.ship.velocity = direction.multiply(10);
    }
    else
    {
        this.ship.reactToAIMessage("NO_GRS_STATION");
        return;
    }

	this.goingReverse = true;
}

this.forward = function ()
{
	if (!this.goingReverse) return;
    this.ship.thrust = this.ship.maxThrust;
	this.goingReverse = false;
}

this.parkEscorts = function ()
{
	var escorts = this.ship.escorts;
	if (!escorts) return;
	for(var i=0;i<escorts.length;i++) {if (escorts[i].isValid) escorts[i].setAI("buoyRepairEscortAI.plist");}
}

this.callEscorts = function ()
{
	var escorts = this.ship.escorts;
	if (!escorts) return;
	for(var i=0;i<escorts.length;i++)
    {
		if (escorts[i].isValid)
        {
			escorts[i].switchAI("escortAI.plist");
			escorts[i].AIState = "FLYING_ESCORT";
        }
    }
}

this.dockEscorts = function ()
{
	var escorts = this.ship.escorts;
	if (!escorts) return;
	for(var i=0;i<escorts.length;i++)
    {
		if (escorts[i].isValid) escorts[i].switchAI("dockingAI.plist");
    }
}

this.hyperspaceHelp = function ()
{
    if (this.ship.distanceTravelled > 9000) this.ship.AIState = "GO_WITCHPOINT";
}
Scripts/buoyRepairExplosive.js
"use strict";
this.name      = "buoyRepairExplosive";
this.author    = "eric walch";
this.copyright = "(C)2008-2011 the autors.";
this.description = "Script for the explosive charge on the station";
this.version   = "1.3";

this.count = 5

this.shipBeingAttacked = function ()
{
	if (--this.count < 0) this.ship.explode();
}
Scripts/buoyRepairShip.js
"use strict";
this.name      = "buoyRepairShip";
this.author    = "eric walch";
this.copyright = "(C)2008-2011 the autors.";
this.description = "ship for repairing Witchpoint & Station Buoy";
this.version   = "1.3.3";

this.buoy = new Array();
this.segmentName = "Navigation Buoy Segment";

this.shipSpawned = function ()
{
	if (this.ship.displayName == this.ship.name)  //sometimes the nameswitch happened before shipSpawned() was called.
            this.ship.displayName = worldScripts.buoyRepair.addShipnumber(this.ship.displayName);

	if (this.ship.subEntities && this.ship.subEntities.length > 2)
    {
		if (worldScripts.buoyRepair.logging) log("buoyRepair", "Adding " + this.ship.displayName +" with role " + this.ship.primaryRole + " and towing a " + this.ship.subEntities[2].name)
		if (this.ship.primaryRole == "repairBuoyTuggerN")
        {
			if (system.shipsWithPrimaryRole("repairBuoyTuggerN").length > 1 || system.shipsWithRole("buoy", system.mainStation, 15000).length > 0)
            {
				this.ship.AIState = "GO_TO_STATION";
				this.ship.primaryRole = "repairBuoyTuggerE"; // we don't want duplicates with the "repairBuoyTuggerN" role.
				return;
            }
			this.ship.AIState = "CLEAR_LAUNCHPATH";
        }
        if (this.ship.subEntities.length > 3) // has a segmented buoy.
        {
            this.position = 0; // means segments in folded position.
            var j = 0;
            for (var i = 0; i < this.ship.subEntities.length; i++)
            {
                // copy all buoy parts into a new array to avoid problems with changing subEntity ordering.
                if (this.ship.subEntities[i].name == this.segmentName) this.buoy[j++] = this.ship.subEntities[i];
            }
        }
        if (this.ship.hasRole("repairBuoyTuggerE"))
        {
            // This version starts with folded buoy to allow launches with it.
            this.unfoldTimer = new Timer(this, this.unfoldBuoy, 5.0);
        }
    }
	else {
		if (this.ship.primaryRole == "defense_ship") {
			if (this.ship.target) this.ship.setAI("interceptAI.plist")
			else this.ship.setAI("dockingAI.plist");}
		if (worldScripts.buoyRepair.logging) log("buoyRepair", "Adding " + this.ship.displayName +" with role " + this.ship.primaryRole + " and towing nothing.");}
	if (this.playerTarget) player.ship.target = this.ship
	delete this.shipSpawned;
}

this.shipDied = function (whom, why)
{
	if (worldScripts.buoyRepair.logging) log("buoyRepair", this.ship.displayName + " was killed by a " + (whom?(whom.displayName?whom.displayName:whom):"[undefined]") + ", because of " + why)
	if (this.ship.subEntities && this.ship.subEntities.length > 2) {
		if (worldScripts.buoyRepair.logging) log("buoyRepair", "Ship was towing a: " + this.ship.subEntities[2].name)
		if (this.ship.primaryRole == "repairBuoyTuggerG") {
			if (worldScripts.buoyRepair.logging) log("buoyRepair", "ship towing a G-beacon died");
			this.addBuoy("grs-factory-buoy");}
		if (this.ship.primaryRole == "repairBuoyTuggerN"){
			if (worldScripts.buoyRepair.logging) log("buoyRepair", "ship towing a N-beacon died");
			this.addBuoy("repaired-grs-buoy")
			system.legacy_addShips("repairBuoyTuggerE", 1);}
		if (this.ship.primaryRole == "repairBuoyTuggerW"){
			if (worldScripts.buoyRepair.logging) log("buoyRepair", "ship towing a W-beacon died");
			this.addBuoy("repaired-grs-buoy-witchpoint");}}
	else {
		if (this.ship.primaryRole == "repairBuoyTuggerG"){
		this.ship.switchAI("buoyRepairShipGAI.plist") // a dead ship with ejected pilot has a nullAI.plist
		if (worldScripts.buoyRepair.grsStation) worldScripts.buoyRepair.grsStation.reactToAIMessage("GRS_G-BUOY_DIED");}}
	if (this.ship.primaryRole == "repairBuoyTugger") {if (worldScripts.buoyRepair.grsStation) worldScripts.buoyRepair.tugger--}
	if (this.ship.primaryRole == "repairBuoyTuggerE") {if (worldScripts.buoyRepair.grsStation) worldScripts.buoyRepair.tuggerE--}
}

this.shipExitedWormhole = function ()
{
	if (worldScripts.buoyRepair.logging) log("buoyRepair", this.ship.displayName + " entered wormhole");
	if (this.ship.primaryRole == "repairBuoyTuggerE") {if (worldScripts.buoyRepair.grsStation) worldScripts.buoyRepair.tuggerE--}
}

this.shipDockedWithStation = function (station)
{
	if (worldScripts.buoyRepair.logging) log("buoyRepair", this.ship.displayName + " docked at " + station.name + " with a energy level of " + Math.round(this.ship.energy) + " out of " + this.ship.maxEnergy);
	if (this.ship.primaryRole == "repairBuoyTugger") {if (worldScripts.buoyRepair.grsStation) worldScripts.buoyRepair.tugger--}
}

this.shipEnteredPlanetaryVicinity = function ()
{
    // Only react for default traders. Other AI can call the folfing in a dedicated AI.
    if (this.ship.AI == "route1traderAI.plist") this.foldBuoy();
}

this.entityDestroyed = function ()
{
    // handler was introduced in Oolite 1.75.1
    this.$cleanupTimers();
}

this.addBuoy = function (buoyRole)
{
	var buoy = this.ship.spawnOne(buoyRole);
	buoy.AIState = "LIGHTS_OFF";
	buoy.orientation = this.ship.orientation;
	buoy.position = this.ship.position.add(this.ship.heading.multiply(this.ship.subEntities[2].position.z));
}

this.releaseBuoyW = function ()
{
	worldScripts.buoyRepair.switch(this.ship, "Navigation Buoy", "repaired-grs-buoy-witchpoint", "MOVE_OUT");
}

this.releaseBuoyG = function ()
{
	worldScripts.buoyRepair.switch(this.ship, "Navigation Buoy", "grs-factory-buoy", "GO_TO_STATION");
	if (this.ship.subEntities.length < 3 && worldScripts.buoyRepair.grsStation) worldScripts.buoyRepair.grsStation.reactToAIMessage("GRS_G-BUOY_DIED");
}

this.releaseBuoyN = function ()
{
	if (Math.random() < 0.7)
    {
        worldScripts.buoyRepair.switch(this.ship, this.segmentName, "repaired-grs-buoy", "DOCK_AT_MAIN_STATION");
    }
	else
    {
		worldScripts.buoyRepair.switch(this.ship, this.segmentName, "repaired-grs-buoy", "MOVE_OUT");
		system.addShips("repairBuoyTuggerE", 1);
    }
}

this.foldBuoy = function ()
{
    if (this.buoy.length == 3)
    {
        // the ship still has all the segments, so proceed with folding.
        this.movement = -0.02;
        if (!isValidFrameCallback(this.$callbackID)) this.$callbackID = addFrameCallback(this.moveBuoySegments.bind(this));
    }
}

this.unfoldBuoy = function ()
{
    if (this.buoy.length == 3)
    {
        // the ship still has all the segments, so proceed with unfolding.
        this.movement = 0.02;
        if (!isValidFrameCallback(this.$callbackID)) this.$callbackID = addFrameCallback(this.moveBuoySegments.bind(this));
    }
}

this.moveBuoySegments = function (delta)
{
    if (!delta) delta = 0.25;
    if (!this.ship || !this.ship.isValid || !this.ship.status || this.buoy.length < 3) {this.$cleanupTimers();return;};
    this.position += this.movement * delta;
    if (this.position >= 1) // buoy is unfolded
    {
        this.$cleanupTimers();
        this.position = 1;
    }
    if (this.position <= 0) // buoy is folded
    {
        this.$cleanupTimers();
        this.position = 0;
    }
    this.buoy[1].orientation = [1, this.position, 0, 0]; // Oolite wil normalise the quaternion for us on assignment.
    this.buoy[2].orientation = [1, 0, 0, this.position];
}

this.$cleanupTimers = function ()
{
	if (this.$callbackID && isValidFrameCallback(this.$callbackID))
	{ 
		removeFrameCallback(this.$callbackID);
        delete this.$callbackID;
	}
    if (this.unfoldTimer)
    {
        this.unfoldTimer.stop();
        delete this.unfoldTimer;
    }
}

this.findGRSStation = function ()
{
	if (worldScripts.buoyRepair.grsStation) this.ship.target = worldScripts.buoyRepair.grsStation
	else this.ship.target = system.mainStation;
}

this.hyperspaceHelp = function ()
{
    if (this.ship.distanceTravelled > 9000) this.ship.AIState = "GO_WITCHPOINT";
}
Scripts/buoyRepairShuttle.js
"use strict";

this.name      = "buoyRepairShuttle";
this.author    = "eric walch";
this.copyright = "� 2008 the autors.";
this.description = "Shuttle script";
this.version   = "1.3";

this.shipSpawned = function ()
{
	this.ship.displayName = worldScripts.buoyRepair.addShipnumber(this.ship.displayName);
	if (this.ship.primaryRole == "buoy_repair_shuttle"){
		this.ship.switchAI("fallingBuoyRepairShuttleAI.plist");
		this.ship.primaryRole = "shuttle"; // only the role shuttle does not crash with planets.
    } else {
		// This is rising shuttle. Set upright.
		var targetVector = this.ship.position.subtract(system.mainPlanet.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);
    }
	if (this.hasValidStation()) this.grsStation = worldScripts.buoyRepair.grsStation;
	delete this.shipSpawned;
}

this.shipDockedWithStation = function (station)
{
	if (this.hasValidStation()) worldScripts.buoyRepair.shuttle--;
}

this.shipApproachingPlanetSurface = function ()
{
	if (this.ship.primaryRole == "shuttle"){
		this.ship.switchAI("fallingBuoyRepairShuttleAI.plist"); // make sure it is not in a gotoWaypointAI
		this.ship.AIState = "LANDING";
		if (worldScripts.buoyRepair.logging) log("repairBuoy", this.ship.displayName + " is approaching surface and prepares for landing.");
    }
}

// the AI message "APPROACH_SURFACE" is often not working because the AI switches to gotoWaypointAI before.
this.shipDied = function (whom, why)
{
	if (worldScripts.buoyRepair.logging) log("buoyRepair", this.ship.displayName + " was killed by a " + (whom.displayName?whom.displayName:whom) + ", because of " + why);
	if (worldScripts.buoyRepair.grsStation) worldScripts.buoyRepair.shuttle--;
}

this.shipLandedOnPlanet = function (planet)
{
	if (worldScripts.buoyRepair.logging) log("buoyRepair", this.ship.displayName + " landed on " + planet);
	if (worldScripts.buoyRepair.grsStation) worldScripts.buoyRepair.shuttle--;
}

this.hasValidStation = function ()
{
    return (worldScripts.buoyRepair.grsStation && worldScripts.buoyRepair.grsStation.isValid);
}

this.findGRSStation = function ()
{
	if (this.hasValidStation()) this.ship.target = worldScripts.buoyRepair.grsStation
	else this.ship.target = system.mainStation;
}

this.checkDistance = function ()
{
	var planet = system.mainPlanet;
	var distance = planet.position.distanceTo(this.ship) - planet.radius;
	if (distance < 2000)  this.ship.AIState = "APPROACH";
}
Scripts/buoyRepairStation.js
"use strict";
this.name      = "buoyRepairStation";
this.author    = "eric walch";
this.copyright = "(C)2008-2011 the autors.";
this.description = "station for assambly Buoy's";
this.version   = "1.3";

this.shipSpawned = function ()
{
	system.addShips("grs-factory-buoy", 1, this.ship.position.add(this.ship.heading.multiply(10E3)), 1);
	this.grsClamp =[false, false];
}

this.shipDied = function ()
{
	worldScripts.buoyRepair.grsStation = false;
}

this.callForHelp = function ()
{
	system.addShips("buoy_repair_viper", 2, worldScripts.buoyRepair.launchSite, 10);
	if (worldScripts.buoyRepair.logging) log("buoyRepair", "adding Viper near surface");
	worldScripts.buoyRepair.viperTarget = this.ship.target;
}

this.addShuttle = function ()
{
	if (worldScripts.buoyRepair.shuttle > 7) return;
	system.addShips("buoy_repair_shuttle_u", 1, worldScripts.buoyRepair.launchSite, 1);
	worldScripts.buoyRepair.shuttle++;
	if (worldScripts.buoyRepair.logging) log("buoyRepair", "adding Shuttle near surface");
}

this.addTugger = function ()
{
	if (Math.random() < 0.5 && worldScripts.buoyRepair.tugger < 3)
    {
		system.addShips("repairBuoyTugger", 1);
		worldScripts.buoyRepair.tugger++;
		if (worldScripts.buoyRepair.logging) log("buoyRepair", "adding Tugger at witchpoint");
    }
}

this.launchTugger = function ()
{
	if (worldScripts.buoyRepair.tuggerE < 3)
    {
        if (worldScripts.buoyRepair.logging) log("buoyRepair", "adding Tugger to launch queue");
        worldScripts.buoyRepair.tuggerE++;
        this.ship.launchShipWithRole("repairBuoyTuggerE");
    }
}

this.launchShuttle = function ()
{
	if (worldScripts.buoyRepair.shuttle > 7) return;
	if (worldScripts.buoyRepair.logging) log("buoyRepair", "adding Shuttle to launch queue");
	worldScripts.buoyRepair.shuttle++;
    this.ship.launchShipWithRole("buoy_repair_shuttle");
}

this.launchTrader = function ()
{
	if (worldScripts.buoyRepair.logging) log("buoyRepair", "adding Trader to launch queue");
    this.ship.launchShipWithRole("trader");
}

this.launchController = function ()
{
	if (worldScripts.buoyRepair.controller > 0) return;
	if (worldScripts.buoyRepair.logging) log("buoyRepair", "adding Controller to launch queue");
	worldScripts.buoyRepair.controller++;
    this.addToStationGroup(this.ship.launchShipWithRole("buoy_repair_control"));
}

this.launchDocker = function ()
{
	if (worldScripts.buoyRepair.docker > 0) return;
	if (worldScripts.buoyRepair.logging) log("buoyRepair", "adding Docker to launch queue");
	worldScripts.buoyRepair.docker++;
    this.addToStationGroup(this.ship.launchShipWithRole("buoy_repair_docker"));
}

this.addToStationGroup = function (ship)
{
   this.ship.group.addShip(ship);
   ship.group = this.ship.group;
}

this.otherShipDocked = function (ship)
{
	if (worldScripts.buoyRepair.logging) log("buoyRepair", ship.displayName + " with role "+ ship.primaryRole +" docked at the GRS station");
	if (ship.isPlayer) player.consoleMessage(expandDescription("[GRS_Welcome]"), 3);
}

this.requestFreeClamp = function ()
{
	var clamp = 0;
	if (!this.grsClamp[0]) clamp +=1;
	if (!this.grsClamp[1]) clamp +=2;
	if (clamp == 3) clamp = Math.ceil(Math.random()*2);
	return clamp;
}

// entity.fuel is used by shaders to control lights
this.clampOn = function (clamp)
{
	if (clamp) {
		var p1 = Math.floor(this.ship.fuel);
		var p2 = this.ship.fuel%1;
		if(clamp===1) this.ship.fuel = p1+0.2;
		else this.ship.fuel = p2+2;
		this.grsClamp[clamp-1] = true;
	}
}

this.clampOff = function (clamp)
{
	if (clamp) {
		var p1 = Math.floor(this.ship.fuel);
		var p2 = this.ship.fuel%1;
		if(clamp===1) this.ship.fuel = p1+0.1;
		else this.ship.fuel = p2+1;
		this.grsClamp[clamp-1] = false;
	}
}

this.raiseLightning = function (clamp)
{
	if (clamp) {
		var p1 = Math.floor(this.ship.fuel);
		var p2 = this.ship.fuel%1;
		if(clamp===1) this.ship.fuel = p1+0.4;
		else this.ship.fuel = p2+4;
	}
}

this.lowerLightning = function (clamp)
{
	if (clamp) {
		var p1 = Math.floor(this.ship.fuel);
		var p2 = this.ship.fuel%1;
		if(clamp===1) this.ship.fuel = p1+0.2;
		else this.ship.fuel = p2+2;
	}
}
Scripts/buoyRepairViper.js
"use strict";

this.name      = "buoyRepairViper";
this.author    = "eric walch";
this.copyright = "� 2008 the autors.";
this.description = "Shuttle script";
this.version   = "1.3";

this.shipSpawned = function ()
{
	if (worldScripts.buoyRepair.logging) log("repairBuoy", this.ship.displayName + " is launching from surface.");
	delete this.shipSpawned;
}

this.shipApproachingPlanetSurface = function ()
{
	if (worldScripts.buoyRepair.logging) log("repairBuoy", this.ship.displayName + " is approaching surface and prepares for landing.");
}

this.shipDied = function (whom, why)
{
	if (worldScripts.buoyRepair.logging) log("buoyRepair", this.ship.displayName + " was killed by a " + (whom.displayName?whom.displayName:whom) + ", because of " + why);
}

this.requestTarget = function ()
{
	if (worldScripts.buoyRepair.viperTarget && worldScripts.buoyRepair.viperTarget.isValid)
    {
        this.ship.target = worldScripts.buoyRepair.viperTarget;
        this.ship.reactToAIMessage("GRS_TARGET_RECEIVED");
    }
    else
    {
        this.ship.reactToAIMessage("GRS_TARGET_LOST");
    }
}

this.findGRSStation = function ()
{
	if (worldScripts.buoyRepair.grsStation && worldScripts.buoyRepair.grsStation.isValid) this.ship.target = worldScripts.buoyRepair.grsStation
	else this.ship.target = system.mainStation;
}

this.checkDistance = function ()
{
	var planet = system.mainPlanet;
	var distance = planet.position.distanceTo(this.ship) - planet.radius;
	if (distance < 2000)  this.ship.AIState = "APPROACH";
}