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

Expansion Her Imperial Majesty's Space Navy

Content

Warnings

  1. Extreanous whitespace on key 'max_police '
  2. Unknown key 'upload_date' at https://wiki.alioth.net/img_auth.php/d/de/Himsn_0.9-alpha.oxz!manifest.plist

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description A more 'believable' Navy presence that sits more comfortably in the Ooniverse as many of us see it. The Navy is there if you go looking. If you do your normal trading, mining and bounty hunting you will never see them. They do not, under any circumstances, meddle in internal system politics. So, you will not be attacked by the Navy if you are an offender or even a fugitive for that matter. That is a police matter. A more 'believable' Navy presence that sits more comfortably in the Ooniverse as many of us see it. The Navy is there if you go looking. If you do your normal trading, mining and bounty hunting you will never see them. They do not, under any circumstances, meddle in internal system politics. So, you will not be attacked by the Navy if you are an offender or even a fugitive for that matter. That is a police matter.
Identifier oolite.oxp.tsoj.himsn oolite.oxp.tsoj.himsn
Title Her Imperial Majesty's Space Navy Her Imperial Majesty's Space Navy
Category Miscellaneous Miscellaneous
Author Gimi, Pleb, Keeper, Smivs, Cody, Disembodied, Cholmondely, cbr, Tsoj Gimi, Pleb, Keeper, Smivs, Cody, Disembodied, Cholmondely, cbr, Tsoj
Version 0.9 0.9
Tags
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
Conflict Expansions
Information URL http://wiki.alioth.net/index.php/Her_Imperial_Majesty%27s_Space_Navy n/a
Download URL https://wiki.alioth.net/img_auth.php/d/de/Himsn_0.9-alpha.oxz http://wiki.alioth.net/index.php/File:Himsn_0.9-alpha.oxz
License GPL v2+ / CC-BY-NC-SA 4.0 GPL v2+ / CC-BY-NC-SA 4.0
File Size n/a
Upload date 1642376758

Documentation

Also read http://wiki.alioth.net/index.php/Her%20Imperial%20Majesty's%20Space%20Navy

README.md

# Her Imperial Majesty's Space Navy

## An expansion pack for [Oolite](http://www.oolite.org/).

"A more 'believable' Navy presence that sits more comfortably in the Ooniverse as many of us see it. The problem with GN is that it's too big. Based on canon and lore, the war against the Thargoids is played out mostly in InterGalactic space, and therefore you wouldn't expect to find a big naval presence in 'normal' space. There would not be navy ships all over the place (clogging up the spacelanes!) and the idea of numerous naval bases (SecComs) in each Galaxy also seems a bit silly. These stations also skew the game quite badly due to their market economics. Also, GN often focuses on pirates, and there is no justification for this within the game - that's what the GalCop Police are for.

We are talking about an OXP which adds a much more discrete (and believable) naval presence, with a more appropriate range of ships. It may in time also offer missions similar to the two in-built missions involving HIMSN: small, covert special-ops type missions rather than the somewhat repetitive mass shoot-em-ups that GN offers.

The Navy is there if you go looking. If you do your normal trading, mining and bounty hunting you will never see them. They do not, under any circumstances, meddle in internal system politics. So, you will not be attacked by the Navy if you are an offender or even a fugitive for that matter. That is a police matter."

