Back to Index Page generated: May 8, 2024, 6:16:03 AM

Expansion Pods

Content

Warnings

  1. Unknown key 'upload_date' at https://wiki.alioth.net/img_auth.php/4/4f/Oolite.oxp.Thargoid.Pods.1.48.oxz!manifest.plist

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description New cargo pods and pod features. New cargo pods and pod features.
Identifier oolite.oxp.Thargoid.Pods oolite.oxp.Thargoid.Pods
Title Pods Pods
Category Mechanics Mechanics
Author Thargoid, Rustem, Milo Thargoid, Rustem, Milo
Version 1.48 1.48
Tags mechanics, cargopods mechanics, cargopods
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
Conflict Expansions
Information URL http://wiki.alioth.net/index.php/Pods_OXP n/a
Download URL https://wiki.alioth.net/img_auth.php/4/4f/Oolite.oxp.Thargoid.Pods.1.48.oxz http://wiki.alioth.net/img_auth.php/d/d3/Pods.oxz
License CC-BY-NC-SA 3.0 CC-BY-NC-SA 3.0
File Size n/a
Upload date 1703763883

Documentation

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

ReadMe & License.txt

Pods OXP by Thargoid.

A small OXP to widen the range of native cargo pods available in the game. I've tried to be balanced with the additions, some are player-positive, some player-negative. All are low probability, but any standard pod appearing in the game could be one of these.

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

License:

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

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

--------------------------------------------------------------
Pods:

Nice:

* Bulk container - larger capacity pod, featuring up to 10 tons of cargo, 100 kilos of metals (gold/platinum) or 200 grammes of gem-stones.
* Missile pod - again exactly what it says, a missile that can be scooped and added to your arsenal (if you have a free pylon). Usually standard missiles, but sometimes ECM hardened ones for the lucky commander.
* Missile pod - if you not have a free pylon. Then a missile pod will scooped as firearms. If you have a free pylon and it has been scooped missile pod to the cargohold. If you like, so you can dumping a firearms and scooped for mount to pylon.
* Fuel pod - similar in nature to the external fuel tank, a pod which can carry up to 3.0 ly of witchspace fuel for your thirsty tanks. Occasionally the fuel has been known to be contaminated, requiring a tank purge.
* Piggybank pod - some poor soul's personal effects, including their life savings of up to 1000 credits.


Less so:

* Empty pod - exactly what it says, either an empty pod or one full of worthless content.
* Trumble pod - pod containing everyone's favourite burger ingredient.
* Retry pod - a little annoyance, a pod that doesn't quite scoop right. If all else fails, try try again...
* Jam pod - no, not a pod full of jam, but when a pod tries to go through a fuel scoop sideways. Pod jams in the scoop, rendering it inoperable until a friendly tech can apply a pry-bar to it in dry-dock.
* Exploding pod - pod explodes within the ship's shields during scooping. Energy damage done to the ship, and fuel scoops destroyed.
* Breach pod - pod explodes in hold, causing hull breach. Some cargo may be vented before breach can be repaired.

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

Instructions:

Place the OXZ file in the AddOns directory of your Oolite installation.

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

Version history:

 19/08/2008 - Version 0.20, Beta-test release version.
 22/08/2008 - version 1.00, Full release, now with Trumble, piggybank, breach and exploding pods added.
 31/08/2008 - version 1.01, minor bug fix for the fuel pods fuel leak.
 04/11/2008 - Version 1.02, scripting update for compatability with v1.72.
 09/04/2009 - Version 1.03, script tidy-up to prevent error for awarding cargo when hold full. Also tweaked trumblepod.
 01/11/2009 - Version 1.10, update to add scanclass and some new roles to the pods.
 18/03/2010 - Version 1.20, update for v1.74 (not compatible with lower versions).
 13/02/2011 - Version 1.21, removal of upper limit, to allow running with 1.75
 19/02/2011 - Version 1.22, correction of Manifest / manifest script glitch
 10/07/2012 - Version 1.30, merged pods and pods_UPS into one, and updated breachpod script (thanks to Eric W). Also added new variants for the standard 1t pods.
 10/12/2012 - Version 1.31, fixed a few case sensitivity issues for non-Windows OS's.
 12/12/2012 - Version 1.32, and a few more I missed before.
 22/12/2012 - Version 1.33, sorted out some [%I] references in description.plist (again thanks Eric!).
 20/01/2013 - Version 1.34, fixed a couple more references I missed last time (yet again thanks to Eric).
 07/02/2013 - Version 1.35, added a rogue "s" back into the big kg script (thanks to Plisken for that one!).

 12/09/2017 - Version 1.36 : update for oolite v1.79 - cag and rustem.
 - Added logging for error cargo type in pods_standardPod.js.
 - Edited name of the cargo type in description.plist and script for pods_standardPod.
 - Edited the scripts: correct name decsriptions, sometimes increased time for display consoleMessage.
 - Edited the shipdata: for pods_emptyBarrel (and pods_UPS_emptyBarrel) decreased value role of the cargopod from 0.1(0.12) to 0.005.
 - Edited the shipdata: for pods_missileBarrel decreased value role of the cargopod from 0.05 to 0.005.
 - Edited the shipdata: for all standart pods decreased value role of the cargopod from 0.5 to 0.05.
 - Added damage sounds to Jam, Exploding and Breach pods.

 14/09/2017 - Version 1.37, updated by Rustem
 - Added "use strict" in the scripts.
 - Improvement of damage sound effect for the correspond pods (thanks cag!).
 - Add time interval for display consoleMessage of Jam pod (again thanks cag!).

 19/09/2017 - Version 1.38, updated by Rustem
 - Fixed: replaced hasScoopMessages on the has_scoop_message in the shipdata.
 - Added no has_scoop_message to: fuelPod, emptyPod, retryPod, jamPod, missilePod, explodingPod, trumblePod (and UPS version also).

 23/10/2017 - Version 1.39, updated by Rustem
 - Added worldScript for storing all the resources. Added timer for exploding and breach pods (thanks cag!).
 - Added group roles as brokenpod, bigpod, dampod for application in the other OXPs. Added group role names from UPS Courier OXP.
 - Rebalanced role weights.
 - New calculation of the credits for piggybank pod.

 27/10/2017 - Version 1.40, updated by Rustem
 - Resorting and optimization by template pods in the shipdata.plist.
 - Added cargopod(hexapod) from CargoWreck OXP like external dependency as broken pods.
 - Edited group role names for standart pods.

 30/10/2017 - Version 1.41, updated by Rustem
 - Added big pod(ccl_crateA) and broken pods(ccl_crateB) for cargopod from Svengali CCL OXP like external dependency.
 - Added model scale factor to big pods.
 - Fixed shipdata bug for external pods.

 18/11/2017 - Version 1.42, updated by Rustem
 - Added a routine for checking a setCargo by other OXPs and etc.
 - Added logging condition in the pod ship.script.

 21/11/2017 - Version 1.43, updated by Rustem
 - Code refactoring: released an one script for Bulk container with NPC-scooping feature.
 - Added a routine for checking a shipUniqueName for renew of the pod name (for cargo scanner).
 - Modified the missilePod script for player-rescooping.
 - Upgraded all scripts for NPC-scooping.

 01/12/2017 - Version 1.44, updated by Rustem
 - Added description for communicate.
 - Fixed bug in the addition cargo to NPC.
 - Code refactoring.

 16/12/2018 - Version 1.45, updated by Rustem
 - Logging is off.
 - Formatted the JS code: scripts.
 - Fixed ship script for trumble pod (a TypeError for player.awardEquipment in pods_standardPod-1t, pods_trumblePod).
 - Tweaks in shipdata.plist, adds a materials for missilePod, adds a standartpod role.
 - Upgraded a scripts for trumblePod.

 20/12/2018 - Version 1.46, updated by Rustem
 - Adds cargopods from the Griff Cargopods OXP as standart pod and piggybank pod.
 - Reduce chance to award a trumble in the trumble pod.
 - Code refactoring of the trumblepod-scooping.

 10/07/2020 - Version 1.47, updated by Milo
 - Fixed errors in the scripts for the breach pod, jam pod, and exploding pod.

 12/07/2020 - Version 1.48, updated by Milo
 - Fixed another error in the script for the exploding pod.
 
