Back to Index Page generated: Jun 26, 2025, 4:38:07 AM

Expansion Loadout By Category

Content

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description Orders all equipment on the F3 Ship Outfitting and F5 Status screens into a grouped structure with headers to make them easier to navigate. For Oolite 1.91 Orders all equipment on the F3 Ship Outfitting and F5 Status screens into a grouped structure with headers to make them easier to navigate. For Oolite 1.91
Identifier oolite.oxp.phkb.LoadoutByCategory oolite.oxp.phkb.LoadoutByCategory
Title Loadout By Category Loadout By Category
Category Miscellaneous Miscellaneous
Author phkb phkb
Version 1.5 1.5
Tags
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
Conflict Expansions
Information URL https://wiki.alioth.net/index.php/Loadout_by_Category n/a
Download URL https://wiki.alioth.net/img_auth.php/4/49/LoadoutByCategory.oxz n/a
License CC-BY-SA 4.0 CC-BY-SA 4.0
File Size n/a
Upload date 1748732950

Documentation

Also read http://wiki.alioth.net/index.php/Loadout%20By%20Category

readme.txt

Loadout By Category
by phkb

Overview
========
This expansion groups all equipment items on the F3 Ship Outfitting and F5 Status screens under related headings and sorted alphabetically to make the lists easier to read and navigate. So, on the F3 screen, all the laser equipment is gathered together under one heading, all the navigation equipment is gathered under another, and so on. The same groups are used on the F5 screen.

There is no other gameplay effect.

Working with Oolite 1.90
========================
There are two versions of this OXP:
    LoadoutByCategory.oxz
    LoadoutByCategory_190.oxz
Obviously, the latter of these items is for v1.90 of Oolite. You cannot run the former in 1.90, and you cannot run the latter in 1.91. Pick the version based on which version of Oolite you are using.

Notes
=====
The OXP works by adding a "sort_order" to every piece of equipment. Any equipment items that haven't been included explicitly will be included in the "General/Miscellaneous" section, but they won't in alphabetical order. 

In 1.91, a new sort order specific to the F3 Ship Outfitting was added - "purchase_sort_order". This OXP utilises this new property to sort the F3 screen independently of the F5 screen, which uses "sort_order".

License
=======
This work is licensed under the Creative Commons Attribution-Noncommercial-Share Alike 4.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/

Version History
===============
1.5
- Fixed compatibility with with ShipVersion.

1.4
- Fixed issue that was preventing the "Armour" heading from appearing on the F3 screen if Hard Ships and Iron Hide Armour were not installed.
- Updates with new equipment items.
- Moved all text into descriptions.plist for easier localisation.

1.3.4
- Updates with new equipment items.

1.3.3
- Removed debug message.

1.3.2
- Added info url to manifest file.
- Fixed incorrectly ordered items in version for 1.90.

1.3.1
- Fixed issued with missing entry in manifest file for 1.90 version.

1.3
- Fixed issue where going to the F5 page directly from a mission page would not add headers to the list.
- Moved "Auxillary Pylon" to Cargo section.

1.2
- Updated ordering on F5 page to keep more important equipment on the first page. 
- Utilises "purchase_sort_order" for equipment for the F3 screen.
- Minimum Oolite version now 1.91.

1.1
- Expanded to include headers on the F5 page.

1.0
- Initial release

Equipment

