Fractal Softworks Forum

Starsector => Suggestions => Topic started by: Serenitis on June 18, 2017, 02:33:36 AM

Title: Automated Repair Unit
Post by: Serenitis on June 18, 2017, 02:33:36 AM
The ARU seems to be a mediocre use of precious OP space, which while nice to have doesn't really give you much return for your investment.
To be honest, the only reason I'd currently use the ARU is for the CR preservation in order to fight multiple battles in quick succession. And even then it would be used only if there was enough OP left after fitting more important things, which there frequently isn't.
It just isn't 'attractive' enough to get used most of the time.

What I would like to see is an addition to the ARU that makes it actually useful for keeping ships alive. Something that would make it worth giving up something else for.
Something like.... The ability to repair the hull of a ship in battle.
Like the Damage Control skill from 0.7. (as scripted by DamageControlPerk2_1)

Since it would be no longer a skill based 'freebie' but rather something you'd have to spend OPs on, I don't think it would be too much.
Whether the hullmod would then need a slight size increase or not is another consideration.

Thoughts?
Title: Re: Automated Repair Unit
Post by: Megas on June 18, 2017, 05:42:00 AM
I used to use this much on some ships during 0.7x when OP was plentiful.  Today, using this hullmod, along with many others, hurts, especially if you do not have Loadout Design 3 (and it still hurts even when you have it).  That said, it is very powerful when combined with Damage Control 2 - weapons and engines repair so fast that it does not matter if they get knocked out - they go back online before the older disabled messages disappear.

The main use for this for me is faster CR recovery on ships you use must.  Quad Tachyon Lance Paragon serves me very well, and I probably want its CR up fast when trying to farm Remnants.

Faster CR recovery would be a good perk, especially as a replacement for that current junk perk in Combat Endurance 2.

Quote
Something like.... The ability to repair the hull of a ship in battle.
No.  hull regeneration was the biggest enabler of soloing fleets.  You trade shots with the enemy, run away, let hull regenerate, repeat.  It is was single most powerful perk before 0.8.

Now, maybe have the hullmod repair some damage after combat for free like Damage Control 2 and Field Repairs 2.  That would be nice.
Title: Re: Automated Repair Unit
Post by: Serenitis on June 19, 2017, 02:52:58 AM
Quote
No.  hull regeneration was the biggest enabler of soloing fleets.  You trade shots with the enemy, run away, let hull regenerate, repeat.  It is was single most powerful perk before 0.8.
I don't think this is an issue at all any more, given that CR exists for everything and the AI is fond of dragging out engagements as long as possible. Not to mention soloing is dead now, if you try it outside the simulator you're gonna have a bad time. And balancing for edge cases is not really a good idea anyway.
And also because:
Quote
Today, using this hullmod, along with many others, hurts, especially if you do not have Loadout Design 3 (and it still hurts even when you have it).
You'd be giving up OP space (which there is already, as noted, a dearth of), essentially trading it for survivability. Which is something I greatly miss from 0.7 where I could have damage control officers on my vital ships, greatly reducing my reluctance to deploy them.
The 'free' repairs after battle ability is nice, but it doesn't help with keeping the ship in the fight (and out of the scrapyard) in the first place.
Quote
Now, maybe have the hullmod repair some damage after combat for free like Damage Control 2 and Field Repairs 2.  That would be nice.
Nice, yes. I suppose it would be kind of neat to have access to that ability at the cost of OP instead of skill points for the sake of continuity with the rest of the abilities which have this. It would be nicer still if there were some means of performing in-combat repairs again. Even if it has some conditional thing like the ship must be at 0 flux, or the ARU generates flux when under heavy use.
I dunno. It just seems like it's the kind of thing that makes a lot of sense to have as an option, and enables a kind of underdog comeback thing that feels p. good for the player.


Title: Re: Automated Repair Unit
Post by: Megas on June 19, 2017, 06:44:58 AM
Soloing everything was not an edge case in 0.6x-0.7x.  It was optimal and relatively easy but tedious to do.  Even today, I try to solo some fights if I can get away with it to conserve resources.  It does not have to be big detachments, but smaller patrols or equivalent.  Not quite big enough to justify deploying your fleet (because you lose more money than you gain), but big enough for a single ship or few to struggle without cheese due to AI's favorite behavior.  A small squad will probably take casualties, but a well-piloted flagship can try to solo the (small enemy) fleet.