// TODO: Add jamming Bulk container.

Equipment

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

Ships

Name
barrel_pods_template
pods_CCL_1tBarrel
Bulk Container
pods_CCL_breachBarrel
pods_CCL_emptyBarrel
pods_CCL_explodingBarrel
pods_CCL_jamBarrel
pods_CCL_piggybankBarrel
pods_CCL_retryBarrel
pods_CCL_templateBarrel
pods_CCL_trumbleBarrel
pods_CWT_breachBarrel
pods_CWT_emptyBarrel
pods_CWT_explodingBarrel
pods_CWT_jamBarrel
pods_CWT_piggybankBarrel
pods_CWT_retryBarrel
pods_CWT_trumbleBarrel
pods_CWTa_1tBarrel
pods_CWTa_templateBarrel
pods_CWTb_1tBarrel
pods_CWTb_templateBarrel
pods_CWTc_1tBarrel
pods_CWTc_templateBarrel
pods_GCP_A
pods_GCP_AW
pods_GCP_B
pods_GCP_BW
pods_GCP_C
pods_GCP_CW
pods_GCP_D
pods_GCP_DW
pods_GCP_E
pods_GCP_EW
pods_GCP_F
pods_GCP_FW
pods_GCP_G
pods_GCP_GW
pods_GCP_H
pods_GCP_HW
pods_GCP_alt_piggybankBarrel
pods_GCP_alt_templateBarrel
pods_GCP_piggybankBarrel
pods_GCP_templateBarrel
pods_UPS_1tBarrel_1
pods_UPS_1tBarrel_2
pods_UPS_barrel_template
pods_UPS_breachBarrel
pods_UPS_emptyBarrel
pods_UPS_explodingBarrel
pods_UPS_jamBarrel
pods_UPS_piggybankBarrel
pods_UPS_retryBarrel
pods_UPS_trumbleBarrel
pods_alloysBarrel
pods_bigBarrel_gems
pods_bigBarrel_kg
Bulk Container
pods_breachBarrel
pods_computersBarrel
pods_emptyBarrel
pods_explodingBarrel
pods_firearmsBarrel
pods_foodBarrel
Fuel Tank
pods_fursBarrel
pods_jamBarrel
pods_liquorWinesBarrel
pods_luxuriesBarrel
pods_machineryBarrel
pods_mineralsBarrel
Unarmed Missile
pods_narcoticsBarrel
pods_piggyBankBarrel
pods_radioactivesBarrel
pods_retryBarrel
pods_slavesBarrel
pods_textileBarrel
pods_trumbleBarrel

Models

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

Scripts

Path
Scripts/pods.js
this.name 			= "pods";
this.author 		= "rustem, cag, Thargoid";
this.copyright 		= "2020 Creative Commons: attribution, non-commercial, sharealike.";
this.description 	= "Central script for storing all the resources (timers & sounds) and functions and all the pod scripts refer to it using a direct reference.";

this.logging = false; // false for release

this.npc_message = true; // for switch npc-message

