Back to Index Page generated: Dec 20, 2024, 7:22:09 AM

Expansion Gates

Content

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description Adds a pair of jump gates to suitable tech/govt systems, enabling quick and safe transfer by-passing route one. All for only 250Cr per journey. Adds a pair of jump gates to suitable tech/govt systems, enabling quick and safe transfer by-passing route one. All for only 250Cr per journey.
Identifier oolite.oxp.Thargoid.Gates oolite.oxp.Thargoid.Gates
Title Gates Gates
Category Activities Activities
Author Thargoid Thargoid
Version 1.13 1.13
Tags activities, system activities, system
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
Conflict Expansions
Information URL http://wiki.alioth.net/index.php/Gates_OXP n/a
Download URL https://wiki.alioth.net/img_auth.php/d/d0/Gates_1.13.oxz n/a
License Creative Commons Attribution - Non-Commercial - Share Alike 3.0 license with clauses - see readme file Creative Commons Attribution - Non-Commercial - Share Alike 3.0 license with clauses - see readme file
File Size n/a
Upload date 1610873477

Documentation

Also read http://wiki.alioth.net/index.php/Gates

Gates v1.13 Readme & License.txt

Gates OXP by Thargoid.

A simple little OXP that will create a pair of jump-gates in higher technology (8+) and stable government (Communist or better) systems. For a small fee of 250 credits per journey, these will take you instantaneously between the area of the system station and the witchpoint.

Originally based on captured alien technology, these have been developed by GalCop initially for military and police usage but are now open to civilian traders and other travellers too. Most gates are of the standard design (known colloquially as the "Spider variant" due to its resemblance to a tarantula), but some older designs ("rose gates", again from their resemblance to a flower) and even occasional captured and reprogrammed alien jump gates may be found.

--------------------------------------------------------------
Compatibility:

This new version requires Oolite v1.74 or higher. But thankfully due to trunk tweaks it looks like things work with sub-ent'd ships again (bring on them Caddy's!).

--------------------------------------------------------------
License:

This OXP is released under the Creative Commons Attribution - Non-Commercial - Share Alike 3.0 license with the following clauses:

* Whilst you are free (and encouraged) to re-use any of the scripting, models or texturing in this OXP, the usage must be distinct from that within this OXP. Unique identifiers such as (but not limited to) unique shipdata.plist entity keys, mission variables, script names (this.name), equipment identity strings (EQ_), description list arrays and entity roles must not be re-used without prior agreement.
* rebundling of this OXP within another distribution is permitted as long as it is unchanged. The following derivates however are permitted and except from the above:
	* the conversion of files between XML and openStep.
	* the merging of files with other files of the same type from other OXPs.
* Even though it is not compulsory, if you are re-using any sizable or recognisable piece of this OXP, please let me know :)

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

Instructions:

Unzip the file, and then move the folder "Gates 1.13.oxp" to the AddOns directory of your Oolite installation. Then start the game up whilst holding down the shift key (until the spinning Cobra Mk III screen appears) and the stations will appear in appropriate systems.

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

Version history:

13/11/2009 - Version 1.00, Initial release (why am I releasing an OXP on Friday 13th????!!!!)
12/04/2010 - version 1.10, update for v1.74 (and higher), plus fun with scanner colouration.
13/02/2011 - Version 1.11, removal of upper limit, to allow running with 1.75
14/02/2011 - Version 1.12, stop timers if player dies in Gated system (errors in log otherwise).
23/10/2011 - Version 1.13, script adjustment to deal with situations when main station is no longer present. Also replace randomness with Ahruman's pseudo-random, to make things more repeatable.

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

Acknowledgements:

* With thanks to Frame for both the initial inspiration for the design (from Solar System 0.1 beta) and also for his pioneering use of ownProperties scripting in bounty scanner, which is re-used here.

* And a follow-on nod to Eric Walch for reminding me of the latter above, and to another_commander for encouragement to issue this OXP, and for help when trunk-beta started docking the player with the gates.

Equipment

This expansion declares no equipment.

Ships

Name
Jump Gate (Captured Alien)
gates_gateTrader
gates_jumpGate
Jump Gate (Rose variant)
Jump Gate (Spider variant)

