Back to Index Page generated: Jun 13, 2026, 7:54:53 PM

Expansion Bank of the Black Monks

Content

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description Bank of the Black Monks invites you to undertake a short term financial pilgrimage for the Black Monks of St. Herod. In addition monasteries, that can be found in safe and advanced systems, sell blessed Holy Fuel. Beware of the Black Monk Gunships that persecute defaulters. Bank of the Black Monks invites you to undertake a short term financial pilgrimage for the Black Monks of St. Herod. In addition monasteries, that can be found in safe and advanced systems, sell blessed Holy Fuel. Beware of the Black Monk Gunships that persecute defaulters.
Identifier oolite.oxp.littlebear.blackmonks oolite.oxp.littlebear.blackmonks
Title Bank of the Black Monks Bank of the Black Monks
Category Activities Activities
Author LittleBear, Griff, spara LittleBear, Griff, spara
Version 2.3 2.3
Tags
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
Conflict Expansions
Dependent Expansions
  • oolite.oxp.Thargoid.PlanetFall2_BlackMonks:2.1
  • Information URL http://wiki.alioth.net/index.php/Black_Monk_Monastery n/a
    Download URL https://wiki.alioth.net/img_auth.php/f/f2/BlackMonks_2.3.oxz n/a
    License CC-BY-NC-SA 4.0 CC-BY-NC-SA 4.0
    File Size n/a
    Upload date 1775649627

    Relationships Diagram

    Documentation

    Also read http://wiki.alioth.net/index.php/Bank%20of%20the%20Black%20Monks

    readme.txt

    			      Bank of the Black Monks OXP - V2.3
    			     ------------------------------------
    
    * Original concept (v1.x), reconcepting and flavor texts by "LittleBear"
    * Reconcepting and scripting by "spara"
    * Models, textures and shaders by "Griff"
    
    ------------------------------------------------------------------------------------------------
    
    An addon for Oolite by Giles Williams.
    
    Based on "Elite" by Ian Bell and David Braben.
    
    Update history
    ---------------
    Version 2.3 - Added normal, specular and gloss maps to all ships and stations.
    	- Fixed missing panel on minesweeper satellite.
    	- Reverted to using default shaders on all ships.
    	- Moved all text into missiontext.plist or descriptions.plist for easier localisation.
    	- Changed F4 Interface screen category to one of the default Oolite categories.
    Version 2.2.1 - A missing semicolon added to the shipdata.
    Version 2.2 - Texts reproof-read and aged by Diziet Sma. A new one shot welcome page shown when entering a monastery for the first time. New names for Defence Ships. Renamed gunship to be "Holy Avenger Mark II" and defence ship to be "Holy Defender Mark I".
    Version 2.1.1 - Texts proof-read and corrected by Cody.
    Version 2.1 - screenIDs added to the mission screens for compatibility with other OXPs. Monk image added as an overlay instead of background picture. New bigger monk image. Bug fixes.
    Version 2.0 - A full rewrite and reconcepting of the OXP. (25.6.2015)
    
    Version 1.46 - Corrected typo in equipment.plist
    Version 1.45 - Corrected another typo in equipment.plist
    version 1.44 - Added copy of minesweeperAI from Random Hits oxp to remove the dependency on that OXP being installed
    Version 1.43 - Lengthened the dock object to workaround defence ship calmness - they now get angry faster :)
    Version 1.42 - fixed incorrect weapon rage & energy stats on one of the defence ship turrets
    Version 1.41 - removed bounty setting from defence ship, set scan_class to Neutral. Increased defence ship toughness stats
    Version 1.4 - added Blackmonk Station Defence Ship
    Version 1.3 - fixed the wrong shader vertex applied to station turrets 
    Version 1.2 - um, can't remember the changes
    Version 1.12 - Updated shaders slightly to avoid ATI missing texture bug. Added Materials so some shader effects work for on computers unable to run shaders
    Version 1.1 - 27th January 2007. 
    
    
    -------------------------------------------------------------------------------------------------
    
    Added:-
    -------
    
    - Vast Black Monk Monasteries appear in safe high tech Systems.
    - Players can to undertake a short term financial pilgrimage for the Black Monks.
    - The dreaded Black Monk Gunships can be seen shooting down NPC debtors who failed to pay up.
    - Players who fail to repay on time will also find themselves in a Gunship's sights!
    - Holy Fuel buyable from the Monasteries.
    
    LittleBear, Griff & spara
    

    Equipment

    Name Visible Cost [deci-credits] Tech-Level
    Holy Fuel yes 800 1+

    Ships

    Name
    Blackmonk Station Defence
    Blackmonk Station Defence
    Holy Defender Mark I
    Blackmonk Station Defence
    Holy Avenger Mark II
    Blackmonk Gunship
    Blackmonk Gunship
    Blackmonk Gunship
    Mine Sweeper Satellite Radar Dish
    Mine Sweeper Satellite
    Black Monk Monastery
    Docking Bay
    Blackmonk Monastery
    Turret

    Models

    This expansion declares no models.

    Scripts

    Path
    Scripts/blackmonk_conditions.js
    "use strict";
    this.name = "blackmonk_conditions";
    
    this.allowAwardEquipment = function (eqKey, ship, context) {
    	if (!player.ship.dockedStation.hasRole("blackmonk_monastery"))
    		return false;
    	return true;
    }
    
    Scripts/blackmonk_defence.js
    "use strict";
    this.name = "blackmonk_defence";
    this.description = "defence script to name the ship";
    
    this.shipSpawned = function () {
    	ship.shipUniqueName = expandDescription("[monk-defence-ship-name]");
    }
    
    Scripts/blackmonk_fuel.js
    "use strict";
    this.name = "blackmonk_fuel";
    
    this.startUp = function () {
    	this.$fillSound = new SoundSource;
    	this.$fillSound.sound = "blackmonk_fill.ogg";
    	if (missionVariables.blackmonk_fuel) {
    		this.$condensedFuel = missionVariables.blackmonk_fuel;
    	} else this.$condensedFuel = 0;
    }
    
    this.playerWillSaveGame = function () {
    	missionVariables.blackmonk_fuel = this.$condensedFuel;
    }
    
    this.playerBoughtEquipment = function (equipment) {
    	if (equipment === "EQ_HOLY_FUEL") {
    		player.ship.removeEquipment(equipment);
    		player.ship.fuel = 7;
    		this.$condensedFuel = 10.5;//1.5*7 = 10.5
    	}
    	else if (equipment === "EQ_FUEL") this.$condensedFuel = 0;
    }
    
    this.shipWillLaunchFromStation = function () {
    	if (this.$condensedFuel > 7) {
    		this.$fuelMonitor = new Timer(this, this._fuelMonitor, 0, 1);
    	}
    }
    
    this.shipWillDockWithStation = function () {
    	if (this.$fuelMonitor) {
    		this.$fuelMonitor.stop();
    		delete this.$fuelMonitor;
    	}
    }
    
    this._fuelMonitor = function () {
    	if (player.ship.fuel < 7 && this.$condensedFuel > player.ship.fuel && !this.$fuelAnimation) {
    		this.$fuelAnimation = addFrameCallback(this._fuelAnimation.bind(this));
    	}
    }
    
    this._fuelAnimation = function () {
    	if (player.ship.fuel < 7 && this.$condensedFuel > player.ship.fuel) {
    		player.ship.fuel += 0.1;
    		this.$condensedFuel -= 0.1;
    		if (!this.$fillSound.isPlaying) this.$fillSound.play();
    	}
    	else {
    		removeFrameCallback(this.$fuelAnimation);
    		delete this.$fuelAnimation;
    		//all gone?
    		if (player.ship.fuel < 7) {
    			this.$condensedFuel = 0;
    			this.$fuelMonitor.stop();
    			delete this.$fuelMonitor;
    		}
    	}
    }
    
    
    Scripts/blackmonk_gunship.js
    "use strict";
    this.name = "blackmonk_gunship";
    this.description = "gunship script to trigger debtor pleas and name the ship";
    
    this.shipAttackedOther = function (other) {
    	if (other.$monkDebtor && Math.random() < 0.1) {
    		other.commsMessage("[debtor-plea]");
    	}
    }
    
    this.shipSpawned = function () {
    	ship.shipUniqueName = expandDescription("[monk-ships]");
    }
    
    Scripts/blackmonk_main.js
    //17.7.2015 -spara-
    
    "use strict";
    this.name = "blackmonks";
    this.author = "spara";
    this.description = "Main script for Black Monks";
    
    this.startUp = function () {
    	if (missionVariables.blackmonk_contract) {
    		this.$contract = JSON.parse(missionVariables.blackmonk_contract);
    		delete missionVariables.blackmonk_contract;
    	}
    	this._setMonkSystems();
    	//control payback on docking
    	this.$offerOnce = false;
    	//control one shot welcome screen
    	if (!missionVariables.blackmonk_intro) this.$monkIntro = true;
    	else this.$monkIntro = false;
    }
    
    this.playerEnteredNewGalaxy = function () {
    	this._setMonkSystems();
    }
    
    //make a list of suitable monk systems
    this._setMonkSystems = function () {
    	this.$monkSystems = new Array();
    	this.$monkSystemIDs = new Array();
    
    	//first we'll utilize the basic rules
    	var systems = SystemInfo.filteredSystems(this, function (other) {
    		if (other.government >= 6 && other.techlevel >= 11 && !other.sun_gone_nova) {
    			return (other);
    		}
    	});
    
    	//only systems that are connected to others so that missions work are accepted
    	for (var i = 0; i < systems.length; i++) {
    		var destinations = 0;
    		for (var j = 0; j < systems.length; j++) {
    			var routeInfo = System.infoForSystem(galaxyNumber, systems[i].systemID).routeToSystem(systems[j]);
    			if (routeInfo && routeInfo.route.length > 9) destinations++;
    		}
    		if (destinations > 0) {
    			this.$monkSystems.push(systems[i]);
    			this.$monkSystemIDs.push(systems[i].systemID);
    		}
    	}
    }
    
    this.playerWillSaveGame = function () {
    	if (this.$contract) {
    		missionVariables.blackmonk_contract = JSON.stringify(this.$contract);
    	}
    }
    
    this.startUpComplete = this.shipDockedWithStation = function () {
    	if (player.ship.dockedStation.hasRole("blackmonk_monastery")) {
    		player.ship.dockedStation.setInterface("blackmonks", {
    			title: expandMissionText("monk_interface_title"),
    			category: expandDescriptions("[interfaces-category-employment]"),
    			summary: expandMissionText("monk_interface_summary"),
    			callback: this._bankingInterface.bind(this)
    		});
    	}
    }
    
    this.shipWillDockWithStation = function (station) {
    	//offer payback on docking
    	this.$offerOnce = true;
    }
    
    //force payback the the player is late and the destination is correct
    this.missionScreenOpportunity = function () {
    	//one shot welcome screen
    	if (this.$monkIntro && player.ship.dockedStation.hasRole("blackmonk_monastery")) {
    		mission.runScreen({
    			titleKey: "monk_title",
    			screenID: "blackmonks",
    			messageKey: "monk_first_visit_one_off_intro",
    		});
    		setScreenOverlay({ name: "monk.png", height: 480 });
    		this.$monkIntro = false;
    		missionVariables.blackmonk_intro = 1;
    	}
    	if (player.ship.dockedStation.hasRole("blackmonk_monastery") && this.$contract) {
    		//correct destination
    		if ((this.$contract.galaxy === galaxyNumber && this.$contract.system === system.ID) || this.$contract.galaxy !== galaxyNumber) {
    			missionVariables.monk_dest_name = System.infoForSystem(this.$contract["galaxy"], this.$contract["system"]).name;
    			//late, force payback
    			if (this.$contract["dealine"] - clock.seconds < 0) {
    				mission.runScreen({
    					titleKey: "monk_title",
    					screenID: "blackmonks",
    					messageKey: "monk_payback_late",
    					choicesKey: "monk_payback_force"
    				},
    					function (choice) {
    						this._payback();
    					}
    				);
    				setScreenOverlay({ name: "monk.png", height: 480 });
    			}
    			//enough credits
    			else if (this.$offerOnce && player.credits >= 30000) {
    				screenID: "blackmonks",
    					mission.runScreen({
    						titleKey: "monk_title",
    						screenID: "blackmonks",
    						messageKey: "monk_payback_early",
    						choicesKey: "monk_payback_choices"
    					},
    						function (choice) {
    							if (choice === "1_YES") {
    								this._payback();
    							}
    						}
    					);
    				setScreenOverlay({ name: "monk.png", height: 480 });
    			}
    			delete missionVariables.monk_dest_name;
    		}
    	}
    	this.$offerOnce = false;
    }
    
    this._bankingInterface = function (page) {
    	//contract running
    	if (this.$contract) {
    		//correct destination early with sufficient credits
    		if (((this.$contract.galaxy === galaxyNumber && this.$contract.system === system.ID) || (this.$contract.galaxy !== galaxyNumber)) && player.credits >= 30000) {
    			mission.runScreen({
    				titleKey: "monk_title",
    				screenID: "blackmonks",
    				messageKey: "monk_payback_early",
    				choicesKey: "monk_payback_choices",
    				exitScreen: "GUI_SCREEN_INTERFACES"
    			},
    				function (choice) {
    					if (choice === "1_YES") {
    						this._payback();
    					}
    				}
    			);
    		}
    		//wrong destination or early without sufficient funds
    		else {
    			missionVariables.monk_dest_name = System.infoForSystem(this.$contract["galaxy"], this.$contract["system"]).name;	//in time, godspeed to the player
    			if (this.$contract["dealine"] - clock.seconds >= 0) {
    				mission.runScreen({
    					titleKey: "monk_title",
    					screenID: "blackmonks",
    					messageKey: "monk_payback_wrong_destination",
    					exitScreen: "GUI_SCREEN_INTERFACES"
    				}
    				);
    			}
    			//too late, hurry the player up
    			else {
    				mission.runScreen({
    					titleKey: "monk_title",
    					screenID: "blackmonks",
    					messageKey: "monk_payback_wrong_destination_late",
    					exitScreen: "GUI_SCREEN_INTERFACES"
    				}
    				);
    			}
    			delete missionVariables.monk_dest_name;
    		}
    		setScreenOverlay({ name: "monk.png", height: 480 });
    	}
    	//offer contract, if there isn't one running
    	else {
    		switch (page) {
    			case "blackmonks":
    				//only offer for hyperspace capable ships
    				if (player.ship.hasHyperspaceMotor) {
    					mission.runScreen({
    						titleKey: "monk_title",
    						screenID: "blackmonks",
    						messageKey: "monk_welcome",
    						choicesKey: "monk_welcome_choices",
    						exitScreen: "GUI_SCREEN_INTERFACES"
    					},
    						function (choice) {
    							if (choice === "1_YES") {
    								this._bankingInterface("offer_list");
    							}
    						}
    					);
    				}
    				else {
    					mission.runScreen({
    						titleKey: "monk_title",
    						screenID: "blackmonks",
    						messageKey: "monk_welcome_no_dice",
    						exitScreen: "GUI_SCREEN_INTERFACES"
    					}
    					);
    				}
    				setScreenOverlay({ name: "monk.png", height: 480 });
    				break;
    			case "offer_list":
    				this.$destinations = new Array();
    				for (var i = 0; i < this.$monkSystems.length; i++) {
    					var routeInfo = system.info.routeToSystem(this.$monkSystems[i]);
    					if (routeInfo && routeInfo.route.length > 9) {
    						this.$destinations.push(this.$monkSystems[i]);
    					}
    				}
    
    				//offer max five shortest routest
    				this.$destinations.sort(function (a, b) { return system.info.routeToSystem(a).route.length - system.info.routeToSystem(b).route.length });
    				if (this.$destinations.length > 5) {
    					this.$destinations = this.$destinations.slice(0, 5);
    				}
    				var options = {};
    				for (var i = 0; i < this.$destinations.length; i++) {
    					var info = system.info.routeToSystem(this.$destinations[i]);
    					var origHours = info.time;
    					var days = Math.ceil(origHours / 24) + Math.ceil(info.route.length / 12); //extra 0.5 hours per system on route rounded up
    					var distance = System.infoForSystem(galaxyNumber, system.ID).distanceToSystem(this.$destinations[i]).toFixed(1);
    					options[i + "_DEST"] = expandMissionText("monk_distance", { dest: this.$destinations[i].name, distance: distance, days: days });
    				}
    				options["99_EXIT"] = expandMissionText("monk_exit");
    				mission.runScreen({
    					titleKey: "monk_title",
    					screenID: "blackmonks",
    					messageKey: "monk_offer_list",
    					choices: options,
    					exitScreen: "GUI_SCREEN_INTERFACES"
    				},
    					function (choice) {
    						if (choice !== "99_EXIT") {
    							this.$offerPointer = choice.split('_')[0];
    							this._setOffer("init");
    							this.$mapMode = "LONG_RANGE_CHART_SHORTEST";
    							this.$prevChoice = "3_NEXT";
    							this.$restoreDestination = player.ship.targetSystem;
    							this._bankingInterface("offer_map");
    						}
    					}
    				);
    				setScreenOverlay({ name: "monk.png", height: 480 });
    				break;
    			case "offer_map":
    				player.ship.hudHidden = true;
    				player.ship.targetSystem = this.$destinations[this.$offerPointer].systemID;
    
    				var options = new Object;
    				options["2_PREV"] = expandMissionText("monk_map_prev");
    				options["3_NEXT"] = expandMissionText("monk_map_next");
    				options["4_BACK"] = expandMissionText("monk_map_back");
    				options["5_SIGN"] = expandMissionText("monk_map_sign");
    				options["6_EXIT"] = expandMissionText("monk_map_exit");
    				if (player.ship.equipmentStatus("EQ_ADVANCED_NAVIGATIONAL_ARRAY") === "EQUIPMENT_OK") {
    					if (this.$mapMode === "LONG_RANGE_CHART_SHORTEST") {
    						options["1_MODE"] = expandMissionText("monk_map_mode1");
    					}
    					else {
    						options["1_MODE"] = expandMissionText("monk_map_mode2");
    					}
    				}
    
    				mission.runScreen({
    					titleKey: "monk_title",
    					screenID: "blackmonks-map",
    					backgroundSpecial: this.$mapMode,
    					messageKey: "monk_offer_details",
    					choices: options,
    					exitScreen: "GUI_SCREEN_INTERFACES",
    					initialChoicesKey: this.$prevChoice
    				},
    					function (choice) {
    						this.$prevChoice = choice;
    						if (choice === "1_MODE") {
    							if (this.$mapMode === "LONG_RANGE_CHART_SHORTEST") {
    								this.$mapMode = "LONG_RANGE_CHART_QUICKEST";
    							}
    							else {
    								this.$mapMode = "LONG_RANGE_CHART_SHORTEST";
    							}
    							this._bankingInterface("offer_map");
    						}
    						else if (choice === "3_NEXT") {
    							this._setOffer("next");
    							this._bankingInterface("offer_map");
    						}
    						else if (choice === "2_PREV") {
    							this._setOffer("prev");
    							this._bankingInterface("offer_map");
    						}
    						else if (choice === "4_BACK") {
    							this._cleanUp();
    							this._bankingInterface("offer_list");
    						}
    						else if (choice === "5_SIGN") {
    							player.ship.hudHidden = false;
    							this._bankingInterface("offer_sign");
    						}
    						else this._cleanUp();
    					}
    				);
    				break;
    			case "offer_sign":
    				mission.runScreen({
    					titleKey: "monk_title",
    					messageKey: "monk_offer_sign",
    					screenID: "blackmonks",
    					exitScreen: "GUI_SCREEN_INTERFACES"
    				}
    				);
    				//tip the player about the ANA
    				if (player.ship.equipmentStatus("EQ_ADVANCED_NAVIGATIONAL_ARRAY") !== "EQUIPMENT_OK") {
    					mission.addMessageTextKey("monk_offer_sign_tip");
    				}
    				this._cleanUp();
    				this.$contract = new Object;
    				this.$contract["galaxy"] = galaxyNumber;
    				this.$contract["system"] = this.$destinations[this.$offerPointer].systemID;
    				this.$contract["dealine"] = clock.seconds + this.$days * 86400;
    				player.credits += 20000;
    				mission.markSystem({ system: this.$contract["system"], name: "blackmonks" });
    				setScreenOverlay({ name: "monk.png", height: 480 });
    				break;
    		}
    	}
    }
    
    this._payback = function () {
    	//clear the marker
    	mission.unmarkSystem({ system: this.$contract["system"], name: "blackmonks" });
    	//enough credits
    	if (player.credits >= 30000) {
    		player.credits -= 30000;
    		delete this.$contract;
    		mission.runScreen({
    			titleKey: "monk_title",
    			messageKey: "monk_payback_enough",
    			screenID: "blackmonks"
    		}
    		);
    		mission.addMessageTextKey("monk_payback_welcome_back");
    		setScreenOverlay({ name: "monk.png", height: 480 });
    	}
    	//not enough credits, but enough equipment
    	else if (this._evaluateEquipment() + player.credits >= 30000) {
    		var sellOutcome = this._sellEquipment();
    		missionVariables.monk_equipment_total = formatCredits(sellOutcome[1], true, true);
    		missionVariables.monk_equipment_list = sellOutcome[0].join(", ");
    		player.credits -= 30000;
    		delete this.$contract;
    		mission.runScreen({
    			titleKey: "monk_title",
    			messageKey: "monk_payback_not_enough",
    			screenID: "blackmonks"
    		}
    		);
    		mission.addMessageTextKey("monk_payback_equipment");
    		mission.addMessageTextKey("monk_payback_welcome_back");
    		setScreenOverlay({ name: "monk.png", height: 480 });
    		delete missionVariables.monk_equipment_total;
    		delete missionVariables.monk_equipment_list;
    	}
    	//not enough credits, not enough equipment, have to sell the ship
    	else {
    		var sellOutcome = this._sellEquipment();
    		missionVariables.monk_equipment_total = formatCredits(sellOutcome[1], true, true);
    		missionVariables.monk_equipment_list = sellOutcome[0].join(", ");
    		missionVariables.monk_old_ship = formatCredits(0.5 * player.ship.price, true, true);
    		this._sellShip();
    		missionVariables.monk_new_ship = formatCredits(player.ship.price, true, true);
    		player.credits -= 30000;
    		player.credits -= player.ship.price;
    		delete this.$contract;
    		player.ship.hudHidden = true;
    		mission.runScreen({
    			titleKey: "monk_title",
    			messageKey: "monk_payback_not_nearly_enough",
    			screenID: "blackmonks"
    		}
    		);
    		missionVariables.monk_balance = formatCredits(player.credits, true, true);
    		mission.addMessageTextKey("monk_payback_equipment");
    		mission.addMessageTextKey("monk_payback_ship");
    		mission.addMessageTextKey("monk_payback_welcome_back");
    		setScreenOverlay({ name: "monk.png", height: 480 });
    
    		delete missionVariables.monk_equipment_total;
    		delete missionVariables.monk_equipment_list;
    		delete missionVariables.monk_old_ship;
    		delete missionVariables.monk_new_ship;
    		delete missionVariables.monk_balance;
    	}
    }
    
    //calculate the value of weapons, missiles and the installed equipment
    this._evaluateEquipment = function () {
    	var value = 0;
    	var equipments = player.ship.equipment;
    	for (var i = 0; i < equipments.length; i++) {
    		if (equipments[i].price > 0 && player.ship.equipmentStatus(equipments[i]) === "EQUIPMENT_OK" && equipments[i].equipmentKey !== "EQ_CARGO_BAY" && equipments[i].equipmentKey !== "EQ_PASSENGER_BERTH") {
    			value += equipments[i].price;
    		}
    	}
    	var missiles = player.ship.missiles;
    	for (var i = 0; i < missiles.length; i++) {
    		if (missiles[i].price > 0) {
    			value += missiles[i].price;
    		}
    	}
    	if (player.ship.portWeapon && player.ship.portWeapon.price > 0) {
    		value += player.ship.portWeapon.price;
    	}
    	if (player.ship.aftWeapon && player.ship.aftWeapon.price > 0) {
    		value += player.ship.aftWeapon.price;
    	}
    	if (player.ship.starboardWeapon && player.ship.starboardWeapon.price > 0) {
    		value += player.ship.starboardWeapon.price;
    	}
    	if (player.ship.forwardWeapon && player.ship.forwardWeapon.price > 0) {
    		value += player.ship.forwardWeapon.price;
    	}
    	return value / 10;
    }
    
    //pay with equipment
    this._sellEquipment = function () {
    
    	var stripped = new Array();
    	var oldBalance = player.credits;
    
    	//strip the missiles
    	var missiles = player.ship.missiles;
    	for (var i = 0; i < missiles.length; i++) {
    		if (player.credits < 30000) {
    			if (missiles[i].price > 0) {
    				player.credits += missiles[i].price / 10;
    				stripped.push(missiles[i].name);
    				player.ship.removeEquipment(missiles[i]);
    			}
    		}
    	}
    	//strip equipment except for LCB and berths. EQ_CARGO_BAY,EQ_PASSENGER_BERTH
    	var equipments = player.ship.equipment;
    	for (var i = 0; i < equipments.length; i++) {
    		if (player.credits < 30000) {
    			if (equipments[i].price > 0 && player.ship.equipmentStatus(equipments[i]) === "EQUIPMENT_OK" && equipments[i].equipmentKey !== "EQ_CARGO_BAY" && equipments[i].equipmentKey !== "EQ_PASSENGER_BERTH") {
    				player.credits += equipments[i].price / 10;
    				stripped.push(equipments[i].name);
    				player.ship.removeEquipment(equipments[i]);
    			}
    		}
    	}
    	//strip lasers
    	if (player.credits < 30000) {
    		if (player.ship.portWeapon && player.ship.portWeapon.price > 0) {
    			player.credits += player.ship.portWeapon.price / 10;
    			stripped.push([player.ship.portWeapon.name, player.ship.portWeapon.price / 10]);
    			player.ship.boardWeapon = null;
    		}
    	}
    	if (player.credits < 30000) {
    		if (player.ship.starboardWeapon && player.ship.starboardWeapon.price > 0) {
    			player.credits += player.ship.starboardWeapon.price / 10;
    			stripped.push(player.ship.starboardWeapon.name);
    			player.ship.starboardWeapon = null;
    		}
    	}
    	if (player.credits < 30000) {
    		if (player.ship.aftWeapon && player.ship.aftWeapon.price > 0) {
    			player.credits += player.ship.aftWeapon.price / 10;
    			stripped.push(player.ship.aftWeapon.name);
    			player.ship.aftWeapon = null;
    		}
    	}
    	if (player.credits < 30000) {
    		if (player.ship.forwardWeapon && player.ship.forwardWeapon.price > 0) {
    			player.credits += player.ship.forwardWeapon.price / 10;
    			stripped.push(player.ship.forwardWeapon.name);
    			player.ship.forwardWeapon = null;
    		}
    	}
    
    
    	return ([stripped, player.credits - oldBalance]);
    }
    
    this._sellShip = function () {
    	//no matter in what condition the player ship is, always sell for 50% of mint price
    	var refundFactor = 0.5;
    	player.credits += player.ship.price * refundFactor;
    	player.replaceShip("adder-player");
    	player.ship.removeEquipment("EQ_HEAT_SHIELD");
    	player.ship.removeEquipment("EQ_MISSILE");
    	player.ship.serviceLevel = 75;
    }
    
    
    //clean up mission variables and restore target system
    this._cleanUp = function () {
    	if (missionVariables.monk_dest_name) {
    		player.ship.hudHidden = false;
    		delete missionVariables.monk_dest_name;
    		delete missionVariables.monk_time;
    		delete missionVariables.monk_deadline;
    		player.ship.targetSystem = this.$restoreDestination;
    	}
    }
    
    this.guiScreenWillChange = function (to, from) {
    	if (this.$contract && to === "GUI_SCREEN_MANIFEST") {
    		var secsLeft = this.$contract["dealine"] - clock.seconds;
    		var hoursLeft = Math.floor((secsLeft) / 3600);
    		if (hoursLeft > 0) {
    			var daysText = expandMissionText("monk_hours_left", { hours: hoursLeft });
    		}
    		else if (hoursLeft === 0) {
    			var daysText = expandMissionText("monk_hour_left");
    		}
    		else var daysText = expandMissionText("monk_deadline_passed");
    		mission.setInstructions(expandMissionText("monk_demand", { system: System.infoForSystem(this.$contract["galaxy"], this.$contract["system"]).name, days: daysText }));
    	}
    	else if (!this.$contract) {
    		player.ship.hudHidden = false;
    		mission.setInstructions(null);
    	}
    }
    
    this._setOffer = function (action) {
    	if (action === "next") {
    		this.$offerPointer++;
    		if (this.$offerPointer >= this.$destinations.length) {
    			this.$offerPointer = 0;
    		}
    	}
    	else if (action === "prev") {
    		this.$offerPointer--;
    		if (this.$offerPointer <= 0) {
    			this.$offerPointer = this.$destinations.length - 1;
    		}
    	}
    	var info = system.info.routeToSystem(this.$destinations[this.$offerPointer]);
    	var origHours = info.time;
    	this.$days = Math.ceil(origHours / 24) + Math.ceil(info.route.length / 12);//0.5 hours per system on route rounded up to full days
    	missionVariables.monk_dest_name = this.$destinations[this.$offerPointer].name;
    	missionVariables.monk_time = expandMissionText("monk_days_hours", { days: this.$days, hours: this.$days * 24 });
    	missionVariables.monk_deadline = clock.days + this.$days;
    }
    
    this.systemWillPopulate = function () {
    
    	if (this.$monkSystemIDs.indexOf(system.ID) !== -1) {
    		system.setPopulator("blackmonk_station", {
    
    			callback: function (pos) {
    				var monastery = system.addShips("blackmonk_monastery", 1, pos, 0)[0];
    				monastery.orientation = [1, 0, 1, 0];
    				var minesweepers = system.addShips("blackmonk_minesweeper", 10, pos, 15E3);
    				for (var i = 0; i < minesweepers.length; i++) {
    					//init the alert mechanism of minesweepers.
    					minesweepers[i].script.$mother = monastery;
    				}
    			}.bind(this),
    			location: "LANE_WP",
    			locationSeed: 937,
    			deterministic: true
    		});
    	}
    
    	//retribution time
    
    	//now the player is in trouble. increasing number of gunships are being spawned close to the witchpoint every time the player enters a system.
    	if (this.$contract && this.$contract["dealine"] - clock.seconds < 0) {
    		var count = Math.ceil((clock.seconds - this.$contract["dealine"]) / 86400);
    		if (count > 5) count = 5;
    		system.setPopulator("blackmonk_punishers", {
    			callback: function (pos) {
    				system.addGroup("blackmonk_gunship", count, pos);
    			}.bind(this),
    			location: "WITCHPOINT"
    		});
    	}
    
    	//ambiance
    
    	//gunships are ridiculously powerful, but very rare. roughly every tenth system has one cruising. running contract doubles the odds to start with and ramps them up close to the deadline.
    	if (this.$contract) {
    		var div = (Math.ceil(this.$contract["dealine"] - clock.seconds) / 86400);
    		if (div >= 2) {
    			var prob = 2 / (Math.ceil(this.$contract["dealine"] - clock.seconds) / 86400);
    			if (prob < 0.2) prob = 0.2;
    		}
    		else var prob = 1;
    	}
    	else var prob = 0.1;
    
    	if (Math.random() < prob) {
    		system.setPopulator("blackmonk_ambience_gunship", {
    			callback: function (pos) {
    				//half the time, spawn ambiance ships close to the witchpoint and move them a bit closer to the planet. a bit is a 0.75 * scanner range. it's a bit boring to all the time have them sitting next to the witchpoint. a bit too staged to my liking.
    				if (Math.random() < 0.5) {
    					var gunship = system.addShips("blackmonk_gunship", 1)[0];
    					gunship.position = gunship.position.add([0, 0, 19200]);
    					var debtor = system.addShips("trader", 1, gunship.position)[0];
    				}
    				else {
    					var gunship = system.addShips("blackmonk_gunship", 1, pos)[0];
    					var debtor = system.addShips("trader", 1, gunship.position)[0];
    				}
    				debtor.$monkDebtor = true;
    				debtor.fuel = 0;//no escape
    			}.bind(this),
    			location: "LANE_WP"
    		});
    		//this is a long shot, a lonely debtor leisurely cruising the lane. with some seriusly bad load of luck it just might meet a blackmonk gunship.
    		system.setPopulator("blackmonk_ambiance_wandering_debtor", {
    			callback: function (pos) {
    				var debtor = system.addShips("trader", 1, pos)[0];
    				debtor.$monkDebtor = true;
    				debtor.fuel = 0;//no escape
    			}.bind(this),
    			location: "LANE_WP"
    		});
    	}
    }
    
    Scripts/blackmonk_minesweeper.js
    "use strict";
    this.name = "blackmonk_minesweeper";
    this.description = "Minesweeper ship script.";
    
    //this.$mother is set from the populator
    
    this.shipBeingAttacked = function (whom) {
    	//relay attack to the possible mother
    	if (this.$mother) {
    		this.$mother.script.shipBeingAttacked(whom);
    		this.$mother.AIScript.shipBeingAttacked(whom);
    	}
    }
    
    Scripts/blackmonk_station.js
    "use strict";
    this.name = "blackmonk_station";
    this.description = "Monastery ship script.";
    
    //give a hostile player a warning when fired upon.
    this.shipBeingAttacked = function (whom) {
    	var aiScript = ship.AIScript;
    	if (whom.isPlayer && aiScript.$warn) {
    		aiScript.$warn = false;
    		ship.commsMessage("[monk-warning]");
    		if (aiScript.$adTimer) {
    			aiScript.$adTimer.stop();
    			delete aiScript.$adTimer;
    		}
    	}
    }