001package com.fs.starfarer.api.impl.campaign.skills; 002 003import com.fs.starfarer.api.Global; 004import com.fs.starfarer.api.campaign.FleetDataAPI; 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.MutableStat.StatMod; 011import com.fs.starfarer.api.combat.ShipAPI.HullSize; 012import com.fs.starfarer.api.combat.StatBonus; 013import com.fs.starfarer.api.fleet.FleetMemberAPI; 014import com.fs.starfarer.api.fleet.MutableFleetStatsAPI; 015import com.fs.starfarer.api.impl.campaign.ids.Stats; 016import com.fs.starfarer.api.ui.TooltipMakerAPI; 017import com.fs.starfarer.api.util.Misc; 018 019public class Salvaging { 020 021 public static float CREW_LOSS_REDUCTION = 75f; 022 public static float SALVAGE_BONUS = 50f; 023 public static final float COMBAT_SALVAGE = 20f; 024 025 public static float CARGO_CAPACITY_MAX_PERCENT = 50; 026 public static float CARGO_CAPACITY_MAX_VALUE = 1000; 027 public static float FUEL_SALVAGE_BONUS = 25f; 028 029 030 public static class Level1 implements FleetStatsSkillEffect { 031 public void apply(MutableFleetStatsAPI stats, String id, float level) { 032 String desc = "Salvaging skill"; 033 stats.getDynamic().getStat(Stats.SALVAGE_VALUE_MULT_FLEET_NOT_RARE).modifyFlat(id, SALVAGE_BONUS * 0.01f, desc); 034 } 035 036 public void unapply(MutableFleetStatsAPI stats, String id) { 037 stats.getDynamic().getStat(Stats.SALVAGE_VALUE_MULT_FLEET_NOT_RARE).unmodify(id); 038 } 039 040 public String getEffectDescription(float level) { 041 //return "+" + (int) max + "% resources and rare items recovered from abandoned stations and other derelicts"; 042 return "+" + (int) SALVAGE_BONUS + "% resources - but not rare items, such as blueprints - recovered from abandoned stations and other derelicts"; 043 } 044 045 public String getEffectPerLevelDescription() { 046 return null; 047 } 048 049 public ScopeDescription getScopeDescription() { 050 return ScopeDescription.FLEET; 051 } 052 } 053 054 public static class Level2 implements FleetStatsSkillEffect { 055 public void apply(MutableFleetStatsAPI stats, String id, float level) { 056 stats.getDynamic().getStat(Stats.FUEL_SALVAGE_VALUE_MULT_FLEET).modifyFlat(id, FUEL_SALVAGE_BONUS * 0.01f); 057 } 058 059 public void unapply(MutableFleetStatsAPI stats, String id) { 060 stats.getDynamic().getStat(Stats.FUEL_SALVAGE_VALUE_MULT_FLEET).unmodify(id); 061 } 062 063 public String getEffectDescription(float level) { 064 float max = 0f; 065 max += FUEL_SALVAGE_BONUS; 066 return "+" + (int) max + "% fuel salvaged"; 067 } 068 069 public String getEffectPerLevelDescription() { 070 return null; 071 } 072 073 public ScopeDescription getScopeDescription() { 074 return ScopeDescription.FLEET; 075 } 076 } 077 078 public static class Level3 implements FleetStatsSkillEffect { 079 public void apply(MutableFleetStatsAPI stats, String id, float level) { 080 stats.getDynamic().getStat(Stats.BATTLE_SALVAGE_MULT_FLEET).modifyFlat(id, COMBAT_SALVAGE * 0.01f); 081 } 082 083 public void unapply(MutableFleetStatsAPI stats, String id) { 084 stats.getDynamic().getStat(Stats.BATTLE_SALVAGE_MULT_FLEET).unmodify(id); 085 } 086 087 public String getEffectDescription(float level) { 088 return "+" + (int) COMBAT_SALVAGE + "% post-battle salvage"; 089 } 090 091 public String getEffectPerLevelDescription() { 092 return null; 093 } 094 095 public ScopeDescription getScopeDescription() { 096 return ScopeDescription.FLEET; 097 } 098 } 099 100 public static class Level5 implements FleetStatsSkillEffect { 101 public void apply(MutableFleetStatsAPI stats, String id, float level) { 102 stats.getDynamic().getStat(Stats.NON_COMBAT_CREW_LOSS_MULT).modifyMult(id, 1f - CREW_LOSS_REDUCTION / 100f); 103 } 104 105 public void unapply(MutableFleetStatsAPI stats, String id) { 106 stats.getDynamic().getStat(Stats.NON_COMBAT_CREW_LOSS_MULT).unmodify(id); 107 } 108 109 public String getEffectDescription(float level) { 110 return "-" + (int)(CREW_LOSS_REDUCTION) + "% crew lost in non-combat operations"; 111 } 112 113 public String getEffectPerLevelDescription() { 114 return null; 115 } 116 117 public ScopeDescription getScopeDescription() { 118 return ScopeDescription.FLEET; 119 } 120 } 121 122 123 public static String CARGO_EFFECT_ID = "sal_cargo_cap_mod"; 124 public static class Level4 extends BaseSkillEffectDescription implements ShipSkillEffect { 125 public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) { 126 id = CARGO_EFFECT_ID; 127 float capMult = getCargoCapacityMult(id, getFleetData(stats)); 128 stats.getCargoMod().modifyMult(id, capMult); 129 } 130 131 public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) { 132 id = CARGO_EFFECT_ID; 133 stats.getCargoMod().unmodifyMult(id); 134 } 135 136 public String getEffectDescription(float level) { 137 return null; 138 } 139 140 protected float getCargoCapacityBase(String id, FleetDataAPI data) { 141 if (data == null) return 0f; 142 143 float cargoCap = 0; 144 for (FleetMemberAPI curr : data.getMembersListCopy()) { 145 StatBonus stat = curr.getStats().getCargoMod(); 146 StatMod mod = stat.getMultBonus(id); 147 if (mod != null) { 148 stat.unmodifyMult(mod.source); 149 } 150 cargoCap += curr.getCargoCapacity(); 151 if (mod != null) { 152 stat.modifyMult(mod.source, mod.value, mod.desc); 153 } 154 } 155 return cargoCap; 156 } 157 158 protected float getCargoCapacityMult(String id, FleetDataAPI data) { 159 if (data == null) return 0f; 160 161 String key = "salvaging1"; 162 Float bonus = (Float) data.getCacheClearedOnSync().get(key); 163 if (bonus != null) return bonus; 164 165 float cargoBase = getCargoCapacityBase(id, data); 166 167 float capMult = 0f; 168 169 if (cargoBase > 0) { 170 float addCapacity = Math.min(cargoBase * (CARGO_CAPACITY_MAX_PERCENT * 0.01f), 171 CARGO_CAPACITY_MAX_VALUE); 172 capMult = 1f + addCapacity / cargoBase; 173 capMult = Math.round(capMult * 100f) / 100f; 174 } 175 176 data.getCacheClearedOnSync().put(key, capMult); 177 return capMult; 178 } 179 180 public void createCustomDescription(MutableCharacterStatsAPI stats, SkillSpecAPI skill, 181 TooltipMakerAPI info, float width) { 182 init(stats, skill); 183 184 info.addSpacer(5f); 185 info.addPara("Cargo capacity increased by %s or %s units, whichever is lower", 186 0f, hc, hc, 187 "" + (int) CARGO_CAPACITY_MAX_PERCENT + "%", 188 "" + (int) CARGO_CAPACITY_MAX_VALUE 189 ); 190 191 if (isInCampaign()) { 192 FleetDataAPI data = Global.getSector().getPlayerFleet().getFleetData(); 193 String id = CARGO_EFFECT_ID; 194 float cargoCap = getCargoCapacityBase(id, data); 195 float capMult = getCargoCapacityMult(id, data); 196 197 float increase = cargoCap * (capMult - 1f); 198 199 boolean has = stats.getSkillLevel(skill.getId()) > 0; 200 String is = "is"; 201 if (!has) is = "would be"; 202 info.addPara(indent + "Your fleet has a base cargo capacity of %s, which " + is + " increased by %s, or approximately %s units", 203 0f, tc, hc, 204 "" + Misc.getRoundedValueMaxOneAfterDecimal(cargoCap), 205 "" + (int)(Math.round((capMult - 1f) * 100f)) + "%", 206 "" + Misc.getRoundedValueMaxOneAfterDecimal(increase) 207 ); 208 //info.addSpacer(5f); 209 } 210 } 211 212 public ScopeDescription getScopeDescription() { 213 return ScopeDescription.FLEET; 214 } 215 } 216} 217 218 219