| Scripts/repairBots_System.js | "use strict";
this.name        = "Repair System";
this.author      = "Thargoid";
this.copyright   = "CC BY-NC-SA 3.0";
this.description = "Damage Control system based on repair bots";
this.version     = "2.14";
this.$repairControllers = [ "EQ_REPAIRBOTS_CONTROLLER",         // 10 charges version
                            "EQ_REPAIRBOTS_CONTROLLER_LIGHT"    // 5 charges version
                          ];
this.$repairRecharges = [ "EQ_REPAIRBOTS_RECHARGE_10",
                          "EQ_REPAIRBOTS_RECHARGE_5"
                        ];
this.$repairControllerCapacity = {
                                    EQ_REPAIRBOTS_CONTROLLER: 10,
                                    EQ_REPAIRBOTS_CONTROLLER_LIGHT: 5
                                 };
this.$repairRechargesCapacity = {
                                    EQ_REPAIRBOTS_RECHARGE_10: 10,
                                    EQ_REPAIRBOTS_RECHARGE_5: 5
                                };
this.$energyCostPerSecond = 1;  // cost of (energy unit)/s while Repair System is active repairing things
                                // self-repair (repairing the REpair System itself) costs double
this.$energyLowThreshold = 0.2;  // Self Repair System shutdown if energy bellow this (fraction of maxEnergy)
this.$energyResumeThreshold = 0.4; // Self-Repair System resumes if energy above this (fraction of max energy)
this.$selfRepairsSystemStatus; // ['Stand-by','Active','Self-repair', 'Shutdown']
this.$controllerVersion;    // The version of Self-Repair System Controller installed in the player ship
this.$delayArray;           // list of damaged equipment to be repaired
this.$repairControllerRepaired = false; // to discern true repair controller additions from repairs
this.$playerDamagedList = [];
this.$disabledEquipment = {}; // dictionary of equipments disabled, i.e., appear as damaged but should not be repaired
this.$accumEnergyCost = 0;
this.$energyCostCounter = 0;
this.$debug = false;
this.$logging = true;
/****************************************************************************************************/
// Event Handlers 
//--------------------------------------------------------------------------------------------------//
this.startUp = function _repsys_startUp() { 
    var ship = player.ship;
    var repairControllers = this.$repairControllers;
    var i;
    this.$controllerVersion = null;
    this.$delayArray = [];
    i = repairControllers.length;
    while (i--) {
        if (ship.equipmentStatus(repairControllers[i]) === "EQUIPMENT_OK" ||
            ship.equipmentStatus(repairControllers[i]) === "EQUIPMENT_DAMAGED") {
            this.$controllerVersion = repairControllers[i];
            if (!missionVariables.repairCounter) 
                missionVariables.repairCounter = this.$repairControllerCapacity[repairControllers[i]];
            break;
        }
    }
    if (this.$controllerVersion)
        if (this.$logging) log(this.name, ship.displayName+" has Repair System Controller "+this.$controllerVersion+" with "+missionVariables.repairCounter+" charges remaining"); 
}
//--------------------------------------------------------------------------------------------------//
this.playerBoughtEquipment = function _repsys_playerBoughtEquipment(equipment) {
    var _player = player;
    var repairRecharges = this.$repairRecharges;
    var i;
    // controllers will be dealt with in equipmentAdded
    
    i = repairRecharges.indexOf(equipment);
    if (i >= 0) {
        // player bought a Sefl-Repair System recharge
        var recharge = this.$repairRechargesCapacity[repairRecharges[i]];
        missionVariables.repairCounter += recharge; 
        log(this.name, "Recharging Self-Repair System with "+recharge+" charges");
        _player.ship.removeEquipment(equipment);
        this.$limitCharges();
    } else if (equipment === "EQ_REPAIRBOTS_REMOVER") {
            var refund = this.$calculateRepairSystemRefund();
            var msg = "Refunding "+formatCredits(refund, false, true)+" for "+EquipmentInfo.infoForKey(this.$controllerVersion).name;
            log(this.name, msg);
            _player.consoleMessage(msg, 5);
            _player.credits += refund;
            this.$removeRepairController();
            _player.ship.removeEquipment(equipment);
    }
}
//--------------------------------------------------------------------------------------------------//
this.equipmentAdded = function _repsys_equipmentAdded(equipment) {
    // deals only wjith the controllers, which can be added by script
    var repairControllers = this.$repairControllers;
    var i = repairControllers.indexOf(equipment);
    if (i >= 0) {
        if (this.$repairControllerRepaired)
            // the controller was repaired
            this.$repairControllerRepaired = false;
        else {
            // player bought a Self-Repair System
            this.$controllerVersion = repairControllers[i];
            missionVariables.repairCounter = this.$repairControllerCapacity[repairControllers[i]];
            log(this.name, player.ship.displayName+"was awarded Self-Repair System with "+missionVariables.repairCounter+" charges");
        }
    }
}
//--------------------------------------------------------------------------------------------------//
this.playerBoughtNewShip = function _repsys_playerBoughtNewShip(ship) {
    var ship = player.ship;
    var repairControllers = this.$repairControllers;
    var i;
    this.$controllerVersion = null;    
    i = repairControllers.length;
    while (i--) {
        if (ship.equipmentStatus(repairControllers[i]) === "EQUIPMENT_OK" ||
            ship.equipmentStatus(repairControllers[i]) === "EQUIPMENT_DAMAGED") {
            missionVariables.repairCounter = this.$repairControllerCapacity[repairControllers[i]];
            this.$controllerVersion = repairControllers[i];
            if (this.$logging) log(this.name, ship.displayName+" has Repair System Controller "+this.$controllerVersion+" with "+missionVariables.repairCounter+" charges remaining"); 
            break;
        }
    }
    if (this.$controllerVersion == null) 
        this.$removeRepairController();
}
 
