001package com.fs.starfarer.api.impl.campaign.skills; 002 003import com.fs.starfarer.api.campaign.FleetDataAPI; 004import com.fs.starfarer.api.characters.FleetTotalItem; 005import com.fs.starfarer.api.characters.FleetTotalSource; 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; 011import com.fs.starfarer.api.combat.ShipAPI.HullSize; 012import com.fs.starfarer.api.fleet.FleetMemberAPI; 013import com.fs.starfarer.api.impl.campaign.ids.Stats; 014import com.fs.starfarer.api.impl.campaign.ids.Strings; 015import com.fs.starfarer.api.ui.TooltipMakerAPI; 016import com.fs.starfarer.api.util.Misc; 017 018public class FighterUplink { 019 020 //public static float DAMAGE_PERCENT = 10; 021 022 public static float MAX_SPEED_PERCENT = 20; 023 public static float CREW_LOSS_PERCENT = 50; 024 025 public static float DAMAGE_BONUS_PERCENT = 10; 026 027 public static float TARGET_LEADING_BONUS = 50f; 028 029 public static float OFFICER_MULT = 1.5f; 030 public static boolean isOfficer(MutableShipStatsAPI stats) { 031 if (stats.getEntity() instanceof ShipAPI) { 032 ShipAPI ship = (ShipAPI) stats.getEntity(); 033 if (ship == null) return false; 034 if (ship.isFighter() && ship.getWing() != null && ship.getWing().getSourceShip() != null) { 035 ship = ship.getWing().getSourceShip(); 036 } 037 return ship.getCaptain() != null && !ship.getCaptain().isDefault(); 038 } else { 039 FleetMemberAPI member = stats.getFleetMember(); 040 if (member == null) return false; 041 return !member.getCaptain().isDefault(); 042 } 043 } 044 045 public static class Level1 extends BaseSkillEffectDescription implements ShipSkillEffect { 046 047 public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) { 048 float crewLossReduction = computeAndCacheThresholdBonus(stats, "fu_crew_loss", CREW_LOSS_PERCENT, ThresholdBonusType.FIGHTER_BAYS); 049 if (isOfficer(stats)) crewLossReduction *= OFFICER_MULT; 050 stats.getDynamic().getStat(Stats.FIGHTER_CREW_LOSS_MULT).modifyMult(id, 1f - crewLossReduction / 100f); 051 } 052 053 public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) { 054 stats.getDynamic().getStat(Stats.FIGHTER_CREW_LOSS_MULT).unmodifyMult(id); 055 } 056 057 public String getEffectDescription(float level) { 058 return null; 059 } 060 061 public void createCustomDescription(MutableCharacterStatsAPI stats, SkillSpecAPI skill, 062 TooltipMakerAPI info, float width) { 063 init(stats, skill); 064 065 066 FleetDataAPI data = getFleetData(null); 067 float crewLossReduction = computeAndCacheThresholdBonus(data, stats, "fu_crew_loss", CREW_LOSS_PERCENT, ThresholdBonusType.FIGHTER_BAYS); 068 069 info.addPara("-%s crew lost due to fighter losses in combat (maximum: %s)", 0f, hc, hc, 070 "" + (int) crewLossReduction + "%", 071 "" + (int) CREW_LOSS_PERCENT + "%"); 072 //info.addSpacer(5f); 073 } 074 075 public ScopeDescription getScopeDescription() { 076 return ScopeDescription.ALL_SHIPS; 077 } 078 079 } 080 081 082 public static class Level2 extends BaseSkillEffectDescription implements ShipSkillEffect, FleetTotalSource { 083 084 public FleetTotalItem getFleetTotalItem() { 085 return getFighterBaysTotal(); 086 } 087 088 public void apply(MutableShipStatsAPI stats, HullSize hullSize, String id, float level) { 089// float damBonus = getDamageBonus(stats); 090// stats.getBallisticWeaponDamageMult().modifyPercent(id, damBonus); 091// stats.getEnergyWeaponDamageMult().modifyPercent(id, damBonus); 092// stats.getMissileWeaponDamageMult().modifyPercent(id, damBonus); 093 094 float speedBonus = getMaxSpeedBonus(stats); 095 if (isOfficer(stats)) speedBonus *= OFFICER_MULT; 096 stats.getMaxSpeed().modifyPercent(id, speedBonus); 097 stats.getAcceleration().modifyPercent(id, speedBonus * 2f); 098 stats.getDeceleration().modifyPercent(id, speedBonus * 2f); 099 100 float aimBonus = getAimBonus(stats); 101 if (isOfficer(stats)) aimBonus *= OFFICER_MULT; 102 stats.getAutofireAimAccuracy().modifyFlat(id, aimBonus * 0.01f); 103 104 float damBonus = getDamageBonus(stats); 105 if (isOfficer(stats)) damBonus *= OFFICER_MULT; 106 stats.getBallisticWeaponDamageMult().modifyPercent(id, damBonus); 107 stats.getEnergyWeaponDamageMult().modifyPercent(id, damBonus); 108 stats.getMissileWeaponDamageMult().modifyPercent(id, damBonus); 109 } 110 111 public void unapply(MutableShipStatsAPI stats, HullSize hullSize, String id) { 112// stats.getBallisticWeaponDamageMult().unmodifyPercent(id); 113// stats.getEnergyWeaponDamageMult().unmodifyPercent(id); 114// stats.getMissileWeaponDamageMult().unmodifyPercent(id); 115 116 stats.getMaxSpeed().unmodifyPercent(id); 117 stats.getAcceleration().unmodifyPercent(id); 118 stats.getDeceleration().unmodifyPercent(id); 119 120 stats.getAutofireAimAccuracy().unmodifyFlat(id); 121 122 stats.getBallisticWeaponDamageMult().unmodifyPercent(id); 123 stats.getEnergyWeaponDamageMult().unmodifyPercent(id); 124 stats.getMissileWeaponDamageMult().unmodifyPercent(id); 125 } 126 127 public String getEffectDescription(float level) { 128 return null; 129 } 130 131// protected float getDamageBonus(MutableShipStatsAPI stats) { 132// FleetDataAPI data = getFleetData(stats); 133// return getDamageBonus(data); 134// } 135// protected float getDamageBonus(FleetDataAPI data) { 136// if (data == null) return DAMAGE_PERCENT; 137// String key = "fighter_uplink_damage"; 138// Float bonus = (Float) data.getCacheClearedOnSync().get(key); 139// if (bonus != null) return bonus; 140// 141// float bays = getNumFighterBays(data); 142// bonus = getThresholdBasedRoundedBonus(DAMAGE_PERCENT, bays, FIGHTER_BAYS_THRESHOLD); 143// 144// data.getCacheClearedOnSync().put(key, bonus); 145// return bonus; 146// } 147 protected float getMaxSpeedBonus(MutableShipStatsAPI stats) { 148 FleetDataAPI data = getFleetData(stats); 149 return getMaxSpeedBonus(data); 150 } 151 152 protected float getMaxSpeedBonus(FleetDataAPI data) { 153 if (data == null) return MAX_SPEED_PERCENT; 154 String key = "fighter_uplink_max_speed"; 155 Float bonus = (Float) data.getCacheClearedOnSync().get(key); 156 if (bonus != null) return bonus; 157 158 float bays = getNumFighterBays(data); 159 bonus = getThresholdBasedRoundedBonus(MAX_SPEED_PERCENT, bays, FIGHTER_BAYS_THRESHOLD); 160 161 data.getCacheClearedOnSync().put(key, bonus); 162 return bonus; 163 } 164 165 protected float getAimBonus(MutableShipStatsAPI stats) { 166 FleetDataAPI data = getFleetData(stats); 167 return getAimBonus(data); 168 } 169 170 protected float getAimBonus(FleetDataAPI data) { 171 if (data == null) return TARGET_LEADING_BONUS; 172 String key = "fighter_uplink_aim"; 173 Float bonus = (Float) data.getCacheClearedOnSync().get(key); 174 if (bonus != null) return bonus; 175 176 float bays = getNumFighterBays(data); 177 bonus = getThresholdBasedRoundedBonus(TARGET_LEADING_BONUS, bays, FIGHTER_BAYS_THRESHOLD); 178 179 data.getCacheClearedOnSync().put(key, bonus); 180 return bonus; 181 } 182 183 protected float getDamageBonus(MutableShipStatsAPI stats) { 184 FleetDataAPI data = getFleetData(stats); 185 return getDamageBonus(data); 186 } 187 188 protected float getDamageBonus(FleetDataAPI data) { 189 if (data == null) return DAMAGE_BONUS_PERCENT; 190 String key = "fighter_uplink_damage"; 191 Float bonus = (Float) data.getCacheClearedOnSync().get(key); 192 if (bonus != null) return bonus; 193 194 float bays = getNumFighterBays(data); 195 bonus = getThresholdBasedRoundedBonus(DAMAGE_BONUS_PERCENT, bays, FIGHTER_BAYS_THRESHOLD); 196 197 data.getCacheClearedOnSync().put(key, bonus); 198 return bonus; 199 } 200 201 public void createCustomDescription(MutableCharacterStatsAPI stats, SkillSpecAPI skill, 202 TooltipMakerAPI info, float width) { 203 init(stats, skill); 204 205 /* 206+37% target leading accuracy (maximum: +50%) 207 Maximum at 6 or less fighter bays in fleet, your fleet has 8 fighter bays 208 */ 209 210 FleetDataAPI data = getFleetData(null); 211 //float damBonus = getDamageBonus(data); 212 float speedBonus = getMaxSpeedBonus(data); 213 float aimBonus = getAimBonus(data); 214 float damBonus = getDamageBonus(data); 215 //float bays = getNumFighterBays(data); 216 217// info.addPara("+%s damage dealt (maximum: %s)", 0f, hc, hc, 218// "" + (int) damBonus + "%", 219// "" + (int) DAMAGE_PERCENT + "%"); 220// addFighterBayThresholdInfo(info, data); 221// 222// info.addSpacer(5f); 223 224 info.addPara("+%s top speed (maximum: %s)", 0f, hc, hc, 225 "" + (int) speedBonus + "%", 226 "" + (int) MAX_SPEED_PERCENT + "%"); 227 info.addPara("+%s target leading accuracy (maximum: %s)", 0f, hc, hc, 228 "" + (int) aimBonus + "%", 229 "" + (int) TARGET_LEADING_BONUS + "%"); 230 info.addPara("+%s damage dealt (maximum: %s)", 0f, hc, hc, 231 "" + (int) damBonus + "%", 232 "" + (int) DAMAGE_BONUS_PERCENT + "%"); 233 addFighterBayThresholdInfo(info, data); 234 info.addPara(indent + "Effect increased by %s for ships with officers, including flagship", 235 0f, tc, hc, 236 "" + Misc.getRoundedValueMaxOneAfterDecimal(OFFICER_MULT) + Strings.X); 237 238 //info.addSpacer(5f); 239 } 240 241 public ScopeDescription getScopeDescription() { 242 return ScopeDescription.ALL_FIGHTERS; 243 } 244 245 } 246 247 248 249} 250 251 252 253 254