/*

anarchies.js

Script for Anarchies.oxp.


Oolite
Copyright © 2004-2012 Giles C Williams and contributors

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.


Anarchies.oxp
Copyright © 2007-2012 "Commander McLane"

This work is licensed under the Creative Commons
Attribution-Noncommercial-Share Alike 3.0 Unported License.

To view a copy of this license, visit
http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter
to Creative Commons, 171 Second Street, Suite 300, San Francisco,
California, 94105, USA.

*/

"use strict";

this.name           = "Anarchies";
this.description    = "Script for Anarchies.oxp";
this.author         = "Commander McLane";
this.copyright      = "© 2012 Commander McLane";
this.license		= "CC-by-nc-sa 3.0";
this.version        = "2.9.4";


/* variables */

this.equipment_key = new Array(
	"EQ_ECM",
	"EQ_FUEL_SCOOPS",
	"EQ_ESCAPE_POD",
	"EQ_ENERGY_BOMB",
	"EQ_ENERGY_UNIT",
	"EQ_NAVAL_ENERGY_UNIT",
	"EQ_DOCK_COMP",
	"EQ_GAL_DRIVE",
	"EQ_FUEL_INJECTION",
	"EQ_SCANNER_SHOW_MISSILE_TARGET",
	"EQ_MULTI_TARGET",
	"EQ_ADVANCED_COMPASS",
	"EQ_ADVANCED_NAVIGATIONAL_ARRAY",
	"EQ_TARGET_MEMORY",
	"EQ_SHIELD_BOOSTER",
	"EQ_NAVAL_SHIELD_BOOSTER",
	"EQ_HEAT_SHIELD",
	"EQ_WORMHOLE_SCANNER"
);

this.behemoth_names = new Array(
    "Argus",
    "Atlas",
    "Bolverk",
    "Colossus",
    "Geryon",
    "Gog",
    "Goliath",
    "Grid",
    "Loki",
    "Magog",
    "Nimrod",
    "Surt",
    "Talos",
    "Tethys",
    "Titan",
    "Ymir"
);


/* functions */