Models

This expansion declares no models.

Scripts

Path
Scripts/gates_gateTrader.js
this.name					= "gates_gateTrader";
this.author					= "Thargoid";
this.copyright				= "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt.";
this.description				= "Script for traders using jumpgates";
this.version				= "1.00";

this.shipSpawned = function()
	{ 
	if(system.isInterstellarSpace || system.sun.isGoingNova || system.sun.hasGoneNova || system.countShipsWithRole("gates_jumpGate") < 2)
		{
		return;
		}
	
	
	function jumpGates(entity) {return entity.isShip && entity.hasRole("gates_jumpGate")}; // all gates except this one
	var gates = system.filteredEntities(this, jumpGates, this.ship); // find the gates in the system
	
	if(this.ship.position.distanceTo(gates[0].position) < 51200 && (this.ship.AIState == "HEAD_FOR_PLANET" || this.ship.AIState == "HEAD_AWAY_FROM_PLANET"))
		{
		this.ship.target = gates[0];
		this.ship.setAI("gates_useGateAI.plist");
		}
	}

this.checkGateDistance = function()
	{	
	if(this.ship.position.distanceTo(this.ship.target.position) > 51200)
		{
		this.ship.reactToAIMessage("NEXT_GATE")
		}
	}
Scripts/gates_jumpGate.js
this.name					= "gates_jumpGate";
this.author					= "Thargoid";
this.copyright				= "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description			= "Script for Thargoid jumpgates";
this.version				= "1.12";


function gates_allGates(entity) {return entity.isShip && entity != this.ship && entity.hasRole("gates_jumpGate")}; // all gates except this one

function gates_clients(entity) {return entity.isShip && entity.primaryRole != "gates_gateGuard" && !entity.isCloaked && !entity.isWeapon && !entity.isRock && !entity.isCargo && (!entity.hasOwnProperty("gates_receivingGate")|| entity.gates_receivingGate == null)}; // ships that can use jumpgates (exclude spawned defenders, missiles, mines, asteroids and cargo pods

function gates_oldClients(entity) {return entity.isShip && entity.hasOwnProperty("gates_receivingGate") && entity.gates_receivingGate != null && entity.position.distanceTo(this.ship.position) > 500 && entity.position.distanceTo(this.ship.position) < 5000}; // ships which have come through this gate and are now between 500m and 5km from it

function gates_outboundNPCs(entity) {return entity.isShip && entity.AI == "exitingTraderAI.plist" && entity.AIState == "HEAD_AWAY_FROM_PLANET" && (!entity.escorts || entity.escorts.length == 0) && system.mainStation && entity.position.distanceTo(system.mainStation.position) < 51200};

function gates_inboundNPCs(entity) {return entity.isShip && entity.AI == "route1traderAI.plist" && entity.AIState == "HEAD_FOR_PLANET" && (!entity.escorts || entity.escorts.length == 0) && entity.position.distanceTo([0,0,0]) < 51200};


this.shipSpawned = function()
	{
	this.ship.scannerDisplayColor1 = "greenColor";
	this.ship.scannerDisplayColor2 = "whiteColor";
	this.playerGreeted = null;
	this.allowGreeting = true;
	this.gatesOnline = true;
	this.ship.orientation = system.mainStation.orientation; // point them all in the same direction, along universal Z.
	this.defenderCount = 10; // max number of defenders that can be launched overall by the gate if attacked
	
	if(this.scanTimer)
		{
		this.scanTimer.start();
		}
	else
		{
		this.scanTimer = new Timer(this, this.shipApproach, 0, 1.0); // scan for jumping ships every 1 second - too long/short?
		}

	if(this.npcTimer)
		{
		this.npcTimer.start();
		}
	else
		{
		this.npcTimer = new Timer(this, this.npcTraders, 0, 180); // scan for NPC traders who may want to use the gates every 3 minutes
		}

	}

this.playerWillEnterWitchspace = this.shipDied = function()
	{
	if(this.scanTimer)
		{
		this.scanTimer.stop();
		}

	if(this.npcTimer)
		{
		this.npcTimer.stop();
		}
	}

