1package com.fs.starfarer.api.impl.hullmods;
4import java.util.ArrayList;
5import java.util.LinkedHashSet;
9import com.fs.starfarer.api.Global;
10import com.fs.starfarer.api.combat.BaseHullMod;
11import com.fs.starfarer.api.combat.MutableShipStatsAPI;
12import com.fs.starfarer.api.combat.ShipAPI;
13import com.fs.starfarer.api.combat.ShipAPI.HullSize;
14import com.fs.starfarer.api.graphics.SpriteAPI;
15import com.fs.starfarer.api.impl.campaign.ids.HullMods;
16import com.fs.starfarer.api.impl.campaign.ids.Stats;
17import com.fs.starfarer.api.impl.campaign.ids.Strings;
18import com.fs.starfarer.api.loading.FighterWingSpecAPI;
19import com.fs.starfarer.api.ui.Alignment;
20import com.fs.starfarer.api.ui.TooltipMakerAPI;
21import com.fs.starfarer.api.util.Misc;
62 cost += spec.getOpCost(stats);
68 if (stats.getVariant() !=
null) {
69 return stats.getVariant().getFittedWings();
71 return new ArrayList<String>();
80 return 1f + dpMod / suppliesPerDep;
86 numBays += stats.getDynamic().getMod(Stats.CONVERTED_HANGAR_MOD).computeEffective(0f);
87 stats.getNumFighterBays().modifyFlat(
id, numBays);
89 boolean sMod = isSMod(stats);
93 else if (hullSize == HullSize.CAPITAL_SHIP) bonus =
SMOD_CAPITAL;
95 stats.getDynamic().getStat(Stats.REPLACEMENT_RATE_INCREASE_MULT).modifyPercent(
id, bonus);
99 boolean crewIncrease = stats.getDynamic().getMod(Stats.CONVERTED_HANGAR_NO_CREW_INCREASE).computeEffective(0f) <= 0;
100 boolean rearmIncrease = stats.getDynamic().getMod(Stats.CONVERTED_HANGAR_NO_REARM_INCREASE).computeEffective(0f) <= 0;
101 boolean dpIncrease = stats.getDynamic().getMod(Stats.CONVERTED_HANGAR_NO_DP_INCREASE).computeEffective(0f) <= 0;
102 boolean refitPenalty = stats.getDynamic().getMod(Stats.CONVERTED_HANGAR_NO_REFIT_PENALTY).computeEffective(0f) <= 0;
106 stats.getDynamic().getStat(Stats.REPLACEMENT_RATE_DECREASE_MULT).modifyMult(
id, 1f /
REPLACEMENT_TIME_MULT);
107 stats.getDynamic().getStat(Stats.REPLACEMENT_RATE_INCREASE_MULT).modifyMult(
id, 1f /
REPLACEMENT_TIME_MULT);
112 stats.getDynamic().getMod(Stats.FIGHTER_REARM_TIME_EXTRA_FRACTION_OF_BASE_REFIT_TIME_MOD).modifyFlat(
id,
REARM_TIME_FRACTION);
118 stats.getDynamic().getMod(Stats.DEPLOYMENT_POINTS_MOD).modifyFlat(
id, dpMod);
120 if (stats.getFleetMember() !=
null) {
121 float perDep = stats.getFleetMember().getHullSpec().getSuppliesToRecover();
123 stats.getCRPerDeploymentPercent().modifyMult(
id, mult);
126 stats.getSuppliesToRecover().modifyFlat(
id, dpMod);
131 stats.getMinCrewMod().modifyFlat(
id,
CREW_REQ);
153 return ship !=
null && !ship.isFrigate() && ship.getHullSpec().getFighterBays() <= 0 &&
155 !ship.getVariant().hasHullMod(HullMods.CONVERTED_BAY) &&
156 !ship.getHullSpec().isPhase();
161 return "Ship's combat readiness lost per deployment is too high";
163 if (ship !=
null && ship.isFrigate())
return "Can not be installed on a frigate";
164 if (ship !=
null && ship.getHullSpec().getFighterBays() > 0)
return "Ship has standard fighter bays";
165 if (ship !=
null && ship.getVariant().hasHullMod(HullMods.CONVERTED_BAY))
return "Ship has fighter bays";
167 return "Can not be installed on a phase ship";
182 if (sprite !=
null) {
183 fighter.setSprite(sprite);
188 if (carrier.getHullStyleId().equals(fighter.getHullStyleId())) {
192 SpriteAPI skin =
null;
193 if (carrier.getOwner() == 0 || carrier.getOriginalOwner() == 0) {
194 cat =
"fighterSkinsPlayerOnly";
197 if (skin !=
null)
return skin;
199 cat =
"fighterSkinsPlayerAndNPC";
205 public static SpriteAPI
getFighterSkin(String cat, ShipAPI fighter, ShipAPI carrier) {
207 String exclude =
"fighterSkinsExcludeFromSharing";
208 String
id = fighter.getHullSpec().getHullId();
209 String style = carrier.getHullStyleId();
214 List<SpriteAPI> matching =
new ArrayList<SpriteAPI>();
215 for (String key : skins) {
216 if (key.equals(
id +
"_" + style)) {
219 if (key.startsWith(
id) && !noSharing.contains(key)) {
224 if (!matching.isEmpty()) {
225 SpriteAPI best =
null;
226 float minDist = Float.MAX_VALUE;
228 for (SpriteAPI curr : matching) {
229 float dist = Misc.getColorDist(carrier.getSpriteAPI().getAverageBrightColor(), curr.getAverageBrightColor());
230 if (dist < minDist) {
266 public void addPostDescriptionSection(TooltipMakerAPI tooltip, HullSize hullSize,
final ShipAPI ship,
float width,
boolean isForModSpec) {
269 Color h = Misc.getHighlightColor();
270 Color bad = Misc.getNegativeHighlightColor();
273 tooltip.addPara(
"Converts the ship's standard shuttle hangar to house a fighter bay. "
274 +
"The improvised flight deck, its crew, and the related machinery all function "
275 +
"at a pace below that of a dedicated carrier.", opad);
286 tooltip.addPara(
"Increases fighter refit time by %s, "
287 +
"and the fighter replacement rate both decays and recovers %s more slowly. "
288 +
"In addition, bombers returning to rearm (or fighters returning for repairs) "
289 +
"take %s of their base refit time to relaunch, "
290 +
"where normally it takes under a second. "
297 tooltip.addPara(
"Increases the minimum crew by %s to account for pilots and flight crews. "
298 +
"Increases the ship's deployment points and supply cost to recover "
299 +
"from deployment by %s for every %s ordnance points spent on "
300 +
"fighters, or by at least %s point. This comes with a proportional increase "
301 +
"in combat readiness lost per deployment.", opad, h,
307 if (isForModSpec || ship ==
null || ship.getMutableStats() ==
null)
return;
309 MutableShipStatsAPI stats = ship.getMutableStats();
310 boolean crewIncrease = stats.getDynamic().getMod(Stats.CONVERTED_HANGAR_NO_CREW_INCREASE).computeEffective(0f) <= 0;
311 boolean rearmIncrease = stats.getDynamic().getMod(Stats.CONVERTED_HANGAR_NO_REARM_INCREASE).computeEffective(0f) <= 0;
312 boolean dpIncrease = stats.getDynamic().getMod(Stats.CONVERTED_HANGAR_NO_DP_INCREASE).computeEffective(0f) <= 0;
313 boolean refitPenalty = stats.getDynamic().getMod(Stats.CONVERTED_HANGAR_NO_REFIT_PENALTY).computeEffective(0f) <= 0;
322 tooltip.addPara(
"Deployment cost: %s", opad, h,
"+" + dpMod);
326 float sizeW = width - numW - 10f;
329 tooltip.beginTable(Misc.getBasePlayerColor(), Misc.getDarkPlayerColor(), Misc.getBrightPlayerColor(),
331 new Object [] {
"Wing", sizeW,
"Seconds to relaunch", numW});
335 float refitPortion = spec.getRefitTime() *
336 ship.getMutableStats().getDynamic().getValue(Stats.FIGHTER_REARM_TIME_EXTRA_FRACTION_OF_BASE_REFIT_TIME_MOD, 0f);
338 Color c = Misc.getTextColor();
340 tooltip.addRow(Alignment.MID, c, spec.getWingName(),
341 Alignment.MID, h, Misc.getRoundedValueOneAfterDecimalIfNotWhole(refitPortion)
344 tooltip.addTable(
"", 0, opad);
354 List<String> negated =
new ArrayList<String>();
355 if (!refitPenalty) negated.add(
"refit time and rate recovery modifiers");
356 if (!rearmIncrease) negated.add(
"relaunch delay");
357 if (!crewIncrease) negated.add(
"increased crew requirement");
358 if (!dpIncrease) negated.add(
"deployment cost increase");
360 if (!negated.isEmpty()) {
361 Color c = Misc.getPositiveHighlightColor();
362 String isOrAre =
"is";
363 if (negated.size() > 1) isOrAre =
"are";
364 if (negated.size() >= 4) isOrAre +=
" all";
365 tooltip.addPara(
"The " + Misc.getAndJoined(negated) +
" " + isOrAre +
" negated on this ship.", c, opad);
static SettingsAPI getSettings()
static float FIGHTER_OP_PER_DP
void applyEffectsToFighterSpawnedByShip(ShipAPI fighter, ShipAPI ship, String id)
static SpriteAPI getFighterSkin(ShipAPI fighter, ShipAPI carrier)
static float SMOD_CAPITAL
String getSModDescriptionParam(int index, HullSize hullSize, ShipAPI ship)
void addPostDescriptionSection(TooltipMakerAPI tooltip, HullSize hullSize, final ShipAPI ship, float width, boolean isForModSpec)
boolean isApplicableToShip(ShipAPI ship)
static int computeDPModifier(float fighterOPCost)
static void setFighterSkin(ShipAPI fighter, ShipAPI carrier)
static float SMOD_CRUISER
static float REPLACEMENT_TIME_MULT
static SpriteAPI getFighterSkin(String cat, ShipAPI fighter, ShipAPI carrier)
static float REARM_TIME_FRACTION
boolean shouldAddDescriptionToTooltip(HullSize hullSize, ShipAPI ship, boolean isForModSpec)
static List< String > getFighterWings(MutableShipStatsAPI stats)
static float CR_THRESHOLD_UNINSTALLABLE
float computeCRMult(float suppliesPerDep, float dpMod)
static float getFighterOPCost(MutableShipStatsAPI stats)
void applyEffectsBeforeShipCreation(HullSize hullSize, MutableShipStatsAPI stats, String id)
String getUnapplicableReason(ShipAPI ship)
List< String > getSpriteKeys(String category)
FighterWingSpecAPI getFighterWingSpec(String wingId)
SpriteAPI getSprite(String filename)