this.$setUpSystem = function(populator)
{
	// nothing is done on relaunching from a station
	if(this.systemIsSetUp) return;
	// system is set up
	this.systemIsSetUp = true;
    // if on an amnesty mission, a battle in interstellar space is set up
    if(system.isInterstellarSpace && missionVariables.anarchies_amnesty == "GO_TO_BATTLE" && Math.round((System.infoForSystem(galaxyNumber, this.system1).coordinates.x + System.infoForSystem(galaxyNumber, this.system2).coordinates.x) / 2 * 2.5 * 10) / 10 == player.ship.galaxyCoordinates.x && Math.round((System.infoForSystem(galaxyNumber, this.system1).coordinates.y + System.infoForSystem(galaxyNumber, this.system2).coordinates.y) / 2 * 5 * 10) / 10 == player.ship.galaxyCoordinates.y)
    {
        system.addShips("behemoth", 3, [0, 0, 0], 15000);
        system.addShips("thargoid", 4, [0, 0, 0], 20000);
        var amnestyReservists = system.addShips("pirate", 5, [0, 0, 0], 15000);
        amnestyReservists.forEach(function(ship){
            this.$prepareAmnestyReservist(ship);
            ship.switchAI("anarchiesAmnestyReservistAI.plist");
        }, this);
        // more ships join the battle over time
        this.addShipsToBattleTimer = new Timer(this, this.$addShipsToBattle, 15, 15);
        // the player's kills are counted
        this.thargoidsKilled = 0;
        missionVariables.anarchies_amnesty = "FIGHT_IN_BATTLE";
        this.systemIsSetUp = true;
    }
    // nothing more is done in interstellar space
    if(system.isInterstellarSpace) return;
	// in Anarchies the following things are added:
	if(system.government === 0)
	{
		// low TL Anarchies have the chance to get either a Sentinel or a Renegade Station
		if(system.techLevel < 3)
		{
			var sdist = 0.2; //where will be the station in the main lane
			var spos = system.mainPlanet.position.multiply(sdist);
			if(system.scrambledPseudoRandomNumber(842) < 0.4) {
				if (!worldScripts.station_validator || worldScripts.station_validator.$deaths("anarchies_sentinel_station").length === 0) {
					if(populator) { //for Oolite 1.79 and above
						system.setPopulator("anarchies_sentinel_station", {
							callback: function(pos) {
							system.addShips("anarchies_sentinel_station", 1, pos, 0);
							}.bind(this),
							location: "COORDINATES",
							coordinates: spos,
							deterministic: true
						});
					} else system.addShipsToRoute("anarchies_sentinel_station", 1, sdist, "wp");
				}
			} else if(system.scrambledPseudoRandomNumber(842) < 0.6) {
				if (!worldScripts.station_validator || worldScripts.station_validator.$deaths("anarchies_renegade_station").length === 0) {
					if(populator) { //for Oolite 1.79 and above
						system.setPopulator("anarchies_renegade_station", {
							callback: function(pos) {
							system.addShips("anarchies_renegade_station", 1, pos, 0);
							}.bind(this),
							location: "COORDINATES",
							coordinates: spos,
							deterministic: true
						});
					} else system.addShipsToRoute("anarchies_renegade_station", 1, sdist, "wp");
				}
			}
		}
		// middle TL Anarchies have the chance to get a Salvage Gang
		else if(system.techLevel < 6)
		{
			if(system.scrambledPseudoRandomNumber(842) < 0.6)
			{
				if (!worldScripts.station_validator || worldScripts.station_validator.$deaths("anarchies_salvage_gang").length === 0) {
					var sdist = 0.3; //where will be the station in the main lane
					var spos = system.mainPlanet.position.multiply(sdist);
					if(populator) { //for Oolite 1.79 and above
						system.setPopulator("anarchies_salvage_gang", {
							callback: function(pos) {
							system.addShips("anarchies_salvage_gang", 1, pos, 0);
							system.addShipsToRoute("anarchies_salvager_tugger", 1, 0.25, "wp");
							}.bind(this),
							location: "COORDINATES",
							coordinates: spos,
							deterministic: true
						});
					} else {
						system.addShipsToRoute("anarchies_salvage_gang", 1, sdist, "wp");
						system.addShipsToRoute("anarchies_salvager_tugger", 1, 0.25, "wp");
					}
				}
			}
		}
		// high TL Anarchies have the chance to get a Hacker Outpost, through meeting a henchman
		else
		{
			if (!worldScripts.station_validator || worldScripts.station_validator.$deaths("anarchies-hacker-outpost").length === 0) {
				system.addShipsToRoute("anarchies_henchman", 1, 0.2, "wp");
				system.addShipsToRoute("anarchies_henchman", 1, 0.3, "ws");
			}
		}
	}
	// also non-Anarchy systems may get a Salvage Gang
	else if(system.scrambledPseudoRandomNumber(842) < 0.15)
	{
		if (!worldScripts.station_validator || worldScripts.station_validator.$deaths("anarchies_salvage_gang").length === 0) {
			system.addShipsToRoute("anarchies_salvage_gang", 1, 0.4, "wp");
			system.addShipsToRoute("anarchies_salvager_tugger", 1, 0.35, "wp");
		}
	}
    // if an amnesty is offered, a Behemoth waits in-system
    if(missionVariables.anarchies_amnesty == "OFFER_MADE" && system.ID == this.amnestySystem && this.amnestyDeadline - (clock.minutes / 24 / 60) < 2.5 && this.amnestyDeadline - (clock.minutes / 24 / 60) > 0)
    {
		this.behemothPosition = new Vector3D(system.mainPlanet.position.subtract(system.mainStation.position));
		this.behemothPosition.z = 0;
		this.behemothPosition = this.behemothPosition.direction();
		this.behemothPosition = this.behemothPosition.multiply(system.mainPlanet.radius * 3);
		this.behemothPosition = this.behemothPosition.add(system.mainPlanet.position);
		var behemoth = system.addShips("behemoth-" + this.behemothName.toLowerCase(), 1, this.behemothPosition, 0);
		behemoth[0].switchAI("anarchiesBehemothAI.plist");
		behemoth[0].primaryRole = "anarchies_behemoth";
		// the Behemoth gets a beacon for easier finding it
		var beaconDistance = 6000;
		if(this.behemothName == "Colossus" || this.behemothName == "Geryon" || this.behemothName == "Gog" || this.behemothName == "Goliath" || this.behemothName == "Loki" || this.behemothName == "Magog" || this.behemothName == "Nimrod" || this.behemothName == "Titan") beaconDistance = -6000;
		var bc = system.addShips("anarchies_behemoth_beacon", 1, behemoth[0].position.add(behemoth[0].orientation.vectorForward().multiply(beaconDistance)), 0)[0];
		bc.beaconLabel = "Behemoth: " + expandDescription("[mission_anarchies_amnesty_behemoth_name]");
        // up to 20 amnesty seekers are added en route to the Behemoth
		var amnestySeekersNumber = Math.ceil(((1 - (this.amnestyDeadline - (clock.minutes / 24 / 60))) * 20) * ((Math.random() * 0.5) + 0.5));
		for(var i = 0; i < amnestySeekersNumber; i++)
		{
			var amnestySeeker = system.addShips("pirate", 1, this.behemothPosition.multiply(Math.random()), 10000);
			amnestySeeker[0].savedCoordinates = this.behemothPosition;
			amnestySeeker[0].switchAI("anarchiesAmnestySeekerAI.plist");
			amnestySeeker[0].bounty += Math.round(Math.random() * 50);
		}
		//further amnesty seekers are added by timer
		this.addAmnestySeekersTimer = new Timer(this, this.$addAmnestySeekers, 15, 30);
		// half as much bounty hunters are added en route as well
		for(var i = 0; i < (amnestySeekersNumber / 2); i++)
		{
			var amnestyHunter = system.addShips("hunter", 1, this.behemothPosition.multiply(Math.random()), 10000);
			amnestyHunter[0].savedCoordinates = this.behemothPosition;
			amnestyHunter[0].switchAI("anarchiesAmnestyHunterAI.plist");
		}
    }
    // after battle, the Behemoth waits in-system again
    if(missionVariables.anarchies_amnesty == "FOUGHT_IN_BATTLE" && system.ID == this.amnestySystem)
    {
		this.behemothPosition = new Vector3D(system.mainPlanet.position.subtract(system.mainStation.position));
		this.behemothPosition.z = 0;
		this.behemothPosition = this.behemothPosition.direction();
		this.behemothPosition = this.behemothPosition.multiply(system.mainPlanet.radius * 3);
		this.behemothPosition = this.behemothPosition.add(system.mainPlanet.position);
		var behemoth = system.addShips("behemoth-" + this.behemothName.toLowerCase(), 1, this.behemothPosition, 0);
		behemoth[0].switchAI("anarchiesBehemothAI.plist");
		behemoth[0].primaryRole = "anarchies_behemoth";
		// the Behemoth gets a beacon for easier finding it
		var beaconDistance = 6000;
		if(this.behemothName == "Colossus" || this.behemothName == "Geryon" || this.behemothName == "Gog" || this.behemothName == "Goliath" || this.behemothName == "Loki" || this.behemothName == "Magog" || this.behemothName == "Nimrod" || this.behemothName == "Titan") beaconDistance = -6000;
		var bc = system.addShips("anarchies_behemoth_beacon", 1, behemoth[0].position.add(behemoth[0].orientation.vectorForward().multiply(beaconDistance)), 0)[0];
		bc.beaconLabel = "Behemoth: " + expandDescription("[mission_anarchies_amnesty_behemoth_name]");
        if (populator === false) system.shipsWithPrimaryRole("buoy-witchpoint")[0].commsMessage("Amnesty seekers head for the Behemoth '" + expandDescription("[mission_anarchies_amnesty_behemoth_name]") + "'. ★ on your compass.");
		// up to 8 returning reservists are added en route to the Behemoth
		var returningReservistsNumber = Math.ceil(Math.random() * 8);
		for(var i = 0; i < returningReservistsNumber; i++)
		{
			var returningReservist = system.addShips("pirate", 1, this.behemothPosition.multiply(Math.random()), 10000);
			returningReservist[0].savedCoordinates = this.behemothPosition;
			this.$prepareAmnestyReservist(returningReservist[0]);
			returningReservist[0].switchAI("anarchiesReturningReservistAI.plist");
		}
		//further returning reservists are added by timer
		this.addReturningReservistsTimer = new Timer(this, this.$addReturningReservists, 15, 30);
    }
}

this.$addAmnestySeekers = function()
{
    // adds more ships heading for the waiting Behemoth
    var amnestySeeker = system.addShipsToRoute("pirate", 1, 0);
    amnestySeeker[0].savedCoordinates = this.behemothPosition;
    amnestySeeker[0].switchAI("anarchiesAmnestySeekerAI.plist");
    amnestySeeker[0].bounty += Math.round(Math.random() * 50);
    this.addAmnestySeekersTimer.interval = (Math.random() * 150) + 20;
}

this.$addShipsToBattle = function()
{
    // randomly adds Thargoids and/or amnesty seeking pirates to the interstellar battle
    // if only 4 or less Thargoids are left, no further reinforcements are added
    if(system.countShipsWithRole("thargoid") < 5)
    {
        this.addShipsToBattleTimer.stop();
        return;
    }
    if(Math.random() < 0.65) system.addShips("thargoid", 1);
    if(Math.random() < 0.65)
    {
        var amnestyReservist = system.addShips("pirate", 1);
        this.$prepareAmnestyReservist(amnestyReservist[0]);
        amnestyReservist[0].switchAI("anarchiesAmnestyReservistAI.plist");
    }
    this.addShipsToBattleTimer.interval = (Math.random() * 30) + 10;
}