(function () {
	"use strict";

	this.$direct_hit_sound = null; // store object ref for sound effects
	this.$warning_sound = null;

	this.$msgTimer = this.$msgTimerJam = this.$msgTimerExp = this.$msgTimerBrh = null; // store timer ref
	this.$hullBreachTimer = this.$removeCargoTimer = null;
	this.$eqpTimer = null;

	this.$message = this.$scooper = []; //"" / []; // WAIT: optimal work for worldScripts.pods?
	this.$msgJam = this.$msgExp = this.$msgBrh = [];
	this.$scrJam = this.$scrExp = this.$scrBrh = [];
	this.$equip = "";
	this.$drship = this.$drcargo = "";
	this.$deqlog = this.$drlog = null;

	// these declarations are not really necessary, unless you rely on their initial value
	// but it's a good way to document your code

	this.startUp = function () {
		var wp = worldScripts.pods;

		// initialize sound effects
		wp.$direct_hit_sound = new SoundSource();
		wp.$direct_hit_sound.loop = false;
		wp.$direct_hit_sound.sound = "[player-direct-hit]";

		wp.$warning_sound = new SoundSource();
		wp.$warning_sound.loop = false;
		wp.$warning_sound.sound = "[@warning]";

		//wp.$initialiseTimer();
		//wp.$hullBreachTimer = new Timer(wp, wp.$hullBreach,14,14) // default + delay / 10 + 4
		//wp.$hullBreachTimer.stop();
		//if (wp.logging) log(this.name, "setup hullBreach timer for worldScripts");
	}

	this.shipWillDockWithStation = this.shipEnteredWitchspace = function () {
		// stop timers
		var wp = worldScripts.pods;
		if (wp.$msgTimer && wp.$msgTimer.isRunning)
			wp.$msgTimer.stop();
		if (wp.$msgTimerJam && wp.$msgTimerJam.isRunning)
			wp.$msgTimerJam.stop();
		if (wp.$msgTimerExp && wp.$msgTimerExp.isRunning)
			wp.$msgTimerExp.stop();
		if (wp.$msgTimerBrh && wp.$msgTimerBrh.isRunning)
			wp.$msgTimerBrh.stop();
		if (wp.$hullBreachTimer && wp.$hullBreachTimer.isRunning)
			wp.$hullBreachTimer.stop();
		if (wp.$removeCargoTimer && wp.$removeCargoTimer.isRunning)
			wp.$removeCargoTimer.stop();
		if (wp.$eqpTimer && wp.$eqpTimer.isRunning)
			wp.$eqpTimer.stop();
		
		// used by player only
		if (wp.$direct_hit_sound.isPlaying)
			wp.$direct_hit_sound.stop();
		if (wp.$warning_sound.isPlaying)
			wp.$warning_sound.stop();

		// used by NPC-ship
		// var sc = this.ship.script; // scr ~ scooper
		// WAIT: clean up timers and etc.
		// delete sc.$msgTimerBrh;
		// delete sc.$hullBreachTimer;
		// sc.$msgBrh = sc.$scrBrh = [];
		// if (sc._delayedMsg_breachPod) { delete sc._delayedMsg_breachPod; }
	}

	//this.shipExitedWitchspace = function () {
	// WAIT: clearing message and scooper arrays

	//this.$message = this.$scooper = [];
	//this.$msgJam = this.$msgExp = this.$msgBrh = [];
	//this.$scrJam = this.$scrExp = this.$scrBrh = [];
	//this.$equip = "";	
	//this.$drship = this.$drcargo = "";
	//this.$deqlog = this.$drlog = null;
	//}

	this._delayedMsg = function (msg, t) {
		var wp = worldScripts.pods;
		if (msg) { // there is a message to output
			wp.$message.push(msg);	// WAIT: handle more than one message at a time //wp.$message = msg; // save msg for use in callback
			if (!wp.$msgTimer) { // 1st message ever, set-up timer
				// new Timer(this : Object, function : Function, delay : Number [, interval : Number]) : Timer
				wp.$msgTimer = new Timer(wp, wp._delayedMsg, t, t);
				if (wp.logging) log(this.name, "setup generic timer");
			} else {
				wp.$msgTimer.start();
				if (wp.logging) log(this.name, "start timer : generic");
			}
		} else { // timer calls itself, we have to write the message
			if (wp.logging) log(this.name, "stop timer : generic");
			player.consoleMessage(wp.$message.shift(), 6);
			if (wp.$message.length === 0) wp.$msgTimer.stop();
		}
	}

	this._delayedMsg_jamPod = function (msg, t) {
		var s = player.ship;
		//var s = this.ship; if (s.isPlayer) { n = "player" } else { n = "npc" }
		var wp = worldScripts.pods;
		if (msg) { // there is a message to output (only for player)
			wp.$scrJam.push(s); // save scr for use in callback
			wp.$msgJam.push(msg); // handle more than one message at a time //wp.$msgJam = msg; // save msg for use in callback
			if (!wp.$msgTimerJam) { // 1st message ever, set-up timer
				wp.$msgTimerJam = new Timer(wp, wp._delayedMsg_jamPod, t, t);
				if (wp.logging) log(this.name, "setup jamPod timer");
			} else {
				wp.$msgTimerJam.start();
				if (wp.logging) log(this.name, "start timer : jamPod");
			}
		} else { // timer calls itself, we have to write the message
			if (wp.logging) log(this.name, "stop timer : jamPod");
			// for pods_jamPod
			s = wp.$scrJam.shift(); // retrieve first ship (should be associated with first timer if multiple timers scheduled)
			s.setEquipmentStatus("EQ_FUEL_SCOOPS", "EQUIPMENT_DAMAGED");
			if (s.isPlayer) {
				wp.$warning_sound.play();
				player.consoleMessage(wp.$msgJam.shift(), 8);
			} else {
				s.commsMessage(wp.$msgJam.shift());
			}
			if (wp.$scrJam.length === 0) wp.$msgTimerJam.stop();
		}
	}

	this._delayedMsg_expPod = function (msg, t) {
		var s = player.ship;
		var wp = worldScripts.pods;
		if (msg) { // there is a message to output (only for player)
			wp.$scrExp.push(s);
			wp.$msgExp.push(msg);
			if (!wp.$msgTimerExp) {
				wp.$msgTimerExp = new Timer(wp, wp._delayedMsg_expPod, t, t);
				if (wp.logging) log(this.name, "setup expPod timer");
			} else {
				wp.$msgTimerExp.start();
				if (wp.logging) log(this.name, "start timer : expPod");
			}
		} else {
			if (wp.logging) log(this.name, "stop timer : expPod");
			// for pods_explodingPod
			s = wp.$scrExp.shift(); // retrieve first ship (should be associated with first timer if multiple timers scheduled)
			let damage = (Math.ceil(Math.random() * 100));
			s.energy -= damage;
			s.removeEquipment("EQ_FUEL_SCOOPS");
			if (s.isPlayer) {
				wp.$direct_hit_sound.play();
				player.consoleMessage(wp.$msgExp.shift(), 8);
			} else {
				s.commsMessage(wp.$msgExp.shift());
			}
			if (wp.$scrExp.length === 0) wp.$msgTimerExp.stop();
		}
	}

	this._delayedMsg_breachPod = function (msg, t) {
		var s = player.ship,
			n = "player";
		var wp = worldScripts.pods;
		if (msg) { // there is a message to output (only for player)
			wp.$scrBrh.push(s);
			wp.$msgBrh.push(msg); // push : addition required a parsing cut/splice/pop message ?
			if (!wp.$msgTimerBrh) {
				wp.$msgTimerBrh = new Timer(wp, wp._delayedMsg_breachPod, t, t);
				if (wp.logging) log(this.name, "setup " + n + "-timer : breachPod");
			} else {
				wp.$msgTimerBrh.start();
				if (logging) log(this.name, "start " + n + "-timer : breachPod");
			}
		} else {
			if (logging) log(this.name, "stop " + n + "-timer : breachPod");
			// for pods_breachPod
			s = wp.$scrBrh.shift(); // retrieve first ship (should be associated with first timer if multiple timers scheduled)
			if (!wp._addHullBreachRoutines(s)) return false;
			if (s.isPlayer) {
				wp.$direct_hit_sound.play();
				player.consoleMessage("ALERT - explosion in the cargo hold! Hull breach, hold content venting!", 8);
				player.consoleMessage(wp.$msgBrh.shift(), 10);
			} else {
				s.commsMessage(wp.$msgBrh.shift());
			}
			if (wp.$scrBrh.length === 0) wp.$msgTimerBrh.stop();
		}
		return true;
	}

	this._msgCargo = function (type, quantity) {
		var msg = quantity;
		if (type && quantity) {
			if (type === "gold" || type === "platinum") { // platinum / Platinum / other roles: platinumpod
				msg += " kilogram "; // gold / Gold / other roles: goldpod
			} else if (type === "gem_stones") { // gem_stones / Gem-Stones / other roles: gemstonespod
				msg += " gram ";
			} else msg += " ton ";
			if (quantity > 1) {
				msg = msg.replace("gram ", "grams "); // msg = msg.replace("ton ", "tons "); // TEST: tons
			}
			msg += displayNameForCommodity(type);
		} else {
			log(this.name, "ERROR: no var in the function this._msgCargo(type, quantity)");
		}
		return msg;
	}

	this._delayedAwrd = function (item, t, debug) { // only for player
		var wp = worldScripts.pods;
		var dg = debug;
		if (!dg) dg = wp.logging;

		if (item) { // there is an equipment to output
			wp.$equip = item;
			wp.$deqlog = dg;
			if (!wp.$eqpTimer) { // 1st item ever, set-up timer
				// new Timer(this : Object, function : Function, delay : Number [, interval : Number]) : Timer
				wp.$eqpTimer = new Timer(wp, wp._delayedAwrd, t, t);
				if (wp.logging) log(this.name, "setup generic timer");
			} else {
				wp.$eqpTimer.start();
				if (wp.logging) log(this.name, "start timer : generic");
			}
		} else { // timer calls itself, we have to write the item
			wp.$eqpTimer.stop();
			if (wp.logging) log(this.name, "stop timer : generic");
			player.ship.awardEquipment(wp.$equip); // ? wp.$warning_sound.play();
			if (wp.$deqlog) log(this.name, "awarded equipment: "+ wp.$equip);
			wp.$equip = "";
			wp.$deqlog = null;
		}
	}

	this._delayedRemoveCargo = function (ship, item, t, debug) {
		var s = ship;
		var wp = worldScripts.pods;
		var dg = debug;
		if (!dg) dg = wp.logging;

		if (item) {
			//if (dg) log(this.name, "will remove "+item.commodity+", type: "+item.$missileType+" missile, dataKey: ["+item.dataKey+"]");
			// TEST: logging for pods_missilePod

			if (dg) log(this.name, "will remove "+ item.name +", dataKey: ["+ item.dataKey +"]");

			wp.$drship = s;
			wp.$drcargo = item;
			wp.$drlog = dg;
			if (!wp.$removeCargoTimer) {
				wp.$removeCargoTimer = new Timer(wp, wp._delayedRemoveCargo, t, t);
				if (wp.logging) log(this.name, "setup removeCargo timer");
			} else {
				wp.$removeCargoTimer.start();
				if (wp.logging) log(this.name, "start timer : removeCargo");
			}
		} else {
			wp.$removeCargoTimer.stop();
			if (wp.logging) log(this.name, "stop timer : removeCargo"); // if (wp.$drship.length > 1 || wp.$drcargo.length > 1) log(this.name, "Error: length > 1");
			wp._removeCargo(wp.$drship, wp.$drcargo, wp.$drlog);
			wp.$drship = wp.$drcargo = "";
			wp.$drlog = null;
		}
	}

	this._removeCargo = function (scooper, item, debug) {
		var dg = debug;
		if (!dg) dg = this.logging;

		if (scooper && item) {
			var s;
			if (scooper.isPlayer) {
				s = "player";
			} else {
				s = "npc";
			}
			if (dg) log(this.name, "removed "+ item.name +" on the " + s + "-ship: " + scooper.name);
			
			//item.remove(true);

			var si = scooper.dumpCargo(1, item.commodity);
			if (si) {
				if (dg) log(this.name, "removed " + displayNameForCommodity(item.commodity) + "(" + item.name + ") on the " + s + "-ship: " + scooper.name);
				si.remove(true);
			} else log(this.name, "Error: not removed: " + item.name); // may be by scooper $hullBreach and etc.
		}
	}

	this._addTrumbleRoutines = function (scooper, item, type, debug) { // only for player
		var wp = worldScripts.pods;
		var scr = scooper;
		var dg = debug;
		var t = type;
		if (!dg) dg = wp.logging;
		if (!scr.isPlayer || !item || !t) return;

		var msg, an, cn, pn; // orig: msg = "Pod contains a few scraps of food, and ... Oh no! A trumble!"
		if (t === "trumble") {
			var choice = (Math.ceil(Math.random() * 4));
			if (choice == 4) { // trumble(food)
				pn = "scraps";
				cn = expandDescription('[pods_food]');
				an = "A cute alien pet.";
				if (player.trumbleCount > 0) {
					msg = "1 ton " + cn + ", and ..." // food for trumble
				}
			} else if (choice == 3) { // trumble(furs)
				pn = "piece";
				cn = expandDescription('[pods_furs]');
				an = "A cute, fluffy pet.";
			} else { // trumble
				pn = "few scraps";
				cn = 'food';
				an = "A trumble!";
			}
		} else {
			if (t === "food") pn = "few scraps"
			else if (t === "furs") pn = "few piece"
			else pn = "little part";

			an = "A trumble!";
			cn = displayNameForCommodity(t).toLowerCase();

			// delete a barrel
			wp._delayedRemoveCargo(scr, item, 0.75, dg);
		}
		if (!msg) {
			msg = "Pod contains a " + pn + " of " + cn + ", and ... Oh no! " + an;
			wp._delayedAwrd("EQ_TRUMBLE", 10, dg);
		}
		wp._delayedMsg(msg, 6);
	}

	// addition function for communicate. // not active used

	this._messageTime = clock.absoluteSeconds // for use of spacing NPC messages by ship scripts.

	this.$communicate = function (source, msgcode) // ~ this._sendMessage
	{
		if (this._messageAllowed() && source.target && source.target.isPlayer)
			source.commsMessage(expandDescription("[" + msgcode + "]"), player.ship)
		// no messages within 5 secs to avoid screen clutter.
	}

	this._messageAllowed = function () {
		if ((clock.absoluteSeconds - this._messageTime) > 5) {
			this._messageTime = clock.absoluteSeconds;
			return true;
		} else return false;
	}

	// next code is used by ship script

	this._addHullBreachRoutines = function (ship) {
		var s = ship;
		var wp = worldScripts.pods;
		var n, sc, logging = wp.logging;
		// initialise ship
		if (s && s.isPlayer) {
			n = "player";
			sc = worldScripts.pods;
		} else {
			n = "npc";
			sc = s.script;
		}
		// damage
		let damage = (Math.ceil(Math.random() * 100));
		s.energy -= damage;
		// initialise timer
		if (typeof(sc) === undefined) {
			log(this.name, "_addHullBreachRoutines encountered an undefined ship script on ship " + s);
			return false;
		} else if (!sc.$hullBreachTimer) {
			sc.$initialiseTimer = wp.$initialiseTimer;
			sc.$initialiseTimer();
		} else {
			sc.$hullBreachTimer.start();
			if (logging) log(sc.name, "start " + n + "-timer : hullBreach");
		}
		return true;
	}

	this.$initialiseTimer = function () {
		var wp = worldScripts.pods;
		var n, s, sc, logging = wp.logging;
		// initialise ship
		if (this === wp) {
			n = "player";
			s = player.ship;
			sc = worldScripts.pods;
		} else {
			n = "npc";
			s = this.ship;
			sc = s.script;
			sc.$hullBreach = wp.$hullBreach;
		}
		// initialise hullBreach timer
		sc.$hullBreachTimer = new Timer(this, sc.$hullBreach, 14, 14) // default + delay / 10 + 4
		//sc.$hullBreachTimer.stop();
		if (logging) log(sc.name, "setup " + n + "-timer : hullBreach");

	}

	this.$hullBreach = function $hullBreach() {
		var wp = worldScripts.pods;
		var n, s, logging = wp.logging;
		// initialise ship
		s = this.ship;
		if (!s) {
			n = "player";
			s = player.ship;
		} else {
			n = "npc";
		}
		var actionChance = Math.ceil(Math.random() * 5);
		switch (actionChance) {
			case 1:
				//do nothing, breach still there, but no pod lost this time.
				break;
			case 2:
				this.$hullBreachTimer.stop();
				if (logging) log(this.name, "stop " + n + "-timer : hullBreach");
				if (s.isPlayer) {
					player.consoleMessage("Hull breach repaired, alert ended.", 6)
				} else {
					s.commsMessage("Oh, repaired! Stop eject!"); // expandDescription
				}
				// end of the emergency, now just got to go hoover up the spilt pods!
				break;
			case 3:
			case 4:
			case 5:
				if (s.dumpCargo()) {
					//bye-bye pod into space! no message about loss as you'd get a screenful.
					break;
				} else { // cargo hold is empty
					this.$hullBreachTimer.stop();
					if (logging) log(this.name, "stop " + n + "-timer : hullBreach");
					if (s.isPlayer) {
						player.consoleMessage("Hull breach repaired, alert ended.", 6)
					} else {
						s.commsMessage("... no more dump!"); // expandDescription
					}
					//delete this.$hullBreachTimer;	//delete this.$hullBreach; // TEST: break cycling
					//may as well seal the breach, the hold's empty!
					break;
				}
			default:
				;
		}
	}

	this.$addMessageRoutines = function (ship, message) // NPC // not used
	{
		var wp = worldScripts.pods;
		var sc = ship.script;
		sc.$initialiseMsgTimer = wp.$initialiseMsgTimer;
		sc.$initialiseMsgTimer();
		//this.ship.script.$initialiseMsgTimer();
	}

	this._sendMessage = function (msgcode) // next code is linked to ship scripts. // ~ this.$communicate
	{
		if (worldScripts["pods"]._messageAllowed() && this.ship.target && this.ship.target.isPlayer)
			this.ship.commsMessage(expandDescription("[" + msgcode + "]"))
	}

	this._initialiseItem = function (scooper, item) // not used
	{
		if (scooper && item) {
			var s;
			if (scooper.isPlayer) {
				s = "player";
			} else {
				s = "npc";
			}
			// for pods_missilePod
			if (this.logging) log(this.name, displayNameForCommodity(item.commodity) + "(" + item.name + ") [" + item.$missileType + "] scooped by " + s + "-ship: " + scooper.name);
		} else log(this.name, "ERROR: no var in the function this._initialiseItem(scooper,item)");
	}

}).call(this);
Scripts/pods_bigPod-gems.js
this.name			= "pods_bigPod-gems";
this.author			= "Thargoid";
this.copyright		= "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description	= "Generates a pod of 1-200 g capacity of gemstones";