Because of the AI's behavior, the enemy will disappear while you wait in the corner, and you can sit there as long as you need to recharge or regenerate everything without peak performance ticking down.  Not applicable in fleet action, but very useful for solo action.

Also, it could be for one-on-one fights, like say... your small flagship against a small Remnant frigate.  You made a mistake, and took too much damage and only have a sliver of hull left away from death.  Just run away to the corner and have hull regenerate, then try again.

Simulator is still good for testing because it remains mostly applicable to real campaign fights.

Now, hull regeneration would be very handy in battlestation fights if I have it because the battlestation cannot move... or a royal pain if the battlestation modules have it too.

Do not forget that current half in-combat repairs help keep you in the fight, and when stacked with Damage Control 2, the ship is nearly immune to knockout due to repair times being so fast.
Title: Re: Automated Repair Unit
Post by: StarSchulz on June 19, 2017, 11:37:58 PM
Currently i find the hullmod very useful when setting up ships to fight an enemy that is very EMP heavy. certain modded factions like DME or the Templars, have a lot of EMP built into their stuff. ships like the onslaught which would prefer its shields to be down, or cant protect its rear benefit from this hullmod a lot, too.

The regeneration is kind of a weird thing, with some of the armor damage reduction applying to hull now it could become far stronger than it already was.
Title: Re: Automated Repair Unit
Post by: FooF on June 20, 2017, 06:02:22 AM
Currently i find the hullmod very useful when setting up ships to fight an enemy that is very EMP heavy. certain modded factions like DME or the Templars, have a lot of EMP built into their stuff. ships like the onslaught which would prefer its shields to be down, or cant protect its rear benefit from this hullmod a lot, too.

The regeneration is kind of a weird thing, with some of the armor damage reduction applying to hull now it could become far stronger than it already was.

Well, even the Onslaught is only going to carry 5% of its 1750 armor toward hull damage so that's only ~90 permanent armor. Against all but the weakest rapid-fire weapons, it doesn't add a whole lot of damage mitigation. I think hull regen is a very tricky beast to balance but it could be done. Previously, you could regen up to 50% of total HP but it only kicked in after you were below that point and it worked indefinitely. That seems too strong for a hull mod.

Perhaps a slower regen rate and a limited amount of HP that could be healed would be the way to go. Something like 0.5% of hull healed per second with a reserve of HP equal to the original max HP. That is to say, the ARU is capable of giving a ship 2x its HP over time but once that reserve runs out, it no longer has a HP-heal function (but it still repairs weapons faster). For an Onslaught, at the extreme end, that would be about 100 HP/sec once you start hitting the hull and 200 seconds worth of 100 HP/sec regen for a total of 20,000 HP. To give a little perspective, a Vulcan Cannon still does about 110 damage/sec against an Onslaught even with permanent armor.

For a frigate, like a Wolf, you're only talking 7.5 hp/sec so maybe ARU would work according to ship size, something like 2/1/.75/.5% while retaining the same reserve "100% pool" of HP. Frigates would regen ~30-50 HP/sec, Destroyers between 30-50, Cruisers between 45-80, and Capitals between 50-100. While the rates are all relatively in-line with each other, a Frigate has much less of a reserve pool by virtue of its smaller max HP. It would "run out" of reserve HP 4x faster than a capital. The bigger ships will have much longer timeframes of regeneration. It won't help in an alpha-strike situation but getting out of battle for a few seconds will net you a few hundred HP.
Title: Re: Automated Repair Unit
Post by: jupjupy on June 20, 2017, 09:01:26 AM
What about having the ARU mod repair up to a certain amount of armor? Say, 10% of the original amount, at maybe 0.25% per second.

So for armor blocks that have fallen below 10%, they regenerate very very slowly towards that number. Would limit their overall effectiveness by preventing you from healing your HP, but giving you a small "damage reduction" that takes time to fill back up.

The only ship I could see this being a problem on would be at worst the Onslaught, but even then... not really.
Title: Re: Automated Repair Unit
Post by: Midnight Kitsune on June 20, 2017, 10:21:49 AM
The issue with armor regen is that there is no way to remove damage decals. Or so I've heard at least.
Title: Re: Automated Repair Unit
Post by: Ranakastrasz on June 20, 2017, 11:03:22 AM
The issue with armor regen is that there is no way to remove damage decals. Or so I've heard at least.