this.$addReturningReservists = function()
{
    // adds more ships heading for the waiting Behemoth
    var returningReservist = system.addShipsToRoute("pirate", 1, 0);
    returningReservist[0].savedCoordinates = this.behemothPosition;
    this.$prepareAmnestyReservist(returningReservist[0]);
    returningReservist[0].switchAI("anarchiesReturningReservistAI.plist");
    this.addReturningReservistsTimer.interval = (Math.random() * 150) + 20;
}

this.$addBountyHunters = function()
{
	// fugitive players may encounter bounty hunters, when they enter a new system or launch
	if(player.bounty > 50 && Math.random() < 0.35)
	{
		system.addShips("anarchies_bounty_hunter", 2, player.ship.position, 15000);
		system.addShipsToRoute("anarchies_bounty_hunter", 2, 0.5, "wp");
	}
	// very fugitive players WILL encounter bounty hunters close to the main station
	if(player.bounty > 255) system.addShipsToRoute("anarchies_bounty_hunter", 2, 1.0);
}

this.$bonusOnBounty = function(target)
{
	// if the player isn't clean and his target was a criminal, he may get a bounty reduction instead of a payment
	if(player.bounty > 0 && !target.hasRole("asteroid") && target.bounty > 0 && Math.random() < 0.16)
	{
		// the reduction depends on the target's bounty
		player.bounty -= Math.ceil(Math.sqrt(target.bounty) * 2 / 3);
		// the player's bounty isn't reduced below 0
		if(player.bounty < 0) player.bounty = 0;
		// the awarded bounty is reduced from the player's money again. unfortunately this isn't yet displayed in the default kill-message
		player.credits -= target.bounty;
		// another message is displayed
		player.consoleMessage("GalCop thanks for your help. The bounty for this kill was exchanged for a reduction of your own bounty.", 6);
	}
}

this.$setUpEquipmentFailureTimer = function()
{
	if(!this.equipmentFailureTimer)
	{
		this.equipmentFailureTimer = new Timer(this, this.$salvagedEquipmentFailed, 20, 20);
	}
	this.equipmentFailureTimer.stop();
}

this.$salvagedEquipmentFailed = function()
{
	// gives a chance that salvaged equipment bought from a Salvage Gang may fail
	// or become working as first hand equipment by simply removing the failure chance
	// not executed if no salvaged equipment has been installed
	if(!missionVariables.anarchies_salvaged_equipment || missionVariables.anarchies_salvaged_equipment == 0) return;
	// there is a 1% random chance for failing, and 0.5% for becoming indistinguishable from first hand equipment
	var failureChance = Math.random();
	if(failureChance < 0.73 || failureChance >= 0.745) return;
	// one of the possible equipment items is chosen
	var equipCount = 0;
	var failingEquipment;
	// the number of possible equipment items is established and stored in equipCount
	for(var i = 0; i < this.equipment_key.length; i++)
	{
		if((missionVariables.anarchies_salvaged_equipment & Math.pow(2,i)) != 0) equipCount++;
	}
	// one of those is chosen with equal probability
	for(var i = 0; i < this.equipment_key.length; i++)
	{
		if((missionVariables.anarchies_salvaged_equipment & Math.pow(2,i)) != 0)
		{
			if(Math.random() < (1/equipCount))
			{
				failingEquipment = i;
				break;
			}
			equipCount--;
		}
	}
	// check if the equipment hasn't been disabled otherwise (in which case it is also removed from the list, because it has to be repaired or newly bought anyway)
	// also check whether we want to make it fail, or make it like first hand equipment; it fails only on the 1% chance from above
	if(player.ship.equipmentStatus(this.equipment_key[failingEquipment]) === "EQUIPMENT_OK" && failureChance < 0.74)
	{
		// equipment status is set to "damaged" and player is notified
		player.ship.setEquipmentStatus(this.equipment_key[failingEquipment], "EQUIPMENT_DAMAGED");
		player.consoleMessage("Oh no! Your second-hand " + EquipmentInfo.infoForKey(this.equipment_key[failingEquipment]).name + " just broke!", 6);
	}
	// item is removed from the list of installed salvaged equipment
	// which also happens on the 0.5% chance from above, or if the equipment was damaged or removed otherwise
	missionVariables.anarchies_salvaged_equipment = missionVariables.anarchies_salvaged_equipment & (Math.pow(2,this.equipment_key.length) - 1 - Math.pow(2,failingEquipment));
}

this.$newBountyCalculation1 = function(cause)
{
	// stores the player's bounty before jumping
	this.playerBounty = player.bounty;
	// a galactic jump still clears the player's bounty
	if(cause == "galactic jump") this.playerBounty = 0;
}

this.$newBountyCalculation2 = function()
{
	// calculates the bounty on the player after arriving in a new system, replacing Oolite's own formula which halves the bounty
	// does nothing for a misjump
	if(system.isInterstellarSpace) return;
	// the default mechanism is used for bounties < 51
	// between 51 and 60 there is a small chance only of reduction, making it likely to stay fugitive for a long time
	if(this.playerBounty > 50 && this.playerBounty < 61 && Math.random() > 0.93) player.bounty = 50;
	// above 60 there is a reduction by 10% (rounded)
	if(this.playerBounty > 60) player.bounty = Math.ceil(this.playerBounty * 0.9);
}

this.$bribeGalcopOfficial = function()
{
	// only started if no other missionscreen is running and only once before next jump
	if(!missionVariables.offering && !this.bribeOffer)
	{
		// offer is made, first missionscreen
		mission.runScreen({screenID:"anarchies_bribe", titleKey:"Anarchies_bribetitle", messageKey:"Anarchies_bribeoffer", choicesKey:"Anarchies_bribeoffer_offer"}, this.$evaluateBribeofferChoices);
		this.bribeOffer = "APPROACH";
		// mission_offering is set, to prevent legacy scripts from running missionscreens
		missionVariables.offering = "ANARCHIES";
		// dice is thrown to establish the bribesum requested
		var bribedice = Math.random();
		if(bribedice < 0.3)
		{
			this.bribesum = 8000;
			this.lowersum = 5000;
			missionVariables.anarchies_bribestring = "8000";
			missionVariables.anarchies_lowerstring = "5000";
		}
		else if(bribedice < 0.7)
		{
			this.bribesum = 10000;
			this.lowersum = 6000;
			missionVariables.anarchies_bribestring = "10000";
			missionVariables.anarchies_lowerstring = "6000";
		}
		else
		{
			this.bribesum = 12000;
			this.lowersum = 7000;
			missionVariables.anarchies_bribestring = "12000";
			missionVariables.anarchies_lowerstring = "7000";
		}
	}
	else if(this.bribeOffer == "DONE")
	{
		// if no further offers are made, let's get rid of some variables which are of no need anymore
		delete this.bribesum;
		delete this.lowersum;
		delete missionVariables.anarchies_bribestring;
		delete missionVariables.anarchies_lowerstring;
		this.bribeOffer = "END";
		// is reset only by the next jump
        // legacy scripts may run missionscreens again
        delete missionVariables.offering;
	}
}

