001package com.fs.starfarer.api.impl.campaign.skills; 002 003import java.awt.Color; 004 005import com.fs.starfarer.api.characters.FleetStatsSkillEffect; 006import com.fs.starfarer.api.characters.MutableCharacterStatsAPI; 007import com.fs.starfarer.api.characters.ShipSkillEffect; 008import com.fs.starfarer.api.characters.SkillSpecAPI; 009import com.fs.starfarer.api.combat.MutableShipStatsAPI; 010import com.fs.starfarer.api.combat.ShipAPI.HullSize; 011import com.fs.starfarer.api.fleet.FleetMemberAPI; 012import com.fs.starfarer.api.fleet.MutableFleetStatsAPI; 013import com.fs.starfarer.api.impl.campaign.DModManager; 014import com.fs.starfarer.api.impl.campaign.ids.Stats; 015import com.fs.starfarer.api.ui.TooltipMakerAPI; 016import com.fs.starfarer.api.util.Misc; 017 018public class HullRestoration { 019 020 public static float RECOVERY_PROB = 2f; 021 public static float CR_PER_SMOD = 5; 022 023 public static float CR_MAX_BONUS = 15; 024 public static float CR_MINUS_PER_DMOD = 5; 025 026 public static float DMOD_AVOID_MAX = 0.9f; 027 public static float DMOD_AVOID_MIN = 0.75f; 028 029 public static float DMOD_AVOID_MIN_DP = 5f; 030 031 public static float DP_REDUCTION = 0.1f; 032 public static float DP_REDUCTION_MAX = 5f; 033 034 035 /** 036 * Lowest probability to avoid d-mods at this DP value and higher. 037 */ 038 public static float DMOD_AVOID_MAX_DP = 60f; 039 040 public static class Level1 implements FleetStatsSkillEffect { 041 public void apply(MutableFleetStatsAPI stats, String id, float level) { 042 stats.getDynamic().getMod(Stats.SHIP_RECOVERY_MOD).modifyFlat(id, RECOVERY_PROB); 043 } 044 public void unapply(MutableFleetStatsAPI stats, String id) { 045 stats.getDynamic().getMod(Stats.SHIP_RECOVERY_MOD).unmodify(id); 046 } 047 public String getEffectDescription(float level) { 048 return "All of your ships are almost always recoverable if lost in combat"; 049 } 050 public String getEffectPerLevelDescription() { 051 return null; 052 } 053 public ScopeDescription getScopeDescription() { 054 return ScopeDescription.FLEET; 055 } 056 } 057 058 public static class Level2 implements ShipSkillEffect { 059 public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) { 060 float dp = DMOD_AVOID_MIN_DP; 061 if (stats.getFleetMember() != null) { 062 dp = stats.getFleetMember().getDeploymentPointsCost(); 063 } 064 float mult = 1f - (dp - DMOD_AVOID_MIN_DP) / (DMOD_AVOID_MAX_DP - DMOD_AVOID_MIN_DP); 065 if (mult > 1f) mult = 1f; 066 if (mult < 0f) mult = 0f; 067 068 float probAvoid = DMOD_AVOID_MIN + (DMOD_AVOID_MAX - DMOD_AVOID_MIN) * mult; 069 070 stats.getDynamic().getMod(Stats.DMOD_ACQUIRE_PROB_MOD).modifyMult(id, 1f - probAvoid); 071 } 072 073 public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) { 074 stats.getDynamic().getMod(Stats.DMOD_ACQUIRE_PROB_MOD).unmodify(id); 075 } 076 077 public String getEffectDescription(float level) { 078 String lowDP = "" + (int) DMOD_AVOID_MIN_DP; 079 String highDP = "" + (int) DMOD_AVOID_MAX_DP; 080 String lowChance = "" + (int) Math.round(DMOD_AVOID_MIN * 100f) + "%"; 081 String highChance = "" + (int) Math.round(DMOD_AVOID_MAX * 100f) + "%"; 082 return "Ships lost in combat have a " + lowChance + " (if " + highDP + " deployment points or higher) to " + highChance + " (" + lowDP + " DP or lower) chance to avoid d-mods"; 083 //"Ships lost in combat have a 90% (if 5 deployment points or lower) to 75% (50 DP or higher) chance to avoid d-mods 084 //return "+" + (int)(CR_PER_SMOD) + "% maximum combat readiness per s-mod built into the hull"; 085 } 086 087 public String getEffectPerLevelDescription() { 088 return null; 089 } 090 091 public ScopeDescription getScopeDescription() { 092 return ScopeDescription.PILOTED_SHIP; 093 } 094 } 095 public static class Level3 implements ShipSkillEffect { 096 public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) { 097 float num = 0f; 098 if (stats.getVariant() != null) { 099 num = stats.getVariant().getSMods().size(); 100 } 101 stats.getMaxCombatReadiness().modifyFlat(id, num * CR_PER_SMOD * 0.01f, "Hull Restoration skill"); 102 } 103 104 public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) { 105 stats.getMaxCombatReadiness().unmodify(id); 106 } 107 108 public String getEffectDescription(float level) { 109 return "+" + (int)(CR_PER_SMOD) + "% maximum combat readiness per s-mod built into the hull"; 110 } 111 112 public String getEffectPerLevelDescription() { 113 return null; 114 } 115 116 public ScopeDescription getScopeDescription() { 117 return ScopeDescription.PILOTED_SHIP; 118 } 119 } 120 121 public static class Level3B implements ShipSkillEffect { 122 public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) { 123 FleetMemberAPI member = stats.getFleetMember(); 124 125 126 float dmods = 0; 127 if (member != null) { 128 dmods = DModManager.getNumDMods(member.getVariant()); 129 } else if (stats.getVariant() != null) { 130 dmods = DModManager.getNumDMods(stats.getVariant()); 131 } 132 133 float bonus = CR_MAX_BONUS - dmods * CR_MINUS_PER_DMOD; 134 bonus = Math.round(bonus); 135 if (bonus < 0) bonus = 0; 136 137 stats.getMaxCombatReadiness().modifyFlat(id, bonus * 0.01f, "Hull Restoration skill"); 138 } 139 140 public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) { 141 stats.getMaxCombatReadiness().unmodify(id); 142 } 143 144 public String getEffectDescription(float level) { 145 return "+" + (int)(CR_MAX_BONUS) + "% maximum combat readiness for all ships, minus " + (int)CR_MINUS_PER_DMOD + "% per d-mod (minimum of 0%)"; 146 } 147 148 public String getEffectPerLevelDescription() { 149 return null; 150 } 151 152 public ScopeDescription getScopeDescription() { 153 return ScopeDescription.PILOTED_SHIP; 154 } 155 } 156 157 public static class Level4A implements FleetStatsSkillEffect { 158 public void apply(MutableFleetStatsAPI stats, String id, float level) { 159 } 160 161 public void unapply(MutableFleetStatsAPI stats, String id) { 162 } 163 164 public String getEffectDescription(float level) { 165 if (FieldRepairsScript.MONTHS_PER_DMOD_REMOVAL == 1) { 166 return "Chance to remove one d-mod per month from a randomly selected ship in your fleet; faster for low-DP ships"; 167 } else if (FieldRepairsScript.MONTHS_PER_DMOD_REMOVAL == 2) { 168 return "Chance to remove a d-mod from a randomly selected ship in your fleet every two months"; 169 } else { 170 return "Chance to remove a d-mod from a randomly selected ship in your fleet every " + 171 FieldRepairsScript.MONTHS_PER_DMOD_REMOVAL + " months"; 172 } 173 } 174 public String getEffectPerLevelDescription() { 175 return null; 176 } 177 public ScopeDescription getScopeDescription() { 178 return ScopeDescription.FLEET; 179 } 180 } 181 182 public static class Level4B implements FleetStatsSkillEffect { 183 public void apply(MutableFleetStatsAPI stats, String id, float level) { 184 } 185 186 public void unapply(MutableFleetStatsAPI stats, String id) { 187 } 188 189 public String getEffectDescription(float level) { 190 return "Chance to quickly remove one d-mod from newly acquired ships; higher for ships with more d-mods"; 191 } 192 public String getEffectPerLevelDescription() { 193 return null; 194 } 195 public ScopeDescription getScopeDescription() { 196 return ScopeDescription.FLEET; 197 } 198 } 199 200 201 public static class Level5 extends BaseSkillEffectDescription implements ShipSkillEffect { 202 public void createCustomDescription(MutableCharacterStatsAPI stats, SkillSpecAPI skill, 203 TooltipMakerAPI info, float width) { 204 init(stats, skill); 205 float opad = 10f; 206 Color c = Misc.getBasePlayerColor(); 207 //info.addPara("Affects: %s", opad + 5f, Misc.getGrayColor(), c, "fleet"); 208 info.addPara("Affects: %s", opad + 5f, Misc.getGrayColor(), c, "pristine and near-pristine ships (at most one d-mod)"); 209 info.addSpacer(opad); 210 211 String max = "" + (int) DP_REDUCTION_MAX; 212 String percent = "" + (int)Math.round(DP_REDUCTION * 100f) + "%"; 213 info.addPara("Deployment point cost reduced by %s or %s points, whichever is less", 214 0f, Misc.getHighlightColor(), Misc.getHighlightColor(), percent, max); 215 216 } 217 218 public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) { 219 FleetMemberAPI member = stats.getFleetMember(); 220 float dmods = 0; 221 if (member != null) { 222 dmods = DModManager.getNumDMods(member.getVariant()); 223 } 224 225 if (dmods > 1) return; 226 227 float baseCost = stats.getSuppliesToRecover().getBaseValue(); 228 float reduction = Math.min(DP_REDUCTION_MAX, baseCost * DP_REDUCTION); 229 230 stats.getDynamic().getMod(Stats.DEPLOYMENT_POINTS_MOD).modifyFlat(id, -reduction); 231 } 232 233 public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) { 234 stats.getDynamic().getMod(Stats.DEPLOYMENT_POINTS_MOD).unmodifyFlat(id); 235 } 236 } 237}