Name Visible Cost [deci-credits] Tech-Level
•• Armour •• yes 0 1+
•• Armour •• yes 0 1+
•• Astrogation •• yes 0 1+
•• Astrogation •• yes 0 1+
•• Berths/Weaponry •• yes 0 1+
•• Cargo/Mining •• yes 0 1+
•• Cargo/Mining •• yes 0 1+
•• Defensive •• yes 0 1+
•• Defensive •• yes 0 1+
•• Energy •• yes 0 1+
•• Energy •• yes 0 1+
•• Escorts/Fighters •• yes 0 1+
•• Escorts/Fighters •• yes 0 1+
•• General/Miscellaneous •• yes 0 1+
•• General/Miscellaneous •• yes 0 1+
•• Illicit •• yes 0 1+
•• Illicit •• yes 0 1+
•• Laser Weapons •• yes 0 1+
•• Laser Weapons •• yes 0 1+
•• Documentation •• yes 0 1+
•• Documentation •• yes 0 1+
•• Laser Mount Switching System •• yes 0 1+
•• Laser Mount Switching System •• yes 0 1+
•• M.F.D.s •• yes 0 1+
•• M.F.D.s •• yes 0 1+
•• Pylon Weapons •• yes 0 1+
•• Pylon Weapons •• yes 0 1+
•• Navigation •• yes 0 1+
•• Navigation •• yes 0 1+
•• Fuel •• yes 0 1+
•• Fuel •• yes 0 1+
•• Self-Repair System •• yes 0 1+
•• Self-Repair System •• yes 0 1+
•• Second-Hand Equipment •• yes 0 1+
•• Second-Hand Equipment •• yes 0 1+
•• Scanners •• yes 0 1+
•• Scanners •• yes 0 1+
•• Shields •• yes 0 1+
•• Shields •• yes 0 1+
•• Targeting •• yes 0 1+
•• Targeting •• yes 0 1+
•• Towbar and Accessories •• yes 0 1+
•• Towbar and Accessories •• yes 0 1+
•• Weaponry •• yes 0 1+

Ships

This expansion declares no ships.

Models

This expansion declares no models.

Scripts

Path
Config/script.js
"use strict";
this.name = "LoadoutCategories";
this.author = "phkb";
this.copyright = "(C) 2023 phkb.";
this.license = "CC-NC-by-SA 4.0";
this.description = "Controls the header items in the equipment lists";

this._useAstrogation = false;
this._eqSort = {};
this._missionScreen = false;

// configuration settings for use in Lib_Config
this._libSettings = {
	Name: this.name,
	Alias: expandDescription("[loadout_alias]"),
	Display: expandDescription("[loadout_display]"),
	Alive: "_libSettings",
	Bool: {
		B0: {
			Name: "_useAstrogation",
			Def: false,
			Desc: expandDescription("[loadout_use_astro]")
		},
		Info: expandDescription("[loadout_use_astro_desc]")
	},
};

// headers for the F3 Ship Outfitting screen
this._headers = ["EQ_REORDERING_REFUELING", "EQ_REORDERING_GENERAL", "EQ_REORDERING_LASERS", "EQ_REORDERING_MISSILES", "EQ_REORDERING_LMSS", 
    "EQ_REORDERING_TRACTORBEAM", "EQ_REORDERING_DEFENSIVE", "EQ_REORDERING_TARGETING", "EQ_REORDERING_SHIELDS", "EQ_REORDERING_CARGO", 
    "EQ_REORDERING_ENERGY", "EQ_REORDERING_REPAIRBOTS", "EQ_REORDERING_SCANNERS", "EQ_REORDERING_MFD", "EQ_REORDERING_LICENSES", "EQ_REORDERING_ILLICIT", 
    "EQ_REORDERING_NAVIGATION", "EQ_REORDERING_ASTROGATION", "EQ_REORDERING_SALVAGE", "EQ_REORDERING_ARMOUR", "EQ_REORDERING_ESCORTS"];

// headers for the F5 Status screen
this._headersAlt = ["EQ_REORDERING_REFUELING_F5", "EQ_REORDERING_GENERAL_F5", "EQ_REORDERING_LASERS_F5", "EQ_REORDERING_MISSILES_F5", "EQ_REORDERING_LMSS_F5", 
    "EQ_REORDERING_TRACTORBEAM_F5", "EQ_REORDERING_DEFENSIVE_F5", "EQ_REORDERING_TARGETING_F5", "EQ_REORDERING_SHIELDS_F5", "EQ_REORDERING_CARGO_F5", 
    "EQ_REORDERING_ENERGY_F5", "EQ_REORDERING_REPAIRBOTS_F5", "EQ_REORDERING_SCANNERS_F5", "EQ_REORDERING_MFD_F5", "EQ_REORDERING_LICENSES_F5", "EQ_REORDERING_ILLICIT_F5", 
    "EQ_REORDERING_NAVIGATION_F5", "EQ_REORDERING_ASTROGATION_F5", "EQ_REORDERING_SALVAGE_F5", "EQ_REORDERING_ARMOUR_F5", "EQ_REORDERING_ESCORTS_F5"];