True, but that isn't a huge deal. As long as you don't repair to 100% its fine. Repair 80% of damage taken. Gradual decay, never hits 100% again.
Title: Re: Automated Repair Unit
Post by: orost on June 21, 2017, 04:01:56 AM
I wrote something similar a while ago if anyone wants to mess with the idea. Starts out repairing 80% of armor damage taken, gets worse as it repairs more eventually decaying towards zero, further hits while armor is repairing interfere with the process (so it works best on infrequent, heavy hits). Also drains some CR.

It's 0.65 code so I don't know if it'll work. Also probably bad code because I don't know Java.

Spoiler
Code
package data.hullmods;

import com.fs.starfarer.api.combat.BaseHullMod;
import com.fs.starfarer.api.combat.ArmorGridAPI;
import com.fs.starfarer.api.combat.ShipAPI;
import com.fs.starfarer.api.combat.ShipAPI.HullSize;
import com.fs.starfarer.api.fleet.FleetMemberAPI;
import com.fs.starfarer.api.fleet.RepairTrackerAPI;
import java.util.HashMap;
import java.util.Map;

class Constants {
    //Up to how much HP in total will be repaired, in multiples of ship's total armor HP
    //Default: 1
    public static final float TOTAL_REPAIR_FACTOR = 1f;

    //How much CR will be lost to repair the maximum amount of armor, in fractions of 100%
    //Default: 0.1 (10%)
    public static final float TOTAL_CR_LOSS = 0.1f;

    //How much of damage taken will be repaired, in fractions of 100%
    //Default: 0.8 (80%)
    public static final float BASE_REPAIR_EFFICIENCY = 0.8f;

    //How long after taking damage until repair starts, in seconds
    //Default: 10
    public static final float REPAIR_TIMEOUT = 10f;

    //Base repair rate, in HP per armor cell per second
    //Default: 0.2
    public static final float BASE_REPAIR_RATE = 0.2f;

    //Scaling repair rate, in percent per second
    //Default: 0.005 (0.5% per second)
    public static final float REPAIR_RATE = 0.01f;

    //How the repair efficiency drops off over time
    //1 is linear, 2 is default, higher values start dropping off later but drop more sharply
    //See curves.png in root directory of the mod for reference
    public static final float EFFICIENCY_CURVE_POWER = 2f;
}

class ShipArmorData {
    public ArmorGridAPI armorGrid;
    public int armorCellsX, armorCellsY;
    public float[][] sinceLastDamage;
    public float[][] expectedRepair;
    public float[][] armorCells;
    public float repairEfficiency;
    public float totalRepaired;
    public float totalRepairedLast;
    public float totalCRLost;
    public float totalRepairCapacity;
    public float maxArmor;
    public boolean initialArmorLoaded;
   
    public boolean CRSynched = false;
    public RepairTrackerAPI RepairTracker;
   
    public ShipArmorData(ShipAPI ship)
    {
        repairEfficiency = Constants.BASE_REPAIR_EFFICIENCY;
        totalRepaired = 0f;
        totalRepairedLast = 0f;
        totalCRLost = 0f;
        armorGrid = ship.getArmorGrid();
        maxArmor = armorGrid.getMaxArmorInCell();
        float[][] armorCellsT = armorGrid.getGrid();
        armorCellsX = armorCellsT.length;
        armorCellsY = armorCellsT[0].length;
        totalRepairCapacity = armorGrid.getArmorRating() * Constants.TOTAL_REPAIR_FACTOR * armorCellsX * armorCellsY / 15f;
        sinceLastDamage = new float[armorCellsX][armorCellsY];
        armorCells = new float[armorCellsX][armorCellsY];
        expectedRepair = new float[armorCellsX][armorCellsY];
        initialArmorLoaded = false;

    }
}

public class ARHM_ArmorRepairHullmod extends BaseHullMod {

    Map<String, ShipArmorData> Ships = new HashMap<String, ShipArmorData>();

    public void advanceInCampaign(FleetMemberAPI member, float amount)
    {
 
        ShipArmorData armorData = Ships.get(member.getId());

        if(armorData != null)
        {
            if(!armorData.CRSynched && armorData.totalCRLost > 0)
            {
                armorData.RepairTracker = member.getRepairTracker();
                armorData.RepairTracker.applyCREvent(-armorData.totalCRLost, "Armor Repair System use");
                armorData.CRSynched = true;
            }
        }
    }