this.shipApproach = function()
	{	
	if(!player.ship || !player.ship.isValid)
		{
		this.shipDied();
		return;
		}
	
	if(this.ship.position.distanceTo(player.ship.position) > 25600 && this.allowGreeting == null)
		{
		this.allowGreeting = true;
		}
	
	var pastClients = system.filteredEntities(this, gates_oldClients, this.ship, 5000) // if any old clients are around, strip their client status
	if(pastClients.length > 0)
		{
		for(var i = 0; i < pastClients.length; i++)
			{
			pastClients[i].gates_receivingGate = null;
			if(pastClients[i].isPlayer) 	
				{
				player.consoleMessage("Jump gate cleared.", 6);
				this.allowGreeting = null;
				}
			}
		}
	
	var queue = system.filteredEntities(this, gates_clients, this.ship, 250); // if there is no-one wanting to jump, end the test
	if(queue.length == 0)
		{
		return;
		}
	
	var gates = system.filteredEntities(this, gates_allGates, this.ship); // check whether there is a second gate to receive the jumper
	if(gates.length == 0) 
		{
		if(queue[0].isPlayer && this.gatesOnline == true) 
			{
			player.consoleMessage("Jump gate off-line.", 6);
			this.gatesOnline = null;
			}
		return;
		}
	else
		{
		this.gatesOnline = true;
		}
	
	if(queue[0].hasOwnProperty("gates_receivingGate") && queue[0].gates_receivingGate == this.ship) // if the jumper has just arrived, end the test
		{
		return;
		}

	if(queue[0].AI == "gates_useGateAI.plist")
		{
		queue[0].reactToAIMessage("JUMPED");
		queue[0].gates_receivingGate = gates[0]; // note the gate that is about to receive the jumper
		queue[0].position = gates[0].position; // move the jumper to the receiving gate
		queue[0].orientation = gates[0].orientation; // re-orient the jumper to point out of the gate
		return;
		}
	
	if(queue[0].isPlayer)
		{
		if(player.credits < 251)
			{
			player.consoleMessage("Insufficient credits to perform jump.", 6);
			return;
			}
		else
			{
			player.consoleMessage("Jump gate activated.", 6);
			player.credits -=250;
			this.playerGreeted = null;
			queue[0].gates_receivingGate = gates[0]; // note the gate that is about to receive the player
			queue[0].position = gates[0].position; // move the player to the receiving gate
			queue[0].orientation = gates[0].orientation; // re-orient the player to point out of the gate
			}
		}
	}

this.greetPlayer = function()
	{
	if(!player.ship.isCloaked && (!player.ship.hasOwnProperty("gates_receivingGate") || player.ship.gates_receivingGate == null) && this.playerGreeted != true && this.allowGreeting == true)
		{
		player.consoleMessage("Welcome Commander, only 250Cr to use the jump gate system.", 6);
		this.playerGreeted = true;
		}
	}

this.findGates = function()
	{
	var gates = system.filteredEntities(this, gates_allGates, this.ship);	
	if(gates.length == 0)
		{
		this.ship.reactToAIMessage("NO_GATE");
		this.ship.scannerDisplayColor1 = "greenColor";
		this.ship.scannerDisplayColor2 = "orangeColor";
		}
	else
		{
		this.ship.reactToAIMessage("GATE_FOUND");
		this.ship.scannerDisplayColor1 = "greenColor";
		this.ship.scannerDisplayColor2 = "whiteColor";
		}
	};
	
this.underAttack = function()
	{
	if(this.defenderCount > 0 && worldScripts["gates_masterScript"] && worldScripts["gates_masterScript"].defenderAllowed())
		{
		var defender = this.ship.spawnOne("police");
		defender.position = this.ship.position;
		defender.orientation = this.ship.orientation;
		this.defenderCount -= 1;
		}
	}

