Back to Index Page generated: Jul 10, 2025, 12:27:02 AM

Expansion Stations for Extra Planets Base

Content

Warnings

  1. Required Expansions mismatch between OXP Manifest and Expansion Manager at character position 0077 (DIGIT ZERO vs LATIN SMALL LETTER N)
  2. No version in dependency reference to oolite.oxp.spara.additional_planets_sr_base:null
  3. No version in dependency reference to oolite.oxp.phkb.MarketScriptInterface:null

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description Adds stations to extra planets with atmosphere. Requires Additional Planets oxp and at least one station pack. Adds stations to extra planets with atmosphere. Requires Additional Planets oxp and at least one station pack.
Identifier oolite.oxp.spara.stations_for_extra_planets oolite.oxp.spara.stations_for_extra_planets
Title Stations for Extra Planets Base Stations for Extra Planets Base
Category Dockables Dockables
Author spara spara
Version 2.1 2.1
Tags stations stations
Required Oolite Version
Maximum Oolite Version
Required Expansions
  • oolite.oxp.spara.additional_planets_sr_base:0
  • oolite.oxp.phkb.MarketScriptInterface:0
  • oolite.oxp.spara.additional_planets_sr_base:
  • oolite.oxp.phkb.MarketScriptInterface:
  • Optional Expansions
    Conflict Expansions
    Information URL http://wiki.alioth.net/index.php/Stations_for_Extra_Planets n/a
    Download URL https://wiki.alioth.net/img_auth.php/a/ad/Sfep_base_2.1.oxz n/a
    License CC-BY-NC-SA 4.0 CC-BY-NC-SA 4.0
    File Size n/a
    Upload date 1749450215

    Documentation

    Also read http://wiki.alioth.net/index.php/Stations%20for%20Extra%20Planets%20Base

    Equipment

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

    Ships

    Name
    sfep_template

    Models

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

    Scripts

    Path
    Config/script.js
    "use strict";
    this.name        = "stations_for_extra_planets";
    this.description = "populator for extra stations";
    
    /*
    	Dear oxp developer, it's totally possible to dynamically add stations to the mix. Just follow these instructions and all is well.
    
    	_Adding stations to the mix_
    
    	-decide which of your stations are coriolis, dodo and ico equivalents.
    	-create an array of arrays [[],[],[]] holding the rolenames of your stations so that in the first array there are your coriolises, in the second one dodos and in the third one icos.
    	-add your stations to the mix by calling worldScripts["stations_for_extra_planets"].$addStations(array_of_arrays_of_your_stations) during startUp.
    */
    
    this.$corStations = [];
    this.$dodStations = [];
    this.$icoStations = [];
    
    this.$roles = [];
    
    this.startUp = function() {
    	//register stations to have default markets of new cargoes
    	if (worldScripts.CargoTypeExtension)
    		worldScripts["CargoTypeExtension"].registerOXPStation("CargoTypeExtension-DefaultMarket","sfep_station");
    	
    	var msi = worldScripts.MarketScriptInterface_Main;
    	msi.$addMarketInterface("station_local", "sfep_updateLocalCommodityDefinition", this.name);
    };
    
    //public function for other oxps to add their stations to the oxp during the startUp. newStations-parameter is an array of three arrays [[],[],[]]. One for coriolises, one for dodos and one for icos.
    this.$addStations = function(newStations) {
    	this.$corStations = this.$corStations.concat(newStations[0]);
    	this.$dodStations = this.$dodStations.concat(newStations[1]);
    	this.$icoStations = this.$icoStations.concat(newStations[2]);
    }
    
    //sort sets once
    this.$runOnce = function() {
    	this.$corStations.sort();
    	this.$dodStations.sort();
    	this.$icoStations.sort();
    	//just to make sure no-one touches the critical arrays after the startUp.
    	delete this.$addStations;
    	delete this.$runOnce;
    }
    
    //additional planets oxp calls this at the start of the populate.
    this.initStationArray = function() {
    	if (this.$runOnce) this.$runOnce();
    	//match extra stations' types to main station type.
    	if (system.techLevel < 11)
    		this.$stations = this.$corStations.concat();
    	else
    		this.$stations = this.$corStations.concat(this.$dodStations, this.$icoStations);
    }
    
    //public function to set station populator. Call with planet coordinates and radius
    this.setStationPopulator = function(coords, radius, index) {
    	if (!this.$stations) this.initStationArray();
    	//sanity check of the array
    	if (this.$stations.length === 0) return;
    
    	//choose station
    	var stationInd = Math.floor(system.scrambledPseudoRandomNumber(coords[0]) * this.$stations.length);
    
    	//check station validator for possible deaths.
    	if (worldScripts.station_validator && (worldScripts.station_validator.$deaths(this.$stations[stationInd]).length !== 0))
    		return;
    
    	//add station to a random location around the planet
    	var polar = Math.PI * system.scrambledPseudoRandomNumber(coords[0]);
    	var azimuth = 2.0 * Math.PI * system.scrambledPseudoRandomNumber(coords[1]);
    	var directionV = Vector3D(Math.sin(polar) * Math.cos(azimuth), Math.sin(polar) * Math.sin(azimuth), Math.cos(polar));
    
    	//prevent the same station appearing multiple times in one system
    	var stationRole = this.$stations.splice(stationInd, 1);
    	this.$roles.push(stationRole[0]);
    
    	system.setPopulator("sfep_"+ (coords[0] + coords[1]), {
    		callback: function(pos) {
    			var addedStation = system.addShips(stationRole, 1, pos, 0)[0];
    
    			//orientate station dock to the planet just like main station
    			var targetVector = coords.subtract(pos ).direction();
    			var angle = addedStation.heading.angleTo(targetVector);
    			var cross = addedStation.heading.cross(targetVector).direction();
    			addedStation.orientation = addedStation.orientation.rotate(cross, -angle);
    
    			//add navigation buoy
    			var addedBuoy = system.addShips("buoy", 1, addedStation.position.add(addedStation.heading.multiply(10E3)),0)[0];
    			addedBuoy.scanClass = "CLASS_BUOY";
    			addedBuoy.displayName = addedStation.displayName + " Buoy";
    			addedBuoy.beaconCode = "N - " + addedBuoy.displayName;
    			addedBuoy.beaconLabel = addedStation.displayName;
    			//Cheyd's buoy has some special ai_code in it and needs to be excluded.
    			if (!addedBuoy.hasRole("DHINavBuoy")) {
    				addedBuoy.setAI("buoyAI.plist");
    				addedBuoy.reactToAIMessage("START_TUMBLING");
    			}
    		}.bind(this),
    		location: "COORDINATES",
    		coordinates: coords.add(directionV.multiply(2 * radius)),
    		deterministic: true,
    		priority: 102
    	});
    }
    
    this.sfep_updateLocalCommodityDefinition = function(goodDefinition, station) {
    
    	if (station && this.$roles.indexOf(station.primaryRole) >= 0) {
    		var distance = station.position.distanceTo(system.mainStation);
    
    		//scale max price difference with distance
    		//1000 km -> 0.05, 5000 km -> 0.15
    		var maxPriceDiff = 0.000000025 * distance + 0.025;
    		var priceDiff = Math.random() * maxPriceDiff;
    		
    		//cheaper or more expensive?
    		var coinToss = Math.round(Math.random());
    		if (coinToss === 0)  var priceMultiplier = 1 - priceDiff;
    		else var priceMultiplier = 1 + priceDiff;
    		
    		goodDefinition.price *= priceMultiplier;
    		
    		//scale quantity with random +/- 100 % scale
    		
    		var quantityDiff = Math.random();
    		var coinToss = Math.round(Math.random());
    		if (coinToss === 0) var quantityMultiplier = 1 - quantityDiff;
    		else var quantityMultiplier = 1 + quantityDiff;
    		
    		goodDefinition.quantity = Math.round(quantityMultiplier * goodDefinition.quantity);
    	}
    	return goodDefinition;
    };