    public void applyEffectsAfterShipCreation(ShipAPI ship, String id)
    {
        String Id = ship.getFleetMemberId();
        if(Id != null)
        {
           Ships.put(ship.getFleetMemberId(), new ShipArmorData(ship));
        }
        else
        {
           Ships.put("" + ship.hashCode(), new ShipArmorData(ship));
        }
    }

    public void advanceInCombat(ShipAPI ship, float amount) {

        String Id = ship.getFleetMemberId();
       
        ShipArmorData armorData;
       
        if(Id != null)
        {
            armorData = Ships.get(Id);
        }
        else
        {
            armorData = Ships.get("" + ship.hashCode());
        }
       
       
       
        armorData.CRSynched = false;

        if(!armorData.initialArmorLoaded)
        {
            for(int i = 0; i < armorData.armorCellsX; i++)
            {
                for(int ii = 0; ii < armorData.armorCellsY; ii++)
                {
                    armorData.armorCells[i][ii] = armorData.armorGrid.getArmorValue(i, ii);     
                }
            }
            armorData.initialArmorLoaded = true;
        }

        for(int i = 0; i < armorData.armorCellsX; i++)
        {
            for(int ii = 0; ii < armorData.armorCellsY; ii++)
            {
                float armorValue = armorData.armorGrid.getArmorValue(i, ii);
                if(armorValue < armorData.armorCells[i][ii])
                {
                    armorData.sinceLastDamage[i][ii] = 0f;
                    armorData.expectedRepair[i][ii] += (armorData.armorCells[i][ii] - armorValue);
                }
                else
                {
                    armorData.sinceLastDamage[i][ii] += amount;
                }
                armorData.armorCells[i][ii] = armorValue;
            }
        }

        for(int i = 0; i < armorData.armorCellsX; i++)
        {
            for(int ii = 0; ii < armorData.armorCellsY; ii++)
            {
                float armorValue = armorData.armorGrid.getArmorValue(i, ii);
                if(armorData.sinceLastDamage[i][ii] > Constants.REPAIR_TIMEOUT && armorValue < armorData.maxArmor && armorData.expectedRepair[i][ii] > 0)
                {
                    float maxRepairFromExpected = armorData.expectedRepair[i][ii] * armorData.repairEfficiency;
                    float maxRepairFromRate = amount * (Constants.BASE_REPAIR_RATE + (armorData.maxArmor * Constants.REPAIR_RATE));
   
                    float repairAmount = Math.min(maxRepairFromExpected, maxRepairFromRate);
                    repairAmount = Math.min(armorData.maxArmor - armorValue, repairAmount);

                    armorData.armorGrid.setArmorValue(i, ii, armorValue + repairAmount);

                    if(maxRepairFromExpected < maxRepairFromRate)
                    {
                        armorData.expectedRepair[i][ii] = 0;
                    }
                    else
                    {
                        armorData.expectedRepair[i][ii] -= maxRepairFromRate / armorData.repairEfficiency;
                    }

                    armorData.totalRepaired += repairAmount;
                }
            }
        }

        float repairDelta = armorData.totalRepaired - armorData.totalRepairedLast;
        float CRLoss = (repairDelta / armorData.totalRepairCapacity) * Constants.TOTAL_CR_LOSS;
        ship.setCurrentCR(ship.getCurrentCR() - CRLoss);
        armorData.totalCRLost += CRLoss;
        armorData.totalRepairedLast = armorData.totalRepaired;

        armorData.repairEfficiency = Math.max(Constants.BASE_REPAIR_EFFICIENCY * (1 - (float)Math.pow((armorData.totalRepaired / armorData.totalRepairCapacity), Constants.EFFICIENCY_CURVE_POWER)), 0);

    }

    public String getDescriptionParam(int index, HullSize hullSize)
    {
        if (index == 0) {return "" + (int) (Constants.REPAIR_RATE * 100) + "%";}
        if (index == 1) {return "" + (int) (Constants.REPAIR_TIMEOUT);}
        if (index == 2) {return "" + (int) (Constants.TOTAL_REPAIR_FACTOR);}
        if (index == 3) {return "" + (int) (Constants.BASE_REPAIR_EFFICIENCY * 100) + "%";}
        if (index == 4) {return "" + (int) (Constants.TOTAL_CR_LOSS * 100 ) + "%";}
        return null;
    }