[Wiki](http://wiki.alioth.net/index.php/Her_Imperial_Majesty%27s_Space_Navy)


## License
GPL v2+  
CC-BY-NC-SA 4.0

**Authors**:  
*Gimi  
Pleb  
Keeper  
Smivs  
Cody  
Disembodied  
Cholmondely  
Tsoj  
cbr*

## Development plan

**Stage 1 - Eye Candy only:**
- [x] Navy units from the core ship-set.
- [x] Navy stations. (HQ and Outpost)
- [x] Basic scripting and and AI behaviour.

**Stage 2 - Thargoid Interaction:**
- [ ] War zones with the Thargoids
- [x] Capital ships
- [ ] Yearly Parade
- [ ] Additional stations (Navy Shipyard and maybe some mission related type of station)
- [ ] Intelligence/Special Operations type ships (e.g. production model of the Constrictor)
    - [ ] AI behaviour

**Stage 3 - Missions:**
- [ ] Player Missions
  

Equipment

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

Ships

Name
himsn_adv_patrol_asp
himsn_adv_patrol_boa_mk2
himsn_adv_patrol_constrictor
Imperial Navy Anaconda
Imperial Navy Asp Mark II
Imperial Navy Boa Class Cruiser
Imperial Navy Constrictor
himsn_defender
himsn_escort
himsn_escort_anaconda
himsn_escort_asp
Imperial Navy Headquarters
himsn_heavy_patrol_leader
Imperial Navy Outpost
Kiota Comms Array
Kiota Disc
Kiota Dock Ring (Hidden)
Kiota Lift
Kiota Small Ring
Kiota Spur
Kiota Strut
Kiota Turret
Imperial Navy Carrier (Komodo Class)
Docking Slit (horizontal)
himsn_light_patrol_leader
himsn_logistics_transport
himsn_misjumper
himsn_missile_corvette
Imperial Navy Sidewinder
Navy Special Ops Asp Mark II
Navy Intelligence Constrictor
Imperial Navy Base

Models

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

Scripts

Path
Scripts/himsn_adv_patrol.js
"use strict";

this.name 			= "himsn_adv_patrol";
this.author         = "Pleb";
this.copyright      = "(C) 2014 Pleb.";
this.licence        = "CC-NC-by-SA 4.0";
this.version 		= "0.9-alpha";

this._generateDestination = function ()
{
	var thisSystem = system.info;
	var targetSystems = SystemInfo.systemsInRange(7);
	if (!targetSystems) return system.ID;
	var count = targetSystems.length;
	var targetSystem = targetSystems[Math.floor(Math.random()*count)];
	var realDistance = System.infoForSystem(galaxyNumber, targetSystem.systemID).routeToSystem(thisSystem).distance;
	var i = 0;
	while ((!realDistance || realDistance > 7) && i<count)
	{
		targetSystem = targetSystems[i++];
		realDistance = System.infoForSystem(galaxyNumber, targetSystem.systemID).routeToSystem(thisSystem).distance;
	}
	return targetSystem.systemID;
}

this.shipSpawned = function ()
{
	if (!missionVariables.himsn_adv_patrol_mission)
	{
		this.ship.destinationSystem = this._generateDestination();
		missionVariables.himsn_adv_patrol_dest = this.ship.destinationSystem;
		missionVariables.himsn_adv_patrol_home = this.ship.homeSystem;
		if (Math.random() < 0.5)
		{
			missionVariables.himsn_adv_patrol_mission = 0;
		}
		else
		{
			missionVariables.himsn_adv_patrol_mission = 1;
		}
		this.ship.awardEquipment("EQ_FUEL_SCOOPS");
		this.ship.awardEquipment("EQ_HEAT_SHIELD");
	}
	else
	{
		this.ship.destinationSystem = missionVariables.himsn_adv_patrol_dest;
		this.ship.homeSystem = missionVariables.himsn_adv_patrol_home;
	}
	
	// Use Escort Formations OXP if installed for random flight formations:
	if (worldScripts["Escort Formations Randomiser"])
	{
		worldScripts["Escort Formations Randomiser"].$setupDefensiveEscorts(this.ship);
	}
}

this.helpRequestReceived = function(ally, enemy)
{
	this.ship.destination = ally.position;
	this.ship.target = enemy;
	this.ship.performAttack();
}

this.shipBeingAttacked = function(whom)
{
	if (whom.scanClass != "CLASS_MILITARY")
	{
		this.ship.target = whom;
		this.ship.requestHelpFromGroup();
		system.filteredEntities(this, function (entity)
		{
			if (entity.scanClass == "CLASS_MILITARY")
			{
				entity.target = whom;
				entity.performAttack();
			}
			if (entity.isStation && entity.hasRole("himsn_station"))
			{
				entity.alertCondition = 3;
				entity.launchDefenseShip();
			}
		});
	}
}
Scripts/himsn_carrier.js
"use strict";

this.name 			= "himsn_carrier";
this.author         = "Pleb";
this.copyright      = "(C) 2014 Pleb.";
this.licence        = "CC-NC-by-SA 4.0";
this.version 		= "0.9-alpha";

this.shipSpawned = function ()
{
	this.ship.awardEquipment("EQ_FUEL_SCOOPS");
	this.ship.awardEquipment("EQ_HEAT_SHIELD");
	
	this.ship.shipUniqueName = "HIMSS "+expandDescription("[himsn_carrier_names]");
	missionVariables.himsn_carrier_name = this.ship.shipUniqueName;
	
	// Use Escort Formations OXP if installed for random flight formations:
	if (worldScripts["Escort Formations Randomiser"])
	{
		worldScripts["Escort Formations Randomiser"].$setupDefensiveEscorts(this.ship);
	}
}

this.helpRequestReceived = function(ally, enemy)
{
	this.ship.destination = ally.position;
	this.ship.target = enemy;
	this.ship.performAttack();
}

this.shipBeingAttacked = function(whom)
{
	if (whom.scanClass != "CLASS_MILITARY")
	{
		this.ship.target = whom;
		this.ship.requestHelpFromGroup();
		system.filteredEntities(this, function (entity)
		{
			if (entity.scanClass == "CLASS_MILITARY")
			{
				entity.target = whom;
				entity.performAttack();
			}
			if (entity.isStation && entity.hasRole("himsn_station"))
			{
				entity.alertCondition = 3;
				entity.launchDefenseShip();
			}
		});
	}
}
Scripts/himsn_carrier_dock.js
"use strict";

this.name 			= "himsn_carrier_dock";
this.author         = "Pleb";
this.copyright      = "(C) 2014 Pleb.";
this.licence        = "CC-NC-by-SA 4.0";
this.version 		= "0.9-alpha";

this.shipSpawned = function ()
{
	this.ship.allowsDocking = true;
}

this.acceptDockingRequestFrom = function(ship)
{
	if (ship.isPlayer)
	{
		return false;
	}
	else
	{
		return true;
	}
}
Scripts/himsn_constrictor_conditions.js
"use strict";

this.name           = "himsn_constrictor_conditions";
this.author         = "Pleb";
this.copyright      = "(C) 2014 Pleb.";
this.licence        = "CC-NC-by-SA 4.0";
this.description    = "This is the conditions script for the HIMSN Constrictor.";
this.version        = "0.9-alpha";

this.allowSpawnShip = function(shipKey)
{
	if (missionVariables.conhunt == "MISSION_COMPLETE" && missionVariables.thargplans == "MISSION_COMPLETE")
	{
		return true;
	}
	else
	{
		return false;
	}
}
Scripts/himsn_main.js
this.name           = "himsn_main";
this.author         = "Pleb";
this.copyright      = "(C) 2014 Pleb.";
this.licence        = "CC-NC-by-SA 4.0";
this.description    = "This is the main worldscript for the HIMSN OXZ.";
this.version        = "0.9-alpha";

"use strict";

// TODO add logging

/**** Functions ****/

this._addAdvPatrol = function()
{
	this._addAdvPatrolSwitch = true;
}

this._addAdvPatrolShips = function(pos)
{
	var advPatrol = system.addShips("himsn_adv_patrol",1,pos,0);
	if (system.ID == missionVariables.himsn_adv_patrol_home) 
	{
		advPatrol.maxEscorts = Math.floor(Math.random() * (4 - 0 + 1) + 0);
	}
}

//TODO why is this never used?
this._addAdvEscort = function()
{
	var pos = system.locationFromCode("WITCHPOINT");
	system.addGroup("himsn_logistics_transport", 1, pos, 0);
}

this._launchAdvPatrol = function()
{
	if (system.ID == -1) return;
	var navyStat = null;
	system.filteredEntities(this, function (entity)
	{
		if (entity.isStation)
		{
			if (entity.hasRole("himsn_station"))
			{
				navyStat = entity;
			}
		}
	});
	if (navyStat)
	{
		navyStat.launchShipWithRole("himsn_adv_patrol", [true]);
		this._advPatrolTimer_3.stop();
		this._advPatrolTimer_3 = new Timer(this,this._launchAdvPatrol,900);
	}
}

//TODO why is this never used?
this._addNavyBattleFleet = function(pos)
{
	// Add Navy Carrier and defending fleet:
	var navyCarrier = system.addShips("himsn_komodo_carrier",1,pos,0)[0];
	var targetVector = system.mainPlanet.position.subtract(navyCarrier.position).direction();
	navyCarrier.orientation = targetVector.rotationTo([0,0,1]);
	navyCarrier.maxEscorts = 16;
	var navyCarrierSidewinders = system.addShips("himsn_escort",8,pos,500);
	var navyCarrierAsps = system.addShips("himsn_escort_asp",5,pos,500);
	var navyCarrierAnacondas = system.addShips("himsn_escort_anaconda",3,pos,500);
	navyCarrierSidewinders[0].orientation = targetVector.rotationTo([0,0,1]);
	navyCarrierSidewinders[0].primaryRole = "escort";
	navyCarrier.escortGroup.addShip(navyCarrierSidewinders[0]);
	navyCarrierSidewinders[0].switchAI("himsn_escort_ai.js");
	navyCarrierSidewinders[1].orientation = targetVector.rotationTo([0,0,1]);
	navyCarrierSidewinders[1].primaryRole = "escort";
	navyCarrier.escortGroup.addShip(navyCarrierSidewinders[1]);
	navyCarrierSidewinders[1].switchAI("himsn_escort_ai.js");
	navyCarrierSidewinders[2].orientation = targetVector.rotationTo([0,0,1]);
	navyCarrierSidewinders[2].primaryRole = "escort";
	navyCarrier.escortGroup.addShip(navyCarrierSidewinders[2]);
	navyCarrierSidewinders[2].switchAI("himsn_escort_ai.js");
	navyCarrierSidewinders[3].orientation = targetVector.rotationTo([0,0,1]);
	navyCarrierSidewinders[3].primaryRole = "escort";
	navyCarrier.escortGroup.addShip(navyCarrierSidewinders[3]);
	navyCarrierSidewinders[3].switchAI("himsn_escort_ai.js");
	navyCarrierSidewinders[4].orientation = targetVector.rotationTo([0,0,1]);
	navyCarrierSidewinders[4].primaryRole = "escort";
	navyCarrier.escortGroup.addShip(navyCarrierSidewinders[4]);
	navyCarrierSidewinders[4].switchAI("himsn_escort_ai.js");
	navyCarrierSidewinders[5].orientation = targetVector.rotationTo([0,0,1]);
	navyCarrierSidewinders[5].primaryRole = "escort";
	navyCarrier.escortGroup.addShip(navyCarrierSidewinders[5]);
	navyCarrierSidewinders[5].switchAI("himsn_escort_ai.js");
	navyCarrierSidewinders[6].orientation = targetVector.rotationTo([0,0,1]);
	navyCarrierSidewinders[6].primaryRole = "escort";
	navyCarrier.escortGroup.addShip(navyCarrierSidewinders[6]);
	navyCarrierSidewinders[6].switchAI("himsn_escort_ai.js");
	navyCarrierSidewinders[7].orientation = targetVector.rotationTo([0,0,1]);
	navyCarrierSidewinders[7].primaryRole = "escort";
	navyCarrier.escortGroup.addShip(navyCarrierSidewinders[7]);
	navyCarrierSidewinders[7].switchAI("himsn_escort_ai.js");
	navyCarrierAsps[0].orientation = targetVector.rotationTo([0,0,1]);
	navyCarrierAsps[0].primaryRole = "escort";
	navyCarrier.escortGroup.addShip(navyCarrierAsps[0]);
	navyCarrierAsps[0].switchAI("himsn_escort_ai.js");
	navyCarrierAsps[1].orientation = targetVector.rotationTo([0,0,1]);
	navyCarrierAsps[1].primaryRole = "escort";
	navyCarrier.escortGroup.addShip(navyCarrierAsps[1]);
	navyCarrierAsps[1].switchAI("himsn_escort_ai.js");
	navyCarrierAsps[2].orientation = targetVector.rotationTo([0,0,1]);
	navyCarrierAsps[2].primaryRole = "escort";
	navyCarrier.escortGroup.addShip(navyCarrierAsps[2]);
	navyCarrierAsps[2].switchAI("himsn_escort_ai.js");
	navyCarrierAsps[3].orientation = targetVector.rotationTo([0,0,1]);
	navyCarrierAsps[3].primaryRole = "escort";
	navyCarrier.escortGroup.addShip(navyCarrierAsps[3]);
	navyCarrierAsps[3].switchAI("himsn_escort_ai.js");
	navyCarrierAsps[4].orientation = targetVector.rotationTo([0,0,1]);
	navyCarrierAsps[4].primaryRole = "escort";
	navyCarrier.escortGroup.addShip(navyCarrierAsps[4]);
	navyCarrierAsps[4].switchAI("himsn_escort_ai.js");
	navyCarrierAnacondas[0].orientation = targetVector.rotationTo([0,0,1]);
	navyCarrierAnacondas[0].primaryRole = "escort";
	navyCarrier.escortGroup.addShip(navyCarrierAnacondas[0]);
	navyCarrierAnacondas[0].switchAI("himsn_escort_ai.js");
	navyCarrierAnacondas[1].orientation = targetVector.rotationTo([0,0,1]);
	navyCarrierAnacondas[1].primaryRole = "escort";
	navyCarrier.escortGroup.addShip(navyCarrierAnacondas[1]);
	navyCarrierAnacondas[1].switchAI("himsn_escort_ai.js");
	navyCarrierAnacondas[2].orientation = targetVector.rotationTo([0,0,1]);
	navyCarrierAnacondas[2].primaryRole = "escort";
	navyCarrier.escortGroup.addShip(navyCarrierAnacondas[2]);
	navyCarrierAnacondas[2].switchAI("himsn_escort_ai.js");
}

this._addNavyHeadquarters = function(pos)
{
	// Add Navy Headquaters and defending fleet:
	navyStation = system.addShips("himsn_headquarters",1,pos,0)[0];
	var navyStationGroup = system.addGroup("himsn_defender",5,pos,8000);
	navyStationGroup.leader = navyStation;
	navyStationGroup.addShip(navyStation);
}

this._addNavySystemBase = function(pos)
{
	// Add Navy Sysytem Base and defending fleet:
	navyStation = system.addShips("himsn_system_base",1,pos,0)[0];
	var targetVector = system.mainPlanet.position.subtract(navyStation.position).direction();
	navyStation.orientation = targetVector.rotationTo([0,0,1]);
	var navyStationGroup = system.addGroup("himsn_defender",3,pos,8000);
	navyStationGroup.leader = navyStation;
	navyStationGroup.addShip(navyStation);
}

this._addNavyInterstellarOutpost = function(pos)
{
	// Add Navy Interstellar Outpost and defending fleet:
	navyStation = system.addShips("himsn_interstellar_outpost",1,pos,0)[0];
	var navyStationGroup = system.addGroup("himsn_defender",3,pos,8000);
	navyStationGroup.leader = navyStation;
	navyStationGroup.addShip(navyStation);
}

this._addNavyPatrol = function (pos)
{
	// 50% chance patrol is heavy or light:
	var patrol;
	if (Math.random() < 0.5)
	{
		if (missionVariables.conhunt == "MISSION_COMPLETE" && missionVariables.thargplans == "MISSION_COMPLETE")
		{
			if (Math.random() < 0.5)
			{
				patrol = "himsn_heavy_patrol_leader";
			}
			else
			{
				patrol = "himsn_missile_corvette";
			}
		}
		else
		{
			patrol = "himsn_light_patrol_leader";
		}
	}
	else
	{
        patrol = "himsn_light_patrol_leader";
	}
	// Add a Navy Patrol:
	system.addGroup(patrol, 1, pos, 0);
}

//TODO why is this never used?
this._addNavyLogisticsTransport = function (pos)
{
	// Add a Navy Logistics Transport:
	system.addGroup("himsn_logistics_transport", 1, pos, 0);
}

//TODO why is this never used?
this._addNavyMissileCorvette = function (pos)
{
	// Add a Navy Missile Corvette:
	system.addGroup("himsn_missile_corvette", 1, pos, 0);
}

this._addNavySpecOpsRecon = function (pos)
{
	// Only add recon (constrictor) if 'Constrictor Hunt' and 'Thargoid Plans' missions are complete:
	if (missionVariables.conhunt == "MISSION_COMPLETE" && missionVariables.thargplans == "MISSION_COMPLETE")
	{
		// Add a Navy Recon:
		system.addGroup("himsn_specops_recon", 1, pos, 0);
	}
}

this._addNavySpecOpsFighter = function (pos)
{
	// Add 3x Navy Spec Ops Fighter:
	system.addGroup("himsn_specops_asp", 3, pos, 0);
}

this._checkIfHostilePeriodIsOver = function ()
{
	// Check if player is considered an enemy of HIMSN and 60 days have passed since being declared an enemy:
	if (missionVariables.himsn_status == "HOSTILE" && clock.adjustedSeconds >= missionVariables.himsn_status_timer)
	{
		missionVariables.himsn_status = "NEUTRAL";
	}
}

this._checkPlayerAngle = function() 
{
	// Check angle for galactic misjump:
	this._oldPlayerAngle = player.ship.vectorForward.direction();
}

this._checkPlayerPitch = function() 
{
	// Check pitch for galactic misjump:
	if (player.ship.pitch) 
	{
		if (player.ship.pitch >= 0.95 || player.ship.pitch <= -0.95) 
		{
			return true;
		} 
		else 
		{
			return false;
		}
	} 
	else 
	{
		var angle = this._oldPlayerAngle.dot(player.ship.vectorForward.direction());
		if (angle < 0.95) 
		{
			return true;
		} 
		else 
		{
			return false;
		}
	}
}

this._checkPlayerMisjump = function() 
{
	// Check pitch for galactic misjump:
	if (this._checkPlayerPitch()) 
	{
		// If pitch okay for misjump then prepare to send player to intergalactic space:
		var jumper = system.addShips("himsn_misjumper",1,[15E5,15E5,15E5],1)[0];
		jumper.scriptedMisjump = true;
		if (jumper.exitSystem()) {
				player.ship.position = [15E5,15E5,15E5];
				this._galacticMisjump = true;
				player.ship.setEquipmentStatus("EQ_GAL_DRIVE","EQUIPMENT_DAMAGED");
		}
	} 
	else 
	{
		// If pitch normal then perform normal galactic jump:
		this._galacticMisjump = false;
		player.ship.scriptedMisjump = false;
	}
}

this._resetGalacticMisjump = this.shipWillEnterWitchspace = function() 
{
	// Reset galactic misjump:
	if (!this._galacticMisjump && System.infoForSystem(galaxyNumber,player.ship.targetSystem).name == "Intergalactic space") 
	{
		System.infoForSystem(galaxyNumber,player.ship.targetSystem).name = null;
	} 
	else if (this._galacticMisjump) 
	{
		player.ship.scriptedMisjump = true;
	}
}

this._repairGalacticHyperDrive = function() 
{
	// Repair galactic hyperdrive when 5 minutes are up:
	player.ship.setEquipmentStatus("EQ_GAL_DRIVE","EQUIPMENT_OK");
	player.consoleMessage("Galactic Hyperdrive recalibration complete. Remaining charge sufficient to complete jump.",10);
}

/**** Event handlers ****/

this.startUp = function ()
{
	//Reset Galactic Misjump variable:
	this._galacticMisjump = false;
	// Check if HIMSN OXZ has run before:
	if (missionVariables.himsn_status == null)
	{
		// Set up internal OXZ variables:
		missionVariables.himsn_status = "NEUTRAL";
		missionVariables.himsn_status_timer = clock.adjustedSeconds;
	}
}

this.playerStartedJumpCountdown = function (type,delay)
{
	if (type == "galactic")
	{
		// Setup timers for Galactic Misjump:
		this._galacticMisjumpTimer2 = new Timer(this,this._checkPlayerAngle,delay-0.5);
		this._galacticMisjumpTimer = new Timer(this,this._checkPlayerMisjump,delay-0.1);
	}
	else if (this._galacticMisjump)
	{
		// Force player to misjump:
		player.ship.scriptedMisjump = true;
	}
	else
	{
		// Reset Galactic Misjump variable:
		this._galacticMisjump = false;
	}
}

this.playerCancelledJumpCountdown = function() 
{
	// Stop and remove Galactic Misjump timers if jump is cancelled:
	if (this._galacticMisjumpTimer) 
	{
		this._galacticMisjumpTimer.stop();
		delete this._galacticMisjumpTimer;
	}
	if (this._galacticMisjumpTimer2) 
	{
		this._galacticMisjumpTimer2.stop();
		delete this._galacticMisjumpTimer2;
	}
}

this.shipWillEnterWitchspace = function (cause)
{
	this._interstellarBaseLocation = false;
	this._headquartersLocation = false;
	// Check if about to jump into interstellar space in between Tetiri and Orlaed in G5:
	if(galaxyNumber == 4 && ((system.ID == 70 && player.ship.targetSystem == 161) || (system.ID == 161 && player.ship.targetSystem == 70)  || (system.ID == 70 && player.ship.targetSystem == 70) || (system.ID == 161 && player.ship.targetSystem == 161)))
	{
		this._headquartersLocation = true;
	}
	// Check if about to jump into interstellar space in between Legees and Laeden in G1:
	if(galaxyNumber == 0 && ((system.ID == 26 && player.ship.targetSystem == 224) || (system.ID == 224 && player.ship.targetSystem == 26)  || (system.ID == 26 && player.ship.targetSystem == 26) || (system.ID == 224 && player.ship.targetSystem == 224)))
	{
		this._interstellarBaseLocation = true;
	}
	// Check if about to jump into interstellar space in between Raried and Maracece in G3:
	if(galaxyNumber == 2 && ((system.ID == 4 && player.ship.targetSystem == 123) || (system.ID == 123 && player.ship.targetSystem == 4)  || (system.ID == 4 && player.ship.targetSystem == 4) || (system.ID == 123 && player.ship.targetSystem == 123)))
	{
		this._interstellarBaseLocation = true;
	}
	// Check if about to jump into interstellar space in between Riusbequ and Quzaarar in G4:
	if(galaxyNumber == 3 && ((system.ID == 217 && player.ship.targetSystem == 221) || (system.ID == 221 && player.ship.targetSystem == 217)  || (system.ID == 217 && player.ship.targetSystem == 217) || (system.ID == 221 && player.ship.targetSystem == 221)))
	{
		this._interstellarBaseLocation = true;
	}
	// Check if about to jump into interstellar space in between Gexequon and Edtizabe in G8:
	if(galaxyNumber == 7 && ((system.ID == 144 && player.ship.targetSystem == 247) || (system.ID == 247 && player.ship.targetSystem == 144)  || (system.ID == 144 && player.ship.targetSystem == 144) || (system.ID == 247 && player.ship.targetSystem == 247)))
	{
		this._interstellarBaseLocation = true;
	}
	if (this._advPatrolTimer_3)
	{
		this._advPatrolTimer_3.stop();
		delete this._advPatrolTimer_3;
	}
}

this.shipWillExitWitchspace = function ()
{
	// Check if player is considered an enemy of HIMSN and 60 days have passed since being declared an enemy:
	this._checkIfHostilePeriodIsOver();
	
	// If player is not jumping into interstellar space make sure galactic misjump variable is reset:
	if (!system.isInterstellarSpace) 
	{
		this._galacticMisjump = false;
	}
	
	// Check if a Galactic Misjump is about to occur:
	if (this._galacticMisjump) 
	{
		// Delete oolite populator scripts:
		delete worldScripts["oolite-populator"].interstellarSpaceWillPopulate;
		delete worldScripts["oolite-populator"].interstellarSpaceWillRepopulate;
		// Set a timer for 2 minutes to recharge galactic hyperdrive:
		this._galacticMisjumpTimer.stop();
		this._galacticMisjumpTimer = new Timer(this,this._repairGalacticHyperDrive,120);
		// Set name for area:
		System.infoForSystem(galaxyNumber,player.ship.targetSystem).name = "Intergalactic space";
		// Adjust player's position to new area of interstellar space:
		player.ship.position = [0,0,1E6];
		// 80% chance of 2x light patrols vs 4-6 thargoids:
		if (Math.random() < 0.8)
		{
			system.addShips("himsn_light_patrol_leader",2,[0,0,1E6],5000);
			system.addShips("thargoid",4+Math.floor(Math.random() * (2 - 0 + 1) + 10),[0,0,1E6],5000);
		}
		// Else 70% chance of 2x heavy patrols vs 6-8 thargoids:
		else if (Math.random() < 0.7)
		{
			if (missionVariables.conhunt == "MISSION_COMPLETE" && missionVariables.thargplans == "MISSION_COMPLETE")
			{
				if (Math.random() < 0.5)
				{
					system.addShips("himsn_heavy_patrol_leader",2,[0,0,1E6],5000);
				}
				else
				{
					system.addShips("himsn_missile_corvette",2,[0,0,1E6],5000);
				}
			}
			else
			{
				system.addShips("himsn_light_patrol_leader",2,[0,0,1E6],5000);
			}
			system.addShips("thargoid",6+Math.floor(Math.random() * (2 - 0 + 1) + 10),[0,0,1E6],5000);
		}
		// If none of the above then just player vs 2-4 thargoids:
		else
		{
			system.addShips("thargoid",2+Math.floor(Math.random() * (2 - 0 + 1) + 10),[0,0,1E6],5000);
		}
		// 30% chance a rogue planet will be spawned:
		if (Math.random() < 0.3)
		{
			// Choose one of eight planets to spawn: 
			var planetchance = Math.random();
			var igPlanet;
			if ((planetchance <= 1) && (planetchance > 0.875)) igPlanet = system.addMoon("himsn_rogue_planet_1");
			if ((planetchance <= 0.875) && (planetchance > 0.75)) igPlanet = system.addMoon("himsn_rogue_planet_2");
			if ((planetchance <= 0.75) && (planetchance > 0.625)) igPlanet = system.addMoon("himsn_rogue_planet_3");
			if ((planetchance <= 0.625) && (planetchance > 0.5)) igPlanet = system.addMoon("himsn_rogue_planet_4");
			if ((planetchance <= 0.5) && (planetchance > 0.375)) igPlanet = system.addMoon("himsn_rogue_planet_5");
			if ((planetchance <= 0.375) && (planetchance > 0.25)) igPlanet = system.addMoon("himsn_rogue_planet_6");
			if ((planetchance <= 0.25) && (planetchance > 0.125)) igPlanet = system.addMoon("himsn_rogue_planet_7");
			if (planetchance <= 0.125) igPlanet = system.addMoon("himsn_rogue_planet_8");
			// 10% chance a navy outpost will be spawned in orbit around planet:
			if (Math.random() < 0.1)
			{
				var planetToStation = Vector3D.randomDirection(2 * igPlanet.radius);
				var igNavyStat = system.addShips("himsn_interstellar_outpost", 1, igPlanet.position.add(planetToStation))[0];
				targetVector = igPlanet.position.subtract(igNavyStat.position).direction();
				angle = igNavyStat.heading.angleTo(targetVector);
				cross = igNavyStat.heading.cross(targetVector).direction();
				igNavyStat.orientation = igNavyStat.orientation.rotate(cross, -angle);
			}
		}
	}
}

this.shipExitedWitchspace = function() 
{
	if (missionVariables.himsn_adv_patrol_dest && system.ID == missionVariables.himsn_adv_patrol_dest && system.countShipsWithRole("himsn_adv_patrol") == 0)
	{
		this._advPatrolTimer_1 = new Timer(this,this._addAdvPatrol,30);
	}
	
	if (this._galacticMisjump) 
	{
		if (!system.isInterstellarSpace) 
		{
			// If player has managed to escape Intergalactic Space the reset galactic misjump variables:
			this._galacticMisjump = false;
			this._resetGalacticMisjump();
		} 
		else 
		{
			// Warn player that Galactic Hyperdrive has malfunctioned:
			if (player.ship.equipmentStatus("EQ_GAL_DRIVE") == "EQUIPMENT_DAMAGED")
			{
				player.consoleMessage("WARNING! Galactic Hyperdrive Malfunction!",10);
				player.consoleMessage("Attempting recalibration with remaining charge...",5);
			}
			player.ship.scriptedMisjump = true;
		}
	}
}

this.guiScreenChanged = function(from,to) 
{
	// Disable short & long range charts and planet info screens:
	if (this._galacticMisjump) 
	{
		if (guiScreen == "GUI_SCREEN_SYSTEM_DATA" || guiScreen == "GUI_SCREEN_SHORT_RANGE_CHART" || guiScreen == "GUI_SCREEN_LONG_RANGE_CHART") 
		{
			mission.runScreen({
				title: "Critical Error",
				message: "Unable to determine location - Cannot load Galactic Chart data."
			});
		}
	}
}

this.shipWillLaunchFromStation = function (station)
{
	// Check if player is considered an enemy of HIMSN and 60 days have passed since being declared an enemy:
	this._checkIfHostilePeriodIsOver();
}

this.interstellarSpaceWillPopulate = function () 
{
	// 15% chance of light patrol encounter:
	var lightpatrolchance = 0.15;
	// 10% chance of heavy patrol encounter:
	var heavypatrolchance = 0.1;
	
	// Add Navy Outpost at designated zero distance locations:
	if (system.ID == -1 && this._interstellarBaseLocation)
	{
		delete worldScripts["oolite-populator"].interstellarSpaceWillPopulate;
		delete worldScripts["oolite-populator"].interstellarSpaceWillRepopulate;
		system.setPopulator("himsn-interstellar-base",
		{
			priority: 200,
			location: "WITCHPOINT",
			groupCount: 1,
			callback: this._addNavyInterstellarOutpost,
			deterministic: true
		});
	}
	else if (system.ID == -1 && this._headquartersLocation)
	{
		delete worldScripts["oolite-populator"].interstellarSpaceWillPopulate;
		delete worldScripts["oolite-populator"].interstellarSpaceWillRepopulate;
		system.setPopulator("himsn-headquarters",
		{
			priority: 200,
			location: "WITCHPOINT",
			groupCount: 1,
			callback: this._addNavyHeadquarters,
			deterministic: true
		});
	}
	// If in interstellar space with no outpost:
	else 
	{
		// 2x heavy patrols vs 6x thargoids:
		if(Math.random() < heavypatrolchance)
		{
			var heavy_patrol;
			if (Math.random() < 0.5)
			{
				heavy_patrol = "himsn_light_patrol_leader";
			}
			else
			{
				heavy_patrol = "himsn_missile_corvette";
				if (missionVariables.conhunt == "MISSION_COMPLETE" && missionVariables.thargplans == "MISSION_COMPLETE")
				{
					if (Math.random() < 0.5)
					{
						heavy_patrol = "himsn_heavy_patrol_leader";
					}
				}
			}
			system.setPopulator("himsn-interstellar-heavy-escort",
			{
				priority: 210,
				location: "WITCHPOINT",
				groupCount: 2,
				callback: function(pos) {
					system.addShips(heavy_patrol,2,pos,0);
				}
			});
			system.setPopulator("himsn-interstellar-heavy-escort-thargoids",
			{
				priority: 210,
				location: "WITCHPOINT",
				groupCount: 6,
				callback: function(pos) {
					system.addShips("thargoid",1,pos,0);
				}
			});
		}
		// 2x light patrols vs 4x thargoids:
		else if(Math.random() < lightpatrolchance)
		{
			system.setPopulator("himsn-interstellar-light-escort",
			{
				priority: 210,
				location: "WITCHPOINT",
				groupCount: 2,
				callback: function(pos) {
					system.addShips("himsn_light_patrol_leader",1,pos,0);
				}
			});
			system.setPopulator("himsn-interstellar-light-escort-thargoids",
			{
				priority: 210,
				location: "WITCHPOINT",
				groupCount: 4,
				callback: function(pos) {
					system.addShips("thargoid",1,pos,0);
				}
			});
		}
	}
}

this.systemWillPopulate = function () 
{
	// 3% chance of patrol appearing:
	var patrolchance = 0.03;
	// 0.2% chance of recon appearing:
	var reconchance = 0.002;
	
	// Check if player is hostile to navy:
	if (missionVariables.himsn_status == "HOSTILE")
	{
		// 30% chance special ops fighters waiting for player at witchpoint & station aegis:
		if (Math.random() < 0.3)
		{
			system.setPopulator("himsn-specops-fighter-witchpoint",
			{
				priority: 200,
				location: "WITCHPOINT",
				groupCount: 1,
				callback: this._addNavySpecOpsFighter,
				deterministic: true
			});
			system.setPopulator("himsn-specops-fighter-station",
			{
				priority: 200,
				location: "STATION_AEGIS",
				groupCount: 1,
				callback: this._addNavySpecOpsFighter,
				deterministic: true
			});
		}
	}
	
	// Add Navy Base to Birera (G3) and Xeer (G1):
	if ((galaxyNumber == 0 && system.ID == 150) || (galaxyNumber == 2 && system.ID == 36))
	{
		system.setPopulator("himsn-system-base",
		{
			priority: 200,
			location: "STAR_ORBIT",
			locationSeed: 67812,
			groupCount: 1,
			callback: this._addNavySystemBase,
			deterministic: true
		});
		// 5% chance of patrol appearing:
		patrolchance = 0.05;
		// 0.5% chance of recon appearing:
		reconchance = 0.005;
		// 3% chance of another patrol appearing on any lane:
		if (Math.random() < 0.03)
		{
			system.setPopulator("himsn-extra-patrol-2",
			{
				priority: 210,
				location: "LANE_WPS",
				groupCount: 1,
				callback: this._addNavyPatrol
			});
		}
	}
	
	// Add patrol on witchpoint-sun lane:
	if (Math.random() < patrolchance)
	{
		system.setPopulator("himsn-patrol",
		{
			priority: 210,
			location: "LANE_WS",
			groupCount: 1,
			callback: this._addNavyPatrol
		});
	}
	
	// Add recon on any lane:
	if (Math.random() < reconchance)
	{
		system.setPopulator("himsn-specops-recon",
		{
			priority: 210,
			location: "LANE_WPS",
			groupCount: 1,
			callback: this._addNavySpecOpsRecon
		});
	}
}

this.systemWillRepopulate = function()
{
	if (missionVariables.himsn_adv_patrol_dest && missionVariables.himsn_adv_patrol_dest == system.ID && this._addAdvPatrolSwitch == true)
	{
		delete this._addAdvPatrolSwitch;
		missionVariables.himsn_adv_patrol_dest = null;
		this._advPatrolTimer_1.stop();
		delete this._advPatrolTimer_1;
		this._addAdvPatrolShips(system.locationFromCode("WITCHPOINT"));
	}
	if (missionVariables.himsn_adv_patrol_home && missionVariables.himsn_adv_patrol_home == system.ID && this._addAdvPatrolSwitch == true)
	{
		delete this._addAdvPatrolSwitch;
		missionVariables.himsn_adv_patrol_home = null;
		missionVariables.himsn_adv_patrol_mission = null;
		this._advPatrolTimer_2.stop();
		delete this._advPatrolTimer_2;
		this._addAdvPatrolShips(system.locationFromCode("WITCHPOINT"));
	}
}
Scripts/himsn_ship.js
"use strict";

this.name 			= "himsn_ship";
this.author         = "Pleb";
this.copyright      = "(C) 2014 Pleb.";
this.licence        = "CC-NC-by-SA 4.0";
this.version 		= "0.9-alpha";

this.shipSpawned = function ()
{
	this.ship.awardEquipment("EQ_FUEL_SCOOPS");
	this.ship.awardEquipment("EQ_HEAT_SHIELD");
	
	// Use Escort Formations OXP if installed for random flight formations:
	if (worldScripts["Escort Formations Randomiser"])
	{
		worldScripts["Escort Formations Randomiser"].$setupDefensiveEscorts(this.ship);
	}
}

this.helpRequestReceived = function(ally, enemy)
{
	this.ship.destination = ally.position;
	this.ship.target = enemy;
	this.ship.performAttack();
}

this.shipBeingAttacked = function(whom)
{
	if (whom.scanClass != "CLASS_MILITARY")
	{
		this.ship.target = whom;
		this.ship.requestHelpFromGroup();
		system.filteredEntities(this, function (entity)
		{
			if (entity.scanClass == "CLASS_MILITARY")
			{
				entity.target = whom;
				entity.performAttack();
			}
			if (entity.isStation && entity.hasRole("himsn_station"))
			{
				entity.alertCondition = 3;
				entity.launchDefenseShip();
			}
		});
	}
}
Scripts/himsn_station.js
"use strict";

this.name 			= "himsn_station";
this.author         = "Pleb";
this.copyright      = "(C) 2014 Pleb.";
this.licence        = "CC-NC-by-SA 4.0";
this.version 		= "0.9-alpha";

this.shipSpawned = function ()
{
	if (system.ID == -1) return;
	this.ship.launchShipWithRole("himsn_adv_patrol", [true]);
	worldScripts["himsn_main"]._advPatrolTimer_2 = new Timer(this,worldScripts["himsn_main"]._addAdvPatrol,1800);
	worldScripts["himsn_main"]._advPatrolTimer_3 = new Timer(this,worldScripts["himsn_main"]._launchAdvPatrol,900);
	
	this.liftArray = [];
	this.liftHomeArray = [];
	this.liftStatusArray = [];
	this.subArray = this.ship.subEntities;
	if (this.subArray.length > 0)
	{
		var listCounter = 0 ; // reset the counter
		for(listCounter = 0;listCounter<this.subArray.length;listCounter++)
		{
			if (this.subArray[listCounter].hasRole("himsn_kiotaLift"))
			{
				this.liftArray.push(this.subArray[listCounter]);
				this.liftHomeArray.push(this.subArray[listCounter].position);
				this.liftStatusArray.push("down");				
			}
		}

		this.distanceTimer = new Timer(this, this.distanceCheck, 0, 10);
	}
}

this.shipBeingAttacked = function(whom)
{
	if (whom.scanClass != "CLASS_MILITARY")
	{
		this.ship.target = whom;
		this.ship.requestHelpFromGroup();
		system.filteredEntities(this, function (entity)
		{
			if (entity.scanClass == "CLASS_MILITARY")
			{
				entity.target = whom;
				entity.performAttack();
			}
		});
	}
}

this.stationReceivedDockingRequest = function(whom)
{
	system.filteredEntities(this, function (entity)
	{
		if (entity.scanClass == "CLASS_MILITARY")
		{
			entity.target = whom;
			entity.destination = entity.target.position;
			entity.desiredRange = 2500;
			entity.performFlyToRangeFromDestination();
		}
	});
}

this.distanceCheck = function()
{
	if(this.checkDistance())
	{
		if(!this.callbackID) { this.callbackID = addFrameCallback(this.moveLifts.bind(this)); }
		if(!this.liftTimer) { this.liftTimer = new Timer(this, this.triggerLifts, 0, 10); }
		if(!this.missileTimer) { this.missileTimer = new Timer(this, this.awardMissile, 0, 30); }
		return;
	}
	else
	{ 
		this.stopTimers(); 
	}	
}

this.checkDistance = function () 
{
	if(!this.ship || ! player.ship || !this.ship.isValid || !player.ship.isValid)
	{ 
		return false; 
	}
	return (this.ship.position.distanceTo(player.ship) < 256E3);
}	
	
this.rotateStation = function (targetVector)
{
	var angle = this.ship.heading.angleTo(targetVector);
	var cross = this.ship.heading.cross(targetVector).direction();
	this.ship.orientation = this.ship.orientation.rotate(cross,-angle);
}

this.awardMissile = function()
{
	if(this.ship.missiles.length < this.ship.missileCapacity)
	{ 
		this.ship.awardEquipment(this.ship.selectNewMissile()); 
	}
}
	
this.triggerLifts = function()
{
	var listCounter = 0 ; // reset the counter
	for(listCounter = 0;listCounter<this.liftArray.length;listCounter++)
	{
		if(this.liftStatusArray[listCounter] === "down" && Math.random() < (0.1 * Math.random()))
		{ 
			this.liftStatusArray[listCounter] = "rising"; 
		}
		if (this.liftStatusArray[listCounter] === "up" && Math.random() < (0.1 * Math.random()))
		{ 
			this.liftStatusArray[listCounter] = "falling"; 
		}	
	}
}

this.moveLifts = function(delta)
{
	if(!this.ship.isValid || !this.ship.status)
	{
		this.shipDied();
		return;
	}
   
	var listCounter = 0 ; // reset the counter
	var distance = delta * 60; // 60 meter per second
	for(listCounter = 0;listCounter<this.liftArray.length;listCounter++)
	{
		if(this.liftStatusArray[listCounter] === "rising")
		{
			this.liftArray[listCounter].position = this.liftArray[listCounter].position.add(this.liftArray[listCounter].vectorUp.multiply(distance));
			if(this.liftArray[listCounter].position.distanceTo(this.liftHomeArray[listCounter]) >= 1145)
			{
				this.liftArray[listCounter].position = this.liftHomeArray[listCounter].add(this.liftArray[listCounter].vectorUp.multiply(1150));
				this.liftStatusArray[listCounter] = "up";
			}
		}
         
		if(this.liftStatusArray[listCounter] === "falling")
		{
			this.liftArray[listCounter].position = this.liftArray[listCounter].position.subtract(this.liftArray[listCounter].vectorUp.multiply(distance));
			if((this.liftArray[listCounter].position.distanceTo(this.liftHomeArray[listCounter]) <= 5) || (this.liftArray[listCounter].position.subtract(this.liftHomeArray[listCounter]).direction().angleTo(this.liftArray[listCounter].vectorUp) < 0.1))
			{
				this.liftArray[listCounter].position = this.liftHomeArray[listCounter];
				this.liftStatusArray[listCounter] = "down";
			}
		}	
	}
}
	
this.playerWillEnterWitchspace = this.entityDestroyed = this.stopTimers = function()
{
	if(this.callbackID)
	{
		removeFrameCallback(this.callbackID); 
		delete this.callbackID;
	}
		
	if(this.missileTimer && this.missileTimer.isRunning)
	{
		this.missileTimer.stop();
		delete this.missileTimer;
	}
		
	if(this.liftTimer && this.liftTimer.isRunning)
	{
		this.liftTimer.stop();
		delete this.liftTimer;
	}
}

this.shipFiredMissile = function(missile, target)
{
	if(missile && target && this.ship.heading.angleTo(target.position.subtract(this.ship.position).direction()) > (Math.PI / 2))
	{
		missile.orientation = missile.orientation.rotate(missile.vectorUp, Math.PI); 
		missile.position = this.ship.position.subtract(this.ship.vectorForward.multiply(this.ship.position.distanceTo(missile.position)));
	}
}
Scripts/himsn_station_dock.js
"use strict";

this.name 			= "himsn_station_dock";
this.author         = "Pleb";
this.copyright      = "(C) 2014 Pleb.";
this.licence        = "CC-NC-by-SA 4.0";
this.version 		= "0.9-alpha";

this.acceptDockingRequestFrom = function(ship)
{
	if (ship.isPlayer)
	{
		if (missionVariables.conhunt == "MISSION_COMPLETE" && missionVariables.thargplans == "MISSION_COMPLETE")
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	else
	{
		return true;
	}
}
Scripts/himsn_station_interface.js
"use strict";

this.name           = "himsn_station_interface";
this.author         = "Tsoj";
this.copyright      = "(C) 2021 Tsoj.";
this.licence        = "CC-NC-by-SA 4.0";
this.description    = "This is the script for station interfaces for the HIMSN OXZ.";
this.version        = "0.9-alpha";

this._timeToFirstWarning = 120; // seconds
this._timeToForcedLaunch = 180; // seconds

this._leaveTimer = null;

this._assert = function(condition, message) {
	if(!condition)
    	log("HIMSN", "ERROR, condition failed: " + message);
}

this._stopLeaveTimer = function(){
	if(this._leaveTimer){
		this._leaveTimer.stop();
		delete this._leaveTimer;
	}
}

this._startLeaveTimer = function(f, t){
	this._stopLeaveTimer();
	this._leaveTimer = new Timer(this, f, t);
}

this._isAtHIMSNStation = function(){
    return player.ship.docked && (
        player.ship.dockedStation.hasRole("himsn_komodo_carrier") ||
        player.ship.dockedStation.hasRole("himsn_station")
    );
}

this._forcedStationLaunch = function() {
	player.bounty += 40;
	mission.runScreen({
		titleKey: "HIMSN_forced_launch_title",
		messageKey: "HIMSN_forced_launch_message",
	}, function(){
		player.ship.launch();
	});
}

this._warningLeaveStation = function(){
	mission.runScreen({
		titleKey: "HIMSN_warning_title",
		messageKey: "HIMSN_warning_message",
		choicesKey: "HIMSN_stay_or_leave"
	}, function (choice){
		if(choice === "HIMSN_stay"){
			this._startLeaveTimer(this._forcedStationLaunch.bind(this), this._timeToForcedLaunch);
		}
		if(choice === "HIMSN_leave"){
			player.ship.launch();
		}
	});
}

this._generateAlienItemPrice = function() {
	let result = {
		price: 100.0,
		isSpecial: false
	};

	if(Math.random() <= 0.05) {
		result.price += (500 + Math.round(4500 * Math.random()))/10;
		result.isSpecial = true;
	}

	return result;
}

this._runMarketScreen = function() {

	const numAlienItems = player.ship.manifest.alien_items;

	const optionPrefix = "HIMSN_option_";

	let options = {};
	for(let i = 1; i < Math.min(10000, numAlienItems); i*=10) {
		options[optionPrefix + i] = "Sell " + i + " alien items";
	}
	if(numAlienItems > 0 && !options[optionPrefix + numAlienItems])
		options[optionPrefix + numAlienItems] = "Sell " + numAlienItems + " alien items";

	mission.runScreen({
		titleKey: "HIMSN_market_title",
		message: expandMissionText("HIMSN_market_message", {num_alien_items: numAlienItems}),
		choices: options,
		allowInterrupt: true
	}, function (text){
		this._assert(text.indexOf(optionPrefix) !== -1, "Options keys all should begin with the option prefix.")
		let x = text.replace(optionPrefix, "");
		
		this._assert(!isNaN(x), "Should be a number: " + x);
		this._assert(x > 0, "Should be only possible to sell positive amounts of alien items.");

		this._startLeaveTimer(this._warningLeaveStation.bind(this), this._timeToFirstWarning);

		const soldAlienItems = Math.min(Math.floor(x), numAlienItems);

		let earnedCredits = 0;
		let numSoldSpecialItems = 0;
		for(let i = 0; i<soldAlienItems; i++){
			const p = this._generateAlienItemPrice();
			earnedCredits += p.price;
			if(p.isSpecial)
				numSoldSpecialItems += 1;
		}
		this._assert(earnedCredits >= 0, "Player shouldn't lose credits by selling alien items.");

		player.ship.manifest.alien_items -= soldAlienItems;
		player.credits += earnedCredits;
		
		mission.runScreen({
			titleKey: "HIMSN_market_title",
			message: expandMissionText("HIMSN_sold_alien_items_message", {
				sold_alien_items: soldAlienItems,
				num_sold_special_items: numSoldSpecialItems,
				earned_credits: earnedCredits
			}),
			allowInterrupt: true
		}, function(){
			this._runMarketScreen();
		});
	});
}

this._runShipyardScreen = function(){
	mission.runScreen({
		titleKey: "HIMSN_shipyard_title",
		messageKey: "HIMSN_shipyard_restricted_message",
		allowInterrupt: true
	});
}

this._runSystemScreen = function(){
	mission.runScreen({
		titleKey: "HIMSN_interfaces_title",
		messageKey: "HIMSN_interfaces_restricted_message",
		allowInterrupt: true
	});
}

this.guiScreenChanged = function () {
    if(this._isAtHIMSNStation()) {
        if (guiScreen === "GUI_SCREEN_MARKET" || guiScreen == "GUI_SCREEN_MARKETINFO")
            this._runMarketScreen();
        if (guiScreen === "GUI_SCREEN_SHIPYARD" || guiScreen === "GUI_SCREEN_EQUIP_SHIP")
            this._runShipyardScreen();
        if (guiScreen === "GUI_SCREEN_INTERFACES")
            this._runSystemScreen();
    }
}

this.shipWillLaunchFromStation = function() {
    if(this._isAtHIMSNStation()) {
        this._startLeaveTimer();
    }
}

this.shipDockedWithStation = function () {
    if(this._isAtHIMSNStation()) {
        mission.runScreen({
            titleKey: "HIMSN_welcome_title",
            messageKey: "HIMSN_welcome_message",
            choicesKey: "HIMSN_stay_or_leave",
        }, function (choice){
            if(choice === "HIMSN_stay"){
                this._startLeaveTimer(this._warningLeaveStation.bind(this), this._timeToFirstWarning);
            }
            if(choice === "HIMSN_leave"){
                player.ship.launch();
            }
        });
    }
}

this.startUpComplete = function() {
    if(this._isAtHIMSNStation()) {
	    this._startLeaveTimer(this._warningLeaveStation.bind(this), this._timeToFirstWarning);
    }
}