//-------------------------------------------------------------------------------------------------------------
this.startUpComplete = function () {
	// register our settings, if Lib_Config is present
	if (worldScripts.Lib_Config) worldScripts.Lib_Config._registerSet(this._libSettings);
    if (missionVariables.LoadoutCategories_UseAstro) this._useAstrogation = (missionVariables.LoadoutCategories_UseAstro == "y" ? true : false);

	if (worldScripts.ShipConfiguration_Core) {
		var sc = worldScripts.ShipConfiguration_Core;
		for (var i = 0; i < this._headersAlt.length; i++) {
			sc._ignoreEquip.push(this._headersAlt[i]);
			sc._ignoreEquip.push(this._headers[i]);
		}
		sc._ignoreEquip.push("EQ_REORDERING_WEAPONONLY_F5");
		sc._ignoreEquip.push("EQ_REORDERING_BERTHWEAPON_F5");

	}

	this.$buildEquipmentSortOrderDict();
}

//-------------------------------------------------------------------------------------------------------------
this.playerWillSaveGame = function() {
    missionVariables.LoadoutCategories_UseAstro = (this._useAstrogation == true ? "y" : "n");
}

//-------------------------------------------------------------------------------------------------------------
this.playerBoughtEquipment = function(equipment, paid) {
    var p = player.ship;
    if (this._headers.indexOf(equipment) >= 0) p.removeEquipment(equipment);
}

/*
	Notes: By default, Oolite sorts the equipment items on the F5 Status screen in reverse order.
	So, the alphabetical list we've applied via the equipment-overrides.plist file ends up reversed.
	When it comes to adding headers to the F5 Status page, it means we add the header at the *end* of
	the list of equipment items (ie. making the order of the header item at the end of the section,
	rather than at the beginning).
	The solution that has been implemented in 1.91 is to separate the sort order property used for the
	F3 screen (it now uses purchase_sort_order). However, the process to produce the overrides file
	can't really be reworked to allow for a 1.90 configuration, so this OXP has been flagged as
	requiring 1.91 or later.
*/

//-------------------------------------------------------------------------------------------------------------
this.guiScreenChanged = function(to, from) {
	var p = player.ship;
	if (to == "GUI_SCREEN_STATUS") {
		this._sum = 0;
		/*
			mods like Hyperspace Hangar and ShipVersion are intercepting the playerBoughtNewShip process to
			bring up a mission screen immediately after purchasing a ship to ask addition questions.
			behind the scenes, guiScreen changes from GUI_SCREEN_SHIPYARD to GUI_SCREEN_STATUS
			before the mission screen can be shown. Timing issues result in some of the header equipment 
			items being visible on Ship Version's display screen.
			To counter this, I've added a brief delay before adding the header equipment items, via a 
			frame callback . That way, if guiScreen changes to GUI_SCREEN_MISSION I can react and 
			not add the headers.
		*/
		if (isValidFrameCallback(this._delay)) removeFrameCallback(this._delay);
		this._delay = addFrameCallback(this.$fcbDelay.bind(this));
	}
	if (from == "GUI_SCREEN_STATUS") {
		var i = this._headersAlt.length;
		while (i--) {
			player.ship.removeEquipment(this._headersAlt[i]);
		}
		player.ship.removeEquipment("EQ_REORDERING_BERTHWEAPON_F5");
		player.ship.removeEquipment("EQ_REORDERING_WEAPONONLY_F5");
	}
}