this.$evaluateBribeofferChoices = function(choice)
{
	if(this.bribeOffer === "APPROACH")
	{
		// second screen, depending on YES or NO
		if(choice === "Anarchies_offer_2_NO")
		{
			mission.runScreen({screenID:"anarchies_bribe", titleKey:"Anarchies_bribetitle", messageKey:"Anarchies_bribeoffer_rejected"});
			this.bribeOffer = "DONE";
			// end, no other offer is made before leaving the system
		}
		else if(choice === "Anarchies_offer_1_YES")
		{
			mission.runScreen({screenID:"anarchies_bribe", titleKey:"Anarchies_bribetitle", messageKey:"Anarchies_bribechoice", choicesKey:"Anarchies_bribe_choices"}, this.$evaluateBribeofferChoices);
			this.bribeOffer = "OFFER";
		}
	}
	else if(this.bribeOffer === "OFFER")
	{
		// third screen, you may have accepted, refused, or tried to bargain
		if(choice === "Anarchies_choice_1_YES")
		{
			// accepted, deal made
			player.credits -= this.bribesum;
			mission.runScreen({screenID:"anarchies_bribe", titleKey:"Anarchies_bribetitle", messageKey:"Anarchies_bribed"});
			player.bounty = 0;
			this.bribeOffer = "DONE";
		}
		else if(choice === "Anarchies_choice_2_NO")
		{
			// refused, bad choice!
			mission.runScreen({screenID:"anarchies_bribe", titleKey:"Anarchies_bribetitle", messageKey:"Anarchies_not_bribed"});
			player.bounty = 350;
			this.bribeOffer = "DONE";
			// no further offer before leaving the system, but beware of bounty hunters!
		}
		else if(choice === "Anarchies_choice_3_LOWER")
		{
			// tried to bargain, let's see...
			if(Math.random() < 0.6)
			{
				// successful, you got your bargain
				player.credits -= this.lowersum;
				mission.runScreen({screenID:"anarchies_bribe", titleKey:"Anarchies_bribetitle", messageKey:"Anarchies_lowered"});
				player.bounty = 0;
			}
			else
			{
				// oh, oh; bad karma
				mission.runScreen({screenID:"anarchies_bribe", titleKey:"Anarchies_bribetitle", messageKey:"Anarchies_not_lowered"});
				player.bounty = 350;
			}
			this.bribeOffer = "DONE";
			// no further offer before leaving the system, see above
		}
	}
}

this.$multipass = function()
{
	// determines the result of using a Multipass, depending on the player's bounty and credits
	// the following will be passed to a shared missionscreen display function
	this.specialEquipment = "EQ_MULTIPASS";
	this.pageTitle = "Connecting to GalCop's central database";
	this.dotCount = 0;
	this.countEnd = 12;
	// costs of sub-ether connection are calculated according to the player's current bounty
	if(player.bounty > 120)
	{
		// have you got enough money?
		if(player.credits >= 7000)
		{
			this.notification = "Anarchies_Multipass_used_successfully";
			player.bounty = 0;
			player.credits -= 7000;
		}
		// or not?
		else
		{
			this.notification = "Anarchies_Multipass_connection_cancelled";
			player.bounty = 100;
			player.credits = 0;
			this.countEnd = 6;
		}
	}
	else if(player.bounty > 50)
	{
		if(player.credits >= 5000)
		{
			this.notification = "Anarchies_Multipass_used_successfully";
			player.bounty = 0;
			player.credits -= 5000;
		}
		else
		{
			this.notification = "Anarchies_Multipass_connection_cancelled";
			player.bounty = 45;
			player.credits = 0;
			this.countEnd = 6;
		}
	}
	else if(player.bounty > 20)
	{
		if(player.credits >= 3000)
		{
			this.notification = "Anarchies_Multipass_used_successfully";
			player.bounty = 0;
			player.credits -= 3000;
		}
		else
		{
			this.notification = "Anarchies_Multipass_connection_cancelled";
			player.bounty = 18;
			player.credits = 0;
			this.countEnd = 6;
		}
	}
	else
	{
		if(player.credits >= 1000)
		{
			this.notification = "Anarchies_Multipass_used_successfully";
			player.bounty = 0;
			player.credits -= 1000;
		}
		else
		{
			this.notification = "Anarchies_Multipass_connection_cancelled";
			player.bounty = 1;
			player.credits = 0;
			this.countEnd = 6;
		}
	}
	// progress notification is started with a timer, relevant data has been stored above
	this.dotTimer = new Timer(this, this.$progressDots, 0, 1.2);
}

this.$multipassedID = function()
{
	// calculates the result of buying a Multi-passed ID, depending on a dice-roll
	// again data for the missionscreen display function, which is the same as above
	this.specialEquipment = "EQ_MULTIPASSED_ID";
	this.pageTitle = "Installing a new transponder";
	this.dotCount = 0;
	this.countEnd = 6;
	// whose second-hand transponder you get, is purely random
	var chance = Math.random();
	if(chance < 0.15)
	{
		this.notification = "Anarchies_Multipassed_ID_highFUG";
		player.bounty = 205;
	}
	else if(chance < 0.3)
	{
		this.notification = "Anarchies_Multipassed_ID_lowFUG";
		player.bounty = 58;
	}
	else if(chance < 0.6)
	{
		this.notification = "Anarchies_Multipassed_ID_OFFEND";
		player.bounty = 15;
	}
	else
	{
		this.notification = "Anarchies_Multipassed_ID_CLEAN";
		player.bounty = 0;
	}
	// the rest is again done with a timer, to which the relevant data is passed
	this.dotTimer = new Timer(this, this.$progressDots, 0, 1.2);
}

this.$progressDots = function()
{
	// prints a couple of dots to indicate a process being executed, afterwards gives out a result screen
	// used by both this.$multipass and this.$multipassedID
	if(this.dotCount > this.countEnd)
	{
		// when we had enough small dots plotted, the final result is displayed, multipass or multipassed ID removed, and mission_offering cleared
		this.dotTimer.stop();
		delete this.dotTimer;
		mission.runScreen({screenID:"anarchies_progress", title:this.pageTitle, messageKey:this.notification});
		player.ship.removeEquipment(this.specialEquipment);
		return;
	}
	mission.runScreen({screenID:"anarchies_progress", title:this.pageTitle, messageKey:"Anarchies_progress_notification_dot_" + this.dotCount, choicesKey:"Anarchies_empty"});
	this.dotCount ++;
}