    public boolean isApplicableToShip(ShipAPI ship) {
        return ship != null;
    }
[close]
Title: Re: Automated Repair Unit
Post by: Ranakastrasz on June 21, 2017, 06:23:50 AM
I wrote something similar a while ago if anyone wants to mess with the idea. Starts out repairing 80% of armor damage taken, gets worse as it repairs more eventually decaying towards zero, further hits while armor is repairing interfere with the process (so it works best on infrequent, heavy hits). Also drains some CR.

It's 0.65 code so I don't know if it'll work. Also probably bad code because I don't know Java.

Spoiler
Code
package data.hullmods;

import com.fs.starfarer.api.combat.BaseHullMod;
import com.fs.starfarer.api.combat.ArmorGridAPI;
import com.fs.starfarer.api.combat.ShipAPI;
import com.fs.starfarer.api.combat.ShipAPI.HullSize;
import com.fs.starfarer.api.fleet.FleetMemberAPI;
import com.fs.starfarer.api.fleet.RepairTrackerAPI;
import java.util.HashMap;
import java.util.Map;

class Constants {
    //Up to how much HP in total will be repaired, in multiples of ship's total armor HP
    //Default: 1
    public static final float TOTAL_REPAIR_FACTOR = 1f;

    //How much CR will be lost to repair the maximum amount of armor, in fractions of 100%
    //Default: 0.1 (10%)
    public static final float TOTAL_CR_LOSS = 0.1f;

    //How much of damage taken will be repaired, in fractions of 100%
    //Default: 0.8 (80%)
    public static final float BASE_REPAIR_EFFICIENCY = 0.8f;

    //How long after taking damage until repair starts, in seconds
    //Default: 10
    public static final float REPAIR_TIMEOUT = 10f;

    //Base repair rate, in HP per armor cell per second
    //Default: 0.2
    public static final float BASE_REPAIR_RATE = 0.2f;

    //Scaling repair rate, in percent per second
    //Default: 0.005 (0.5% per second)
    public static final float REPAIR_RATE = 0.01f;

    //How the repair efficiency drops off over time
    //1 is linear, 2 is default, higher values start dropping off later but drop more sharply
    //See curves.png in root directory of the mod for reference
    public static final float EFFICIENCY_CURVE_POWER = 2f;
}

class ShipArmorData {
    public ArmorGridAPI armorGrid;
    public int armorCellsX, armorCellsY;
    public float[][] sinceLastDamage;
    public float[][] expectedRepair;
    public float[][] armorCells;
    public float repairEfficiency;
    public float totalRepaired;
    public float totalRepairedLast;
    public float totalCRLost;
    public float totalRepairCapacity;
    public float maxArmor;
    public boolean initialArmorLoaded;
   
    public boolean CRSynched = false;
    public RepairTrackerAPI RepairTracker;
   
    public ShipArmorData(ShipAPI ship)
    {
        repairEfficiency = Constants.BASE_REPAIR_EFFICIENCY;
        totalRepaired = 0f;
        totalRepairedLast = 0f;
        totalCRLost = 0f;
        armorGrid = ship.getArmorGrid();
        maxArmor = armorGrid.getMaxArmorInCell();
        float[][] armorCellsT = armorGrid.getGrid();
        armorCellsX = armorCellsT.length;
        armorCellsY = armorCellsT[0].length;
        totalRepairCapacity = armorGrid.getArmorRating() * Constants.TOTAL_REPAIR_FACTOR * armorCellsX * armorCellsY / 15f;
        sinceLastDamage = new float[armorCellsX][armorCellsY];
        armorCells = new float[armorCellsX][armorCellsY];
        expectedRepair = new float[armorCellsX][armorCellsY];
        initialArmorLoaded = false;

    }
}

public class ARHM_ArmorRepairHullmod extends BaseHullMod {

    Map<String, ShipArmorData> Ships = new HashMap<String, ShipArmorData>();

    public void advanceInCampaign(FleetMemberAPI member, float amount)
    {
 
        ShipArmorData armorData = Ships.get(member.getId());

        if(armorData != null)
        {
            if(!armorData.CRSynched && armorData.totalCRLost > 0)
            {
                armorData.RepairTracker = member.getRepairTracker();
                armorData.RepairTracker.applyCREvent(-armorData.totalCRLost, "Armor Repair System use");
                armorData.CRSynched = true;
            }
        }
    }

