Scripts/ShieldCycler.js |
"use strict";
this.name = "Shield Cycler";
this.author = "Lone_Wolf";
this.copyright = "(C) 2011-2012, 2014-2015 Lone_Wolf.";
this.licence = "CC-BY-SA 4.0";
this.description = "Keeps shield energy aligned with a specific configuration";
this.version = "2.1";
/* Main script for Shield Cycler
* + functions used in other SC scripts
* + functions used by/for other oxps
*/
/* All settings that need saving are stored in missionVariables.sc_settings using JSON
for ease of use & performance the SC scripts internally use the object this._sc_settings / worldScripts["Shield Cycler"]._sc_settings
name Type Comment
$sc_settings obj
threshold int percentage, can be 0-100
start_configuration int number , 0 = disabled, 1 = aft 2 = fwd 3 = equal
current_cycle_position int number, position in the cycle (Equal, Fwd, Equal, Aft, Disabled), first position being 0
current_configuration int number , 0 = disabled, 1 = aft 2 = fwd 3 = equal
cycler_mask int bitmask (size = 4 ) used to keep track which settings are available for cycling
bit order (MSB first) : equal, forward, aft , disabled
bit = 1 : available, 0 not available
functional int percentage, 100 is fully functional, 20 is minimum
version int number, 0=none 1 = basic , 2 = standard, 3 =advanced
manual_version int number, 0=none 1 = basic , 2 = standard, 3 =advanced
};
NOTE 1: missionvariables are loaded at startup, then converted into this._sc_setting object .
during game the missionvariables are NOT kept uptodate.
they are updated only when player saves game.
NOTE 2: the settings object cane change from version to version.
other OXPs that need to interact with Shield Cycler
equipment items
EQ_SC_SHIELD_CYCLER_INTERNAL - present if shield cycler is installed, for backward compatibility
EQ_SC_SHIELD_CYCLER_BASIC
EQ_SC_SHIELD_CYCLER_STANDARD
EQ_SC_SHIELD_CYCLER_ADVANCED
EQ_SC_MANUAL_CONFIGURATOR_INTERNAL - present if a manual configurator is installed, for backward compatibility
EQ_SC_MANUAL_CONFIGURATOR_BASIC
EQ_SC_MANUAL_CONFIGURATOR_STANDARD
EQ_SC_MANUAL_CONFIGURATOR_ADVANCED
EQ_SC_SELL_SHIELD_CYCLER
EQ_SC_SELL_MANUAL
EQ_SC_SC_REPAIR
NOTE: EQ_SC_SHIELD_CYCLER_* and EQ_SC_MANUAL_CONFIGURATOR_* will be present in the savefile but NOT visible on the F5 equipment screen
*/
this.$debug = true;
this.$logging = true;
this.$compatibility = true;
// RO stuff, i haven't been able to figure out how to make these read-only, so the values here can be changed by code, but that's not supposed to happen
this.$sc_const = {
sc_list: ["None","EQ_SC_SHIELD_CYCLER_BASIC","EQ_SC_SHIELD_CYCLER_STANDARD","EQ_SC_SHIELD_CYCLER_ADVANCED"],
manual_list: ["None","EQ_SC_MANUAL_CONFIGURATOR_BASIC","EQ_SC_MANUAL_CONFIGURATOR_STANDARD","EQ_SC_MANUAL_CONFIGURATOR_ADVANCED"],
sc_names: ["None", "Basic", "Standard", "Advanced"],
manual_names: ["None", "Basic", "Standard", "Advanced"],
modes: { disabled:0, aft:1, forward:2, both:3, count:4 },
cycle: [ 3, 2, 3, 1, 0 ],
mode_names: [ "Disabled", "Aft", "Forward", "Equal"],
};
// WORM stuff
this.$sc_worm = {
sc_cost: [],
manual_cost: []
};
// R/W stuff
this.$sc_settings = {
threshold: 100,
current_cycle_position: 0,
start_configuration: this.$sc_const.cycle[0],
current_configuration: this.$sc_const.cycle[0],
cycler_mask: 0x00f,
functional: 100,
version: 0,
manual_version: 0,
};
this.$sc_disabled = false;
// for backwards compatibility, it's not used anymore
// (some OXP might be acessing it)
// it will reflect changes to this.$sc_settings
this._sc_settings = {
sc : this.$sc_settings,
general : {
disabled : this.$sc_settings.current_configuration === 0,
sc_disabled : this.$sc_settings.current_configuration === 0,
savegame_version : 0
}
};
this._sc_const = this.$sc_const;
//
// Properties for internal use
//
this.$sc_cycler_loss = [
// power loss for no cycler, basic, standard, advanced (one sbu-array for each)
// each sub-array holds energy cost in % of energy transfer
// indexes on the sub-arrays based on <energy transfer> / <energy bank size>
[ 0, 0, 0, 0, 0, 0 ], // no cycler present, so no power loss
[ 0.0600, 0.0840, 0.1176, 0.1646, 0.2305, 0.3227 ], // basic cycler
[ 0.0450, 0.0585, 0.0760, 0.0989, 0.1285, 0.1671 ], // standard cycler
[ 0.0300, 0.0360, 0.0432, 0.0518, 0.0622, 0.0746 ], // advanced cycler
];
// powerloss multiplier for manual configurators
// none, basic, standard, advanced
this.$sc_manual_reduction = [ 1, 1, 0.50, 0.20];
this._sc_error = 0;
/* used for error tracking
* 0 = no error
* 1 = savegame to old
* 2 = savegame to new
*/
this._sc_display_status_title = "Shield Cycler Status";
// for Lib_Config
this._scConfig = {
Name: "Shield Cycler",
Display: "Shield Cycler Config",
Alive: "_scConfig",
Bool: {
B0: {
Name: "$sc_disabled",
Desc: "disable SC OXP.",
Def: false,
Hide: false,
Notify: "_scChange_disabled",
},
Info: "enable/disable Shield Cycler oxp functionality"
},
SInt: {
S0: {
Name: "$sc_settings.threshold",
Desc: "threshold %",
Def:100, Min:0, Max:100,
Hide: false,
Notify: "_scChange_threshold",
},
S1: {
Name: "$sc_settings.start_configuration",
Desc: "launch setting",
Def:3, Min:0, Max:3,
Hide: false,
Notify: "_scChange_start_configuration",
},
Info: "Threshold % determines when adjusting is done. 100=always, 0=never.\nStart configuration is the configuration that will be set upon launch (3=equal, 2=fwd, 1=aft, 0=disabled)."
},
EInt: {
E0: {
Name: "$sc_settings.cycler_mask",
Desc: ["Disabled","Aft","Forward","Equal"],
Def:0x001, Min:0x000, Max:0x00f,
Hide: false,
Notify: "_scChange_cycler_mask",
},
Info: "enable/disable the availability of the settings for manual cycling. Note: if you disable all, Shield Cycler oxp will enable the disabled setting."
}
}
//
// Event Handlers
//
//--------------------------------------------------------------------------------------------------//
this.startUp = function _sc_startUp() {
var wsc = worldScripts["Shield Cycler"];
var ship = player.ship;
var i, list;
this.ship = ship;
if (missionVariables.sc_settings) {
let ret = wsc._parseSavedSettings(missionVariables.sc_settings);
if (ret)
log(this.name, "missionVariables sc_settings has invalid JSON string: "+missionVariables.sc_settings);
delete missionVariables.sc_settings;
} else {
wsc._resetSettings(wsc.$sc_settings);
wsc.$sc_settings.version = 0;
wsc.$sc_settings.manual_version = 0;
}
// set Lib_Config settings visibility
wsc._setLibConfigVisibility();
// calculate price values
list = wsc.$sc_const.sc_list;
i = list.length;
while (i--)
if (i === 0)
wsc.$sc_worm.sc_cost[i] = 0;
else
wsc.$sc_worm.sc_cost[i] = EquipmentInfo.infoForKey(list[i]).price;
list = wsc.$sc_const.manual_list;
i = list.length;
while (i--)
if (i === 0)
wsc.$sc_worm.manual_cost[i] = 0;
else
wsc.$sc_worm.manual_cost[i] = EquipmentInfo.infoForKey(list[i]).price;
if (this.$logging) log(wsc.name, "Shield Cycler completed settings: "+JSON.stringify(wsc.$sc_settings));
}
//--------------------------------------------------------------------------------------------------//
this.startUpComplete = function _sc_startUpComplete() {
var wsc = worldScripts["Shield Cycler"];
wsc._sc_update_status();
if (worldScripts.Lib_Config) {
var ret = worldScripts.Lib_Config._registerSet(wsc._scConfig);
if (this.$debug) log(wsc.name, "Lib_Config regsterSet returned "+ret);
}
}
//--------------------------------------------------------------------------------------------------//
this.playerWillSaveGame = function _sc_playerWillSaveGame() {
missionVariables.sc_settings = JSON.stringify(worldScripts["Shield Cycler"]._sc_settings);
};
//--------------------------------------------------------------------------------------------------//
this.playerBoughtNewShip = this.playerReplacedShip = function _sc_playerReplacedShip(ship) {// player ship only
var wsc = worldScripts["Shield Cycler"];
this.ship = player.ship;
// sell shieldcycler equipment if still present and reset settings
if (this.$sc_settings.version !== 0) {
log(this.name, "Player's got a new ship, removing Shield Cycler equipments");
if (this.$sc_settings.manual_version !== 0)
wsc._sc_remove_manual();
wsc._sc_remove_shield_cycler();
wsc._sc_update_status();
}
}
//--------------------------------------------------------------------------------------------------//
this.equipmentDamaged = this.equipmentDestroyed = function _sc_equipmentDamaged(eqKey) {// NPC-ready
// can be called from NPCs ship.script if 'this' is made to be the ship's script
var wsc = worldScripts["Shield Cycler"];
if (eqKey === wsc.$sc_const.sc_list[this.$sc_settings.version] || eqKey === wsc.$sc_const.manual_list[this.$sc_settings.manual_version]) {
player.commsMessage("Shield Cycler devices taking damage, functionality is reduced",6);
this.ship.setEquipmentStatus(EquipmentInfo.infoForKey(eqKey), "EQUIPMENT_OK");
if (this.$sc_settings.functional >= 50 )
this.$sc_settings.functional -= 10;
else
this.$sc_settings.functional = 40;
if (this.$logging) log(wsc.name, "Shield Cycler devices taking damage, functionality is reduced to"+this.$sc_settings.functional+"%");
}
}
//--------------------------------------------------------------------------------------------------//
this.playerBoughtEquipment = function _sc_playerBoughtEquipment(eqKey) {// player ship only
var wsc = worldScripts["Shield Cycler"];
if (wsc.$sc_const.sc_list.indexOf(eqKey) >= 0) {
// SC device proper (EQ_SHIELD_CYCLER_BASIC, EQ_SHIELD_CYCLER_STANDARD, EQ_SHIELD_CYCLER_ADVANCED)
wsc._sc_equipment_setup(eqKey);
} else if (wsc.$sc_const.manual_list.indexOf(eqKey) >= 0) {
// SC Manual Configurator (EQ_SC_MANUAL_CONFIGURATOR_BASIC, EQ_SC_MANUAL_CONFIGURATOR_STANDARD, EQ_SC_MANUAL_CONFIGURATOR_ADVANCED)
wsc._sc_equipment_setup(eqKey);
} else if (eqKey === "EQ_SC_SELL_SHIELD_CYCLER") {
player.credits += wsc._sc_remove_shield_cycler();
wsc._sc_update_status();
} else if (eqKey === "EQ_SC_SELL_MANUAL_CONFIGURATOR") {
player.credits += wsc._sc_remove_manual();
wsc._sc_update_status();
} else if (eqKey === "EQ_SC_SC_REPAIR") {
wsc.$sc_settings.functional = 100;
this.ship.removeEquipment(equipmentKey);
wsc._sc_update_status();
}
}
//--------------------------------------------------------------------------------------------------//
this.shipLaunchedFromStation = function _sc_shipLaunchedFromStation(station) {// NPC-ready
var wsc = worldScripts["Shield Cycler"];
var sc_eqs = wsc._sc_get_sc_versions(null);
if (wsc.$sc_settings.version !== sc_eqs.version) {
log(this.name, this.ship.displayName+" settings ("+wsc.$sc_settings.version+"/"+wsc.$sc_settings.manual_version+") don't match installed equipments ("+sc_eqs.version+"/"+sc_eqs.manual_version+"), adjusting settings");
wsc.$sc_settings.version = sc_eqs.version;
wsc.$sc_settings.manual_version = sc_eqs.manual_version;
}
if (wsc.$sc_disabled) return;
// check if player has a Shield Cycler
if (this.$sc_settings.version === 0) return;
if (this.$sc_settings.current_configuration)
// don't change it if it's 0:Disabled
this.$sc_settings.current_configuration = this.$sc_settings.start_configuration;
this.$sc_settings.current_cycle_position = wsc.$sc_const.cycle.indexOf(this.$sc_settings.start_configuration);
wsc._sc_sc_adjust.call(this, true, "Shield Cycler");
}
//--------------------------------------------------------------------------------------------------//
this.shipTakingDamage = function _sc_shipTakingDamage(amount, fromEntity, damageType) {// NPC-ready
var wsc = worldScripts["Shield Cycler"];
if (wsc.$sc_disabled) return;
if (this.$sc_settings.version === 0) return;
if (this.$logging) log(wsc.name, this.ship.displayName+" taking "+amount.toFixed(1)+" damage of type "+damageType+" from "+fromEntity.displayName);
wsc._sc_sc_adjust.call(this, false, "Shield Cycler");
}
//--------------------------------------------------------------------------------------------------//
this.shipLaunchedEscapePod = function _sc_shipLaunchedEscapePod(escapepod, passengers) {// player ship only
var wsc = worldScripts["Shield Cycler"];
// reset devices / vars when pilot ejects
if (this.$sc_settings.version === 0) return;
if (this.$sc_settings.manual_version !== 0) {
wsc._sc_remove_manual();
}
wsc._sc_remove_shield_cycler();
}
//
// Internal Functions
//
//--------------------------------------------------------------------------------------------------//
this._parseSavedSettings = function _sc_parseSavedSettings(saved) {// NPC-ready
// can be called to configure NPCs if 'this' is made to be the ship's script
// parse a settings JSON string and initialize the OXP settings object
// deals with JSON strings in legacy settings format
var that = _sc_parseSavedSettings;
var wsc = worldScripts["Shield Cycler"];
var unchanged_fields = (that.unchanged_fields = that.unchanged_fields ||
["threshold","start_configuration","current_configuration","cycler_mask", "functional","version", "manual_version"]);
var tmp;
if (saved && saved.length > 0) {
try {
tmp = JSON.parse(saved);
} catch (e) {
log(wsc.name, "JSON exception parsing settings: "+e);
return 3;
}
} else
if (wsc.$debug) log(wsc.name, "empty settings JSON string");
// create settings object in NPC ship's script
if (!this.$sc_settings) this.$sc_settings = {};
if (!tmp) {
// empty settings, assume v2.x
wsc._resetSettings(this.$sc_settings);
// "equipments rule"
wsc._reconcileSettings.call(this, false);
} else if ("sc" in tmp && !("current_cycle_position" in tmp.sc)) {
// settings from Shield Cycler v1.x
// copy unchanged fields
if (this.$debug) log(wsc.name, this.ship.displayName+": restoring from v1.x settings");
wsc._resetSettings(this.$sc_settings);
var i = unchanged_fields.length;
while (i--) if (tmp.sc[unchanged_fields[i]]) this.$sc_settings[unchanged_fields[i]] = tmp.sc[unchanged_fields[i]];
// set changed fields
this.$sc_settings.current_cycle_position = wsc.$sc_const.cycle.indexOf(wsc.$sc_settings.current_configuration);
// will not have the actual equipments installed, so "settings rule!"
wsc._reconcileSettings.call(this, true);
} else if ("current_cycle_position" in tmp) {
// settings from Shield Cycler v2.x
if (this.$debug) log(wsc.name, this.ship.displayName+": restoring from v2.x settings");
this.$sc_settings = tmp;
if (typeof this.$sc_settings.version === "string") {
// deprecated development version of settings
this.$sc_settings.version = wsc.$sc_const.sc_list.indexOf(this.$sc_settings.version);
this.$sc_settings.manual_version = wsc.$sc_const.sc_list.indexOf(this.$sc_settings.manual_version);
}
// already migrated to new version, so "equipments rule!"
wsc._reconcileSettings.call(this, false);
} else if ("sc" in tmp && ("current_cycle_position" in tmp.sc)) {
// v2.x compatibility object
if (this.$debug) log(wsc.name, this.ship.displayName+": restoring from v2.x compatibility settings");
this.$sc_settings = tmp.sc;
if (typeof this.$sc_settings.version === "string") {
// deprecated development version of settings
this.$sc_settings.version = wsc.$sc_const.sc_list.indexOf(this.$sc_settings.version);
this.$sc_settings.manual_version = wsc.$sc_const.sc_list.indexOf(this.$sc_settings.manual_version);
}
// already migrated to new version, so "equipments rule!"
wsc._reconcileSettings.call(this, false);
} else {
if (this.$debug) log(wsc.name, this.ship.displayName+": no setting to restore, setting None");
this.$sc_settings.version = this.$sc_settings.manual_version = 0;
wsc._resetSettings(this.$sc_settings);
wsc._reconcileSettings.call(this, false);
}
if (this.ship == player.ship)
// copy reference to legacy settings object
wsc._sc_settings.sc = wsc.$sc_settings;
return 0;
}
//--------------------------------------------------------------------------------------------------//
this._reconcileSettings = function _sc_reconcileSettings(settings_rule) {// NPC-ready
// can be called to configure NPCs if 'this' is made to be the ship's script
var wsc = worldScripts["Shield Cycler"];
var ship = this.ship;
var list, i;
if (settings_rule) {
// Truth is what's in the settings (legacy of v1.x)
// remove installed SC equipments if not the one in settings
if (this.$debug) log(wsc.name, this.ship.displayName+": reconciling settings with 'settings rule' (for legacy settings) :"+JSON.stringify(this.$sc_settings));
list = wsc.$sc_const.sc_list;
i = list.length;
while (i--)
if (i > 0 && i !== this.$sc_settings.version && ship.equipmentStatus(list[i]) === "EQUIPMENT_OK") {
if (this.$logging) log(wsc.name, ship.displayName+" "+list[i]+" is not in Shield Cycler settings, removing");
ship.removeEquipment(list[i]);
}
list = wsc.$sc_const.manual_list;
i = list.length;
while (i--)
if (i > 0 && i !== this.$sc_settings.manual_version && ship.equipmentStatus(list[i]) === "EQUIPMENT_OK") {
if (this.$logging) log(wsc.name, ship.displayName+" "+list[i]+" is not in Shield Cycler settings, removing");
ship.removeEquipment(list[i]);
}
// award the correct ones
if (this.$sc_settings.version !== 0) ship.awardEquipment(wsc.$sc_const.sc_list[this.$sc_settings.version]);
if (this.$sc_settings.manual_version !== 0) ship.awardEquipment(wsc.$sc_const.manual_list[this.$sc_settings.manual_version]);
if (this.$logging) log(wsc.name, this.ship.displayName+": awarded "+wsc.$sc_const.sc_list[this.$sc_settings.version]+" and "+wsc.$sc_const.manual_list[this.$sc_settings.manual_version]);
} else {
// Truth is whatever is installed in the ship (v2.x)
log(wsc.name, this.ship.displayName+": reconciling settings with 'equipments rule' (for v2.x SC)");
list = wsc.$sc_const.sc_list;
i = list.length;
while (i--)
if (i > 0 && ship.equipmentStatus(list[i]) === "EQUIPMENT_OK") {
if (this.$logging) log(wsc.name, this.ship.displayName+": found "+list[i]+", setting it up");
wsc._sc_equipment_setup.call(this, list[i]);
break;
}
list = wsc.$sc_const.manual_list;
i = list.length;
while (i--)
if (i > 0 && ship.equipmentStatus(list[i]) === "EQUIPMENT_OK") {
if (this.$logging) log(wsc.name, this.ship.displayName+": found "+list[i]+", setting it up");
wsc._sc_equipment_setup.call(this, list[i]);
break;
}
log(wsc.name, this.ship.displayName+": Shield Cycler settings: "+JSON.stringify(this.$sc_settings));
}
if (wsc.$compatibility) {
// awards the deprecated internal equipments for compatibility reasons
// (so when saved the ship would still work with v1.x)
if (this.$sc_settings.version !== 0 && ship.equipmentStatus("EQ_SC_SHIELD_CYCLER_INTERNAL") !== "EQUIPMENT_OK")
ship.awardEquipment("EQ_SC_SHIELD_CYCLER_INTERNAL");
if (this.$sc_settings.manual_version !== 0 && ship.equipmentStatus("EQ_SC_MANUAL_CONFIGURATOR_INTERNAL") !== "EQUIPMENT_OK")
ship.awardEquipment("EQ_SC_MANUAL_CONFIGURATOR_INTERNAL");
}
}
//--------------------------------------------------------------------------------------------------//
this._setLibConfigVisibility = function _sc_setLibConfigVisibility() {// player ship only
var wsc = worldScripts["Shield Cycler"];
if (this.ship != player.ship) return;
wsc._changeConfiguration(1, (this.$sc_settings.version < 2));
wsc._changeConfiguration(2, (this.$sc_settings.version < 3));
wsc._changeConfiguration(3, (this.$sc_settings.manual_version < 3));
}
//--------------------------------------------------------------------------------------------------//
this._changeConfiguration = function _sc_changeConfiguration(setting, hide) {// player ship only
// sets/resets visibility of configure options in LibConfig
var wsc = worldScripts["Shield Cycler"];
if (this.ship != player.ship) return;
switch (setting) {
case 1:
wsc._scConfig.SInt.S0.Hide = hide;
break;
case 2:
wsc._scConfig.SInt.S1.Hide = hide;
break;
case 3:
wsc._scConfig.EInt.E0.Hide = hide;
break;
default:
break;
}
}
//--------------------------------------------------------------------------------------------------//
this._resetSettings = function _sc_resetSettings(settings) {// NPC-ready
var wsc = worldScripts["Shield Cycler"];
settings.threshold = 100;
settings.current_cycle_position = 0;
settings.start_configuration = wsc.$sc_const.cycle[0];
settings.current_configuration = wsc.$sc_const.cycle[0];
settings.cycler_mask = 0x00f;
settings.functional = 100;
}
//==================================================================================================//
//
// Functions for use by other OXPs
//
//--------------------------------------------------------------------------------------------------//
this._sc_get_sc_versions = function _sc_get_sc_versions(versions) {// NPC-ready
// can be called for NPCs ship.script if 'this' is made to be the ship's script
// versions == null means get data from installed equipments
// versions = { sc:<integer>, manual:<integer> } means get the data for those sc equipments
var wsc = worldScripts["Shield Cycler"];
var ret;
var ship = this.ship;
var sc = {
sc_eqKey: null,
version: 0,
version_name: "None",
manual_eqKey: null,
manual_version: 0,
manual_version_name: "None"
};
function verify_equipment_list(list) {
var i;
i = list.length;
while (i--)
if (i > 0 && ship.equipmentStatus(list[i]) === "EQUIPMENT_OK") {
return {eqKey: list[i], version: i};
}
return {eqKey: "None", version: 0};
}
if (!versions) {
// data from installed equipments
ret = verify_equipment_list(wsc.$sc_const.sc_list);
sc.sc_eqKey = (ret.eqKey === "None" ? null : ret.eqKey);
sc.version = ret.version;
sc.version_name = wsc.$sc_const.sc_names[ret.version];
ret = verify_equipment_list(wsc.$sc_const.manual_list);
sc.manual_eqKey = (ret.eqKey === "None" ? null : ret.eqKey);
sc.manual_version = ret.version;
sc.manual_version_name = wsc.$sc_const.manual_names[ret.manual_version];
} else {
// data from specified equipments
if (versions.sc < wsc.$sc_const.sc_list.length) {
sc.sc_eqKey = wsc.$sc_const.sc_list[versions.sc];
sc.version = versions.sc;
sc.version_name = wsc.$sc_const.sc_names[sc.version];
}
if (versions.manual < wsc.$sc_const.manual_list.length) {
sc.manual_eqKey = wsc.$sc_const.manual_list[versions.manual];
sc.manual_version = versions.manual;
sc.manual_version_name = wsc.$sc_const.manual_names[sc.manual_version];
}
}
return sc;
}
//--------------------------------------------------------------------------------------------------//
this._sc_award_equipment = function _sc_award_equipment(eqKey) { //NPC-only
// can be called from NPCs ship.script if 'this' is made to be the ship's script
var wsc = worldScripts["Shield Cycler"];
if (this.ship == player.ship) return false;
var ret;
var i = wsc.$sc_const.sc_list.indexOf(eqKey);
if (i >= 0) {
ret = this.ship.awardEquipment(eqKey);
if (ret)
wsc._sc_equipment_setup.call(this, eqKey);
if (wsc.$debug) log(wsc.name, this.ship.displayName+" awarding "+eqKey+", success:"+ret);
return ret;
} else {
i = wsc.$sc_const.manual_list.indexOf(eqKey);
if (i >= 0) {
ret = this.ship.awardEquipment(eqKey);
if (ret)
wsc._sc_equipment_setup.call(this, eqKey);
if (wsc.$debug) log(wsc.name, this.ship.displayName+" awarding "+eqKey+", success:"+ret);
return ret;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------//
this._sc_equipment_setup = function _sc_equipment_setup(eqKey) { //NPC-ready
// can be called from NPCs ship.script if 'this' is made to be the ship's script
// sets the equipment up, but the equipment must already have been awarded to the ship
var wsc = worldScripts["Shield Cycler"];
var npc = (this.ship != player.ship);
if (this.ship.equipmentStatus(eqKey) !== "EQUIPMENT_OK") return;
var index = wsc.$sc_const.sc_list.indexOf(eqKey);
if (index >= 0) {
// SC device proper (EQ_SHIELD_CYCLER_BASIC, EQ_SHIELD_CYCLER_STANDARD, EQ_SHIELD_CYCLER_ADVANCED)
if (!this.$sc_settings) {
// NPC setup!
this.$sc_settings = {};
wsc._resetSettings(this.$sc_settings);
this.$sc_settings.version = 0;
this.$sc_settings.manual_version = 0;
if (wsc.$compatibility && ship.equipmentStatus("EQ_SC_SHIELD_CYCLER_INTERNAL") !== "EQUIPMENT_OK")
ship.awardEquipment("EQ_SC_SHIELD_CYCLER_INTERNAL");
}
this.$sc_settings.version = index;
wsc._resetSettings(this.$sc_settings);
if (!npc) wsc._sc_update_status.call(this);
} else {
index = wsc.$sc_const.manual_list.indexOf(eqKey);
if (index >= 0) {
// SC Manual Configurator (EQ_SC_MANUAL_CONFIGURATOR_BASIC, EQ_SC_MANUAL_CONFIGURATOR_STANDARD, EQ_SC_MANUAL_CONFIGURATOR_ADVANCED)
this.$sc_settings.manual_version = index;
if (wsc.$compatibility && ship.equipmentStatus("EQ_SC_MANUAL_CONFIGURATOR_INTERNAL") !== "EQUIPMENT_OK")
ship.awardEquipment("EQ_SC_MANUAL_CONFIGURATOR_INTERNAL");
if (!npc) wsc._sc_update_status();
}
}
}
//--------------------------------------------------------------------------------------------------//
this._sc_remove_manual = function _sc_remove_manual() {// NPC-ready
// can be called to configure NPCs if 'this' is made to be the ship's script
// removes manual configurator devices only
// returns refund value in credits
var wsc = worldScripts["Shield Cycler"];
if (this.$sc_settings.manual_version === 0) return 0;
var refund = wsc.$sc_worm.manual_cost[this.$sc_settings.manual_version];
refund = refund * this.$sc_settings.functional * 0.01;
this.ship.removeEquipment(wsc.$sc_const.manual_list[this.$sc_settings.manual_version]);
this.$sc_settings.manual_version = 0;
this.$sc_settings.cycler_mask = 0x00f;
// hide configuration for advanced manual configurator
if (this.ship == player.ship) wsc._changeConfiguration(3, true);
refund = parseInt(refund * 0.1 * 0.6);
return refund;
}
//--------------------------------------------------------------------------------------------------//
this._sc_remove_shield_cycler = function _sc_remove_shield_cycler() {// NPC-ready
// can be called to configure NPCs if 'this' is made to be the ship's script
// removes all shield cycler devices
// returns refund value in credits
var wsc = worldScripts["Shield Cycler"];
if (this.$sc_settings.version === 0) return 0;
var refund = 0;
// if manual configurator devices are present, remove them first
if (this.$sc_settings.manual_version !== 0)
refund = wsc._sc_remove_manual.call(this);
refund += wsc.$sc_worm.sc_cost[this.$sc_settings.version];
if (this.ship == player.ship)
wsc._changeConfiguration(this.$sc_settings.version-1, true);
refund *= this.$sc_settings.functional * 0.01;
this.ship.removeEquipment(wsc.$sc_const.sc_list[this.$sc_settings.version]);
this.$sc_settings.version = 0;
wsc._resetSettings(this.$sc_settings);
refund = parseInt(refund * 0.1 * 0.6);
return refund;
}
//--------------------------------------------------------------------------------------------------//
this._sc_update_status = function _sc_update_status() {// player ship only
var wsc = worldScripts["Shield Cycler"];
var sc_display_status = [];
var ship = this.ship;
if (ship != player.ship) return;
sc_display_status.push(wsc._sc_display_status_title);
mission.setInstructions(null, "SC Core"); // for old savefiles
if (this.$sc_settings.version === 0 ||
ship.equipmentStatus(wsc.$sc_const.sc_list[this.$sc_settings.version]) !== "EQUIPMENT_OK") {
if (this.$logging) log(wsc.name, "Player ship has no ShieldCycler, cleaning message in Manifest Screen: "+sc_display_status);
mission.setInstructions(null, "Shield Cycler");
return;
};
sc_display_status.push("SC version: " + wsc.$sc_const.sc_names[this.$sc_settings.version]);
sc_display_status.push("Manual Configurator: " + wsc.$sc_const.manual_names[this.$sc_settings.manual_version]);
sc_display_status.push(" " + this.$sc_settings.functional + "%% functional");
if (this.$logging) log(wsc.name, "Player ship has ShieldCycler, setting up message in Manifest Screen: "+sc_display_status);
mission.setInstructions(sc_display_status, "Shield Cycler");
}
//--------------------------------------------------------------------------------------------------//
this._sc_sc_adjust = function _sc_sc_adjust(init, caller) {// NPC-ready
// can be called from NPCs ship.script if 'this' is made to be the ship's script
// adjusts shields based on Shield Cycler settings stored in 'this'
// uses Shield Capacitors if present and charged
// THIS UPDATES THE SHIP'S SHIELD CHARGE AND DEDUCTS ENERGY COST
var wsc = worldScripts["Shield Cycler"];
var ship = this.ship;
if (wsc == null || this.$sc_settings.version === 0 ||
ship.equipmentStatus(wsc.$sc_const.sc_list[this.$sc_settings.version]) !== "EQUIPMENT_OK")
return;
// setup things for shield cycling
var adjust_input = {
caller: (caller ? caller : "Unknown"),
setting: this.$sc_settings.current_configuration,
functional: this.$sc_settings.functional,
fwd: ship.forwardShield,
fwd_threshold: (ship.maxForwardShield * this.$sc_settings.threshold * 0.01),
aft: ship.aftShield,
aft_threshold: (ship.maxAftShield * this.$sc_settings.threshold * 0.01),
version: this.$sc_settings.version,
manual_version: this.$sc_settings.manual_version,
init: init,
max_energy: ship.maxEnergy,
ship: ship
};
var _old_energy = ship.energy;
var adjust_output = {power: 0, fwd:0, aft:0};
adjust_output = wsc._sc_adjust(adjust_input);
if (adjust_input.init)
player.commsMessage("Cycler configuration : " + wsc.$sc_const.mode_names[adjust_input.setting]);
if (this.$logging || ship == player.ship.target) log(wsc.name, ship.displayName+": adjusting shields from (F/A) "+adjust_input.fwd.toFixed(0)+"/"+adjust_input.aft.toFixed(0)+" to "+adjust_output.fwd.toFixed(0)+"/"+adjust_output.aft.toFixed(0)+", energy:"+_old_energy.toFixed(1)+"->"+ship.energy.toFixed(1))
return;
}
//--------------------------------------------------------------------------------------------------//
this._sc_adjust = function _sc_adjust(adjust) {// NPC ready
// can be called for NPCs withouth having to mess with 'this'
// adjusts shields based on Shield Cycler settings stored in 'adjust' parameter
// uses Shield Capacitors if present and charged
// THIS UPDATES THE SHIP'S SHIELD CHARGE AND DEDUCTS ENERGY COST IF adjust.ship IS DEFINED
/* adjust is an object set by the calling function
properties of the object adjust :
caller string identifier of calling oxp
setting int 0 = disabled, 1 = aft, 2 = forward, 3 = equal
functional % indicates how much damage shieldcycler device has, 100 = no damage
fwd int current forward shield strength
fwd_threshold int see code
aft int aft shield strength
aft_threshold int see code
version int number 0:None,1:Basic,2:Standard,3:advanced determining which version of automatic shield cycler is present
manual_version string number 0:None,1:Basic,2:Standard,3:Advanced determining which version of manual configurator is present
init bool true : calc powerloss for switching to another setting
false : calc powerloss for cycling
max_energy int needed to calculate powerloss for init = true
ship object needed to alter the shield charge
returns an object with these properties :
power: amount of energy used for cycling or -1 in case of error
fwd: new forward shield value
aft: new aft shield value
NOTE1 : this function is intended to be usable for both player & npc ships
NOTE2: this function UPDATES SHIP'S SHIELD PROPERTIES
*/
// set result at power 0, fwd & aft at input values. This corresponds with no changes needed.
// initialise some things
var wsc = worldScripts["Shield Cycler"];
var wsec = worldScripts["shieldequalizercapacitors"];
var result = { power:0,fwd:adjust.fwd,aft:adjust.aft};
var ac = {fwd:adjust.fwd,aft:adjust.aft};
var sc_mode = wsc.$sc_const.mode_names[adjust.setting];
var sc_cycler_loss = wsc.$sc_cycler_loss[adjust.version];
var ship = adjust.ship;
var npc = (ship != player.ship);
var logging = (npc ? (ship.script.$logging || ship == player.ship.target) : this.$logging);
var debug = (npc ? ship.script.$debug : this.$debug);
var energy_transfer = -1;
var desired_transfer = 0;
var shCap, apply_capacitor_fwd, apply_capacitor_aft, energy_range;
var seen = [];
var strip_cycling_obj = function(k, v) { // for use with JSON.stringify in log messages
if (v != null && typeof v == "object") {
if (seen.indexOf(v) >= 0) return;
seen.push(v);
}
return v;
}
if (ship && debug) log(wsc.name, ship.displayName+" - adjust_input: "+JSON.stringify(adjust, strip_cycling_obj)+", energy:"+ship.energy.toFixed(1));
if (ship) {
// caller was updated to use Shield Cycler v1.13
if (npc)
shCap = ship.script;
else
shCap = wsec;
apply_capacitor_fwd = (shCap.$forwardshieldcapacitor ? shCap.$forwardshieldcapacitor.bind(shCap) : null);
apply_capacitor_aft = (shCap.$aftshieldcapacitor ? shCap.$aftshieldcapacitor.bind(shCap) : null);
}
if (shCap && apply_capacitor_fwd) {
// ship has Shield Capacitors... use them!
apply_capacitor_fwd();
apply_capacitor_aft();
result.fwd = ac.fwd = ship.forwardShield;
result.aft = ac.aft = ship.aftShield;
}
if (wsc.$sc_disabled) return result;
switch (sc_mode) {
case "Equal":
if (ac.aft !== ac.fwd)
if ( (ac.fwd < adjust.fwd_threshold) || (ac.aft < adjust.aft_threshold) ) {
desired_transfer = 0.5 * Math.abs(ac.fwd - ac.aft);
energy_transfer = desired_transfer * adjust.functional * 0.01 ;
result.fwd = (ac.fwd < ac.aft) ? ac.fwd + energy_transfer : ac.fwd - energy_transfer ;
result.aft = (ac.fwd < ac.aft) ? ac.aft - energy_transfer : ac.aft + energy_transfer ;
}
break;
case "Forward":
if (ac.fwd < adjust.fwd_threshold) {
desired_transfer = (adjust.fwd_threshold - ac.fwd <= ac.aft) ? adjust.fwd_threshold - ac.fwd : ac.aft ;
energy_transfer = desired_transfer * adjust.functional * 0.01 ;
result.fwd = ac.fwd + energy_transfer;
result.aft = ac.aft - energy_transfer;
}
break;
case "Aft":
if (ac.aft < adjust.aft_threshold) {
desired_transfer = (adjust.aft_threshold - ac.aft <= ac.fwd) ? adjust.aft_threshold - ac.aft : ac.fwd ;
energy_transfer = desired_transfer * adjust.functional * 0.01 ;
result.fwd = ac.fwd - energy_transfer;
result.aft = ac.aft + energy_transfer;
}
break;
case "Disabled":
// no adjustments are done in disabled configuration, so no energy is transferred
desired_transfer = 0;
break;
default:
// should never happen unless caller has set an invalid mode
desired_transfer = -1;
result.power = -1;
log(wsc.name,JSON.stringify(adjust, strip_cycling_obj));
log(wsc.name,wsc.$sc_const.names[adjust.setting]);
log(wsc.name,JSON.stringify(result));
log(wsc.name,"error while adjusting shields");
break;
}
// no transfer done, so no power loss
if (desired_transfer == 0) {
result.power = 0;
} else if (desired_transfer < 0) return result;
else if (adjust.init)
// configuration change costs 2 * (number of energy banks) energy units
result.power = 2 * (Math.floor(adjust.max_energy / 64) + 1);
else {
energy_range = Math.floor(energy_transfer / 64);
if (energy_range >= sc_cycler_loss.length) energy_range = sc_cycler_loss.length - 1;
result.power = energy_transfer * sc_cycler_loss[energy_range];
result.power *= wsc.$sc_manual_reduction[adjust.manual_version];
}
if (debug)
log(wsc.name, (ship?ship.displayName:"")+"-> Mode:"+ sc_mode+" threshold:"+adjust.fwd_threshold.toFixed(1)+"/"+adjust.aft_threshold.toFixed(1)+", desired_transfer:"+desired_transfer.toFixed(1)+", transfer:"+energy_transfer.toFixed(1)+", in (after capacitors):"+ac.fwd.toFixed(1)+"/"+ac.aft.toFixed(1)+", out:"+result.fwd.toFixed(1)+"/"+result.aft.toFixed(1)+", r_power:"+result.power.toFixed(4)+"("+(100*result.power/energy_transfer).toFixed(1)+"%)"+(ship && ship.script && ship.script.$EscortDeckUsable ?", escortDeckUsable:"+ship.script.$EscortDeckUsable:""));
else if (logging)
log(wsc.name, (ship?ship.displayName:"")+": adjusting shields (after capacitors) from (F/A) "+ac.fwd.toFixed(0)+"/"+ac.aft.toFixed(0)+" to "+result.fwd.toFixed(0)+"/"+result.aft.toFixed(0)+" with "+result.power.toFixed(1)+" energy cost (thresholds "+adjust.fwd_threshold.toFixed(1)+"/"+adjust.aft_threshold.toFixed(1)+")");
if (ship) {
ship.aftShield = result.aft;
ship.forwardShield = result.fwd;
if (isNaN(result.power))
log("Shield Cycler", ship.displayName+": energy cost coul not be applied, invalid value: "+result.power+", energy trasnfer: "+energy_transfer.toFixed(3)+", energy range:"+energy_range+", % cost:"+sc_cycler_loss[energy_range]);
else
ship.energy -= result.power;
}
return result;
}
//--------------------------------------------------------------------------------------------------//
this._sc_stop = function _sc_stop() { // NPC-ready
// can be called from NPCs ship.script if 'this' is made to be the ship's script
// returns:
// -2 if device was stopped already
// 0 if stopping was succesfull
var success = -3;
if (!this.$sc_settings.current_configuration)
return -2;
this.$sc_settings.current_configuration = 0;
return 0;
}
//--------------------------------------------------------------------------------------------------//
this._sc_start = function _sc_start(device) {// NPC-ready
// can be called from NPCs ship.script if 'this' is made to be the ship's script
// returns:
// -2 if device was started already
// 0 if starting was succesfull
var wsc = worldScripts["Shield Cycler"];
var success = -3;
if (this.$sc_settings.current_configuration)
return -2;
this.$sc_settings.current_configuration = wsc.$sc_const.cycle[this.$sc_settings.current_cycle_position];
return 0;
}
//--------------------------------------------------------------------------------------------------//
this._sc_store_devices = function _sc_store_devices() {// NPC-ready
// can be called for NPCs if 'this' is made to be the ship's script
// Shield Cycler devices are not portable between ships and will stay that way.
// This poses a problem for oxps (like Ship Storage Helper) that store ships for later retrieval
// returns an object with 2 strings :
// first holds SC values in JSON format
// second (now deprecated) used to hold an encrypted version of first
var wsc = worldScripts["Shield Cycler"];
var sc_values = {
json: "",
enc: ""
};
if (this.$sc_settings)
sc_values.json = JSON.stringify(this.$sc_settings);
else if (this._sc_settings)
sc_values.json = JSON.stringify(this._sc_settings);
return sc_values;
}
//--------------------------------------------------------------------------------------------------//
this._sc_retrieve_devices = function _sc_retrieve_devices(sc_values) {// NPC-ready
// can be called for NPCs if 'this' is made to be the ship's script
// counterpart of wsc._sc_store_devices
// input : an object created by wsc._sc_store_devices
// returns a code value :
// 0 : import sucessfull
// 1 : input != an object
// 2 : object has wrong structure
// 3 : invalid json data
// 4 : plain version doesn't match encrypted version
// 5 : stored data to old
// 6 : stored data to new
var wsc = worldScripts["Shield Cycler"];
var npc = (this.ship != player.ship);
if (typeof sc_values !== "object") return 1;
if (typeof sc_values.json != "string") return 2;
// if (sc_values.json.length == 0) return 0;
if (!npc && worldScripts.Lib_Config) worldScripts.Lib_Config._unregisterSet(wsc._scConfig);
var ret = wsc._parseSavedSettings.call(this, sc_values.json);
if (ret) {
return ret;
}
if (!npc && worldScripts.Lib_Config) {
wsc._setLibConfigVisibility();
worldScripts.Lib_Config._registerSet(wsc._scConfig);
}
log(wsc.name,"imported stored ship data");
if (this.ship == player.ship)
wsc._sc_update_status();
return 0;
}
//--------------------------------------------------------------------------------------------------//
this._scChange_disabled = function _scChange_disabled() {
var wsc = worldScripts["Shield Cycler"];
wsc._sc_settings.general.disabled = wsc._sc_settings.general.sc_disabled = wsc.$sc_disabled;
}
//--------------------------------------------------------------------------------------------------//
this._scChange_threshold = function _scChange_threshold() {
return;
}
//--------------------------------------------------------------------------------------------------//
this._scChange_start_configuration = function _scChange_start_configuration() {
return;
}
//--------------------------------------------------------------------------------------------------//
this._scChange_cycler_mask = function _scChange_cycler_mask() {
return;
}
|