this.$rippedOffByRenegades = function()
{
	// nothing happens if the player is fugitive
	if(player.bounty > 50) return;
	if(!this.rippedOff)
	{
		mission.runScreen({screenID:"anarchies_renegades", title:"Ambush", messageKey:"Anarchies_Renegade_Station_Rippedoff"}, this.$launchPlayer);
		// how much money have you got?
		if(player.credits < 10000)
		{
			mission.addMessageTextKey("Anarchies_Renegade_Station_Rippedoff_1");
			player.credits = 0;
		}
		else
		{
			mission.addMessageTextKey("Anarchies_Renegade_Station_Rippedoff_2");
			player.credits -= 10000;
		}
		this.rippedOff = true;
	}
}

this.$launchPlayer = function()
{
	player.ship.removeAllCargo();
	this.rippedOff = null;
	player.ship.launch();
	// and off you go
}

this.$setSalvagedEquipmentChances = function()
{
	// sets the availability chances for salvaged equipment items
	// these are verified in equipment.plist
	missionVariables.salvaged_ecm_chance = Math.floor(Math.random()*100);
	missionVariables.salvaged_fuel_scoops_chance = Math.floor(Math.random()*100);
	missionVariables.salvaged_escape_pod_chance = Math.floor(Math.random()*100);
	missionVariables.salvaged_energy_bomb_chance = Math.floor(Math.random()*100);
	missionVariables.salvaged_energy_unit_chance = Math.floor(Math.random()*100);
	missionVariables.salvaged_naval_unit_chance = Math.floor(Math.random()*100);
	missionVariables.salvaged_dock_comp_chance = Math.floor(Math.random()*100);
	missionVariables.salvaged_gal_drive_chance = Math.floor(Math.random()*100);
	missionVariables.salvaged_injectors_chance = Math.floor(Math.random()*100);
	missionVariables.salvaged_target_enhancement_chance = Math.floor(Math.random()*100);
	missionVariables.salvaged_multi_target_chance = Math.floor(Math.random()*100);
	missionVariables.salvaged_adv_compass_chance = Math.floor(Math.random()*100);
	missionVariables.salvaged_adv_array_chance = Math.floor(Math.random()*100);
	missionVariables.salvaged_target_memory_chance = Math.floor(Math.random()*100);
	missionVariables.salvaged_shield_booster_chance = Math.floor(Math.random()*100);
	missionVariables.salvaged_naval_booster_chance = Math.floor(Math.random()*100);
	missionVariables.salvaged_heat_shield_chance = Math.floor(Math.random()*100);
	missionVariables.salvaged_wormhole_scanner_chance = Math.floor(Math.random()*100);
}

this.$salvagedEquipmentBought = function(boughtEquipmentKey)
{
	// checks which salvaged equipment was bought at a Salvage Gang
	for(var i = 0; i < this.equipment_key.length; i++)
	{
		// whatever it was ...
		if(boughtEquipmentKey == (this.equipment_key[i] + "_SALVAGED")) break;
	}
	// the equipment is stored in a missionVariable, to make it failable later
	missionVariables.anarchies_salvaged_equipment = missionVariables.anarchies_salvaged_equipment | Math.pow(2,i);
	// to make it usable the salvaged equipment is replaced with the standard variant
	player.ship.removeEquipment(boughtEquipmentKey);
	player.ship.awardEquipment(this.equipment_key[i]);
}

this.$resetSalvagedEquipmentChances = function()
{
	// delete a bunch of unnecessary missionVariables at launching from a Salvage Gang
	delete missionVariables.salvaged_ecm_chance;
	delete missionVariables.salvaged_fuel_scoops_chance;
	delete missionVariables.salvaged_escape_pod_chance;
	delete missionVariables.salvaged_energy_bomb_chance;
	delete missionVariables.salvaged_energy_unit_chance;
	delete missionVariables.salvaged_naval_unit_chance;
	delete missionVariables.salvaged_dock_comp_chance;
	delete missionVariables.salvaged_gal_drive_chance;
	delete missionVariables.salvaged_injectors_chance;
	delete missionVariables.salvaged_target_enhancement_chance;
	delete missionVariables.salvaged_multi_target_chance;
	delete missionVariables.salvaged_adv_compass_chance;
	delete missionVariables.salvaged_adv_array_chance;
	delete missionVariables.salvaged_target_memory_chance;
	delete missionVariables.salvaged_shield_booster_chance;
	delete missionVariables.salvaged_naval_booster_chance;
	delete missionVariables.salvaged_heat_shield_chance;
	delete missionVariables.salvaged_wormhole_scanner_chance;
}

this.$displayTimeDHM = function(minutes)
{
    // this function takes an integer number of minutes and converts it into a string of the form
    // 'd' days, 'h' hours and 'm' minutes, accomodating all cases of singular, plural, and 0
    if(minutes < 0) minutes = -minutes;
    var daysComponent = Math.floor(minutes / 24 / 60);
    var hoursComponent = Math.floor((minutes % (24 * 60)) / 60);
    var minutesComponent = minutes % 60;
    var timeString = "";
    if(daysComponent > 0) timeString += daysComponent + " day";
    if(daysComponent > 1) timeString += "s";
    if(timeString != "")
    {
        if(hoursComponent > 0 && minutesComponent > 0) timeString += ", ";
        else if(hoursComponent > 0) timeString += " and ";
    }
    if(hoursComponent > 0) timeString += hoursComponent + " hour";
    if(hoursComponent > 1) timeString += "s";
    if(timeString != "" && minutesComponent > 0) timeString += " and ";
    if(minutesComponent > 0) timeString += minutesComponent + " minute";
    if(minutesComponent > 1) timeString += "s";
    if(timeString == "") timeString = "no time";
    return timeString;
}