//-------------------------------------------------------------------------------------------------------------
this.$fcbDelay = function $fcbDelay(delta) {
	this._sum += delta;
	if (guiScreen != "GUI_SCREEN_STATUS") return;
	if (this._sum < 0.1) return;
	var p = player.ship;
	var eq = p.equipment;
	var i = this._headersAlt.length;
	while (i--) {
		var hdr = this._headersAlt[i];
		if (hdr.indexOf("EQ_REORDERING_LASERS") >= 0) {
			var found = false;
			if (p.forwardWeapon.equipmentKey != "EQ_WEAPON_NONE" || p.aftWeapon.equipmentKey != "EQ_WEAPON_NONE" || 
				p.portWeapon.equipmentKey != "EQ_WEAPON_NONE" || p.starboardWeapon.equipmentKey != "EQ_WEAPON_NONE") {
				if (p.passengerCapacity == 0) {
					p.awardEquipment("EQ_REORDERING_WEAPONONLY_F5");
				} else {
					p.awardEquipment("EQ_REORDERING_BERTHWEAPON_F5");
				}
			}
		} else {
			var item = EquipmentInfo.infoForKey(this._headersAlt[i]);
			var num1 = parseInt(item.scriptInfo.sortOrder) - 990;
			var num2 = parseInt(item.scriptInfo.sortOrder);
			var found = false;
			var eql = eq.length;
			while (eql--) {
				var item = eq[eql];
				var so = this._eqSort[item.equipmentKey];
				if (so && so > 0) {
					if (so > num1 && so < num2) {
						found = true;
						break;
					}
				}
			}
			if (found == true) {
				switch (this._headersAlt[i]) {
					case "EQ_REORDERING_NAVIGATION_F5":
						if (this._useAstrogation == false) p.awardEquipment(hdr);
						break;
					case "EQ_REORDERING_ASTROGATION_F5":
						if (this._useAstrogation == true) p.awardEquipment(hdr);
						break;
					default:
						p.awardEquipment(hdr);
				}
			}
		}
	}
	removeFrameCallback(this._delay);
}

//-------------------------------------------------------------------------------------------------------------
this.$buildEquipmentSortOrderDict = function() {
	var eq = EquipmentInfo.allEquipment;
	var i = eq.length;
	while (i--) {
		var item = eq[i];
		if (item.equipmentKey.indexOf("_F5") == -1 && item.hasOwnProperty("scriptInfo") && item.scriptInfo.hasOwnProperty("sortOrder")) {
			this._eqSort[item.equipmentKey] = parseInt(item.scriptInfo.sortOrder);
		}
	}
}
Scripts/loadout_categories_conditions.js
"use strict";
this.name = "LoadoutCategories_Conditions";
this.author = "phkb";
this.copyright = "2023 phkb";
this.description = "Condition script for equipment.";
this.license = "CC BY-NC-SA 3.0";

//-------------------------------------------------------------------------------------------------------------
this.allowAwardEquipment = function (equipment, ship, context) {
    if (equipment.indexOf("_F5") >= 0) {
        return (context == "scripted");
    }
    // hide headers for OXP-specific items
    switch (equipment) {
        case "EQ_REORDERING_WEAPONONLY":
        case "EQ_REORDERING_BERTHWEAPON":
            if (context != "scripted") return false;
            break;
        case "EQ_REORDERING_LMSS":
            if (!worldScripts.LMSS_Core) return false;
            break;
        case "EQ_REORDERING_TRACTORBEAM":
            if (!worldScripts.towbar) return false;
            break;
        case "EQ_REORDERING_REPAIRBOTS":
            if (!worldScripts["Repair System"] && !worldScripts.hardships && !worldScripts["Caduceus Damage Control Node"]) return false;
            break;
        case "EQ_REORDERING_SALVAGE":
            if (!worldScripts.Anarchies || player.ship.dockedStation.name !== "Salvage Gang") return false;
            break;
        case "EQ_REORDERING_NAVIGATION":
            if (worldScripts.LoadoutCategories._useAstrogation == true) return false;
            break;
        case "EQ_REORDERING_ASTROGATION":
            if (worldScripts.LoadoutCategories._useAstrogation == false) return false;
            break;
    }
    return true;
}