//--------------------------------------------------------------------------------------------------//
this.guiScreenWillChange = function _repsys_guiScreenWillChange(to, from) {
    if (this.$controllerVersion == null) return;
    if (to === "GUI_SCREEN_MANIFEST") {
        switch (this.$getRepairSystemEqStatus()) {
            case "EQUIPMENT_OK": {
                if (missionVariables.repairCounter > 0)
                    this.repairDisplay = "Remaining repair system charges - " + missionVariables.repairCounter;
                else
                    this.repairDisplay = "Repair system offline - recharge required";
                mission.setInstructions(this.repairDisplay); 
                break;
            }
        
            case "EQUIPMENT_DAMAGED": {
                mission.setInstructions("Repair system offline - damaged");
                break;
            }            
            
            case "EQUIPMENT_UNAVAILABLE":
            case "EQUIPMENT_UNKNOWN": {
                this.$removeRepairController();
                break;
            }
        }
    }    
}    
//--------------------------------------------------------------------------------------------------//
this.equipmentDamaged = function _repsys_equipmentDamaged(equipment) {
    if (this.$controllerVersion == null) return;
    if (player.ship.docked) return;
    if (equipment == this.$controllerVersion) this.$repairControllerDamaged = true;
    if (this.$disabledEquipment && equipment in this.$disabledEquipment && this.$disabledEquipment[equipment].length > 0) {
        if (this.$debug) log(this.name, "Damaged "+equipment+" is on the disabled list, ignoring");
        return;
    }
    var eqInfo = EquipmentInfo.infoForKey(equipment);
    if (eqInfo.scriptInfo.thargoidRepairBotChance &&
        !isNaN(eqInfo.scriptInfo.thargoidRepairBotChance) &&
        eqInfo.scriptInfo.thargoidRepairBotChance == 0)
        return;
    if (this.$logging) log(this.name, "Equipment "+equipment+" damaged, putting in list for eventual repair");
    if (this.$delayArray.indexOf(equipment) === -1)
        this.$delayArray.push(equipment);
    if (!this.$equipmentDelay)  
        this.$equipmentDelay = new Timer(this, this.$checkEquipment, 0.5, 5); 
    else 
        this.$equipmentDelay.start();
}
//--------------------------------------------------------------------------------------------------//
this.equipmentDestroyed  = function _repsys_equipmentDestroyed(equipment) {
    if (equipment == this.$controllerVersion) {
        log(this.name, "Self-Repair System Controller destroyed"); 
        this.$removeRepairController();
    } else {
        var eqInfo = EquipmentInfo.infoForKey(equipment);
        log(this.name, "Equipment "+eqInfo.name+" ("+equipment+") destroyed");
    }
}    
//--------------------------------------------------------------------------------------------------//
this.shipWillDockWithStation = this.shipDied = function _repsys_shipWillDockWithStation() {
    this.$stopTimers();
    this.$selfRepairsSystemStatus = 'Shutdown';
}
//--------------------------------------------------------------------------------------------------//
this.shipWillLaunchFromStation = function _repsys_shipWillLaunchFromStation() {
    this.$startRepairSystem("Launch");
}
/****************************************************************************************************/
// Internal Functions 
//--------------------------------------------------------------------------------------------------//
this.$checkEquipment = function _repsys_checkEquipment() {
    var logging = this.$logging;
    var debug = this.$debug;
    if(!this.$delayArray || this.$delayArray.length === 0) return;
    // get one equipment from the damaged list
    var equipment = this.$delayArray.pop();
    if(player.ship.equipmentStatus(equipment) !== "EQUIPMENT_DAMAGED") { 
        if (logging) log(this.name, "Equipment "+EquipmentInfo.infoForKey(equipment).name+" ("+equipment+") has already been repaired");
        return; 
    }
    
    if (equipment == this.$controllerVersion) {
        // Self-Repair Controller damaged
        if (this.$damageControlTimer && this.$damageControlTimer.isRunning) {
            this.$damageControlTimer.stop();
            delete this.$damageControlTimer;
        }
        var repairTime = 60 + Math.ceil(Math.random() * 120);
        if (logging) log(this.name, "Repair system entering self-repair mode, repair time "+repairTime);
        player.consoleMessage("Repair system entering self-repair mode", 6);
        this.$selfRepairsSystemStatus = 'Self-repair';
        this.$selfRepairTimer = new Timer(this, this.$selfRepair, repairTime);
        if (debug) log(this.name, "Starting timer for selfRepair, repair time "+repairTime);
        this.$startEnergyConsumption();
    } else {
        // other equipment than the Self-repair System Controller was damaged
        if ((missionVariables.repairCounter && missionVariables.repairCounter > 0) && 
               (!this.$damageControlTimer || !this.$damageControlTimer.isRunning)) {
            // Self-Repair System in standby, activating
            var repairTime = 120 + Math.ceil(Math.random() * 180);
            if (logging) log(this.name, "Repair system activated, repair time "+repairTime);
            player.consoleMessage("Repair system activated", 6);
            this.$selfRepairsSystemStatus = 'Active';
            this.$damageControlTimer = new Timer(this, this.$repairSystems, repairTime);
            if (debug)log(this.name, "Starting timer for repairSystems");
            this.$startEnergyConsumption();
        }
    }
}
//--------------------------------------------------------------------------------------------------//
this.$selfRepair = function _repsys_selfRepair() {
    var _player = player;
    var logging = this.$logging;
    var debug = this.$debug;
    if (this.$controllerVersion == null ) return;
    
    if(Math.random() < 0.75) {
        // 75% chance of self-repair
        missionVariables.repairCounter -= 2;
        if (missionVariables.repairCounter < 0) missionVariables.repairCounter = 0;
        if (logging) log(this.name, "Repair System self-repair complete, deducted charges, "+missionVariables.repairCounter+" remain");
        this.$repairControllerRepaired = true;
        _player.ship.setEquipmentStatus(this.$controllerVersion,"EQUIPMENT_OK");
        this.$checkSystems();
        if ((missionVariables.repairCounter && missionVariables.repairCounter > 0) && 
            this.$playerDamagedList.length > 0) {
            // there are damaged equipments, activate system
            _player.consoleMessage("Repair system online and activated", 6);
            var repairTime = 120 + Math.ceil(Math.random() * 180);
            if (logging) log(this.name, "Repair System online and activated, repair time "+repairTime);
            this.$selfRepairsSystemStatus = 'Active';
            this.$damageControlTimer = new Timer(this, this.$repairSystems, repairTime);
            if (debug) log(this.name, "Starting timer for repairSystems, repair time "+repairTime);
            this.$startEnergyConsumption();
        } else {
            this.$stopEnergyConsumption();
            if (missionVariables.repairCounter && missionVariables.repairCounter > 0) { 
                // no damaged equipment
                if (logging) log(this.name, "Repair system online and in standby mode");
                _player.consoleMessage("Repair system online and in standby mode", 6); 
                this.$selfRepairsSystemStatus = 'Standby';
            } else {
                if (logging) log(this.name, "Repair system offline - repair charges exhausted, recharge required");
                _player.consoleMessage("Repair system offline - repair charges exhausted, recharge required", 5);
                mission.setInstructions("Repair system offline - recharge required");
                this.$selfRepairsSystemStatus = 'Shutdown';
            }
        }
     } else {
        if (_player.ship.equipmentStatus(this.$controllerVersion) === "EQUIPMENT_DAMAGED") {
            // Self-repair System Controller still damaged (just in case it was repaired in the meantime)
            var repairTime = 60 + Math.ceil(Math.random() * 120);
            if (logging) log(this.name,"Repair system offline - self-repair continues");
            player.consoleMessage("Repair system offline - self-repair continues", 6);
            this.$selfRepairsSystemStatus = 'Self-repair';
            this.$selfRepairTimer = new Timer(this, this.$selfRepair, repairTime);
            if (debug) log(this.name, "Starting timer for selfRepair, repair time: "+repairTime);
            this.$startEnergyConsumption();
        }
    }
}
//--------------------------------------------------------------------------------------------------//
this.$checkSystems = function _repsys_checkSystems() {
    var ship = player.ship;
    var equipment = ship.equipment;
    var logging = this.$logging;
    var debug = this.$debug;
    var eqInfo, eq, i;
    this.$playerDamagedList.length = 0;
    i = equipment.length;
    while (i--) {
        eqInfo = equipment[i];
        eq = eqInfo.equipmentKey;    
        if (ship.equipmentStatus(eq) === "EQUIPMENT_DAMAGED") {
            if (eqInfo.scriptInfo.thargoidRepairBotChance &&
                !isNaN(eqInfo.scriptInfo.thargoidRepairBotChance) &&
                eqInfo.scriptInfo.thargoidRepairBotChance == 0)
                // equipment scriptInfo says not to repair the equipment
                continue;
            if (this.$disabledEquipment && eq in this.$disabledEquipment && this.$disabledEquipment[eq].length > 0)
                // equipment in disabled equipment "list", so it's not really broken
                continue;
            this.$playerDamagedList.push(eq) // if it's broke and fixable, add it to the list.
        }
    }
    if (debug) {
        log(this.name, "Damaged equipment list: '"+this.$playerDamagedList+"'");
        log(this.name, "Disabled equipment: "+JSON.stringify(this.$disabledEquipment));
    }
}
//--------------------------------------------------------------------------------------------------//
this.$energyConsumption = function _repsys_energyConsumption() {
    var ship = player.ship;
    var logging = this.$logging;
    var debug = this.$debug;
    var eqStatus;
    var energyCost;
    if (!this.$controllerVersion) return;
    eqStatus = ship.equipmentStatus(this.$controllerVersion);
    if (eqStatus === "EQUIPMENT_OK")
        energyCost = this.$energyCostPerSecond / 2;
    else if (eqStatus === "EQUIPMENT_DAMAGED")
        energyCost = this.$energyCostPerSecond;
    if (isNaN(energyCost)) {
        // defense againts invulnerable ship bug
        log(this.name, "energyCost is NaN: "+energyCost+", $energyCostPerSecond:"+this.$energyCostPerSecond);
        return;
    }
    ship.energy -= energyCost;
    this.$energyCostCounter++;
    this.$accumEnergyCost += energyCost;
    if (this.$energyCostCounter % 60 === 0) { // 30s
        if (debug) log(this.name, "Energy cost in the last 30s: "+this.$accumEnergyCost.toFixed(1));
        this.$energyCostCounter  = 0;
        this.$accumEnergyCost = 0;
    }
    if (ship.energy <= this.$energyLowThreshold * ship.maxEnergy) {
        if (logging) log(this.name, "Low energy threshold reached, shutting down Self-Repair System");
        player.consoleMessage("Low energy threshold reached, shutting down Self-Repair System", 5);
        this.$selfRepairsSystemStatus = 'Shutdown';
        this.$stopTimers();
        if (!this.$energyResumeTimer)
            this.$energyResumeTimer = new Timer(this, this.$verifyEnergyResume, 0.5, 0.5);
        else if (!this.$energyResumeTimer.isRunning)
            this.$energyResumeTimer.start();
    }
}
//--------------------------------------------------------------------------------------------------//
this.$verifyEnergyResume = function _repsys_verifyEnergyResume() {
    var ship = player.ship;
    if (this.$debug) log(this.name, ship.displayName+" energy:"+ship.energy.toFixed(0)+", activation threshold:"+this.$energyResumeThreshold);
    if (ship.energy >= this.$energyResumeThreshold * ship.maxEnergy) {
        this.$stopTimers();
        this.$startRepairSystem("Resume");
    }
}
//--------------------------------------------------------------------------------------------------//
this.$startRepairSystem = function _repsys_startRepairSystem(context) {
    var _player = player;
    var logging = this.$logging;
    var debug = this.$debug;
    if (!this.$controllerVersion) return;
    var eqStatus = this.$getRepairSystemEqStatus();
    if (this.$controllerVersion && logging) log(this.name, context+": Repair System equipment status: "+eqStatus);
    if (eqStatus === "EQUIPMENT_OK") {
        this.$checkSystems();
        if (missionVariables.repairCounter && missionVariables.repairCounter > 0 && this.$playerDamagedList.length > 0) {
            // there is equipment damaged and the Self-Repair System has charges
            var repairTime = 120 + Math.ceil(Math.random() * 180);
            if (logging) log(this.name, context+": Repair system activated");
            _player.consoleMessage("Repair system activated", 6);
            this.$selfRepairsSystemStatus = 'Active';
            this.$damageControlTimer = new Timer(this, this.$repairSystems, repairTime);    
            if (debug) log(this.name, "starting timer for repairSystems, repair time: "+repairTime);
            this.$startEnergyConsumption();
        } else if (missionVariables.repairCounter && missionVariables.repairCounter > 0) {
            // Self-repair System has charges
            if (logging) log(this.name, context+": Repair System Online, no equipment damaged, entering Standby mode");
            _player.consoleMessage("Repair System Online, no equipment damaged, entering Standby mode", 6);
            this.$selfRepairsSystemStatus = 'Standby';
        } else {
            // Self-Repair System charges exausted
            if (logging) log(this.name, context+": Repair charges exhausted ("+missionVariables.repairCounter+"), shutting down");
            _player.consoleMessage("Repair System exhausted - recharge required", 6); 
            this.$selfRepairsSystemStatus = 'Shutdown';
            this.$stopTimers();
        }
    } else {
        var repairTime = 60 + Math.ceil(Math.random() * 120);
        if (logging) log(this.name, context+": Repair System entering self-repair mode, repair time "+repairTime);
        player.consoleMessage("Repair System entering self-repair mode", 6);
        this.$selfRepairsSystemStatus = 'Self-repair';
        this.$selfRepairTimer = new Timer(this, this.$selfRepair, repairTime);    
        if (debug) log(this.name, "starting timer for selfRepair, repairt time: "+repairTime);
        this.$startEnergyConsumption();
    }
}
//--------------------------------------------------------------------------------------------------//
this.$repairSystems = function _repsys_repairSystems() {
    var _player = player;
    var logging = this.$logging;
    var debug = this.$debug;
    var fixedItem, fixedName, fixedTech, fixChance;
    this.$checkSystems();
    if (this.$playerDamagedList.length === 0) {
        if (logging) {
            log(this.name, "Available ship repair completed ("+missionVariables.repairCounter+" charges remain)");
            log(this.name, "Repair system entering standby mode");
        }
        _player.consoleMessage("Available ship repair completed - Repair system entering standby mode", 5);
        this.$selfRepairsSystemStatus = 'Standby';
        this.$stopEnergyConsumption();
        return;
    } else {
        var damagedEquipment = Math.floor(Math.random() * this.$playerDamagedList.length); // pick a random element from the list...
        fixedItem = this.$playerDamagedList[damagedEquipment]; // ...define the item...
        fixedName = EquipmentInfo.infoForKey(fixedItem).name; // define it's screen name
        fixedTech = EquipmentInfo.infoForKey(fixedItem).effectiveTechLevel // tech level of the item
        if (_player.ship.equipmentStatus(fixedItem) !== "EQUIPMENT_DAMAGED") {
            if (debug) log(this.name, "Equipment random-chosen for repair ("+fixedItem+") is already repaired, picking another");
            this.$repairSystems();
            return;
        } 
         
        var eqInfo = EquipmentInfo.infoForKey(fixedItem);
        switch(true) {
            case (eqInfo.scriptInfo.thargoidRepairBotChance !== undefined && !isNaN(eqInfo.scriptInfo.thargoidRepairBotChance)): {
                fixChance = parseFloat(eqInfo.scriptInfo.thargoidRepairBotChance);
                break;
            }
            case (fixedTech < 9): {
                fixChance = 1; 
                break;
            }
            case ((fixedTech > 8) && (fixedTech < 17)): {
                fixChance = 1 - ((fixedTech - 8)/10); 
                break;
            }
            case (fixedTech == 99): {
                fixChance = 0.1; 
                break;
            }
            default: {
                fixChance = 0.2; 
                break;
            }
        }    
        var rnd = Math.random();
        if (debug) log(this.name, "Probability of fixing "+fixedName+" is "+fixChance.toFixed(3)+", random: "+rnd.toFixed(3));    
        if(rnd < fixChance)
            this.$fixItem(eqInfo);
        else {
            if (missionVariables.repairCounter && missionVariables.repairCounter > 0) {
                var repairTime = 120 + Math.ceil(Math.random() * 180);
                _player.consoleMessage(fixedName + ": repair attempt failed - work continuing.", 5);
                if (logging) log(this.name, "Repair attempt of "+fixedItem+" failed, trying again in "+repairTime);
                this.$selfRepairsSystemStatus = 'Active';
                this.$damageControlTimer = new Timer(this, this.$repairSystems, repairTime);
                if (debug) log(this.name, "starting timer for repairSystems, repair time: "+repairTime);
                this.$startEnergyConsumption();
            } else {
                if (logging) log(this.name, "Repair charges exhausted ("+missionVariables.repairCounter+") while trying to repair "+fixedItem+", damaged equipment:"+this.$playerDamagedList);
                _player.consoleMessage("Repair system exhausted - recharge required", 6); 
                this.$selfRepairsSystemStatus = 'Shutdown';
                this.$stopEnergyConsumption();
            }
        }
    }
}
//--------------------------------------------------------------------------------------------------//
this.$fixItem = function _repsys_fixItem(eqInfo) {
    var _player = player;
    var eq = eqInfo.equipmentKey;
    var logging = this.$logging;
    var debug = this.$debug;
    if (missionVariables.repairCounter > 0) {
        _player.ship.setEquipmentStatus(eq,"EQUIPMENT_OK"); // and actually fix the thing!
        missionVariables.repairCounter--;
        if (logging) log(this.name, eqInfo.name+" online and operational, deducted one charge ("+missionVariables.repairCounter+" remain)");
        _player.consoleMessage(eqInfo.name + " online and operational", 5);
        switch (eq) {
            // specific OXP equipment which need rebooting after fixing, or have other issues.
            case "EQ_FRAME_FUEL_COLLECTOR": {
                if (worldScripts["Fuel Collector"])
                    worldScripts["Fuel Collector"].shipLaunchedFromStation(); // restart the timers in it's world script
                break;
            }
            case "EQ_FRAME_BOUNTY_SCANNER": {
                if (worldScripts["Bounty Scanner"])
                    worldScripts["Bounty Scanner"].shipLaunchedFromStation(); // restart the timers in it's world script
                break;
            }
            case "EQ_EEU": {
                if (worldScripts["Emergency Energy Unit"])
                    worldScripts["Emergency Energy Unit"].shipLaunchedFromStation(); // restart the timers in it's world script
                break;
            }
            case "EQ_ROCKHERMIT_SCANNER": { 
                if (worldScripts["rockHermit_Locator"]) {
                    if(worldScripts["rockHermit_Locator"].version === "1.2.3")
                        worldScripts["rockHermit_Locator"].shipLaunchedFromStation() // use the inbuild scripting of the OXP to restart it.
                    else {
                        this.$beacons = system.shipsWithPrimaryRole("rockbeacof"); // list the inactive beacons (no lights or "R" on compass) 
                        if (this.$beacons.length > 0) { 
                            for (let i=0; i<this.$beacons.length;i++) { 
                                if (oolite.compareVersion('1.73') <= 0) 
                                    this.$beacons[i].position = this.$beacons[i].position.multiply(100); //throw the rockbeacof into space... 
                                else 
                                    this.$beacons[i].setPosition(this.$beacons[i].position.multiply(100)); //throw the rockbeacof into space... 
                                this.$beacons[i].explode(); //...and blow it up. 
                            } 
                        } 
                        worldScripts["rockHermit_Locator"].buoy = "rockbeacon" 
                        worldScripts["rockHermit_Locator"].addBuoys() // no inactive beacons, so use original code to add active beacons. 
                    }
                } 
                break; 
            }
        }
        if (this.$playerDamagedList.length > 1) {
            if (missionVariables.repairCounter && missionVariables.repairCounter > 0) {
                var repairTime = 120 + Math.ceil(Math.random() * 180);
                if (logging) log(this.name, "Further damage detected - repairs continuing, repair time "+repairTime);
                _player.consoleMessage("Further damage detected - repairs continuing", 6);
                this.$selfRepairsSystemStatus = 'Active';
                this.$damageControlTimer = new Timer(this, this.$repairSystems, repairTime);
                if (debug) log(this.name, "starting timer for repairSystems, repair time: "+repairTime);
                this.$startEnergyConsumption();    
            } else  { 
                if (logging) log(this.name, "Repair system exhausted - recharge required"); 
                _player.consoleMessage("Repair system exhausted - recharge required", 6); 
                this.$selfRepairsSystemStatus = 'Shutdown';
                this.$stopEnergyConsumption();
            }
        } else {
            if (logging) log(this.name, "No further damage, Repair system entering standby mode");
            _player.consoleMessage("No further damage, Repair system entering standby mode", 6); 
            this.$selfRepairsSystemStatus = 'Standby';
            this.$stopEnergyConsumption();
        }
    }
}
//--------------------------------------------------------------------------------------------------//
this.$startEnergyConsumption = function _repsys_startEnergyConsumption() {
    if (!this.$energyConsumptionTimer)
        this.$energyConsumptionTimer = new Timer(this, this.$energyConsumption, 0.5, 0.5);
    else if (!this.$energyConsumptionTimer.isRunning)
        this.$energyConsumptionTimer.start();
}
//--------------------------------------------------------------------------------------------------//
this.$stopEnergyConsumption = function _repsys_stopEnergyConsumption() {
    if (this.$energyConsumptionTimer && this.$energyConsumptionTimer.isRunning) {
        this.$energyConsumptionTimer.stop();
        delete this.$energyConsumptionTimer;
        if (this.$debug) log(this.name, "Energy cost in the last "+(this.$energyCostCounter/2).toFixed(1)+"s: "+this.$accumEnergyCost.toFixed(1));
        this.$energyCostCounter  = 0;
        this.$accumEnergyCost = 0;
    }
}
//--------------------------------------------------------------------------------------------------//
this.$stopTimers = function _repsys_stopTimers() { 
    if(this.$damageControlTimer && this.$damageControlTimer.isRunning) {
        this.$damageControlTimer.stop();
        delete this.$damageControlTimer;
    }
    if (this.$selfRepairTimer && this.$selfRepairTimer.isRunning) {
        if (this.$controllerVersion) player.ship.setEquipmentStatus(this.$controllerVersion,"EQUIPMENT_OK");
        this.$selfRepairTimer.stop();
        delete this.$selfRepairTimer;
    }    
    if (this.$equipmentDelay && this.$equipmentDelay.isRunning) {
        this.$equipmentDelay.stop();
        delete this.$equipmentDelay;
    }
    if (this.$energyConsumptionTimer && this.$energyConsumptionTimer.isRunning) {
        this.$energyConsumptionTimer.stop();
        delete this.$energyConsumptionTimer;
    }
    if (this.$energyResumeTimer && this.$energyResumeTimer.isRunning) {
        this.$energyResumeTimer.stop();
        delete this.$energyResumeTimer;
    }
}
//--------------------------------------------------------------------------------------------------//
this.$getRepairSystemEqStatus = function _repsys_getRepairSystemEqStatus() {
    if (this.$controllerVersion == null) return null;
    return (player.ship.equipmentStatus(this.$controllerVersion))
}
//--------------------------------------------------------------------------------------------------//
this.$limitCharges = function _repsys_limitCharges() {
    var limit = (this.$controllerVersion ? this.$repairControllerCapacity[this.$controllerVersion] : null);
    if (limit == null) {
        if (missionVariables.repairCounter) delete missionVariables.repairCounter;
    } else if (missionVariables.repairCounter > limit)
        missionVariables.repairCounter = limit;
}
//--------------------------------------------------------------------------------------------------//
this.$removeRepairController = function _repsys_removeRepairController() {
    if (this.$controllerVersion) player.ship.removeEquipment(this.$controllerVersion);
    this.$controllerVersion = null;
    if (missionVariables.repairCounter) delete missionVariables.repairCounter;
    this.$stopTimers(); 
    mission.setInstructions(null);
}
//--------------------------------------------------------------------------------------------------//
this.$calculateRepairSystemRefund = function _repsys_calculateRepairSystemRefund() {
    var ship = player.ship;
    var eq = this.$controllerVersion;
    var eqInfo = EquipmentInfo.infoForKey(eq);
    var refund;
    if (ship.equipmentStatus(eq) === "EQUIPMENT_OK") {
        refund = eqInfo.price * 0.80 / 10;
        log(this.name, "Refund for "+eqInfo.name+" ("+eq+") calculated at "+refund);
        return refund;
    }
    return 0;
}
//-----------------------------------------------------------------------------------------------//
this.$disableEquipment = function _repsys_disableEquipment(eqKey, who, why) {
    var that = _repsys_disableEquipment;
    var ws = worldScripts["Repair System"];
    var validStatus = (that.validStatus = that.validStatus || ["EQUIPMENT_OK", "EQUIPMENT_DAMAGED"]);
    var pship = player.ship;
    var eqStatus = pship.equipmentStatus(eqKey);
    var logging = ws.$logging;
    var debug = ws.$debug;
    if (validStatus.indexOf(eqStatus) === -1) {
        log(this.name, "Error: "+eqKey+" has invalid status "+eqStatus+" for disabling, ignoring");
        return false;
    }
    if (!ws.$disabledEquipment) ws.$disabledEquipment = {};
    if (!(eqKey in ws.$disabledEquipment)) ws.$disabledEquipment[eqKey] = [];
    var disabledReasons = ws.$disabledEquipment[eqKey];
    var i = disabledReasons.length;
    var found = false;
    while (i--)
        if (disabledReasons[i].who === who) {
            found = true;
            disabledReasons[i].why = why;
            break;
        }
    if (!found) ws.$disabledEquipment[eqKey].push({who: who, why: why});
    if (eqStatus !== "EQUIPMENT_DAMAGED")
        pship.setEquipmentStatus(eqKey, "EQUIPMENT_DAMAGED");
    var ok = (pship.equipmentStatus(eqKey) === "EQUIPMENT_DAMAGED");
    if (logging) log(ws.name, eqKey+" has been disabled by "+who+" because "+why+", success: "+ok);
    return ok;
}
//-----------------------------------------------------------------------------------------------//
this.$enableEquipment = function _repsys_enableEquipment(eqKey, who) {
    var that = _repsys_enableEquipment;
    var ws = worldScripts["Repair System"];
    var validStatus = (that.validStatus = that.validStatus || ["EQUIPMENT_OK", "EQUIPMENT_DAMAGED"]);
    var pship = player.ship;
    var eqStatus = pship.equipmentStatus(eqKey);
    var logging = ws.$logging;
    var debug = ws.$debug;
    var error;
    if (debug) log(ws.name, who+" asked for "+eqKey+" to be enabled");
    if (validStatus.indexOf(eqStatus) === -1)
        error = eqKey+" has invalid status "+eqStatus+" for enabling, ignoring";
    else if (!ws.$disabledEquipment)
        error = "Can't find a disabled equipment list";
    else if (!(eqKey in ws.$disabledEquipment))
        error = eqKey+" is not in the disabled equipment list";
    else {
        var disabledReasons = ws.$disabledEquipment[eqKey];
        var i = disabledReasons.length;
        var why = null;
        while (i--)
            if (disabledReasons[i].who === who) {
                why = disabledReasons[i].why;
                disabledReasons.splice(i, 1);
            }
        if (!why)
            error = eqKey+" was not disabled by "+who;
        else {
            if (disabledReasons.length > 0) {
                if (logging) log(ws.name, who+" was removed from the disabled list of "+eqKey+", but there are "+disabledReasons.length+" more, so it stays disabled");
                return false;
            } else {
                pship.setEquipmentStatus(eqKey, "EQUIPMENT_OK");
                var ok = (pship.equipmentStatus(eqKey) === "EQUIPMENT_OK");
                delete ws.$disabledEquipment[eqKey];
                if (logging) log(ws.name, eqKey+" was enabled, success: "+ok);
                return ok;
            }
        } 
    }
    log(ws.name, "Error: "+error);
    return error;
}
 |