this.$amnestyOffer = function()
{
    if(!missionVariables.anarchies_amnesty && worldScripts.behemoth && (((player.ship.dockedStation.name == "Free Trade Zone" || player.ship.dockedStation.name == "Hacker Outpost" || player.ship.dockedStation.name == "Salvage Gang") && Math.random() < 0.2) || (system.government == 0 && Math.random() < 0.05) || (system.government > 0 && Math.random() < 0.02)))
    {
        // a system in the galaxy is randomly chosen
        this.amnestySystem = Math.floor(Math.random() * 256);
        if(this.amnestySystem == system.ID) return;
        // and the route from the current system calculated
        var amnestyRoute = system.info.routeToSystem(System.infoForSystem(galaxyNumber, this.amnestySystem), "OPTIMIZED_BY_TIME");
        // if the chosen system is unreachable, the code stops
        if(amnestyRoute == null) return;
        // the amnesty system, its name and distance are stored in the save-file, both for later reference and for transfering them to a mission screen
        missionVariables.anarchies_amnesty_system = this.amnestySystem;
        missionVariables.anarchies_amnesty_system_name = System.infoForSystem(galaxyNumber, this.amnestySystem).name;
        var amnestySystemDistance = Math.round(system.info.distanceToSystem(System.infoForSystem(galaxyNumber, this.amnestySystem)) * 5) / 5;
        missionVariables.anarchies_amnesty_system_distance = amnestySystemDistance;
        // the deadline is calculated:
        // first the minimum time is extended by a factor of 1.25, (it's possible to play with that; for bigger distances it's impossible to meet the deadline with few long jumps)
        // then it is rounded to noon of the day
        this.amnestyDeadline = Math.round((clock.hours + (amnestyRoute.time * 1.25) + 12) / 24) - 0.5;
        // if you could only arrive earliest in the afternoon, the deadline is extended one day
        if(this.amnestyDeadline < (clock.hours + amnestyRoute.time) / 24) this.amnestyDeadline += 1;
        // the deadline is stored in the save-file for later reference
        missionVariables.anarchies_amnesty_deadline = this.amnestyDeadline;
        // the day is stored in the save-file, again for displaying it on mission screens
        missionVariables.anarchies_amnesty_offer_date = Math.floor(this.amnestyDeadline);
        // like for contracts, the start window is calculated, and saved in the save-file for display on screen
        // first the time until deadline
        missionVariables.anarchies_amnesty_time = this.$displayTimeDHM((this.amnestyDeadline * 24 * 60) - clock.minutes);
        // then the end of the start window (time until deadline minus minimum travel time)
        missionVariables.anarchies_amnesty_start_time = this.$displayTimeDHM((this.amnestyDeadline * 24 * 60) - clock.minutes - Math.floor(amnestyRoute.time * 60));
        // one of the Behemoths is chosen randomly
        var behemothNumber = Math.floor(Math.random() * 16);
        this.behemothName = this.behemoth_names[behemothNumber];
        missionVariables.anarchies_amnesty_behemoth_name = this.behemothName;
        // all necessary information is put on a news screen
        mission.runScreen({screenID:"anarchies_amnesty", titleKey:"Anarchies_iNewstitle", messageKey:"Anarchies_amnesty_news", overlay:"anarchies_iNews.png"});
        missionVariables.anarchies_amnesty = "OFFER_MADE";
        return;
    }
	
    if(missionVariables.anarchies_amnesty == "OFFER_MADE" && system.ID == this.amnestySystem && player.ship.dockedStation.displayName.indexOf("Behemoth") >= 0 && player.ship.dockedStation.displayName.indexOf(this.behemothName) >= 0)
    {
        // no further ships jump into the system
        this.addAmnestySeekersTimer.stop();
        // one of the systems in range is randomly chosen
        this.system1 = system.info.systemsInRange()[Math.floor(Math.random() * system.info.systemsInRange().length)];
        // a second one is chosen, in range of the first system
        this.system2 = System.infoForSystem(galaxyNumber, this.system1.systemID).systemsInRange()[Math.floor(Math.random() * System.infoForSystem(galaxyNumber, this.system1.systemID).systemsInRange().length)];
        // the two systems are ordered in proximity to the current system
        if(system.info.distanceToSystem(System.infoForSystem(galaxyNumber, this.system1.systemID)) > system.info.distanceToSystem(System.infoForSystem(galaxyNumber, this.system2.systemID)))
        {
            var changeSystems = this.system1;
            this.system1 = this.system2;
            this.system2 = changeSystems;
        }
        // their numbers and names are put into mission variables, for later reference and to put them on a mission screen
        missionVariables.anarchies_amnesty_destination1_name = this.system1.name;
        missionVariables.anarchies_amnesty_destination2_name = this.system2.name;
        this.system1 = this.system1.systemID;
        this.system2 = this.system2.systemID;
        missionVariables.anarchies_amnesty_destination1 = this.system1;
        missionVariables.anarchies_amnesty_destination2 = this.system2;
        // the mission briefing is given
        mission.runScreen({screenID:"anarchies_amnesty", title:"Amnesty offer", messageKey:"Anarchies_amnesty_briefing", overlay:"anarchies_military_star.png"});
        // the two systems are marked, the player has to misjump between them
        mission.markSystem(this.system1, this.system2);
        // the relevant information is put on the manifest screen
        mission.setInstructionsKey("Anarchies_amnesty_order");
        // other ships join the player, he may travel with them
        this.launchAmnestyReservistsTimer = new Timer(this, this.$launchAmnestyReservist, 5, 20);
        missionVariables.anarchies_amnesty = "GO_TO_BATTLE";
        return;
    }
    if(missionVariables.anarchies_amnesty == "FOUGHT_IN_BATTLE" && system.ID == this.amnestySystem && player.ship.dockedStation.displayName.indexOf("Behemoth") >= 0 && player.ship.dockedStation.displayName.indexOf(this.behemothName) >= 0)
    {
        // no further ships jump into the system
        this.addReturningReservistsTimer.stop();
        // how well did the player?
        if(missionVariables.anarchies_amnesty_thargoids_killed >= 4)
        {
            // he succeeded, amnesty is granted
            missionVariables.anarchies_amnesty_order_date = this.amnestyDeadline - 14.5;
            mission.runScreen({screenID:"anarchies_amnesty", title:"Amnesty granted", messageKey:"Anarchies_amnesty_debriefing_yes", overlay:"anarchies_military_star.png"});
            player.bounty = 0;
        }
        else
        {
            // he didn't succeed, but there are different levels of failure
            switch(missionVariables.anarchies_amnesty_thargoids_killed)
            {
                // complete failure
                case 0:
                    missionVariables.anarchies_amnesty_debriefing_1 = "is not a single kill of a capital Thargoid ship";
                    missionVariables.anarchies_amnesty_debriefing_2 = "";
                    break;
                // at least he did something
                case 1:
                    missionVariables.anarchies_amnesty_debriefing_1 = "is only one kill of a capital Thargoid ship";
                    missionVariables.anarchies_amnesty_debriefing_2 = "For your participation in the battle 500 Cr have been transferred to your account. ";
                    player.credits += 500;
                    break;
                // almost there, but not yet
                default:
                    missionVariables.anarchies_amnesty_debriefing_1 = "are only " + missionVariables.anarchies_amnesty_thargoids_killed + " kills of capital Thargoid ships";
                    missionVariables.anarchies_amnesty_debriefing_2 = "For your participation in the battle 1000 Cr have been transferred to your account. ";
                    player.credits += 1000;
            }
            // information about the outcome
            mission.runScreen({screenID:"anarchies_amnesty", title:"No amnesty granted", messageKey:"Anarchies_amnesty_debriefing_no", overlay:"anarchies_military_star.png"});
            player.credits += 1000;
        }
        // mission ends, clear all variables
        this.$endAmnestyOffer();
        // launch some happy, freshly pardoned pirates
        var clearedReservists = Math.ceil(Math.random() * 6);
        while(clearedReservists > 0)
        {
            var clearedReservist = system.shipsWithPrimaryRole("anarchies_behemoth")[0].launchShipWithRole("pirate");
            clearedReservist.bounty = 0;
            clearedReservist.setAI("exitingTraderAI.plist");
            clearedReservists --;
        }
    }
}

