Back to Index Page generated: Nov 12, 2024, 11:02:04 PM

Expansion Shield Cycler

Content

Warnings

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

Manifest

from Expansion Manager's OXP list from Expansion Manifest
Description Distributes shield energy between fore and aft shields. Adjustable with OXPConfig. Distributes shield energy between fore and aft shields. Adjustable with OXPConfig.
Identifier oolite.oxp.Lone_Wolf.ShieldCycler oolite.oxp.Lone_Wolf.ShieldCycler
Title Shield Cycler Shield Cycler
Category Equipment Equipment
Author Lone_Wolf Lone_Wolf
Version 1.12 1.12
Tags
Required Oolite Version
Maximum Oolite Version
Required Expansions
  • oolite.oxp.Svengali.CCL:1.7.1
  • oolite.oxp.Svengali.OXPConfig:2.3.1
  • oolite.oxp.Svengali.CCL:1.7.1
  • oolite.oxp.Svengali.OXPConfig:2.3.1
  • Optional Expansions
    Conflict Expansions
  • oolite.oxp.Lone_Wolf.ShieldCyclerNext:0
  • oolite.oxp.Lone_Wolf.ShieldCyclerNext:
  • Information URL http://wiki.alioth.net/index.php/ShieldCycler n/a
    Download URL https://wiki.alioth.net/img_auth.php/c/c5/ShieldCycler_1.12.oxz n/a
    License CC BY-SA 4 CC BY-SA 4
    File Size n/a
    Upload date 1610873465

    Documentation

    Also read http://wiki.alioth.net/index.php/Shield%20Cycler

    ShieldCycler v 1.12 ReadMe & License.txt

    --------------------------------------------------------------
    
    License:
    This work is licensed under the Creative Commons Attribution-Share Alike 4.0 Unported License.
    To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/ 
    or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. 
    
    --------------------------------------------------------------
    
    Now Fully Configurable !
    
    Thanks to Svengali and everyone that contributed to Cabal Common Library & OxpConfig.
    
    --------------------------------------------------------------
    
    Background
    
    Why do spaceships have 2 shields and not 1 (round ship) or 12 (dodecahedron station) ?
    
    Early shields could not protect a whole spaceship, only small areas of the ship.
    Engines, power core, cockpit, crew quarters were among the first areas to get shields protection.
    Soon this let to many small isolated shield pockets throughout the ship, and that was not managable.
    The military (well known for having the 'right' priorities) decided that the crucial parts of a spaceship were 
    powercore and cockpit.
    Without power your weapons are useless, and you also need someone to press the trigger (or repair the powercore ...).
    In all existing shipdesigns at the time the powercore was at the back of the ship, and the cockpit at the front side.
    (there was no weapon powerful enough to damage a space station, so they didn't have shields at all).
    This resulted in aft shields and forward shields.
    
    As shield technology improved, more and more of the ship got shield protection.
    The closer the aft and forward shielded parts got together, the more they influenced and weakened eachother.
    A new device was proposed to deal with these problems : a shield inhibitor.
    The idea was to put many of these devices in speficic locations in the ship to achieve the desired effect.
    During Proof of Concept small scale lab tests of the inhibitor, an intern messed up some settings.
    Instead of 2 separate shields they had 1 shield for about 2 minutes.
    The designer was informed of this, checked and realised he had used simplified algorithms for the basic components.
    By using the latest quantum physics algortihms for the components, he was able to proof both combining and separation of shields were possible.
    
    Converting the algorithm to a solution usable in a device however was much harder.
    Analysis showed that solving the combining equations would take atleast 1000 times
    the computer effort needed for the separation.
    Guess what solution was chosen by the military ?
    
    Location :
    
    "The Loving Feline", a Seedy Space Bar somewhere in Santaari
    
    While sipping Zaquession evil juice, commander Lone_Wolf (rated competent) reflected upon his trip here.
    During the voyage from the witchpoint to the main station, his cobbie had become the target of 10 pirates at once.
    Injectors saved the cobbie, but while running 6 equipment items had been damaged. 
    Lone_Wolf was an engineer before he chose a new careerpath as a bountyhunter / trader and had repaired the items with succes.
    What bothered him however was that when the damage occurred, his forward shields were still at full strength.
    Only the aft shield was depleted.
    He knew the shield technology history, but computers had become much more powerful since that choice was made.
    "A combining inhibitor would have saved me a lot of work today, and likely have saved the lives of many pilots".
    a few tables further a mixed group of 5 pilots was talking, all were rated dangerous or higher.
    "Time to ask more experienced pilots"
    
    From the experiended pilots Lone_Wolf learned that there were rumours about a "Shield Equalizer" being in development. No details about it were known though, not even the name of the designer or company.
    Lone_Wolf decided it was best to start a design by himself and see if he could find more info.
    Fortunately the Loving Feline had a high enough tech level and good hyperspace communications, so he decided to stay there a while. (the presence of both clean and pirate ships near would help with testing).
    The first prototype of LW's "Shield Cycler" was ready soon, and worked ok, but lacked options for control and finetuning.
    A few weeks later a redesigned prototype was ready for it's first in-flight tests, but no clean pilots were available to help with testing. Lone_Wolf decided to take a break and do some research.
    He found out the hypermail address of the developer of "Shield Equalizer" , CommonSenseOTB, and contacted him.
    
    It turned out this guy was indeed working on a similar device, but felt it should be fully automated and need very little pilot control. 
    He also planned to combine the equalizer with a capacitor that stored shield energy & indicated he planned to use the Shield Equalizer as the starting point for a company.
    LW had no interest in starting a company, but intended to release the design into the public domain, so engineers everywhere could build it.
    LW and CSOTB did agree to make their designs compatible, so pilots could use both but their goals were to different to make 1 device.
    
    
    Shield Cycler
    
    Continually adjusts shield energy in automatic or manually chosen configuration.
    
    
    Both - Equal shields aft and forward
    Forward - Max forward shield, remainder on aft shield
    Aft - Max aft shield, remainder (if any) on forward shield
    Disabled : inactive
    
    Threshold, launch configuration and enabling / disabling manual cycler settings can be done through OxpConfig while docked.
    All adjustments are instantaneous, but use some ship energy.
    The powerloss needed for changing the configuration is related to number of energy banks and the same for all types of cyclers.
    Shield adjusting comes with a powerloss that depends on the amount of energy that needs to be transferred and differs between types.
    
    
    To enjoy all options ShieldCycler offers, you should have 2 other oxps installed :
      Cabal Common Library 1.7.1
      OxpConfig 2.3.1 or later
    
    
    Buyable Devices :
    
    Shield Cycler Basic, 100 credits , TL 2
        works automatically, both setting.
    
    Manual Configurator Basic 200 credits, TL 1
        requires SC Basic or better
        primable with Shift+n
        allows in-flight manual switching between both/forward/aft/disabled configuration
        powerloss for changing is : nr_of_energy_banks + 5
    
    Shield Cycler Standard, 24900 credits, TL 11
        reduced powerloss
        requires Shield Booster, compatible with Mil. Shields
        Allows the setting of a threshold that determines when adjustments begins.
        
    Manual Configurator Standard, 36600 credits, TL 11
        requires SC Standard or Advanced
        primable with Shift+n
        allows in-flight manual switching between both/forward/aft configuration
        reduces powerloss of SC Standard & SC Advanced by 20%
    
    
    Shield Cycler Advanced, 61500 credits, TL 14
        requires Mil. Shields
        reduced powerlosses
        allows choosing of a specific setting on Launch
        
    Manual Configurator Advanced, 146400 credits, TL 14
        requires SC Advanced
        primable with Shift+n
        reduces powerloss of SC Advanced by 50%
        uses ship power of 2* energy banks for each in-flight change
        Allows to disable any of the possible settings.
        NOTE : atleast 1 needs to be enabled.
        
    Sell in-flight configurator, 100 credits, TL 1
        removes all in-flight configuration devices and thus reverts all to the automatic version, 60% refund
    
    Sell Shield Cycler, 100 credits, TL 1
        removes all automatic shield cycler devices, 60% refund
        Will only be visible if you have no manual configurator anymore.
    
    
    Power loss table for shield adjustments (values shown are valid when you have no manual configurator installed)
    
    transferred energy            < 64    64 - 127    128 - 191   192 - 255   256 - 319   > 320
    Shield Cycler Basic           4       5           6           8           12          14      
    Shield Cycler Standard        3       4           4           6           8           10
    Shield Cycler Advanced        2       2           3           4           6           7
    
    Notes for players :
      
    -   Shield Cycler & Manual Configurator devices can be damaged, although NOT destroyed.
        When damaged they will still work, but with reduced functionality.
        There is a repair option, accessible from the F3 screen.
    
    -   None of the shield cyclers / manual configurator devices are visible in the F3 equipment screen, they are however visible in F5+F5 screen.
    
    -   The basic versions of Shield Cycler and Manual Configurator lay the groundwork which the other versions need,
        that's the main reason why the standard/advanced versions are listed as upgrades.
        removal is done by downgrading, but to make it easier for pilots the tech will combine several downgrades into one.
        
    
    
    Notes for "Dark Siders" :
    
    -   If you have equipment items that are not compatible or require shieldcycler devices to be present  :
        The presence of any shield cycler device can be checked by testing for "EQ_SC_SHIELD_CYCLER_INTERNAL" .
        to test for Manual Configurator devices only, use "EQ_SC_MANUAL_CONFIGURATOR_INTERNAL"
    
    -   There are several functions for use by other oxps, check wiki .
        
    -   Incase you wish to use ShieldCycler for npc ships, check SC_Core.js script, function this._sc_adjust and contact me.
    
    --------------------------------------------------------------
    
    Todo list / current situation
    
    releases :
    oxp & oxz Shield Cycler 1.12 (stable version)
    
    oxp & oxz Shield Cycler Next 1.12 (development version )
    
    
    Plans/Future versions
        
    
    v1.13 switch to OxpConfig v3
          list OxpConfig v3 as required dependency
    
    v1.14
        in-flight repair options
        Thargoid has told me he feels partial repairs don't fit in with the goal of repairbots. He has warned me about several potential problems, and urged me to keep them contained in my oxp at first due to these.
    
    v1.20
    
        re-release 1.14.x as stable
        remove code to convert pre-1.10 savegames
        add new cycler mode "Lowest" that mimics shieldequalizer functionality
        investigate whether the timer based functionality (smooth transfer / sound ) used by shieldequaliser can be combined with my event-driven approach for shield cycler device
        add capacitors from shieldequalizer, making sure they are compatible with other oxps. 
        Keep timer-based behaviour for capacitors ?
        bigger capacitors, like in hardships oxp
        additonal configure options (using OxpConfig) to work with the new devices
        add start/stop functionality for capacitors
        have SC next conflict with shieldequalizer+capacitors oxp
    
        
        
        
    --------------------------------
    History
    
    v 1.12
    new stable version
    small fixes
    
    v 1.11.3 :
    Upon buying a new ship, shield cycler devices were not removed anymore, corrected.
    small fixes
    
    v1.11.2
    Cabal Common Library and OxpConfig are now required dependencies
    new external methods _sc_store_devices & _sc_retrieve_devices : allows Ship Storage Helper to store/retrieve ships with SC devices installed correctly
    
    v1.11.1
        bugfix in shipLaunchedEscapePod
        implemented 1.82 functionality
        Minimum Oolite version is now 1.81
    
    v1.11
    
        switch from unbreakable equipment to loss of functionality when damaged
        used schema :
        every direct hit will reduce functionality by 10% , but it won't go below 40% functionality
        since the presence / absence of shield booster and mil shields already influences SC performance, there is no additonal functionality loss when they are damaged
        new repair option when docked (F3 screen) 
        repair price  :
        calculate total price of all installed SC devices
        multiply by .5
        multiply with (100 -functionality)/100
    
    v1.10.2
        oxpcSettings : switched from Notify to DynamicNotify
        conflicts with ShieldCycler 1.0 oxz
        released as oxz
    
    v1.10.1
        small bugfixes
    
    v1.10.
    
        Major rewrite
        code split over many (currently 9) script files instead of 2 to improve maintainability / flexibility.
        objects are used to share information between scripts where possible 
        oxp disables itself if savegame to old or to new.
        start/stop functionality changed
        new option through oxpconfig to disable entire oxp
          (the options for pilots to disable Shield Cycler were limited and dependant on having certain equipment).
        use JSON for missionvariables
        add functionality for npc ships to use shield cycler
          (npc ships wanting to use this will need a custom ship script to give them shield functionality, an alternative would be to adjust customshields oxp to use this new functionality)
        display device versions & damage level on F5+F5 screen
          (damage level won't change until 1.11.0 )
        power loss for changing configuration was 2 * (nr_of_energybanks + 1) , this led to a ship with 8 banks loosing almost an entire bank of energy after just 3 changes.
          new formula : nr_of_energybanks + 5
        added shipLaunchedEscapePod event
    
    1.0
    - added code to test for savegames created with 1.10+ (JSON)
    - minor fix in equipment.plist
    - license changed to CC-by-SA 4
    - released as oxz & oxp
    
    
    0.31
    - new function : b-key sets shieldcycler back to whatever the launch setting is
    - optimizied & simplified code
    - updated CCL / OxpConfig requirements
    - added manifest.plist to oxp
    - requires Oolite 1.80
    
    
    0.30.3
    - adjusted to work with CCL 1.6 & OxpConfig 2.0.12
    
    0.30.2
    - small fixes
    - updated to check for recent cabal_common & oxpconfig versions
    - auto-sell cycler devices when player buys a new ship
    
    0.30.1
    - bugfixes
    - encountered problems related to different JS execution contexts for equipment event handlers, shipscript event handlers and worldscript event handlers
      rewrite has as side-benefit that the code no longer uses global vars ( except missionvars) .
    - added sc_stop & sc-start functions so other oxps can stop/start cycler functionality
    - more in-script documentation
    
    0.21.2
    - added configurable options
      requires Cabal Common Library 1.4.1 (or later) and OxpConfig2 2.03 (or later)
    - If CCL / OxpConfig2 are not present or to old, everything works but there will be no configure options
    - cleaned up/ optimised code
    
    0.20.1
    - cycling to forward when forward shield was at full strength used energy, corrected.
    
    0.20
    - brought back disabled setting (was removed in 0.14 )
    - shipLaunchedFromStation didn't check if player has a shield cycler, fixed
    - Equipment names changed to EQ_SC_AAAAAA scheme
    - variables now all start with sc_
    - both automatic and manual versions are now available, see above for details
    - halved power needed for switching configuration, as old number meant 4 switches would drain a complete energybank
    - preparations to use OxpConfig for changing settings in later version
    
    0.14
    -	Basic Shield cycler made incompatible with Shield Booster and Mil. Shields
    	Standard Shield cycler incompatible with Mil. Shields
    -	cycling the configuration now subtracts 4 * # of energy banks from ship energy. 
    -	adjusting also uses shield energy, but the amount is now fixed and related to the transferred amount of shield energy.
    
    0.13
    -	created basic, standard & advanced version incl. sell option.
    -	cycling / adjusting uses ship energy
    -	added EQ_Shield_Equalizer as incompatible equipment
    -	clean / optimize code
    
    0.12 
    -	first public version with 1 device
    

    Equipment

    Name Visible Cost [deci-credits] Tech-Level
    In-flight configurator Advanced no 1464000 14+
    In-flight configurator for Shield Cycler no 2000 2+
    SC Manual Configurator no 1 2+
    standard version In-flight configurator no 366000 11+
    Repair SC devices yes 0 2+
    Sell in-flight configurator yes 1000 2+
    Sell Shield Cycler yes 1000 2+
    Advanced Shield Cycler no 615000 14+
    Basic Shield Cycler no 1000 2+
    Shield Cycler no 1 2+
    Standard Shield Cycler no 249000 11+

    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/SC_Core.js
    "use strict";
    this.name           = "SC Core";
    this.author         = "Lone_Wolf";
    this.copyright      = "(C) 2011-2012, 2014-2015 Lone_Wolf.";
    this.licence        = "CC-by-SA 4.0";
    this.description    = "calculate shield values when cycling";
    this.version        = "1.12";
    
        this._sc_cycler_loss =
        //  power loss for no cycler, basic,standard, advanced adjustments based on adjustment / 64
        //  64 is used because that's the amount of energy in 1 energybank.
          [
    	[ 0, 0, 0, 0, 0, 0 ],     // no cycler present, so no power loss
    	[ 4, 5, 6, 8, 12, 14 ],   // basic cycler
    	[ 3, 4, 4, 6, 8, 10 ],    // standard cycler
    	[ 2, 2, 3, 4, 6, 7 ],     // advanced cycler
          ];
        this._sc_manual_reduction =
        // powerloss multiplier for manual configurators
        // none, basic, standard, advanced
        [ 1, 1, 0.50, 0.20];
    
    this.startUp = function()
      {
        if ( worldScripts["Shield Cycler"].startUp ) { worldScripts["Shield Cycler"].startUp(); };
      };
    
    this._sc_sc_adjust = function(init)
      {
        // setup things for player.ship shield cycling
        var adjust_input =
          {
    	caller: "Shield Cycler",
    	setting: worldScripts["Shield Cycler"]._sc_settings.sc.current_configuration,
    	functional: worldScripts["Shield Cycler"]._sc_settings.sc.functional,
    	fwd: player.ship.forwardShield,
    	fwd_threshold: ( player.ship.maxForwardShield * worldScripts["Shield Cycler"]._sc_settings.sc.threshold * 0.01 ),
    	aft: player.ship.aftShield,
    	aft_threshold: ( player.ship.maxAftShield * worldScripts["Shield Cycler"]._sc_settings.sc.threshold * 0.01 ),
    	version: worldScripts["Shield Cycler"]._sc_settings.sc.version,
    	manual_version: worldScripts["Shield Cycler"]._sc_settings.sc.manual_version,
    	init: init,
    	max_energy: player.ship.maxEnergy
          };
        var adjust_output = {power: 0, fwd:0, aft:0};
        adjust_output = this._sc_adjust(adjust_input);
        if ( adjust_input.init )
          { player.commsMessage( "Cycler configuration : " + worldScripts["Shield Cycler"]._sc_const.names[ adjust_input.setting ] ); };
        if ( adjust_output.power > 0 )
          {
            // apply changes to shields & energy
    	player.ship.forwardShield = adjust_output.fwd;
    	player.ship.aftShield = adjust_output.aft;
    	player.ship.energy -= adjust_output.power;
          };
        return adjust_output.power;
      };
    
      
      
      
      
      
    this._sc_adjust = function (adjust)
      {
        /* adjust is an object set by the calling function
          properties of the object adjust :
    	name		type	meaning
         	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,1,2,3 determining which version of automatic shield cycler is present
    	manual_version	string	number 0,1,2,3 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
    	
          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
    	
    	NOTE : this function is intended to be usable for both player & npc ships
        */
        // set result at power 0, fwd & aft at input values. This corresponds with no changes needed.
        var result = { power:0,fwd:adjust.fwd,aft:adjust.aft};
        var energy_transfer = -1;
        var desired_transfer = 0;
        switch ( worldScripts["Shield Cycler"]._sc_const.names[adjust.setting] )
        {
          case "Equal":
              if ( adjust.aft !== adjust.fwd )
                {
                  if ( (adjust.fwd < adjust.fwd_threshold) || (adjust.aft < adjust.aft_threshold)  )
                    {
                      desired_transfer = 0.5 * Math.abs( adjust.fwd - adjust.aft );
    		  energy_transfer = desired_transfer * adjust.functional * 0.01 ;
                      result.fwd = ( adjust.fwd < adjust.aft ) ? adjust.fwd + energy_transfer : adjust.fwd - energy_transfer ;
                      result.aft = ( adjust.fwd < adjust.aft ) ? adjust.aft - energy_transfer : result.aft = adjust.aft + energy_transfer ;
                    };
                };
              break;
          case "Forward":
              if ( adjust.fwd < adjust.fwd_threshold )
                { 
                  desired_transfer  = ( desired_transfer <= adjust.aft ) ? adjust.fwd_threshold - adjust.fwd : adjust.aft ;
                  energy_transfer = desired_transfer * adjust.functional * 0.01 ;
    	      result.fwd = adjust.fwd + energy_transfer;
                  result.aft = adjust.aft - energy_transfer;
                };
              break;
          case "Aft":
              if ( adjust.aft < adjust.aft_threshold )
                {
                  desired_transfer  = ( desired_transfer > adjust.fwd ) ? adjust.aft_threshold - adjust.aft : adjust.fwd ;
    	      energy_transfer = desired_transfer * adjust.functional * 0.01 ;
    	      result.fwd = adjust.fwd - energy_transfer;
                  result.aft = adjust.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(this.name,JSON.stringify(adjust));
    	log(this.name,worldScripts["Shield Cycler"]._sc_const.names[adjust.setting]);
    	log(this.name,JSON.stringify(result));
    	log(this.name,"error while adjusting shields");
            break;
        };
        // no transfer done, so no power loss
        if ( desired_transfer = 0 ) { result.power = 0; return result;};
        // incase something went very wrong
        if ( desired_transfer < 0 ) { return result; };
        if ( adjust.init )
    	    { 
    	      result.power = 2 * ( Math.floor( adjust.max_energy / 64) + 1);
    	    }
    	  else
    	    { 
    	      result.power = this._sc_cycler_loss[adjust.version] [Math.floor(desired_transfer / 64)];
    	      result.power *= this._sc_manual_reduction[adjust.manual_version];
    	    };
        return result;
      };
    
    Scripts/SC_Equipment_Conditions.js
    "use strict";
    this.name           = "SC equipment condtion script";
    this.author         = "Lone_Wolf";
    this.copyright      = "(C) 2011-2012, 2014-2015 Lone_Wolf.";
    this.licence        = "CC-by-SA 4.0";
    this.description    = "SC equipment condition script";
    this.version        = "1.12";
    
    this.allowAwardEquipment = function(equipment, ship, context)
    {
      if ( worldScripts["Shield Cycler"].startUp ) { worldScripts["Shield Cycler"].startUp(); };
      var allowed = false;
      switch ( equipment )
        {
          case "EQ_SC_SHIELD_CYCLER_BASIC":
    	allowed = ( worldScripts["Shield Cycler"]._sc_settings.sc.version == worldScripts["Shield Cycler"]._sc_const.none ) ? true : false;
    	break;
          case "EQ_SC_SHIELD_CYCLER_STANDARD":
    	allowed = ( worldScripts["Shield Cycler"]._sc_settings.sc.version == worldScripts["Shield Cycler"]._sc_const.basic ) ? true : false;
    	break;
          case "EQ_SC_SHIELD_CYCLER_ADVANCED":
    	allowed = ( worldScripts["Shield Cycler"]._sc_settings.sc.version == worldScripts["Shield Cycler"]._sc_const.standard ) ? true : false;
    	break;
          case "EQ_SC_MANUAL_CONFIGURATOR_BASIC":
    	if ( worldScripts["Shield Cycler"]._sc_settings.sc.version != worldScripts["Shield Cycler"]._sc_const.none ) 
    	  { 
    	    allowed = ( worldScripts["Shield Cycler"]._sc_settings.sc.manual_version == worldScripts["Shield Cycler"]._sc_const.none ) ? true : false; 
    	  };
    	break;
          case "EQ_SC_MANUAL_CONFIGURATOR_STANDARD":
    	if ( worldScripts["Shield Cycler"]._sc_settings.sc.version > worldScripts["Shield Cycler"]._sc_const.basic )
    	  {
    	    allowed = ( worldScripts["Shield Cycler"]._sc_settings.sc.manual_version == worldScripts["Shield Cycler"]._sc_const.basic ) ? true : false;
    	  };
    	break;
          case "EQ_SC_MANUAL_CONFIGURATOR_ADVANCED":
    	if ( worldScripts["Shield Cycler"]._sc_settings.sc.version == worldScripts["Shield Cycler"]._sc_const.advanced )
    	  {
    	    allowed = ( worldScripts["Shield Cycler"]._sc_settings.sc.manual_version == worldScripts["Shield Cycler"]._sc_const.standard ) ? true : false;
    	  };
    	break;
          case "EQ_SC_SELL_SHIELD_CYCLER":
    	if ( worldScripts["Shield Cycler"]._sc_settings.sc.version > worldScripts["Shield Cycler"]._sc_const.none )
    	  {
    	    allowed = ( worldScripts["Shield Cycler"]._sc_settings.sc.manual_version == worldScripts["Shield Cycler"]._sc_const.none ) ? true : false;
    	  };
    	break;
          case "EQ_SC_SELL_MANUAL_CONFIGURATOR":
    	allowed = ( worldScripts["Shield Cycler"]._sc_settings.sc.manual_version != worldScripts["Shield Cycler"]._sc_const.none ) ? true : false;
    	break;
          case "EQ_SC_SHIELD_CYCLER_INTERNAL":
    	allowed = ( context == "scripted" ) ? true : false;
    	break;
          case "EQ_SC_MANUAL_CONFIGURATOR_INTERNAL":
    	allowed = ( context == "scripted" ) ? true : false;
    	break;
          case "EQ_SC_SC_REPAIR":
    	if ( worldScripts["Shield Cycler"]._sc_settings.sc.version > worldScripts["Shield Cycler"]._sc_const.none )  
    	  {
    	    allowed = ( worldScripts["Shield Cycler"]._sc_settings.sc.functional < 100 ) ? true : false;
    	  };
    	break;
          default:
    	break;
        };
      return allowed;
    };
    
    this.updateEquipmentPrice = function(equipment, price)
    {
      var repair_cost = price;
      if ( equipment == "EQ_SC_SC_REPAIR" )
        {
          repair_cost = worldScripts["Shield Cycler"]._sc_worm.sc_cost[ worldScripts["Shield Cycler"]._sc_settings.sc.version ];
          repair_cost += worldScripts["Shield Cycler"]._sc_worm.manual_cost[ worldScripts["Shield Cycler"]._sc_settings.sc.manual_version ];
          repair_cost *= 0.1;
          repair_cost = 0.5 * repair_cost *  (100 - worldScripts["Shield Cycler"]._sc_settings.sc.functional ) / 100;
        };
      return repair_cost;
    };
    
      
    Scripts/SC_Equipment_Events.js
    "use strict";
    this.name           = "SC equipment events";
    this.author         = "Lone_Wolf";
    this.copyright      = "(C) 2011-2012, 2014-2015 Lone_Wolf.";
    this.licence        = "CC-by-SA 4.0";
    this.description    = "SC equipment event handler";
    this.version        = "1.12";
    
    this.activated = function()
      {
        if ( worldScripts["Shield Cycler"].startUp ) { worldScripts["Shield Cycler"].startUp(); };
        // Triggered by pressing n-key while shieldcycler is primed
        // is only called when player has a manual configurator installed and player presses n-key while device is primed
        // verify if oxp is active, just-in-case
        if ( worldScripts["Shield Cycler"]._sc_settings.general.disabled ) { return; };
        // verify if shield cycler devices are active, just in case
        if ( worldScripts["Shield Cycler"]._sc_settings.general.sc_disabled ) { return; };
        var loop_ready = false;
        var new_config = worldScripts["Shield Cycler"]._sc_settings.sc.current_configuration;
        do
          {
    	new_config = ( new_config + 1 ) % worldScripts["Shield Cycler"]._sc_const.cycle.count;
    	loop_ready = !( worldScripts["Shield Cycler"]._sc_settings.sc.cycler_mask & Math.pow(2, new_config) );
           }
        while ( loop_ready );
        worldScripts["Shield Cycler"]._sc_settings.sc.current_configuration = new_config;
        var error = worldScripts["SC Core"]._sc_sc_adjust(true);
        if (error < 0 )
          {
    	player.commsMessage("Error - check latest log",10);
    	log(this.name,"error while cycling settings");
          };
      };
    
    this.mode = function()
      {
        if ( worldScripts["Shield Cycler"].startUp ) { worldScripts["Shield Cycler"].startUp(); };
        // verify if oxp is active
        if ( worldScripts["Shield Cycler"]._sc_settings.general.disabled ) { return; };
        // checking if SC devices are active
        if ( worldScripts["Shield Cycler"]._sc_settings.general.sc_disabled ) { return; };
        worldScripts["Shield Cycler"]._sc_settings.sc.current_configuration = worldScripts["Shield Cycler"]._sc_settings.sc.start_configuration;
        var error = worldScripts["SC Core"]._sc_sc_adjust(true);
        if (error < 0 )
          {
    	player.commsMessage( "Error - check latest log",10);
    	log(this.name,"error while resetting to start configuration");
          };
      };
    
    Scripts/SC_Savegame_Compatibility_Check.js
    "use strict";
    this.name           = "SC check savegame compatiblity";
    this.author         = "Lone_Wolf";
    this.copyright      = "(C) 2011-2012, 2014-2015 Lone_Wolf.";
    this.licence        = "CC-by-SA 4.0";
    this.description    = "SC check savegame compatiblity";
    this.version        = "1.12";
    
    this._sc_check_savegame = function(savegame_version)
      {
        // return values
        // 0 : to old
        // 1 : conversion needed
        // 2 : missionvars not present, creation needed
        // 3 : missionvars present & correct version
        // 4 : to new
        if ( missionVariables.sc_settings == null )
          {
    	// pre v1.10 or missionvars not created yet
    	if ( missionVariables.sc_config !== null || missionVariables.sc_active !== null ) 
    	  {
    	    // if either of those are used, the savegame was created with a pre 0.21.2 version and to old
    	    return 0;
    	  }
    	if ( missionVariables.sc_threshold !== null)
    	  {
    	    // missionVariables.sc_threshold exists, so savegame is from 0.21.2 or later, but before v1.10
    	    // in higher versions conversion of this format will no longer be supported
    	    return 1;
    	  }
    	// must be a new v1.10+ game, missionvars need to be created
    	return 2;
          };
        // missionVariables.sc_settings  exists, so must be v1.10 or later and uses JSON
        var temp_settings = JSON.parse(missionVariables.sc_settings);
        var savegame_diff = savegame_version - temp_settings.general.savegame_version ;
        if ( savegame_diff  < -1 )
          { 
    	// savegame format is more then 1 version behind of current version, conversion is not supported so to old
    	return 0;
          }
        if ( savegame_diff == -1 )
          { 
    	// savegame is 1 version behind, conversion supported
    	// intended for future use when savegame_version > 0
    	return 1;
          };
        if ( savegame_diff == 0 )
          { 
    	// savegame format hasn't changed
    	return 3;
          };
        // savegame was created with a newer version then supported by installed version of SC
        // should occur only when user has downgraded SC
        return 4;
      };
      
    Scripts/SC_Savegame_Conversion.js
    "use strict";
    this.name           = "SC savegame conversion";
    this.author         = "Lone_Wolf";
    this.copyright      = "(C) 2011-2012, 2014-2015 Lone_Wolf.";
    this.licence        = "CC-by-SA 4.0";
    this.description    = "SC convert savegames";
    this.version        = "1.12";
    
    // code to convert 0.21.2 <= savegame < 1.10.0 to new JSON format introduced in 1.10
    
    this._sc_convert_0_21_2 = function()
      {
        if ( missionVariables.sc_configuration_options !== null ) { delete missionVariables.sc_configuration_options; };      // removed in 0.21.3
        worldScripts["Shield Cycler"]._sc_settings.sc.threshold = parseInt(missionVariables.sc_threshold); 
        delete missionVariables.sc_threshold;
        // configuration order is reversed in 1.10
        worldScripts["Shield Cycler"]._sc_settings.sc.start_configuration = 3 - parseInt(missionVariables.sc_start_configuration);
        delete missionVariables.sc_start_configuration;
        // new in 1.10
        worldScripts["Shield Cycler"]._sc_settings.sc.current_configuration = worldScripts["Shield Cycler"]._sc_settings.sc.start_configuration;
        // cycler possible options were stored in 4 vars, now in a bitmask
        worldScripts["Shield Cycler"]._sc_settings.sc.cycler_mask = 0x00f;
        var temp_mask = 0;
        if ( this._sc_string2bool(missionVariables.sc_both_enabled) ) { temp_mask += 8; };
        delete missionVariables.sc_both_enabled;
        if ( this._sc_string2bool(missionVariables.sc_forward_enabled) ) { temp_mask += 4; };
        delete missionVariables.sc_forward_enabled;
        if ( this._sc_string2bool(missionVariables.sc_aft_enabled) ) { temp_mask += 2; };
        delete missionVariables.sc_aft_enabled;
        if ( this._sc_string2bool(missionVariables.sc_disabled_enabled) ) { temp_mask += 1; };
        delete missionVariables.sc_disabled_enabled;
        worldScripts["Shield Cycler"]._sc_settings.sc.cycler_mask = temp_mask;
        worldScripts["Shield Cycler"]._sc_settings.sc.version = parseInt(missionVariables.sc_version);
        switch ( worldScripts["Shield Cycler"]._sc_settings.sc.version )
          {
    	case worldScripts["Shield Cycler"]._sc_const.advanced:
    	  worldScripts["Shield Cycler"]._sc_change_configuration(2, false);
    	case worldScripts["Shield Cycler"]._sc_const.standard:
    	  worldScripts["Shield Cycler"]._sc_change_configuration(1, false);
    	  break;
    	default:
    	  break;
          };
        delete missionVariables.sc_version;
        worldScripts["Shield Cycler"]._sc_settings.sc.manual_version = parseInt(missionVariables.sc_manual_version);
        if ( worldScripts["Shield Cycler"]._sc_settings.sc.manual_version === worldScripts["Shield Cycler"]._sc_const.advanced )
          { worldScripts["Shield Cycler"]._sc_change_configuration(3, false); };
        delete missionVariables.sc_manual_version;
        // new in 1.10 
        worldScripts["Shield Cycler"]._sc_settings.sc.functional = 100;
        worldScripts["Shield Cycler"]._sc_settings.general.disabled = false;
        worldScripts["Shield Cycler"]._sc_settings.general.sc_disabled = false;
        worldScripts["Shield Cycler"]._sc_settings.general.savegame_version = worldScripts["Shield Cycler"]._sc_const.savegame_version;
        log(this.name,JSON.stringify(worldScripts["Shield Cycler"]._sc_settings));
        delete this._sc_string2bool;
      };
    
    this._sc_string2bool = function(setting)
    /*  Missionvars are stored as strings, but i need booleans. this function uses simple logic to ensure i get true booleans, not fuzzy ones.
        returns a boolean value of either true or false
    */
      {
        if ( setting === "true" )
          { return true;}
        else
          { return false;};
      };
    
    
    Scripts/SC_Shipscript_Events.js
    "use strict";
    this.name           = "SC shipscript events";
    this.author         = "Lone_Wolf";
    this.copyright      = "(C) 2011-2012 , 2014-2015 Lone_Wolf.";
    this.licence        = "CC-by-SA 4.0";
    this.description    = "SC shipscript events handler";
    this.version        = "1.12";
    
    
    this.startUp = function()
      {
        if ( worldScripts["Shield Cycler"].startUp ) { worldScripts["Shield Cycler"].startUp(); };
      };
    
    this.shipLaunchedFromStation = function(station)
      {
        if ( worldScripts["Shield Cycler"]._sc_settings.general.disabled ) { return; };
        if ( worldScripts["Shield Cycler"]._sc_settings.general.sc_disabled ) { return; };
        // check if player has a Shield Cycler
        if ( worldScripts["Shield Cycler"]._sc_settings.sc.version == worldScripts["Shield Cycler"]._sc_const.none ) { return; };
        worldScripts["Shield Cycler"]._sc_settings.sc.current_configuration = worldScripts["Shield Cycler"]._sc_settings.sc.start_configuration;
        worldScripts["SC Core"]._sc_sc_adjust(true);
      };
    
    this.shipTakingDamage = function(amount, fromEntity, damageType)  
      {   
        if ( worldScripts["Shield Cycler"]._sc_settings.general.disabled ) { return; };
        if ( worldScripts["Shield Cycler"]._sc_settings.general.sc_disabled ) { return; };
        if ( worldScripts["Shield Cycler"]._sc_settings.sc.version == worldScripts["Shield Cycler"]._sc_const.none ) { return; };
        worldScripts["SC Core"]._sc_sc_adjust(false);
      };
    
    this.shipLaunchedEscapePod = function(escapepod, passengers)
      {
        // reset devices / vars when pilot ejects
        if ( worldScripts["Shield Cycler"]._sc_settings.sc.version == worldScripts["Shield Cycler"]._sc_const.none ) { return; };
        if ( worldScripts["Shield Cycler"]._sc_settings.sc.manual_version != worldScripts["Shield Cycler"]._sc_const.none ) 
          { 
    	worldScripts["Shield Cycler"]._sc_change_configuration(3, true);
    	player.ship.removeEquipment("EQ_SC_MANUAL_CONFIGURATOR_INTERNAL");
    	worldScripts["Shield Cycler"]._sc_settings.sc.manual_version  = worldScripts["Shield Cycler"]._sc_const.none;
    	worldScripts["Shield Cycler"]._sc_settings.sc.cycler_mask  = 0x00f;
          };
        worldScripts["Shield Cycler"]._sc_change_configuration(2, true);
        worldScripts["Shield Cycler"]._sc_change_configuration(1, true);
        player.ship.removeEquipment("EQ_SC_SHIELD_CYCLER_INTERNAL");
        worldScripts["Shield Cycler"]._sc_settings.sc.version  = worldScripts["Shield Cycler"]._sc_const.none;
        worldScripts["Shield Cycler"]._sc_settings.sc.start_configuration = worldScripts["Shield Cycler"]._sc_const.both;
        worldScripts["Shield Cycler"]._sc_settings.sc.threshold = 100;
        worldScripts["Shield Cycler"]._sc_settings.sc.functional = 100;
        worldScripts["Shield Cycler"]._sc_update_oxpconfig_vars();
      };
    
    Scripts/SC_Worldscript_Events.js
    "use strict";
    this.name           = "SC worldscript events";
    this.author         = "Lone_Wolf";
    this.copyright      = "(C) 2011-2012 , 2014-2015 Lone_Wolf.";
    this.licence        = "CC-by-SA 4.0";
    this.description    = "SC worldscript event handler";
    this.version        = "1.12";
    
    this.startUp = function()
      {
        if ( worldScripts["Shield Cycler"].startUp ) { worldScripts["Shield Cycler"].startUp(); };
      };
    
    // worldscript events
    this.guiScreenWillChange = function(to, from)
      {
        if ( to !== "GUI_SCREEN_MANIFEST" ) { mission.setInstructions(null); return; };
        if ( worldScripts["Shield Cycler"]._sc_settings.sc.version == worldScripts["Shield Cycler"]._sc_const.none ) { return; };
        var _sc_display_strings = ["none","basic","standard","advanced"];
        var sc_display_cycler = _sc_display_strings[ worldScripts["Shield Cycler"]._sc_settings.sc.version ];
        var sc_display_manual = "";
        var sc_display_functional = worldScripts["Shield Cycler"]._sc_settings.sc.functional ;
        if ( worldScripts["Shield Cycler"]._sc_settings.sc.manual_version != worldScripts["Shield Cycler"]._sc_const.none )
          { 
            sc_display_manual = _sc_display_strings[ worldScripts["Shield Cycler"]._sc_settings.sc.manual_version ];
          };
        var instruct = 
          [
            "Shield Cycler Status",
            "SC version: "  + sc_display_cycler,
            "Manual Configurator: " + sc_display_manual,
            sc_display_functional + " %% functional"
          ];
        mission.setInstructions( instruct );
      };
    
    this.playerWillSaveGame = function()
      {
        missionVariables.sc_settings = JSON.stringify(worldScripts["Shield Cycler"]._sc_settings);
      };
    
    this.playerBoughtNewShip = function(ship)
      {
        // sell shieldcycler equipment if still present and reset missionvars
        if ( worldScripts["Shield Cycler"]._sc_settings.sc.version == worldScripts["Shield Cycler"]._sc_const.none ) { return; };
        var refund = 0;
        if ( worldScripts["Shield Cycler"]._sc_settings.sc.manual_version != worldScripts["Shield Cycler"]._sc_const.none ) 
          { 
    	refund = worldScripts["Shield Cycler"]._sc_remove_manual();
          };
        refund += worldScripts["Shield Cycler"]._sc_remove_shield_cycler();
      };
    
    this.equipmentDamaged = function(equipmentKey)
      {
        switch ( equipmentKey )
          {
    	case "EQ_SC_SHIELD_CYCLER_INTERNAL":
    	case "EQ_SC_MANUAL_CONFIGURATOR_INTERNAL":
    	  player.commsMessage("ShieldCycler devices taking damage, functionality is reduced",6);
    	  player.ship.setEquipmentStatus(EquipmentInfo.infoForKey(equipmentKey), "EQUIPMENT_OK");
    	  if ( worldScripts["Shield Cycler"]._sc_settings.sc.functional >= 50 )
    	    { worldScripts["Shield Cycler"]._sc_settings.sc.functional -= 10; }
    	  else
    	    {  worldScripts["Shield Cycler"]._sc_settings.sc.functional = 40; };
    	  break;
    	default:
    	  break;
          };
      };
    
    this.playerBoughtEquipment = function(equipmentKey)
      {
        // This function supplements the code in equipment.plist & SC_Equipment_Condtion.js
        switch ( equipmentKey )
            {
              case "EQ_SC_SHIELD_CYCLER_BASIC":
                player.ship.removeEquipment(equipmentKey);
    	    player.ship.awardEquipment("EQ_SC_SHIELD_CYCLER_INTERNAL");
                worldScripts["Shield Cycler"]._sc_settings.sc.start_configuration = worldScripts["Shield Cycler"]._sc_const.cycle.both;
                worldScripts["Shield Cycler"]._sc_settings.sc.threshold = 100;
    	    worldScripts["Shield Cycler"]._sc_update_oxpconfig_vars();
                worldScripts["Shield Cycler"]._sc_settings.sc.functional = 100;
    	    worldScripts["Shield Cycler"]._sc_settings.sc.version  = worldScripts["Shield Cycler"]._sc_const.basic;
                break;
              case "EQ_SC_SHIELD_CYCLER_STANDARD":
                player.ship.removeEquipment(equipmentKey);
                worldScripts["Shield Cycler"]._sc_change_configuration(1, false);
    	    worldScripts["Shield Cycler"]._sc_settings.sc.version  = worldScripts["Shield Cycler"]._sc_const.standard;
                break;
              case "EQ_SC_SHIELD_CYCLER_ADVANCED":
                player.ship.removeEquipment(equipmentKey);
                worldScripts["Shield Cycler"]._sc_change_configuration(2, false);
    	    worldScripts["Shield Cycler"]._sc_settings.sc.version  = worldScripts["Shield Cycler"]._sc_const.advanced;
                break;
              case "EQ_SC_MANUAL_CONFIGURATOR_BASIC":
    	    player.ship.removeEquipment(equipmentKey);
                player.ship.awardEquipment("EQ_SC_MANUAL_CONFIGURATOR_INTERNAL");
                worldScripts["Shield Cycler"]._sc_settings.sc.cycler_mask  = 0x00f;
    	    worldScripts["Shield Cycler"]._sc_settings.sc.manual_version  = worldScripts["Shield Cycler"]._sc_const.basic;
                break;
              case "EQ_SC_MANUAL_CONFIGURATOR_STANDARD":
    	    player.ship.removeEquipment(equipmentKey);
    	    worldScripts["Shield Cycler"]._sc_settings.sc.manual_version  = worldScripts["Shield Cycler"]._sc_const.standard;
                break;
              case "EQ_SC_MANUAL_CONFIGURATOR_ADVANCED":
    	    player.ship.removeEquipment(equipmentKey);
                worldScripts["Shield Cycler"]._sc_change_configuration(3, false);
    	    worldScripts["Shield Cycler"]._sc_settings.sc.manual_version  = worldScripts["Shield Cycler"]._sc_const.advanced;
                break;
              case "EQ_SC_SELL_MANUAL_CONFIGURATOR":
                player.credits = player.credits + worldscripts["Shield Cycler"]._sc_remove_manual();
                break;
    	  case "EQ_SC_SELL_SHIELD_CYCLER":
                player.credits = player.credits + worldscripts["Shield Cycler"]._sc_remove_shield_cycler();
                break;
    	  case "EQ_SC_SC_REPAIR":
                worldScripts["Shield Cycler"]._sc_settings.sc.functional = 100;
    	    break;
              default:
                break;
            };
      };
    
    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        = "1.12";
    
    /* 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	Introduced in	Used by / Comment
    	_sc_settings			obj	1.10
    	  sc				obj	1.10
    		threshold		int	0.21.2		OxpConfig
    								    percentage, can be 0-100
    		start_configuration     int	0.21.2		OxpConfig
    								    number , 0 = disabled 1 = aft 2 = fwd 3 = equal
    		current_configuration	int	1.10		shipscript events, equipment events
    								    number , 0 = disabled 1 = aft 2 = fwd 3 = equal
    		cycler_mask            	int	1.10		OxpConfig
    								    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	1.10		equipment condition script
    								    percentage, 100 is fully functional, 20 is minimum 
    								    for 1.10 only 100 is used
    								    in 1.11+ this value will be decreased when EQ_SC_SHIELD_CYCLER_INTERNAL or EQ_SC_MANUAL_CONFIGURATOR_INTERNAL get hit
    		version			int	0.21.2		SC_Core.js
    								 number, 0=none 1 = basic , 2 = standard, 3 =advanced 
    		manual_version		int	0.21.2		SC_Core.js
    								 number, 0=none 1 = basic , 2 = standard, 3 =advanced 
              general			obj     1.10
    		disabled		bool	1.10		if true, all devices handled by this oxp will do nothing
    		sc_disabled		bool	1.10		if true, presence of EQ_SC_SHIELD_CYCLER_INTERNAL & EQ_SC_MANUAL_CONFIGURATOR_INTERNAL will have no effect
    		savegame_version	int	1.10		This is a special var intended to track missionVariables changes
    
      NOTE : missionvariables are loaded at startup, then converted into this._sc_setting object .
    	 during game the missionvariables are NOT kept uptodate.
    	 they are stored only when player saves game, done in SC_Worldscript_Events.js .
    
      equipment items
        EQ_SC_SHIELD_CYCLER_INTERNAL          - indicates any shield cycler/manual configurator is installed
        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
        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_INTERNAL and EQ_SC_MANUAL_CONFIGURATOR_INTERNAL will be present in the savefile but NOT visible on the F5 equipment screen
    
    */
    
    // 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 =
      {
        none:0,basic:1,standard:2,advanced:3,
        cycle: { disabled:0,aft:1,forward:2,both:3,count:4 },
        names: [ "Disabled","Aft","Forward","Equal"],
        savegame_version:0
      };
    
    // WORM stuff
    this._sc_worm =
      {
        sc_cost: [0, 0, 0, 0 ],
        manual_cost: [ 0, 0, 0, 0 ]
      };
      
    // R/W stuff
    this._sc_settings =
      {
        sc:
          {
    	threshold:100,
    	start_configuration:this._sc_const.both,
    	current_configuration:this._sc_const.both,
    	cycler_mask:0x00f,
    	functional:100,
    	version:this._sc_const.none,
    	manual_version:this._sc_const.none
          },
        general: { disabled:false,sc_disabled:false,savegame_version:this._sc_const.savegame_version }
      };
    	
    // Properties for internal use
    this._sc_error = 0;
        /* used for error tracking
        * 0 = no error
        * 1 = savegame to old
        * 2 = savegame to new
        */
    
    // for OxpConfig
    // these need to be kept in sync at all times 
    this._sc_oxp_status = this._sc_settings.general.disabled;
    this._sc_sc_status = this._sc_settings.general.sc_disabled;
    // only changed through oxpconfig, synced from this.oxpcNotifyOnChange()
    this._sc_threshold = this._sc_settings.sc.threshold;
    this._sc_start_configuration = this._sc_settings.sc.start_configuration;
    this._sc_cycler_mask = this._sc_settings.sc.cycler_mask;
    this.deactivated = false;
        /*  this property is used by OxpConfig to detect whether it should allow configuration changes.
    	deactivated = false : default behaviour
    	deactivated = true :  OxpConfig will not allow configuration changes
        */
    
    this.oxpcSettings = 
      { 
        Info:
          {
            Name:"Shield Cycler",DynamicNotify:true,LeaveData:true,
            InfoB:"enable / disable Shield Cycler oxp functionality / the devices it manages",
            InfoS:"Threshold % determines when adjusting is done. 100 = always, 0 = never. Start configuration is the configuration that will be set upon launch (3 = equal, 2 = fwd, 1= aft, 0 = disabled).",
            InfoE:"enable / disable the availability of the settings for manual cycling. Note : if you disable all, Shield Cycler oxp will enable the disabled setting"
          },
        Bool0: {Name:"_sc_oxp_status",Def:false,Hide:false,Desc:"disable SC OXP."},
        Bool1: {Name:"_sc_sc_status",Def:false,Hide:false,Desc:"disable cycler devices."},
        SInt0: {Name:"_sc_threshold",Def:100,Max:100,Hide:true,Desc:"threshold %"},
        SInt1: {Name:"_sc_start_configuration",Def:3,Max:3,Hide:true,Desc:"launch setting"},
        EInt0: {Name:"_sc_cycler_mask",Def:0x001,Max:0x00f,Hide:true,Desc:["Disabled","Aft","Forward","Equal"]}
      };
    
    this.startUp = function()
      {
        // CCL & OxpConfig are required for SC, but this is taken care of by Oolite itself through the manifest.plist file.
        // This version of SC requires 1.81+ , that is checked through manifest.plist & requires.plist
        switch ( worldScripts["SC check savegame compatiblity"]._sc_check_savegame(this._sc_settings.general.savegame_version) )
          {
    	case 0:
    	  // savegame to old
    	  this._sc_settings.general.disabled = true;
    	  this.deactivated= true;
    	  this._sc_error = 1;
    	  player.commsMessage("Your savegame is to old for this version of Shield Cycler",10);
    	  player.commsMessage("Shield Cycler is DISABLING itself now",10);
    	  player.commsMessage("ask for help on Oolite BBS.",10);
    	  log(this.name," - DISABLED because savefile is to old");
    	  break;
    	case 1:
    	  // savegame needs converting from old-style missionvars to JSON
    	  worldScripts["SC savegame conversion"]._sc_convert_0_21_2();
    	  this._sc_update_oxpconfig_vars();
    	  log(this.name," - savegame missionvars converted into _sc_settings");
    	  break;
    	case 2:
    	  // missionvars not present, will be created when game is saved
    	  break;
    	case 3:
    	  // everything in order, load missionvars
    	  this._sc_settings = JSON.parse(missionVariables.sc_settings);
    	  this._sc_update_oxpconfig_vars();
      	  if ( ( this._sc_settings.sc.version > this._sc_const.basic ) ) { this._sc_change_configuration(1, false); };
    	  if ( this._sc_settings.sc.version == this._sc_const.advanced ) { this._sc_change_configuration(2, false); };
    	  if ( this._sc_settings.sc.manual_version == this._sc_const.advanced ) { this._sc_change_configuration(3, false); };	  
    	  log(this.name," - savegame missionvars loaded");
    	  break;
    	case 4:
    	  // savegame to new
    	  this._sc_settings.general.disabled = true;
    	  this.deactivated= true;
    	  this._sc_error = 2;
    	  player.commsMessage("Your savegame is to NEW for this version of Shield Cycler",10);
    	  player.commsMessage("Shield Cycler is DISABLED",10);
    	  player.commsMessage("ask for help on Oolite BBS.",10);
    	  log(this.name," - DISABLED because savefile  is to NEW");
    	  break;
    	default:
    	  break;
          };
        if ( !this._sc_settings.general.disabled )
          {
            // calculate total price values
            this._sc_worm.sc_cost[1] = EquipmentInfo.infoForKey("EQ_SC_SHIELD_CYCLER_BASIC").price;
            this._sc_worm.sc_cost[2] = this._sc_worm.sc_cost[1] + EquipmentInfo.infoForKey("EQ_SC_SHIELD_CYCLER_STANDARD").price;
            this._sc_worm.sc_cost[3] = this._sc_worm.sc_cost[2] + EquipmentInfo.infoForKey("EQ_SC_SHIELD_CYCLER_ADVANCED").price;
            this._sc_worm.manual_cost[1] = EquipmentInfo.infoForKey("EQ_SC_MANUAL_CONFIGURATOR_BASIC").price;
            this._sc_worm.manual_cost[2] = this._sc_worm.manual_cost[1] + EquipmentInfo.infoForKey("EQ_SC_MANUAL_CONFIGURATOR_STANDARD").price;
            this._sc_worm.manual_cost[3] = this._sc_worm.manual_cost[2] + EquipmentInfo.infoForKey("EQ_SC_MANUAL_CONFIGURATOR_ADVANCED").price;
          };
            
      delete this.startUp;
      };
    
    // Helper functions for all SC scripts including this one
      this._sc_change_configuration = function(setting, hide)
      {
        // sets/resets visibility of configure options in OCPConfig
        switch ( setting )
          {
            case 1:
                this.oxpcSettings.SInt0.Hide = hide;
                break;
            case 2:
                this.oxpcSettings.SInt1.Hide = hide;
                break;
            case 3:
                this.oxpcSettings.EInt0.Hide = hide;
                break;
            default:
                break;
          };
      };
      
    this._sc_update_oxpconfig_vars = function()
      {
        this._sc_oxp_status = this._sc_settings.general.disabled;
        this._sc_sc_status = this._sc_settings.general.sc_disabled;
        this._sc_threshold = this._sc_settings.sc.threshold;
        this._sc_start_configuration = this._sc_settings.sc.start_configuration;
        this._sc_cycler_mask = this._sc_settings.sc.cycler_mask;  
      };
    
    this._sc_remove_manual = function()
      {
        // remove manual configurator devices only
        // returns refund value in credits
        var refund1 = this._sc_worm.manual_cost[this._sc_settings.sc.manual_version];
        refund1 = refund1 * this._sc_settings.sc.functional * 0.01;
        player.ship.removeEquipment("EQ_SC_MANUAL_CONFIGURATOR_INTERNAL");
        this._sc_settings.sc.manual_version  = this._sc_const.none;
        this._sc_settings.sc.cycler_mask  = 0x00f;
        this._sc_update_oxpconfig_vars();
        refund1 = parseInt(refund1 * 0.1 * 0.6);
        return refund1;
      };  
    
    this._sc_remove_shield_cycler = function()
      {
        // remove all shield cycler devices
        // returns refund value in credits
        var refund1 = 0;
        // if manual configurator devices are present, remove them first
        if ( this._sc_settings.sc.manual_version != this._sc_const.none )
          {
            refund1 = this._sc_remove_manual();
          }
        refund1 = refund1 + this._sc_worm.sc_cost[ this._sc_settings.sc.version ];
        switch ( this._sc_settings.sc.version )
          {
            case this._sc_const.advanced:
               this._sc_change_configuration(2, true);
            case this._sc_const.standard:
               this._sc_change_configuration(1, true);
               break;
            default:
              break;
          };
        refund1 = refund1 * this._sc_settings.sc.functional * 0.01;
        player.ship.removeEquipment("EQ_SC_SHIELD_CYCLER_INTERNAL");
        this._sc_settings.sc.version  = this._sc_const.none;
        this._sc_settings.sc.start_configuration = this._sc_const.both;
        this._sc_settings.sc.threshold = 100;
        this._sc_update_oxpconfig_vars();
        this._sc_settings.sc.functional = 100;
        refund1 = parseInt(refund1 * 0.1 * 0.6);
        return refund1;
      };
      
    
      
    // functions for use by other oxps
    
    this._sc_stop = function(device)
      {
    /*	device is a string to indicate which devices handled by SC oxp need to be stopped
    	currently has 2 possible values : 
    	"ALL" : disable all devices
    	"SC" : disables just the shieldcycler
    	In future versions there will be more options
    
    	returns
    	-3 if SC was disabled
    	-2 if device was stopped already
    	-1 device string invalid
    	0 if stopping was succesfull
    	NOTE : no messages to player or logfile, imo this is the responsibility of the calling oxp
    	NOTE : calling worldScripts["Shield Cycler"]._sc_stop("SC") DOES NOT disable the entire oxp.
    */
        var success = -3;
        if ( this._sc_error == 0 )
          {
    	switch ( device )
    	  {
    	    case "ALL":
    	      if ( this._sc_settings.general.disabled )
    		{ success = -2; }
    	      else 
    		{ 
    		  this._sc_settings.general.disabled = true;
    		  this._sc_update_oxpconfig_vars();
    		  success = 0;
    		};
    	      break;
    	    case "SC":
    	      if ( this._sc_settings.general.sc_disabled )
    		{ success = -2; }
    	      else
    		{
    		  this._sc_settings.general.sc_disabled = true;
    		  this._sc_update_oxpconfig_vars;
    		  success = 0;
    		};
    	      break;
    	    default:
    	      succes = -1;
    	      break;
    	  };
          };
        return success;
      };
    
    this._sc_start = function(device)
      {
    /*	device is a string to indicate which devices handled by SC oxp need to be started
    	currently has 2 possible values : 
    	"ALL" : start all devices
    	"SC" : start just the shieldcycler
    
    	returns
    	-3 if SC is disabled
    	-2 if device was started already
    	-1 device string invalid
    	0 if starting was succesfull
    	Note : no messages to player or logfile, imo this is the responsibility of the calling oxp
    */
        var success = -3;
        var adjust_error = 0;
        if ( this._sc_error == 0 )
          {
    	switch ( device )
    	  {
    	    case "ALL":
    	      if ( !this._sc_settings.general.disabled )
    		{ success = -2; }
    	      else
    		{
    		  this._sc_settings.general.disabled = false;
    		  this._sc_settings.general.sc_disabled = false;
    		  this._sc_update_oxpconfig_vars();
    		  // start sc_device
    		  if ( this._sc_settings.sc.version > this._sc_const.none ) 
    		    { 
    		      adjust_error = worldScripts["SC Core"]._sc_sc_adjust(true);
    		      if ( adjust_error < 0 )
    			{
    			  player.commsMessage("ERROR while starting shield cycler device, check latest log",10); 
    			  log(this.name," unable to adjust shields while starting entire oxp");
    			};
    		    };
    		  success = 0;
    		};
    	      break;
    	    case "SC":
    	      if ( !this._sc_settings.general.sc_disabled )
    		{ success = -2; }
    	      else
    		{
    		  this._sc_settings.general.sc_disabled = false;
    		  this._sc_update_oxpconfig_vars();
    		  if ( this._sc_settings.sc.version > this._sc_const.none ) 
    		    { 
    		      adjust_error = worldScripts["SC Core"]._sc_sc_adjust(true);
    		      if ( adjust_error  < 0 )
    			{
    			  player.commsMessage("ERROR while starting shield cycler device, check latest log",10); 
    			  log(this.name," unable to adjust shields while starting sc device");
    			};
    		      success = 0;
    		    };
    		};
    	      break;
    	    default:
    	      success = -1;
    	      break;
    	  };
          };
        return success;
      };
    
    
    this._sc_store_devices = function()
      {
        // 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 is encrypted version of first
        var sc_values =
          {
            json: "",
            enc: ""
          };
        sc_values.json = JSON.stringify(this._sc_settings);
        var helper = new worldScripts.Cabal_Common_Functions.Cabal_Common();
        sc_values.enc = helper.strEncrypt( sc_values.json, "ShieldCycler" );
        // since ship is stored, ignore refund
        var temp = this._sc_remove_shield_cycler();
        return sc_values;
      }
      
    this._sc_retrieve_devices = function(sc_values)
      {
        // counterpart of this._sc_store_devices
        // input : an object created by this._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
        
        if ( typeof sc_values !== "object" ) { return 1; };
        if ( typeof sc_values.json !== "string" || sc_values.enc !== "string" ) { return 2; };
        var temp = "";
        try
          { temp = JSON.parse(sc_values.json) }
        catch(e)
          { return 3; };
        var helper = new worldScripts.Cabal_Common_Functions.Cabal_Common();
        if ( sc_values.json !== helper.strDecrypt( sc_values.json, "ShieldCycler" ) ) { return 4; };
        // Data is valid JSON and created by SC
        var version_diff = parseInt( this._sc_settings.general.savegame_version - sc_values.general.savegame_version  ) ;
        if ( version_diff < -1 ) { return 5;} ; // to old
        if ( version_diff > 1 ) { return 6; } ; // to new
        // version_diff == 1 is impossible for now, but in future versions it will indicate conversion is needed
        // only case left is when version_diff == 0
        this._sc_settings = temp;
        this._sc_update_oxpconfig_vars();
        if ( ( this._sc_settings.sc.version > this._sc_const.basic ) ) { this._sc_change_configuration(1, false); };
        if ( this._sc_settings.sc.version == this._sc_const.advanced ) { this._sc_change_configuration(2, false); };
        if ( this._sc_settings.sc.manual_version == this._sc_const.advanced ) { this._sc_change_configuration(3, false); };     
        log(this.name," - imported stored ship data");
        return 0;
      };
    
    // OXPConfig2 related
    
    this.oxpcNotifyOnChange = function(n)
      {
        // called by OXPConfig when player changes values
        switch (n)
          {
    	case 1:
    	  // booleans changed
    	  var error = 0;
    	  if ( this._sc_oxp_status !== this._sc_settings.general.disabled )
    	    {
    	      var old_status = this._sc_settings.general.disabled;
    	      error = ( this._sc_oxp_status ) ? this._sc_stop("ALL") : this._sc_start("ALL");
    	      if ( error == 0 )
    		{ 
    		  this._sc_settings.general.disabled = this._sc_oxp_status;
    		}
    	      else
    		{ 
    		  log(this.name," old value:" + old_status);
    		  log(this.name," new value:" + this._sc_oxp_status);
    		  log(this.name," - problem with applying change for SC oxp status");
    		  this._sc_oxp_status = old_status;
    		};
    	    }
    	  else
    	    {
    	      if ( this._sc_sc_status !== this._sc_settings.general.sc_disabled )
    		{
    		  if ( this._sc_settings.sc.version > this._sc_const.none )
    		    {
    		      this._sc_sc_status = this._sc_settings.general.sc_disabled;
    		      log(this.name," Buy a shieldcycler before you try to change it's status !");
    		    }
    		  else
    		    {
    		      old_status = this._sc_settings.general.sc_disabled;
    		      if ( this._sc_sc_status ) { error = this._sc_stop("SC"); } else { error = this._sc_start("SC"); }
    		      if ( error == 0 )
    			{ 
    			  this._sc_settings.sc.general.sc_disabled = this._sc_sc_status;
    			}
    		      else
    			{ 
    			  log(this.name," old value:" + this._sc_settings.general.sc_disabled );
    			  log(this.name," new value:" + this._sc_sc_status );
    			  log(this.name," - problem with applying change for SC device status");
    			  this._sc_sc_status = old_status;
    			};
    		    };
    		};
    	    };
    	  break;
    	case 2:
    	  // integers changed
    	  this._sc_settings.sc.threshold = this._sc_threshold;
    	  this._sc_settings.sc.start_configuration = this._sc_start_configuration;
    	  break;
    	case 4:
    	  // bitmask changed
    	  if ( this._sc_cycler_mask == 0x000 ) { this._sc_cycler_mask = 0x001;}
    	  this._sc_settings.sc.cycler_mask = this._sc_cycler_mask;
    	  break;
    	default:
    	  break;
          };
      };