    public void applyEffectsAfterShipCreation(ShipAPI ship, String id)
    {
        String Id = ship.getFleetMemberId();
        if(Id != null)
        {
           Ships.put(ship.getFleetMemberId(), new ShipArmorData(ship));
        }
        else
        {
           Ships.put("" + ship.hashCode(), new ShipArmorData(ship));
        }
    }

    public void advanceInCombat(ShipAPI ship, float amount) {

        String Id = ship.getFleetMemberId();
       
        ShipArmorData armorData;
       
        if(Id != null)
        {
            armorData = Ships.get(Id);
        }
        else
        {
            armorData = Ships.get("" + ship.hashCode());
        }
       
       
       
        armorData.CRSynched = false;

        if(!armorData.initialArmorLoaded)
        {
            for(int i = 0; i < armorData.armorCellsX; i++)
            {
                for(int ii = 0; ii < armorData.armorCellsY; ii++)
                {
                    armorData.armorCells[i][ii] = armorData.armorGrid.getArmorValue(i, ii);     
                }
            }
            armorData.initialArmorLoaded = true;
        }

        for(int i = 0; i < armorData.armorCellsX; i++)
        {
            for(int ii = 0; ii < armorData.armorCellsY; ii++)
            {
                float armorValue = armorData.armorGrid.getArmorValue(i, ii);
                if(armorValue < armorData.armorCells[i][ii])
                {
                    armorData.sinceLastDamage[i][ii] = 0f;
                    armorData.expectedRepair[i][ii] += (armorData.armorCells[i][ii] - armorValue);
                }
                else
                {
                    armorData.sinceLastDamage[i][ii] += amount;
                }
                armorData.armorCells[i][ii] = armorValue;
            }
        }

        for(int i = 0; i < armorData.armorCellsX; i++)
        {
            for(int ii = 0; ii < armorData.armorCellsY; ii++)
            {
                float armorValue = armorData.armorGrid.getArmorValue(i, ii);
                if(armorData.sinceLastDamage[i][ii] > Constants.REPAIR_TIMEOUT && armorValue < armorData.maxArmor && armorData.expectedRepair[i][ii] > 0)
                {
                    float maxRepairFromExpected = armorData.expectedRepair[i][ii] * armorData.repairEfficiency;
                    float maxRepairFromRate = amount * (Constants.BASE_REPAIR_RATE + (armorData.maxArmor * Constants.REPAIR_RATE));
   
                    float repairAmount = Math.min(maxRepairFromExpected, maxRepairFromRate);
                    repairAmount = Math.min(armorData.maxArmor - armorValue, repairAmount);

                    armorData.armorGrid.setArmorValue(i, ii, armorValue + repairAmount);

                    if(maxRepairFromExpected < maxRepairFromRate)
                    {
                        armorData.expectedRepair[i][ii] = 0;
                    }
                    else
                    {
                        armorData.expectedRepair[i][ii] -= maxRepairFromRate / armorData.repairEfficiency;
                    }

                    armorData.totalRepaired += repairAmount;
                }
            }
        }

        float repairDelta = armorData.totalRepaired - armorData.totalRepairedLast;
        float CRLoss = (repairDelta / armorData.totalRepairCapacity) * Constants.TOTAL_CR_LOSS;
        ship.setCurrentCR(ship.getCurrentCR() - CRLoss);
        armorData.totalCRLost += CRLoss;
        armorData.totalRepairedLast = armorData.totalRepaired;

        armorData.repairEfficiency = Math.max(Constants.BASE_REPAIR_EFFICIENCY * (1 - (float)Math.pow((armorData.totalRepaired / armorData.totalRepairCapacity), Constants.EFFICIENCY_CURVE_POWER)), 0);

    }

    public String getDescriptionParam(int index, HullSize hullSize)
    {
        if (index == 0) {return "" + (int) (Constants.REPAIR_RATE * 100) + "%";}
        if (index == 1) {return "" + (int) (Constants.REPAIR_TIMEOUT);}
        if (index == 2) {return "" + (int) (Constants.TOTAL_REPAIR_FACTOR);}
        if (index == 3) {return "" + (int) (Constants.BASE_REPAIR_EFFICIENCY * 100) + "%";}
        if (index == 4) {return "" + (int) (Constants.TOTAL_CR_LOSS * 100 ) + "%";}
        return null;
    }

    public boolean isApplicableToShip(ShipAPI ship) {
        return ship != null;
    }
[close]

Yea, that's the mod I was thinking of. 80% regent.