this.$displayTimeTillAmnestyDeadline = function()
{
    // displays the remaining time till deadline, and the remaining distance on the manifest screen
    // if there isn't currently an offer, nothing is displayed
    if(!missionVariables.anarchies_amnesty || missionVariables.anarchies_amnesty != "OFFER_MADE") return;
    // if the offer has expired, the information is cleared
    if((this.amnestyDeadline * 24 * 60) - clock.minutes < 0)
    {
        mission.setInstructions(null);
        return;
    }
    // the remaining time is recalculated and the mission variable refreshed
    missionVariables.anarchies_amnesty_time = this.$displayTimeDHM((this.amnestyDeadline * 24 * 60) - clock.minutes);
    // the remaining distance is recalculated and the mission variable refreshed
    var amnestySystemDistance = Math.round(system.info.distanceToSystem(System.infoForSystem(galaxyNumber, this.amnestySystem)) * 5) / 5;
    missionVariables.anarchies_amnesty_system_distance = amnestySystemDistance;
    mission.setInstructionsKey("Anarchies_amnesty_reminder");
}

this.$launchAmnestyReservist = function()
{
    // launch a candidate for amnesty from the Behemoth
    var amnestyReservist = system.shipsWithPrimaryRole("anarchies_behemoth")[0].launchShipWithRole("pirate");
    this.$prepareAmnestyReservist(amnestyReservist);
    amnestyReservist.switchAI("anarchiesAmnestyReservistAI.plist");
    this.launchAmnestyReservistsTimer.interval = (Math.random() * 40) + 5;
}

this.$prepareAmnestyReservist = function(ship)
{
    // the reservists need some amendments to their ship scripts
    // jumping towards the battle
    ship.script.$jumpToTargetSystem = function()
    {
        if(system.ID == worldScripts.Anarchies.system1)
        {
            var targetSystem = worldScripts.Anarchies.system2;
            this.ship.scriptedMisjump = true;
        }
        else
        {
            var targetSystem = worldScripts.Anarchies.system1;
        }
        if(this.ship.exitSystem(targetSystem) == false) this.ship.reactToAIMessage("WITCHSPACE_UNAVAILABLE");
    }
    // check for correct system after the battle
    ship.script.$checkSystem = function()
    {
        if(system.ID == worldScripts.Anarchies.amnestySystem)
        {
            this.ship.savedCoordinates = worldScripts.Anarchies.behemothPosition;
            this.ship.reactToAIMessage("AMNESTY_SYSTEM");
        }
        else
        {
            this.ship.reactToAIMessage("SYSTEM1");
        }
    }
    // jumping towards the Behemoth after battle
    ship.script.$jumpToAmnestySystem = function()
    {
        if(system.info.distanceToSystem(System.infoForSystem(galaxyNumber, worldScripts.Anarchies.amnestySystem)) < 7)
        {
            var targetSystem = worldScripts.Anarchies.amnestySystem;
        }
        else
        {
            var targetSystem = worldScripts.Anarchies.system1;
        }
        if(this.ship.exitSystem(targetSystem) == false) this.ship.reactToAIMessage("WITCHSPACE_UNAVAILABLE");
    }
    // new bounty calculation, analog to the player
    // storing the bounty before jump
    ship.script.$CMcLoldShipWillEnterWormhole = ship.script.shipWillEnterWormhole;
    ship.script.shipWillEnterWormhole = function()
    {
        this.shipBounty = this.ship.bounty;
        if(ship.script.$CMcLoldShipWillEnterWormhole) ship.script.$CMcLoldShipWillEnterWormhole();
    }
    // restoring the bounty according to a new calculation after jump
    ship.script.$CMcLoldShipExitedWormhole = ship.script.shipExitedWormhole;
    ship.script.shipExitedWormhole = function()
    {
        if(this.ship.script.shipBounty)
        {
            if(this.shipBounty > 50) this.ship.bounty = this.shipBounty;
            if(this.shipBounty > 55) this.ship.bounty = Math.ceil(this.shipBounty * 0.9);
            if(system.isInterstellarSpace) this.ship.bounty = this.shipBounty;
        }
        if(ship.script.$CMcLoldShipExitedWormhole) ship.script.$CMcLoldShipExitedWormhole();
    }
    // when created first time, the ship has a considerable bounty
    ship.bounty += Math.round(Math.random() * 50);
    // to enable sunskimming, it gets proper insulation
    ship.heatInsulation = 7;
}

this.$endAmnestyOffer = function()
{
    // clear all traces of the amnesty mission
    if(this.system1) mission.unmarkSystem(this.system1, this.system2);
    mission.setInstructions(null);
    delete missionVariables.anarchies_amnesty_system;
    delete missionVariables.anarchies_amnesty_system_name;
    delete missionVariables.anarchies_amnesty_system_distance;
    delete missionVariables.anarchies_amnesty_deadline;
    delete missionVariables.anarchies_amnesty_offer_date;
    delete missionVariables.anarchies_amnesty_time;
    delete missionVariables.anarchies_amnesty_start_time;
    delete missionVariables.anarchies_amnesty_behemoth_name;
    delete missionVariables.anarchies_amnesty_destination1;
    delete missionVariables.anarchies_amnesty_destination2;
    delete missionVariables.anarchies_amnesty_destination1_name;
    delete missionVariables.anarchies_amnesty_destination2_name;
    delete missionVariables.anarchies_amnesty_thargoids_killed;
    delete missionVariables.anarchies_amnesty_order_date;
    delete missionVariables.anarchies_amnesty_debriefing_1;
    delete missionVariables.anarchies_amnesty_debriefing_2;
    delete missionVariables.anarchies_amnesty;
}


/* event handlers */

this.startUp = function()
{
    this.$setUpEquipmentFailureTimer();
        this.$firstMissionScreenOpportunity = true;
	this.escapePodUsed = false;
	this.systemIsSetUp = false;
    // restore some amnesty-related variables from the save-game
    if(missionVariables.anarchies_amnesty)
    {
        this.amnestySystem = missionVariables.anarchies_amnesty_system;
        this.amnestyDeadline = missionVariables.anarchies_amnesty_deadline;
        this.behemothName = missionVariables.anarchies_amnesty_behemoth_name;
        this.system1 = missionVariables.anarchies_amnesty_destination1;
        this.system2 = missionVariables.anarchies_amnesty_destination2;
    }
}