this.logging = false; // false for release

this.shipWasScooped = function (scooper) {
	"use strict";
	var wp = worldScripts.pods;
	let type = this.ship.commodity; // setCargoType
	let quantity = parseInt(this.ship.commodityAmount);
	// content cargopod role
	if (this.logging && type) log("pods", this.name + " : input setCargo : " + type + "[" + quantity + "] for " + scooper.name);

	if (wp && scooper.isPlayer) {
		if (!type) {
			var msg;
			let award = (Math.ceil(Math.random() * 200));

			if (player.ship.cargoSpaceAvailable > 0) {
				manifest["gem_stones"] += award; // this.ship.setCargo(cargo, award);
				//player.consoleMessage(award + " grams Gem-Stones", 6);
				msg = award + " grams Gem-Stones";
			} else {
				//player.consoleMessage("Not enough space in your cargo hold for the pod!", 6);
				msg = "Not enough space in your cargo hold for the pod!";
			}
			wp._delayedMsg(msg, 3);
		} else {
			wp._msgCargo(type, quantity);
			if (this.logging) log(this.name, "player scooped pre-setCargo");
		}
	}
}
Scripts/pods_bigPod-kg.js
this.name			= "pods_bigPod-kg";
this.author			= "Thargoid";
this.copyright		= "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description	= "Generates a pod of 1-100 kg capacity";

this.logging = false; // false for release

this.shipWasScooped = function (scooper) {
	"use strict";
	var wp = worldScripts.pods;
	let type = this.ship.commodity; // setCargoType
	let quantity = parseInt(this.ship.commodityAmount);
	// content cargopod role
	if (this.logging && type) log("pods", this.name + " : input setCargo : " + type + "[" + quantity + "] for " + scooper.name);

	if (wp && scooper.isPlayer) {
		if (!type) {
			var msg;
			let award = (Math.ceil(Math.random() * 100));
			let cargo = expandDescription('[pods_contentKilos]');

			if (player.ship.cargoSpaceAvailable > 0) {
				manifest[cargo] += award;
				msg = award + " kilograms " + displayNameForCommodity(cargo);
			} else {
				msg = "Not enough space in your cargo hold for the pod!";
			}
			wp._delayedMsg(msg, 3);
		} else {
			wp._msgCargo(type, quantity);
			if (this.logging) log(this.name, "player scooped pre-setCargo");
		}
	}
}
Scripts/pods_bigPod-t.js
this.name			= "pods_bigPod-t";
this.author			= "Thargoid";
this.copyright		= "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description	= "Generates a pod of 1-10 (2-20 for pods_CCL_bigPod) ton capacity";