this.npcTraders = function()
	{
	var outTraders = system.filteredEntities(this, gates_outboundNPCs); // list of outbound traders
	var inTraders = system.filteredEntities(this, gates_inboundNPCs); // list of inbound traders
	var gates = system.shipsWithRole("gates_jumpGate");

	if(gates.length < 2)
		{
		return;
		}

	if(inTraders.length > 0)
		{
		for(var i = 0; i < inTraders.length; i++)
			{
			if(Math.random() < 0.2 && gates.length > 0)
				{
				inTraders[i].target = gates[0];
				inTraders[i].script.checkGateDistance = this.checkGateDistance;
				inTraders[i].setAI("gates_useGateAI.plist");
				}
			}
		}

	if(outTraders.length > 0)
		{
		for(var i = 0; i < outTraders.length; i++)
			{
			if(Math.random() < 0.2 && gates.length > 0)
				{
				outTraders[i].target = gates[0];
				outTraders[i].script.checkGateDistance = this.checkGateDistance;
				outTraders[i].setAI("gates_useGateAI.plist");
				}
			}
		}
	}

// The function below is assigned to NPC ships using the jump gates

this.checkGateDistance = function()
	{	
	if(this.ship.position.distanceTo(this.ship.target.position) > 51200)
		{
		this.ship.reactToAIMessage("NEXT_GATE")
		}
	}
Scripts/gates_masterScript.js
this.name					= "gates_masterScript";
this.author					= "Thargoid";
this.copyright				= "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description			= "WorldScript for Gates OXP.";
this.version				= "1.13";

this.startUp = function()
	{
	this.defenderTime = clock.absoluteSeconds; 
	}
	

this.shipWillExitWitchspace = function()
	{
	if(system.isInterstellarSpace || system.sun.isGoingNova || system.sun.hasGoneNova) 
		{ // stop the script if interstellar space, or system is going Nova(to allow Nova mission unhindered) or indeed if it has gone nova already.
		return;
		}

	this.setUpGates();
	}

this.shipWillLaunchFromStation = function(station)
	{
	if(station.isMainStation)
		{
		this.setUpGates();
		delete this.shipWillLaunchFromStation;
		}
	}

this.setUpGates = function()
	{
	if(system.countShipsWithRole("gates_jumpGate") > 0 || system.techLevel < 7 || system.government < 4 || this.scrambledPseudoRandom(34.12) < 0.25)
		{
		return;
		}

	log("Adding jump gates to the " + system.name + " system");

	system.legacy_addShipsAt("gates_jumpGate", 1, "wpu", [0,0,0.02]);
      
    this.xOffset = (Math.random() * 10000); // x offset between 0 and 10km
	this.yOffset = (Math.random() * 10000); // y offset between 0 and 10km
	this.zOffset = (Math.random() * 25000) + 15000; // z offset between 15 and 40km

      if(Math.random() > 0.5) // 50:50 chance of offsetting in the other direction
         {
         this.xOffset = -this.xOffset;
         }
      if(Math.random() > 0.5) // 50:50 chance of offsetting in the other direction
         {
         this.yOffset = -this.yOffset;
         }
	
	if(system.mainStation)
		{ system.legacy_addShipsAtPrecisely("gates_jumpGate", 1, "abs", system.mainStation.position.subtract([this.xOffset, this.yOffset, this.zOffset]));}
	}

this.scrambledPseudoRandom = function(salt) // Ahruman's random number generator.
	{
    // Convert from float in [0..1) with 24 bits of precision to integer.
    var n = Math.floor(system.pseudoRandomNumber * 16777216.0);
   
    // Add salt to enable generation of different sequences.
    n += salt;
   
    // Scramble with basic LCG psuedo-random number generator.
    n = (214013 * n + 2531011) & 0xFFFFFFFF;
    n = (214013 * n + 2531011) & 0xFFFFFFFF;
    n = (214013 * n + 2531011) & 0xFFFFFFFF;
   
    // Convert from (effectively) 32-bit signed integer to float in [0..1).
    return n / 4294967296.0 + 0.5;
	};	
	
// the function below is referenced by the gates themselves via their own script, or are assigned to NPC ships using the gates.

this.defenderAllowed = function() 
	{ 
	if(this.defenderTime && (clock.absoluteSeconds - this.defenderTime) > 20) 
		{ 
		this.defenderTime = clock.absoluteSeconds; 
		return true; 
		} 
	else 
		{
		return false; 
		}
	}