this.shipWillEnterWitchspace = function(cause)
{
	this.$newBountyCalculation1(cause);
	this.systemIsSetUp = false;
    // leaving the battle means leaving the battle
    if(missionVariables.anarchies_amnesty == "FIGHT_IN_BATTLE") missionVariables.anarchies_amnesty = "FOUGHT_IN_BATTLE";
    // all timers are stopped if the player leaves the system
    if(this.addAmnestySeekersTimer && this.addAmnestySeekersTimer.isRunning) this.addAmnestySeekersTimer.stop();
    if(this.launchAmnestyReservistsTimer && this.launchAmnestyReservistsTimer.isRunning) this.launchAmnestyReservistsTimer.stop();
    if(this.addShipsToBattleTimer && this.addShipsToBattleTimer.isRunning) this.addShipsToBattleTimer.stop();
    if(this.addReturningReservistsTimer && this.addReturningReservistsTimer.isRunning) this.addReturningReservistsTimer.stop();
}

this.shipWillExitWitchspace = function()
{
	this.$newBountyCalculation2();
	this.$addBountyHunters();
    // four days after the last amnesty deadline the variables are cleared, and another offer becomes possible
    if(missionVariables.anarchies_amnesty && missionVariables.anarchies_amnesty != "FIGHT_IN_BATTLE" && clock.days > this.amnestyDeadline + 4) this.$endAmnestyOffer();
	this.$setUpSystem(false);
	delete this.bribeOffer;
}

this.shipExitedWitchspace = function() 
{
    if(missionVariables.anarchies_amnesty == "OFFER_MADE" && system.ID == this.amnestySystem && this.amnestyDeadline - (clock.minutes / 24 / 60) < 2.5 && this.amnestyDeadline - (clock.minutes / 24 / 60) > 0)
	{
		var buoy = system.shipsWithPrimaryRole("buoy-witchpoint");
		if (buoy && buoy.length > 0) buoy[0].commsMessage("Amnesty seekers head for the Behemoth '" + expandDescription("[mission_anarchies_amnesty_behemoth_name]") + "'. ★ on your compass.");
	}
}

this.shipWillDockWithStation = function(station)
{
        this.$firstMissionScreenOpportunity = true;

	// stops the equipment failure timer while docked
	this.equipmentFailureTimer.stop();
	// restores the player's bounty after using the escape pod
	if(this.escapePodUsed)
	{
		player.bounty = this.playerBounty;
		this.escapePodUsed = false;
	}
	if(station.name == "Salvage Gang") this.$setSalvagedEquipmentChances();
}

this.missionScreenOpportunity = function()
{
    if( this.$firstMissionScreenOpportunity ) {
        this.$firstMissionScreenOpportunity = false;
	if(player.ship.docked && player.ship.dockedStation.isMainStation && this.bribeOffer != null && this.bribeOffer != "END") this.$bribeGalcopOfficial();
	if(player.ship.docked && player.ship.dockedStation.name === "Renegade Station") this.$rippedOffByRenegades();
    // you get an explanatory briefing at your first visit on a Hacker Outpost; the fact is stored in mission_anarchies_multipass
	if(player.ship.docked && player.ship.dockedStation.name === "Hacker Outpost" && !missionVariables.anarchies_multipass)
    	{
        	mission.runScreen({screenID:"anarchies_hacker", title:"Welcome to the Hacker Outpost", messageKey:"Anarchies_Hacker_Outpost_Briefing"});
        	missionVariables.anarchies_multipass = "YES";
    	}
    	if(player.ship.docked) this.$amnestyOffer();
    }
}

this.guiScreenWillChange = function(to, from)
{
    if(to == "GUI_SCREEN_MANIFEST") this.$displayTimeTillAmnestyDeadline();
}

this.guiScreenChanged = function(to, from)
{
	// a corrupt GalCop official turns up only in Anarchy main stations, in the equipment department, if the player has enough money and isn't clean, and by chance
	if(player.ship.docked && player.ship.dockedStation.isMainStation && system.government == 0 && !missionVariables.offering && player.bounty > 0 && player.credits >= 12000 && to == "GUI_SCREEN_EQUIP_SHIP" && Math.random() > 0.86) this.$bribeGalcopOfficial();
}

this.playerBoughtEquipment = function(equipmentKey)
{
	// the processes are now run immediately after buying the equipment, independent from the next tickle
	if(equipmentKey == "EQ_MULTIPASS") this.$multipass();
	if(equipmentKey == "EQ_MULTIPASSED_ID") this.$multipassedID();
	// if you buy a used Naval energy unit while you still have the normal one, Oolite 1.72 would remove your expensive new purchase again
	// we don't want that, so we're removing the standard unit, and everything's fine
	if(equipmentKey == "EQ_NAVAL_ENERGY_UNIT_SALVAGED")
	{
		player.ship.removeEquipment("EQ_ENERGY_UNIT");
		// the extra energy unit is also removed from the list of bought salvaged equipment, if it should have been listed there
		missionVariables.anarchies_salvaged_equipment = missionVariables.anarchies_salvaged_equipment & (Math.pow(2,this.equipment_key.length) - 1 - Math.pow(2,4));
	}
	// any used equipment is installed properly right away
	if(equipmentKey.substr(equipmentKey.length - 9,9) === "_SALVAGED") this.$salvagedEquipmentBought(equipmentKey);
}

this.shipWillLaunchFromStation = function(station)
{
	if(station.name === "Salvage Gang") this.$resetSalvagedEquipmentChances();
	this.$addBountyHunters();
	this.$setUpSystem(false);
	this.equipmentFailureTimer.start();
}

this.shipTargetDestroyed = function(target)
{
    // the bonus on your own bounty if you have killed a pirate is currently disabled,
    // because Oolite is doing this all on its own since version 1.74
    // this.$bonusOnBounty(target);
    // when fighting a battle to get amnesty, your kills are counted
    if(system.isInterstellarSpace && missionVariables.anarchies_amnesty == "FIGHT_IN_BATTLE" && target.hasRole("thargoid") && !player.ship.isCloaked)
    {
        this.thargoidsKilled ++
        missionVariables.anarchies_amnesty_thargoids_killed = this.thargoidsKilled;
        if(this.thargoidsKilled <= 4)
        {
            player.consoleMessage(expandMissionText("Anarchies_amnesty_" + this.thargoidsKilled + "_killed"));
            mission.setInstructionsKey("Anarchies_amnesty_" + this.thargoidsKilled + "_killed");
        }
    }
}

this.shipLaunchedEscapePod = function(escapepod)
{
	// stores the player's bounty in a script variable
	this.playerBounty = player.bounty;
	// remembers use of escape pod
	this.escapePodUsed = true;
}

this.systemWillPopulate = function() { //for Oolite 1.79 and above
	this.$setUpSystem(true);
}