Back to Index Page generated: Jul 27, 2025, 4:28:30 AM

Expansion Skilled NPCs

Content

Warnings

  1. No version in dependency reference to oolite.oxp.Svengali.OXPConfig:null
  2. Optional Expansions mismatch between OXP Manifest and Expansion Manager at character position 0063 (DIGIT ZERO vs LATIN SMALL LETTER N)

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description Enables higher-quality flight AI for routine NPCs. Can be configured with OXPConfig or Library for even more challenge. Enables higher-quality flight AI for routine NPCs. Can be configured with OXPConfig or Library for even more challenge.
Identifier oolite.oxp.cim.skilled-npcs oolite.oxp.cim.skilled-npcs
Title Skilled NPCs Skilled NPCs
Category Mechanics Mechanics
Author cim cim
Version 1.7 1.7
Tags
Required Oolite Version
Maximum Oolite Version
Required Expansions
Optional Expansions
  • oolite.oxp.Svengali.OXPConfig:0
  • oolite.oxp.Svengali.Library:1.2
  • oolite.oxp.Svengali.OXPConfig:
  • oolite.oxp.Svengali.Library:1.2
  • Conflict Expansions
    Information URL http://wiki.alioth.net/index.php/Skilled_NPCs_OXP n/a
    Download URL https://wiki.alioth.net/img_auth.php/0/02/Skilled_NPCs.oxz http://wiki.alioth.net/img_auth.php/0/02/Skilled_NPCs.oxz
    License CC-BY-SA 3.0 CC-BY-SA 3.0
    File Size n/a
    Upload date 1753398228

    Documentation

    Also read http://wiki.alioth.net/index.php/Skilled%20NPCs

    Equipment

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

    Ships

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

    Models

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

    Scripts

    Path
    Scripts/skilled-npcs.js
    "use strict";
    this.author = "cim";
    this.copyright = "© 2011-2014 cim.";
    this.license = "CC-BY-SA 3.0";
    this.name = "Skilled NPCs";
    this.description = "OXP to enable high-skill combat routines on most standard NPCs";
    
    this.$baseline = 0;
    this.$baselinePirate = this.$baseline;
    this.$baselineAssassin = this.$baseline;
    this.$baselineHunter = this.$baseline;
    this.$baselineTrader = this.$baseline;
    this.$baselineAliens = this.$baseline;
    this.$baselineOthers = this.$baseline;
    this.$boostPirate = true;
    this.$boostAssassin = true;
    this.$boostHunter = true;
    this.$boostTrader = true;
    this.$boostAliens = true;
    this.$boostOthers = false;
    this.$defaultReaction = 1.5;
    this.$reactionPirate = this.$defaultReaction;
    this.$reactionAssassin = this.$defaultReaction;
    this.$reactionHunter = this.$defaultReaction;
    this.$reactionTrader = this.$defaultReaction;
    this.$reactionAliens = this.$defaultReaction;
    this.$reactionOthers = this.$defaultReaction;
    
    this.oxpcSettings = {
    	Info: {
    		Name: this.name,
    		Display: expandDescription("[skilled_config_alias]"),
    		InfoS: expandDescription("[skilled_config_sint_info]"),
    		InfoB: expandDescription("[skilled_config_bool_info]")
    	},
    	SInt0: { Name: "$baseline", Def: 0, Max: 10, Desc: expandDescription("[skilled_oxpc_difficulty_level]") },
    	Bool0: { Name: "$boostPirate", Def: true, Desc: expandDescription("[skilled_oxpc_pirates_assassins]") },
    	Bool1: { Name: "$boostHunter", Def: true, Desc: expandDescription("[skilled_oxpc_police_hunter]") },
    	Bool2: { Name: "$boostTrader", Def: true, Desc: expandDescription("[skilled_oxpc_trader]") },
    	Bool3: { Name: "$boostAliens", Def: true, Desc: expandDescription("[skilled_oxpc_thargoid]") },
    	Bool4: { Name: "$boostOthers", Def: false, Desc: expandDescription("[skilled_oxpc_other]") }
    };
    
    this.libSettings = {
    	Name: this.name,
    	Display: expandDescription("[skilled_config_display]"),
    	Alias: expandDescription("[skilled_config_alias]"),
    	Alive: "libSettings",
    	Bool: {
    		B0: { Name: "$boostPirate", Def: true, Desc: expandDescription("[skilled_boost_pirates]") },
    		B1: { Name: "$boostAssassin", Def: true, Desc: expandDescription("[skilled_boost_assassins]") },
    		B2: { Name: "$boostHunter", Def: true, Desc: expandDescription("[skilled_boost_hunters_police]") },
    		B3: { Name: "$boostTrader", Def: true, Desc: expandDescription("[skilled_boost_traders]") },
    		B4: { Name: "$boostAliens", Def: true, Desc: expandDescription("[skilled_boost_thargoids]") },
    		B5: { Name: "$boostOthers", Def: false, Desc: expandDescription("[skilled_boost_others]") },
    		Info: expandDescription("[skilled_config_bool_info]")
    	},
    	SInt: {
    		S0: { Name: "$baselinePirate", Def: 0, Min: 0, Max: 10, Desc: expandDescription("[skilled_baseline_pirates]") },
    		S1: { Name: "$baselineAssassin", Def: 0, Min: 0, Max: 10, Desc: expandDescription("[skilled_baseline_assassins]") },
    		S2: { Name: "$baselineHunter", Def: 0, Min: 0, Max: 10, Desc: expandDescription("[skilled_baseline_hunters]") },
    		S3: { Name: "$baselineTrader", Def: 0, Min: 0, Max: 10, Desc: expandDescription("[skilled_baseline_traders]") },
    		S4: { Name: "$baselineAliens", Def: 0, Min: 0, Max: 10, Desc: expandDescription("[skilled_baseline_aliens]") },
    		S5: { Name: "$baselineOthers", Def: 0, Min: 0, Max: 10, Desc: expandDescription("[skilled_baseline_others]") },
    		Info: expandDescription("[skilled_config_sint_info]")
    	},
    };
    
    this.libSettings2 = {
    	Name: this.name,
    	Display: expandDescription("[skilled_config_display2]"),
    	Alias: expandDescription("[skilled_config_alias]"),
    	Alive: "libSettings2",
    	SInt: {
    		S0: { Name: "$reactionPirate", Def: 1.5, Float: 1, Min: 0.1, Max: 3, Desc: expandDescription("[skilled_reaction_pirates]") },
    		S1: { Name: "$reactionAssassin", Def: 1.5, Float: 1, Min: 0.1, Max: 3, Desc: expandDescription("[skilled_reaction_assassins]") },
    		S2: { Name: "$reactionHunter", Def: 1.5, Float: 1, Min: 0.1, Max: 3, Desc: expandDescription("[skilled_reaction_hunters]") },
    		S3: { Name: "$reactionTrader", Def: 1.5, Float: 1, Min: 0.1, Max: 3, Desc: expandDescription("[skilled_reaction_traders]") },
    		S4: { Name: "$reactionAliens", Def: 1.5, Float: 1, Min: 0.1, Max: 3, Desc: expandDescription("[skilled_reaction_aliens]") },
    		S5: { Name: "$reactionOthers", Def: 1.5, Float: 1, Min: 0.1, Max: 3, Desc: expandDescription("[skilled_reaction_others]") },
    		Info: expandDescription("[skilled_config2_sint_info]")
    	},
    };
    
    this._trueValues = ["yes", "1", 1, "true", true];
    
    this.startUp = function () {
    	if (worldScripts.Lib_Config) {
    		if (missionVariables.SkilledNPC_Baseline) this.$baseline = parseInt(missionVariables.SkilledNPC_Baseline);
    		if (missionVariables.SkilledNPC_BaselinePirate) this.$baselinePirate = parseInt(missionVariables.SkilledNPC_BaselinePirate);
    		else this.$baselinePirate = this.$baseline;
    		if (missionVariables.SkilledNPC_BaselineAssassin) this.$baselineAssassin = parseInt(missionVariables.SkilledNPC_BaselineAssassin);
    		else this.$baselineAssassin = this.$baselinePirate;
    		if (missionVariables.SkilledNPC_BaselineHunter) this.$baselineHunter = parseInt(missionVariables.SkilledNPC_BaselineHunter);
    		else this.$baselineHunter = this.$baseline;
    		if (missionVariables.SkilledNPC_BaselineTrader) this.$baselineTrader = parseInt(missionVariables.SkilledNPC_BaselineTrader);
    		else this.$baselineTrader = this.$baseline;
    		if (missionVariables.SkilledNPC_BaselineAliens) this.$baselineAliens = parseInt(missionVariables.SkilledNPC_BaselineAliens);
    		else this.$baselineAliens = this.$baseline;
    		if (missionVariables.SkilledNPC_BaselineOthers) this.$baselineOthers = parseInt(missionVariables.SkilledNPC_BaselineOthers);
    		else this.$baselineOthers = this.$baseline;
    
    		if (missionVariables.SkilledNPC_DefaultReaction) this.$defaultReaction = parseFloat(missionVariables.SkilledNPC_DefaultReaction);
    		if (missionVariables.SkilledNPC_ReactionPirate) this.$reactionPirate = parseFloat(missionVariables.SkilledNPC_ReactionPirate);
    		else this.$reactionPirate = this.$defaultReaction;
    		if (missionVariables.SkilledNPC_ReactionAssassin) this.$reactionAssassin = parseFloat(missionVariables.SkilledNPC_ReactionAssassin);
    		else this.$reactionAssassin = this.$defaultReaction;
    		if (missionVariables.SkilledNPC_ReactionHunter) this.$reactionHunter = parseFloat(missionVariables.SkilledNPC_ReactionHunter);
    		else this.$reactionHunter = this.$defaultReaction;
    		if (missionVariables.SkilledNPC_ReactionTrader) this.$reactionTrader = parseFloat(missionVariables.SkilledNPC_ReactionTrader);
    		else this.$reactionTrader = this.$defaultReaction;
    		if (missionVariables.SkilledNPC_ReactionAliens) this.$reactionAliens = parseFloat(missionVariables.SkilledNPC_ReactionAliens);
    		else this.$reactionAliens = this.$defaultReaction;
    		if (missionVariables.SkilledNPC_ReactionOthers) this.$reactionOthers = parseFloat(missionVariables.SkilledNPC_ReactionOthers);
    		else this.$reactionOthers = this.$defaultReaction;
    
    		if (missionVariables.SkilledNPC_BoostPirate) this.$boostPirate = (this._trueValues.indexOf(missionVariables.SkilledNPC_BoostPirate) >= 0 ? true : false);
    		if (missionVariables.SkilledNPC_BoostAssassin) this.$boostAssassin = (this._trueValues.indexOf(missionVariables.SkilledNPC_BoostAssassin) >= 0 ? true : false);
    		if (missionVariables.SkilledNPC_BoostHunter) this.$boostHunter = (this._trueValues.indexOf(missionVariables.SkilledNPC_BoostHunter) >= 0 ? true : false);
    		if (missionVariables.SkilledNPC_BoostTrader) this.$boostTrader = (this._trueValues.indexOf(missionVariables.SkilledNPC_BoostTrader) >= 0 ? true : false);
    		if (missionVariables.SkilledNPC_BoostAliens) this.$boostAliens = (this._trueValues.indexOf(missionVariables.SkilledNPC_BoostAliens) >= 0 ? true : false);
    		if (missionVariables.SkilledNPC_BoostOthers) this.$boostOthers = (this._trueValues.indexOf(missionVariables.SkilledNPC_BoostOthers) >= 0 ? true : false);
    		// disable OXP config, in preference to Library
    		if (worldScripts.OXPConfig) {
    		}
    	}
    }
    
    this.startUpComplete = function () {
    	// register our settings, if Lib_Config is present
    	if (worldScripts.Lib_Config) {
    		worldScripts.Lib_Config._registerSet(this.libSettings);
    		worldScripts.Lib_Config._registerSet(this.libSettings2);
    	} else if (worldScripts.OXPConfig) {
    		this.$baselinePirate = this.$baseline;
    		this.$baselineAssassin = this.$baseline;
    		this.$baselineHunter = this.$baseline;
    		this.$baselineTrader = this.$baseline;
    		this.$baselineAliens = this.$baseline;
    		this.$baselineOthers = this.$baseline;
    	}
    }
    
    this.missionScreenOpportunity = function () {
    	// we need to monitor the baseline setting, in case it gets updated by OXP config
    	this.$backup = this.$baseline;
    }
    
    this.missionScreenEnded = function () {
    	// check for OXP config changing the baseline
    	if (worldScripts.OXPConfig) {
    		if (this.$baseline != this.$backup) {
    			this.$baselinePirate = this.$baseline;
    			this.$baselineAssassin = this.$baseline;
    			this.$baselineHunter = this.$baseline;
    			this.$baselineTrader = this.$baseline;
    			this.$baselineAliens = this.$baseline;
    			this.$baselineOthers = this.$baseline;
    		}
    		// if library isn't installed, make sure the assassin flag mirrors the pirate one
    		if (!worldScripts.Lib_Config) this.$boostAssassin = this.$boostPirate;
    	}
    }
    
    this.playerWillSaveGame = function () {
    	if (worldScripts.Lib_Config) {
    		missionVariables.SkilledNPC_Baseline = this.$baseline;
    		missionVariables.SkilledNPC_BaselinePirate = this.$baselinePirate;
    		missionVariables.SkilledNPC_BaselineAssassin = this.$baselineAssassin;
    		missionVariables.SkilledNPC_BaselineHunter = this.$baselineHunter;
    		missionVariables.SkilledNPC_BaselineTrader = this.$baselineTrader;
    		missionVariables.SkilledNPC_BaselineAliens = this.$baselineAliens;
    		missionVariables.SkilledNPC_BaselineOthers = this.$baselineOthers;
    		missionVariables.SkilledNPC_BoostPirate = this.$boostPirate;
    		missionVariables.SkilledNPC_BoostAssassin = this.$boostAssassin;
    		missionVariables.SkilledNPC_BoostHunter = this.$boostHunter;
    		missionVariables.SkilledNPC_BoostTrader = this.$boostTrader;
    		missionVariables.SkilledNPC_BoostAliens = this.$boostAliens;
    		missionVariables.SkilledNPC_BoostOthers = this.$boostOthers;
    		missionVariables.SkilledNPC_ReactionPirate = this.$reactionPirate;
    		missionVariables.SkilledNPC_ReactionAssassin = this.$reactionAssassin;
    		missionVariables.SkilledNPC_ReactionHunter = this.$reactionHunter;
    		missionVariables.SkilledNPC_ReactionTrader = this.$reactionTrader;
    		missionVariables.SkilledNPC_ReactionAliens = this.$reactionAliens;
    		missionVariables.SkilledNPC_ReactionOthers = this.$reactionOthers;
    	}
    }
    
    this.shipSpawned = function (ship) {
    	if (ship.accuracy >= 5) {
    		return; // already been custom-set, so don't adjust it
    	}
    	if (!ship.autoWeapons) {
    		return; // ship does not agree to 3rd-party adjustments
    	}
    
    	var role = ship.primaryRole;
    	if (ship.scriptInfo.skilled_npc_role) {
    		role = ship.scriptInfo.skilled_npc_role;
    	}
    
    	var gov = System.infoForSystem(galaxyNumber, ship.homeSystem).government;
    
    	switch (role) {
    		case "off":
    			break; // never boosted, ever, even if has auto_weapons for other purposes
    		case "assassin-light":
    		case "assassin-medium":
    		case "assassin-heavy":
    			if (!this.$boostAssassin) break;
    			if (ship.accuracy < 0) {
    				ship.accuracy = -ship.accuracy;
    			}
    			ship.accuracy += this.$baselineAssassin;
    			ship.accuracy += Math.random() * (7 - gov);
    			if (ship.accuracy < (7 - gov)) {
    				ship.accuracy += (7 - gov) * 0.75;
    			}
    			ship.reactionTime = this.$reactionAssassin;
    			break;
    		case "pirate":
    		case "pirate-light-fighter":
    		case "pirate-medium-fighter":
    		case "pirate-heavy-fighter":
    		case "pirate-light-freighter":
    		case "pirate-medium-freighter":
    		case "pirate-heavy-freighter":
    		case "pirate-interceptor":
    		case "pirate-aegis-raider":
    			if (!this.$boostPirate) break;
    			if (ship.accuracy < 0) {
    				ship.accuracy = -ship.accuracy;
    			}
    			ship.accuracy += this.$baselinePirate;
    			ship.accuracy += Math.random() * (7 - gov);
    			if (ship.accuracy < (7 - gov)) {
    				ship.accuracy += (7 - gov) * 0.75;
    			}
    			ship.reactionTime = this.$reactionPirate;
    			break;
    		case "hunter":
    		case "hunter-medium":
    		case "hunter-heavy":
    			if (!this.$boostHunter) break;
    			if (ship.accuracy < 0) {
    				ship.accuracy = -ship.accuracy;
    			}
    			ship.accuracy += this.$baselineHunter;
    			ship.accuracy += Math.random() * (gov);
    			if (ship.accuracy < (gov)) {
    				ship.accuracy += (gov) * 0.75;
    			}
    			ship.reactionTime = this.$reactionHunter;
    			break;
    		case "escort":
    		case "escort-medium":
    		case "escort-heavy":
    		case "defense_ship":
    			if (!this.$boostTrader) break;
    			if (ship.accuracy < 0) {
    				ship.accuracy = -ship.accuracy;
    			}
    			ship.accuracy += this.$baseline;
    			if (ship.scanClass == "CLASS_POLICE") {
    				ship.accuracy *= 2;
    			}
    			ship.accuracy += Math.random() * 5;
    			if (ship.escortGroup.leader && ship.accuracy < ship.escortGroup.leader.accuracy) {
    				ship.accuracy += Math.random() * ship.escortGroup.leader.accuracy;
    			}
    			ship.reactionTime = this.$reactionTrader;
    			break;
    		case "miner":
    		case "scavenger":
    		case "trader":
    		case "trader-courier":
    		case "trader-smuggler":
    			if (!this.$boostTrader) break;
    			if (ship.accuracy < 0) {
    				ship.accuracy = -ship.accuracy;
    			}
    			ship.accuracy += this.$baselineTrader;
    			ship.accuracy += Math.random() * (7 - gov) * 0.5;
    			ship.reactionTime = this.$reactionTrader;
    			break;
    		case "police":
    		case "interceptor":
    		case "wingman":
    			if (!this.$boostHunter) break;
    			if (ship.accuracy < 0) {
    				ship.accuracy = -ship.accuracy;
    			}
    			ship.accuracy += this.$baselineHunter;
    			ship.accuracy *= 2;
    			ship.accuracy += Math.random() * gov;
    			ship.reactionTime = this.$reactionHunter;
    			break;
    		case "thargoid":
    		case "thargon":
    		case "griff_robot_thargon":
    		case "griff_organic_thargon":
    			if (!this.$boostAliens) break;
    			if (ship.accuracy < 0) {
    				ship.accuracy = -ship.accuracy;
    			}
    			ship.accuracy += this.$baselineAliens;
    			ship.accuracy *= 2;
    			ship.reactionTime = this.$reactionAliens;
    			break;
    		default:
    			if (!this.$boostOthers) break;
    			if (ship.accuracy < 0) {
    				ship.accuracy = -ship.accuracy;
    			}
    			ship.accuracy += this.$baselineOthers;
    			ship.accuracy += Math.random() * this.$baselineOthers;
    			ship.reactionTime = this.$reactionOthers;
    	}
    }