this.logging = false; // false for release

this.shipWasScooped = function (scooper) {
	"use strict";
	var wp = worldScripts.pods;
	let type = this.ship.commodity; // setCargoType
	let quantity = parseInt(this.ship.commodityAmount);
	// content cargopod role
	if (this.logging && type) log("pods", this.name + " : input setCargo : " + type + "[" + quantity + "] for " + scooper.name);

	if (wp && scooper.isPlayer && player.ship.cargoSpaceAvailable > 0) {
		if (!type) {
			var msg;
			let award = (Math.ceil(Math.random() * 10));
			let cargo = expandDescription('[pods_contentTons]');

			if (this.ship && this.ship.hasRole("pods_CCL_bigPod-t")) {
				award *= 2;
			};

			if (player.ship.cargoSpaceAvailable > award) {
				manifest[cargo] += award; // this.ship.setCargo(cargo, award);
				msg = award + " tons " + displayNameForCommodity(cargo);
			} else {
				manifest[cargo] += player.ship.cargoSpaceAvailable; // this.ship.setCargo(cargo, player.ship.cargoSpaceAvailable);
				msg = player.ship.cargoSpaceAvailable + " tons " + displayNameForCommodity(cargo) + " - hold full";
			}
			wp._delayedMsg(msg, 3);
		} else {
			wp._msgCargo(type, quantity);
			if (this.logging) log(this.name, "player scooped pre-setCargo");
		}
	}
}
Scripts/pods_bigPod.js
this.name 			= "pods_bigPod";
this.author 		= "Thargoid";
this.copyright 		= "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description 	= "Generates a bigpods: pod of 1-10 (2-20 for pods_CCL_bigPod) ton capacity, pod of 1-100 kg capacity, pod of 1-200 g capacity of gemstones";

this.logging = false; // false for release

this.shipWasScooped = function (scooper) {
	"use strict";
	// initialise scooper
	var n, scr = scooper;
	if (scr.isPlayer) {
		n = "player";
	} else {
		n = "npc";
	}
	// initialise item
	var itm = this.ship;
	var dk = itm.dataKey;
	var pr = itm.primaryRole;

	var wp = worldScripts.pods;
	if (wp) {
		var cargo, msg, tc, setNewBarrel; //  "1t-cargopod"
		let type = itm.commodity;
		let quantity = parseInt(itm.commodityAmount);

		tc = pr + "(bigpod)";
		if (!type) { // initialise RFID-broken bigpod: check roles and set content (type, quantity)
			// initialise bigBarrels
			if (itm && itm.hasRole("bigpod")) {
				if (dk === "pods_bigBarrel_t" || dk === "pods_CCL_bigBarrel_t") {
					setNewBarrel = true;
					cargo = expandDescription('[pods_contentTons]');
					quantity = (Math.ceil(Math.random() * 10));
					if (dk === "pods_CCL_bigBarrel_t") {
						quantity *= 2;
					}
				} else if (dk === "pods_bigBarrel_kg") {
					cargo = expandDescription('[pods_contentKilos]');
					quantity = (Math.ceil(Math.random() * 100));
				} else { // if (dk === "pods_bigBarrel_gems") {
					cargo = "gem_stones";
					quantity = (Math.ceil(Math.random() * 200));
				}
				type = cargo;
			} else {
				log(this.name, "Error: no " + tc + " role in the [" + dk + "]");
				return;
			}
			if (this.logging) log(this.name, "initialised a " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");

			// set a new barrels or save a barrel:
			if (setNewBarrel && scr.isPlayer) {
				scr.manifest[type] += quantity;
			} else {
				this.ship.setCargo(type, quantity);
			}
			// operation : scr.manifest[type] += quantity - not worked for NPC

			// events and messages
			if (scr.isPlayer) {
				msg = wp._msgCargo(type, quantity); // standart named cargo
				wp._delayedMsg(msg, 3);
				// reset / broken RFID for scooped pods (kg/gram)
				if (worldScripts["Cargo Scanner"] && itm.shipUniqueName) itm.shipUniqueName = displayNameForCommodity(type);
			}
		} else { // pre-set bigpod
			if (this.logging) log(this.name, "identified a pre-set " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");

			// reset a barrel var: for NPC not replaced bulk barrels --> operation : scr.manifest[type] += quantity - not worked for NPC

			// events and messages
			if (scr.isPlayer) {
				if (setNewBarrel) { // not used this version
					scr.manifest[type] += quantity;
					wp._delayedRemoveCargo(scr, itm, 0.75);
				}
				msg = wp._msgCargo(type, quantity); // has_scoop_message = no
				wp._delayedMsg(msg, 1); // player.consoleMessage(msg, 6);
			}
		}
		if (this.logging) log(this.name, n + " scooped: " + type);
	}
}
Scripts/pods_breachPod.js
this.name 			= "pods_breachPod";
this.author 		= "Thargoid";
this.copyright 		= "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description 	= "Script for an exploding pod, causing damage plus a hull breach and cargo loss";

this.logging = false; // false for release

this.shipWasScooped = function (scooper) {
	"use strict";
	// initialise scooper
	var n, scr = scooper;
	if (scr.isPlayer) {
		n = "player";
	} else {
		n = "npc";
	}
	// initialise item
	var itm = this.ship;
	var dk = itm.dataKey;
	var pr = itm.primaryRole;

	var wp = worldScripts.pods;
	if (wp) {
		var cargo, msg, tc; //  "1t-cargopod"
		let type = itm.commodity;
		let quantity = parseInt(itm.commodityAmount);

		tc = pr + "(breach)";
		if (!type) { // initialise RFID-broken breach pod: set content (type, 1)
			// initialise breach / set 1 firearms in the breach pod for NPC : quantity = 1; // radioactives / alien_items / firearms
			if (scr.isPlayer) {
				type = "radioactives";
			} else {
				type = "firearms";
			} // used --> displayNameForCommodity
			// set a barrel
			itm.setCargo(type, quantity);
			if (this.logging) log(this.name, "initialised a " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");
		} else { // pre-set cargopod
			if (this.logging) log(this.name, "identified a pre-set " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");
		}

		wp._delayedRemoveCargo(scr, itm, 0.75);
		//msg = wp._msgCargo(type, quantity); // breach pod / has_scoop_message = yes //player.consoleMessage(msg, 6); // wp._delayedMsg(msg, 1);

		// events and messages : damage in both events
		if (scr.isPlayer) {
			msg = "ALERT - Emergency repair systems activated.";
			if(!wp._delayedMsg_breachPod(msg, 4)) { // damage + hullBreach + msg
				log(this.name, "shipWasScooped encountered error calling wp._delayedMsg_breachPod(msg, 4) with scr = " + scr + ", itm = " + itm + ", pr = " + pr + ", type = " + type + ", quantity = " + quantity);
				return;
			}
		} else {
			if(!wp._addHullBreachRoutines(scr)) { // setup : damage + hullBreach
				log(this.name, "shipWasScooped encountered error calling wp._addHullBreachRoutines(scr) with scr = " + scr + ", itm = " + itm + ", pr = " + pr + ", type = " + type + ", quantity = " + quantity);
				return;
			}
			if (wp.npc_message) {
				if (Math.random() > 0.5) {
					msg = "Who transported it is bad " + expandDescription('[pods_radioactives]') + " as " + displayNameForCommodity(type) + "?";
				} else {
					msg = "Help, it is deadly " + displayNameForCommodity(type) + "! Hull breach...";
				}
				scr.commsMessage(msg);
			}
		}
		if (this.logging) log(this.name, n + " scooped a breach pod: " + type);
	}
}
Scripts/pods_emptyPod.js
this.name 			= "pods_emptyPod";
this.author 		= "Thargoid";
this.copyright 		= "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description 	= "Generates an empty or otherwise worthless cargo pod";

this.logging = false; // false for release

this.shipWasScooped = function (scooper) {
	"use strict";
	// initialise scooper
	var n, scr = scooper;
	if (scr.isPlayer) {
		n = "player";
	} else {
		n = "npc";
	}
	// initialise item
	var itm = this.ship;
	var dk = itm.dataKey;
	var pr = itm.primaryRole;

	var wp = worldScripts.pods;
	if (wp) {
		var cargo, msg, tc; //  "1t-cargopod"
		let type = itm.commodity;
		let quantity = parseInt(itm.commodityAmount);

		tc = pr + "(empty)";
		if (!type) { // initialise RFID-broken empty pod: set content ("empty", 1)
			// initialise empty cargo : type = "null"; quantity = 0;
			if (this.logging) log(this.name, "initialised a " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");

			// events and messages
			if (scr.isPlayer) {
				wp._delayedMsg(expandDescription('[pods_emptyPodMessage]'), 2);
			}
		} else { // pre-set cargopod
			if (this.logging) log(this.name, "identified a pre-set " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");

			// events and messages
			if (scr.isPlayer) {
				msg = wp._msgCargo(type, quantity); // has_scoop_message = no
				player.consoleMessage(msg, 6); // wp._delayedMsg(msg, 1);
			}
		}
		if (this.logging) log(this.name, n + " scooped: " + type);
	}
}
Scripts/pods_explodingPod.js
this.name 			= "pods_explodingPod";
this.author 		= "Thargoid";
this.copyright 		= "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description 	= "Script for an exploding pod. No cargo loss, just damage to ship and scoops destroyed";

this.logging = false; // false for release

this.shipWasScooped = function (scooper) {
	"use strict";
	// initialise scooper
	var n, scr = scooper;
	if (scr.isPlayer) {
		n = "player";
	} else {
		n = "npc";
	}
	// initialise item
	var itm = this.ship;
	var dk = itm.dataKey;
	var pr = itm.primaryRole;

	var wp = worldScripts.pods;
	if (wp) {
		var cargo, msg, tc; //  "1t-cargopod"
		let type = itm.commodity;
		let quantity = parseInt(itm.commodityAmount);

		tc = pr + "(exploding)";
		if (!type) { // initialise RFID-broken exploding pod: set content (null, 1)
			// initialise an exploding cargo : type = "null"; quantity = 0; // set a barrel : null set
			if (this.logging) log(this.name, "initialised a " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");
		} else { // pre-set cargopod
			if (this.logging) log(this.name, "identified a pre-set " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");
			// delete a barrel
			wp._delayedRemoveCargo(scr, itm, 0.75);
		}

		// events and messages : exploded in both events
		if (scr.isPlayer) {
			msg = "ALERT - Pod cracked and exploded during scooping. Scoops destroyed!";
			wp._delayedMsg_expPod(msg, 2);
		} else {
			scr.removeEquipment("EQ_FUEL_SCOOPS");
			if (wp.npc_message) {
				if (Math.random() > 0.5) {
					msg = expandDescription('[msg_exploding]');
				} else {
					msg = "It is bad cannister for " + expandDescription('[pods_firearms]') + "!";
				}
				scr.commsMessage(msg);
			}
		}
		if (this.logging) log(this.name, n + " scooped a exploded pod: " + type);
	}
}
Scripts/pods_fuelPod.js
this.name 			= "pods_fuelPod";
this.author 		= "Thargoid";
this.copyright 		= "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description 	= "A cargo pod containing up to 3 ly of fuel, or sometimes non-fuel which contaminates everything";
this.version 		= "2.5.5";

this.logging = false; // false for release

this.shipWasScooped = function (scooper) {
	"use strict";
	// initialise scooper
	var n, scr = scooper;
	if (scr.isPlayer) {
		n = "player";
	} else {
		n = "npc";
	}
	// initialise item
	var itm = this.ship;
	var dk = itm.dataKey;
	var pr = itm.primaryRole;

	var wp = worldScripts.pods;
	if (wp) {
		var cargo, msg, tc; //  "1t-cargopod"
		let type = itm.commodity;
		let quantity = parseInt(itm.commodityAmount);

		tc = "fuel-tank";
		if (!type) { // set content ("fuel", quantity)
			type = "quirium fuel";
			// initialise a fuel pod, events and messages
			let newfuel = ((Math.ceil(Math.random() * 32)) / 10);
			if (newfuel < 3.1) {
				scr.fuel += newfuel;
				if (scr.isPlayer) player.consoleMessage("Fuel Tank - " + newfuel + " ly transferred!", 6);
			} else {
				scr.fuelLeakRate = 10;
				if (scr.isPlayer) {
					wp.$warning_sound.play();
					wp._delayedMsg("ALERT - Transferred substance is not witchspace fuel! Tanks contaminated, venting...", 2);
				}
			}
		} else { // pre-set fuel pod
			if (this.logging) log(this.name, "identified a pre-set " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");

			// events and messages
			if (scr.isPlayer) {
				player.consoleMessage("Fuel Tank - No fuel for transfer!", 6);
				msg = wp._msgCargo(type, quantity); // has_scoop_message = no
				player.consoleMessage(msg, 6); // wp._delayedMsg(msg, 1);
			}
		}
		if (this.logging) log(this.name, n + " scooped: " + type);
	}
}
Scripts/pods_jamPod.js
this.name 			= "pods_jamPod";
this.author 		= "Thargoid";
this.copyright 		= "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description 	= "Script to jam a pod in the fuel scoops, disabling them";

this.logging = false; // false for release

this.shipWasScooped = function (scooper) {
	"use strict";
	// initialise scooper
	var n, scr = scooper;
	if (scr.isPlayer) {
		n = "player";
	} else {
		n = "npc";
	}
	// initialise item
	var itm = this.ship;
	var dk = itm.dataKey;
	var pr = itm.primaryRole;

	var wp = worldScripts.pods;
	if (wp) {
		var cargo, msg, tc; //  "1t-cargopod"
		let type = itm.commodity;
		let quantity = parseInt(itm.commodityAmount);

		tc = pr + "(jam)";
		if (!type) { // initialise RFID-broken jammed pod: set content (null, 1)
			// jammed cargo : type = "null"; quantity = 0; // set a barrel : null set
			if (this.logging) log(this.name, "initialised a " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");
		} else { // pre-set cargopod
			if (this.logging) log(this.name, "identified a pre-set " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");
			// delete a barrel
			wp._delayedRemoveCargo(scr, itm, 0.75);
		}

		// events and messages : jammed in both events
		if (scr.isPlayer) {
			msg = "ALERT - Cargo pod jammed in fuel scoops. Scoops disabled.";
			wp._delayedMsg_jamPod(msg, 2);
		} else {
			scr.setEquipmentStatus("EQ_FUEL_SCOOPS", "EQUIPMENT_DAMAGED");
			if (wp.npc_message) {
				msg = expandDescription('[msg_jamming]');
				scr.commsMessage(msg);
			}
		}
		if (this.logging) log(this.name, n + " scooped a jammed pod: " + type);
	}
}
Scripts/pods_missilePod.js
this.name 			= "pods_missilePod";
this.author 		= "Thargoid & Arexack Heretic & Rustem";
this.copyright 		= "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description 	= "A cargo pod containing either a standard or hardened missile";

"use strict";

this.logging = false; // false for release

this.ship.$missileType = null;

this.shipSpawned = function () {
	if (!this.ship) return;
	this.ship.$missileType = (Math.random() > 0.25 ? "standard" : "hardened");
	//var si = this.ship.scriptInfo;	//var pr = this.ship.primaryRole;
	//if (si && si.missileType == "hardened") this.ship.$missileType = "hardened"
	//else if (si && si.missileType == "standard") this.ship.$missileType = "standard";
	delete this.shipSpawned;
}

this.shipWasScooped = function (scooper) {
	// initialise scooper
	var n, scr = scooper;
	if (scr.isPlayer) {
		n = "player";
	} else {
		n = "npc";
	}
	// initialise item
	var itm = this.ship;
	var dk = itm.dataKey;
	var pr = itm.primaryRole;

	var wp = worldScripts.pods;
	if (wp) {
		var cargo, msg, tc; //  "1t-cargopod"
		let type = itm.commodity;
		let quantity = parseInt(itm.commodityAmount);

		tc = "missile";
		if (!type) { // initialise RFID-broken missile: check missiles, pylon and set content (type, 1)
			// check content cargopod role

			// initialise a missile, events and messages
			if (scr.missiles.length < scr.missileCapacity) {
				itm.$missileType = this.$awardMissile(scr, itm);
				tc = itm.$missileType + " missile";
				if (this.logging) log(this.name, n + " scooped a " + tc + ", mounted to pylon");
			} else // cargo hold
			{
				if (!itm.missileType) itm.$missileType = (Math.random() > 0.25 ? "standard" : "hardened"); // reserv. string
				if (itm.setCargo("firearms")) tc = itm.$missileType + " missile";
				if (scr.isPlayer) {
					wp._delayedMsg("1 " + tc + " (Firearms)", 2);
					if (worldScripts["Cargo Scanner"] && itm.shipUniqueName) itm.shipUniqueName = itm.$missileType; // TODO: telescope indentifed, moved to _delayedMsg / _msgCargo
				}
			}
			if (this.logging) log(this.name, n + " scooped: " + tc);
		} else { // pre-set missile pod
			if (this.logging) log(this.name, "identified a pre-set " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");

			// re-initialise a missile, events and messages
			if (type != "firearms") {
				itm.$missileType = null;
				delete this.shipDied;
			}
			if (itm.$missileType && scr.missiles.length < scr.missileCapacity) {
				itm.$missileType = this.$awardMissile(scr, itm); // adjustCargo/delete/remove for empty of the barrel?
				tc = itm.$missileType + " missile";
				wp._delayedRemoveCargo(scr, itm, 0.75);
				if (this.logging) log(this.name, n + " scooped a " + tc + ", mounted to pylon");
			} else // cargo hold
			{
				if (scr.isPlayer) {
					msg = wp._msgCargo(type, quantity); // has_scoop_message = no
					wp._delayedMsg(msg, 1); // player.consoleMessage(msg, 6);
					if (itm.$missileType && worldScripts["Cargo Scanner"] && itm.shipUniqueName) itm.shipUniqueName = itm.$missileType;
				}
				if (this.logging) log(this.name, n + " scooped a pre-set " + tc + ": " + type);
			}
		}
	}
	//delete this.shipWasScooped; // one scoop attempt
}

this.$awardMissile = function (scooper, item) {
	var wp = worldScripts.pods;
	var scr = scooper;
	var eq, mt = item.$missileType;
	if (!mt) {
		let choice = (Math.ceil(Math.random() * 4));
		if (choice == 4) {
			mt = "hardened";
		} else {
			mt = "standard";
		}
	}
	eq = (mt === "standard" ? "EQ_MISSILE" : "EQ_HARDENED_MISSILE");
	if (scr.awardEquipment(eq)) {
		if (scr.isPlayer) {
			if (wp) wp.$warning_sound.play();
			player.consoleMessage("Pylon mount: Missile class - " + mt, 6);
		}
		return mt;
	} else return "unarmed";
}

this.shipDied = function () {
	delete this.shipDied; // prefent recursion
	// TODO: Upgraded a method and tuned a value of the energy detonate in missileBarrel shipdata
	this.ship.switchAI("missileAI.plist");
	this.ship.AIState = "DETONATE";
}
Scripts/pods_piggybankPod.js
this.name 			= "pods_piggyBankPod";
this.author 		= "Thargoid";
this.copyright 		= "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description 	= "Generates a pod with someone's personal effects, including 1-2000 credits";

this.logging = false; // false for release

this.shipWasScooped = function (scooper) {
	"use strict";
	// initialise scooper
	var n, scr = scooper;
	if (scr.isPlayer) {
		n = "player";
	} else {
		n = "npc";
	}
	// initialise item
	var itm = this.ship;
	var dk = itm.dataKey;
	var pr = itm.primaryRole;

	var wp = worldScripts.pods;
	if (wp) {
		var cargo, msg, tc; //  "1t-cargopod"
		let type = itm.commodity;
		let quantity = parseInt(itm.commodityAmount);

		tc = pr + "(piggybank)";
		if (!type) { // initialise RFID-broken piggybank pod
			// piggybank pod : type = "null"; quantity = 0;
			if (this.logging) log(this.name, "initialised a " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");

			// set a barrel : null set : empty pod, only credits
		} else { // pre-set 1t-cargopod
			if (this.logging) log(this.name, "identified a pre-set " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");

			// events and messages
			//if (scr.isPlayer) {
			//msg = wp._msgCargo(type,quantity); // has_scoop_message = yes
			//player.consoleMessage(msg, 6); // wp._delayedMsg(msg, 1);
			//}
		}
		// events and messages : added credits in both events for player only
		if (scr.isPlayer) {
			let podloot = (5 + Math.ceil(Math.pow(Math.random(), 3) * 2000));
			player.credits += podloot;
			wp._delayedMsg("Pod contains someone's personal effects, including " + podloot + " credits!", 5);
			if (this.logging) log(this.name, "+" + podloot + " credits");
		}
		if (this.logging) log(this.name, n + " scooped: " + type);
	}
}
Scripts/pods_retryPod.js
this.name 			= "pods_retryPod";
this.author 		= "Thargoid";
this.copyright 		= "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description 	= "Script to cause pod scooping frustration";

this.logging = false; // false for release

this.shipWasScooped = function (scooper) {
	"use strict";
	// initialise scooper
	var n, scr = scooper;
	if (scr.isPlayer) {
		n = "player";
	} else {
		n = "npc";
	}
	// initialise item
	var itm = this.ship;
	var dk = itm.dataKey;
	var pr = itm.primaryRole;

	var wp = worldScripts.pods;
	if (wp) {
		var cargo, msg, tc; //  "1t-cargopod"
		let type = itm.commodity;
		let quantity = parseInt(itm.commodityAmount);

		tc = pr + "(retry)";
		if (!type) { // initialise RFID-broken 1t-cargopod: set content (null, 0)
			// retry pod : type = "null"; quantity = 0;
			if (this.logging) log(this.name, "initialised a " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");

			// all types of retrypod spawned random standart 1t-cargopod
			var p;
			if (itm && itm.hasRole("pods_UPS_retryPod")) {
				p = scr.spawn("[ups-barrel]", 1);
			} else if (itm && itm.hasRole("pods_CCL_retryPod")) {
				p = scr.spawn("[ccl_crateB]", 1);
			} else if (itm && itm.hasRole("pods_CWT_retryPod")) {
				p = scr.spawn("[hexapod_c]", 1);
			} else {
				p = scr.spawn("[barrel]", 1);
			}
			if (p && type && quantity) p[0].setCargo(type, quantity); // else error
			if (scr.isPlayer) wp._delayedMsg("ALERT - Cargo pod misaligned in scoops. Ejecting - please retry.", 2);
		} else { // pre-set cargopod
			if (this.logging) log(this.name, "identified a pre-set " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");

			// events and messages
			if (scr.isPlayer) {
				msg = wp._msgCargo(type, quantity); // has_scoop_message = no
				player.consoleMessage(msg, 6);
			}
		}
		if (this.logging) log(this.name, n + " scooped: " + type);
	}
}
Scripts/pods_standardPod-t.js
this.name 			= "pods_standardPod-1t";
this.author 		= "Thargoid & Rustem";
this.copyright		= "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description 	= "A smaller script for alternative standard 1t pods, random content, perhaps with trumble. Used for external dependency barrels.";

this.logging = false; // false for release

this.shipWasScooped = function (scooper) {
	"use strict";
	// initialise scooper
	var n, scr = scooper;
	if (scr.isPlayer) {
		n = "player";
	} else {
		n = "npc";
	}
	// initialise item
	var itm = this.ship;
	var dk = itm.dataKey;
	var pr = itm.primaryRole;

	var wp = worldScripts.pods;
	if (wp) {
		var cargo, msg, tc; //  "1t-cargopod"
		let type = itm.commodity;
		let quantity = parseInt(itm.commodityAmount);

		tc = pr + "(1t-random)";
		if (!type) { // initialise RFID-broken 1t-cargopod: check scriptInfo and set content (type, quantity)
			// initialise cargo type // TODO: need edit/delete trumble part. //quantity = 1;
			if (scr.isPlayer && missionVariables.novacount && player.ship.equipmentStatus("EQ_TRUMBLE") === "EQUIPMENT_UNAVAILABLE") {
				type = "trumble";
			} else // set random cargo in the 1t-cargopod
			{
				type = expandDescription('[pods_contentTons]');
			}
			if (this.logging) log(this.name, "initialised a " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");

			// set a barrel
			itm.setCargo(type, quantity);

			// events and messages
			if (scr.isPlayer) {
				if (type !== "trumble") {
					msg = wp._msgCargo(type, quantity); // standart named cargo
					wp._delayedMsg(msg, 2);
					// reset / broken RFID for 1t-cargopod role
					if (worldScripts["Cargo Scanner"] && itm.shipUniqueName) itm.shipUniqueName = displayNameForCommodity(type);
				} else {
					wp._scoopTrumbleRoutines(scr, itm, type, this.logging);
				}
			}
		} else { // pre-set 1t-cargopod
			if (this.logging) log(this.name, "identified a pre-set " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");

			// events and messages
			if (scr.isPlayer) {
				msg = wp._msgCargo(type, quantity); // has_scoop_message = no
				player.consoleMessage(msg, 6); // wp._delayedMsg(msg, 1);

				// perhaps for trumbles
				if (((type === "food" || type === "furs") && Math.random() < 0.1) ||
					(missionVariables.novacount && player.ship.equipmentStatus("EQ_TRUMBLE") === "EQUIPMENT_UNAVAILABLE")) {

					wp._scoopTrumbleRoutines(scr, itm, type, this.logging);
				}
			}
		}
		if (this.logging) log(this.name, n + " scooped a random pod: " + type);
	}
}
Scripts/pods_standardPod.js
this.name 			= "pods_standardPod";
this.author 		= "Thargoid";
this.copyright 		= "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description 	= "Generates message and award for alternative standard 1t pods";

this.logging = false; // false for release

this.shipWasScooped = function (scooper) {
	"use strict";
	// initialise scooper
	var n, scr = scooper;
	if (scr.isPlayer) {
		n = "player";
	} else {
		n = "npc";
	}
	// initialise item
	var itm = this.ship;
	var dk = itm.dataKey;
	var pr = itm.primaryRole;

	var wp = worldScripts.pods;
	if (wp) {
		var cargo, msg, tc; //  "1t-cargopod"
		let type = itm.commodity;
		let quantity = parseInt(itm.commodityAmount);

		tc = pr + "(standard)";
		if (!type) { // initialise RFID-broken 1t-cargopod: check scriptInfo and set content (type, quantity)
			// initialise cargo type
			type = itm.scriptInfo.podType; //quantity = 1;
			switch (type) {
				case "food":
					{
						cargo = expandDescription('[pods_food]');
						break;
					}
				case "textiles":
					{
						cargo = expandDescription('[pods_textiles]');
						break;
					}
				case "radioactives":
					{
						cargo = expandDescription('[pods_radioactives]');
						break;
					}
				case "slaves":
					{
						cargo = expandDescription('[pods_slaves]');
						break;
					}
				case "liquor_wines":
					{
						cargo = expandDescription('[pods_liquorWines]');
						break;
					}
				case "luxuries":
					{
						cargo = expandDescription('[pods_luxuries]');
						break;
					}
				case "narcotics":
					{
						cargo = expandDescription('[pods_narcotics]');
						break;
					}
				case "computers":
					{
						cargo = expandDescription('[pods_computers]');
						break;
					}
				case "machinery":
					{
						cargo = expandDescription('[pods_machinery]');
						break;
					}
				case "alloys":
					{
						cargo = expandDescription('[pods_alloys]');
						break;
					}
				case "firearms":
					{
						cargo = expandDescription('[pods_firearms]');
						break;
					}
				case "furs":
					{
						cargo = expandDescription('[pods_furs]');
						break;
					}
				case "minerals":
					{
						cargo = expandDescription('[pods_minerals]');
						break;
					}
			}
			if (!cargo || cargo === "" || !type || type === "") {
				log(this.name, "ERROR: Unable to set correct a cargo type by standard routine in the [" + dk + "]");
				return;
			}
			if (this.logging) log(this.name, "initialised a " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");

			// set a barrel
			itm.setCargo(type, quantity); // : save a barrel // scr.manifest[type] += quantity;  // : set a new barrel for player

			// events and messages
			if (scr.isPlayer) {
				msg = "1 ton " + cargo + " (" + displayNameForCommodity(type) + ")"; // description named cargo / msg = wp._msgCargo(type,quantity); // standart named cargo
				wp._delayedMsg(msg, 2);
				// reset / broken RFID for 1t-cargopod role
				if (worldScripts["Cargo Scanner"] && itm.shipUniqueName) itm.shipUniqueName = displayNameForCommodity(type);
			}
		} else { // for pre-set 1t-cargopod
			if (this.logging) log(this.name, "identified a pre-set " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");

			// events and messages
			if (scr.isPlayer) {
				msg = wp._msgCargo(type, quantity); // has_scoop_message = no
				player.consoleMessage(msg, 6); // wp._delayedMsg(msg, 1);
			}
		}
		if (this.logging) log(this.name, n + " scooped a standard pod: " + type);
	}
}
Scripts/pods_trumblePod.js
this.name 			= "pods_trumblePod";
this.author 		= "Thargoid";
this.copyright 		= "Creative Commons: attribution, non-commercial, sharealike with clauses - see readme.txt";
this.description 	= "Script for a pod with a trumble in it. OK so I succumbed ;)";

this.logging = false; // false for release

this.shipWasScooped = function (scooper) {
	"use strict";
	// initialise scooper
	var n, scr = scooper;
	if (scr.isPlayer) {
		n = "player";
	} else {
		n = "npc";
	}
	// initialise item
	var itm = this.ship;
	var dk = itm.dataKey;
	var pr = itm.primaryRole;

	var wp = worldScripts.pods;
	if (wp) {
		var cargo, msg, tc; //  "1t-cargopod"
		let type = itm.commodity;
		let quantity = parseInt(itm.commodityAmount);

		tc = pr + "(trumble)";
		if (!type) { // initialise RFID-broken 1t-cargopod: check scriptInfo and set content (type, quantity)
			// set 1 food or furs in the trumble pod for NPC //quantity = 1;
			if (scr.isPlayer) {
				if (this._checkTrumble()) {
					type = "trumble";
				} else type = expandDescription('[pods_contentTons]'); // set random cargo in the cargopod for player
			} else type = (Math.random() > 0.75 ? "food" : "furs");
			if (this.logging) log(this.name, "initialised a " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");

			// set a barrel
			itm.setCargo(type, quantity);

			// events and messages
			if (scr.isPlayer) {
				if (!this.$isTrumble) {
					msg = wp._msgCargo(type, quantity); // standart named cargo
					wp._delayedMsg(msg, 2);
					// reset / broken RFID for 1t-cargopod role
					if (worldScripts["Cargo Scanner"] && itm.shipUniqueName) itm.shipUniqueName = displayNameForCommodity(type);
				} else {
					wp._addTrumbleRoutines(scr, itm, type, this.logging);
				}
			}
		} else { // pre-set 1t-cargopod
			if (this.logging) log(this.name, "identified a pre-set " + tc + ": " + type + "[" + quantity + "] for " + n + "-scooping");

			// events and messages
			if (scr.isPlayer) {
				//msg = wp._msgCargo(type, quantity); // has_scoop_message = yes
				//player.consoleMessage(msg, 6);

				// perhaps for trumbles
				if (this._checkTrumble()) {
					wp._addTrumbleRoutines(scr, itm, type, this.logging);
				}
			}
		}
		if (this.logging) log(this.name, n + " scooped a trumble pod: " + type);
	}
}

this.$isTrumble = false;

this._checkTrumble = function () {
	if (player.trumbleCount > 0 ||
		missionVariables.trumbles === "TRUMBLE_BOUGHT" && Math.random() < 0.1 ||
		missionVariables.novacount && player.ship.equipmentStatus("EQ_TRUMBLE") === "EQUIPMENT_UNAVAILABLE") {
		this.$isTrumble = true
	}
	return this.$isTrumble
}