1package com.fs.starfarer.api.impl.hullmods;
4import java.util.ArrayList;
7import com.fs.starfarer.api.GameState;
8import com.fs.starfarer.api.Global;
9import com.fs.starfarer.api.campaign.CampaignFleetAPI;
10import com.fs.starfarer.api.combat.BaseHullMod;
11import com.fs.starfarer.api.combat.HullModFleetEffect;
12import com.fs.starfarer.api.combat.MutableShipStatsAPI;
13import com.fs.starfarer.api.combat.ShipAPI;
14import com.fs.starfarer.api.combat.ShipAPI.HullSize;
15import com.fs.starfarer.api.fleet.FleetMemberAPI;
16import com.fs.starfarer.api.impl.campaign.ids.HullMods;
17import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
18import com.fs.starfarer.api.impl.campaign.ids.Strings;
19import com.fs.starfarer.api.ui.LabelAPI;
20import com.fs.starfarer.api.ui.TooltipMakerAPI;
21import com.fs.starfarer.api.util.Misc;
23@SuppressWarnings(
"unchecked")
24public class
PhaseField extends BaseHullMod implements HullModFleetEffect {
34 public static float MIN_CR = 0.1f;
35 public static String MOD_KEY =
"core_PhaseField";
37 public static float PROFILE_MULT = 0.5f;
39 public static float MIN_FIELD_MULT = 0.25f;
42 stats.getSensorProfile().modifyMult(
id, PROFILE_MULT);
47 if (index == 0)
return "" + (int) ((1f - PROFILE_MULT) * 100f) +
"%";
53 String key =
"$updatedPhaseFieldModifier";
54 if (fleet.isPlayerFleet() && fleet.getMemoryWithoutUpdate() !=
null &&
55 !fleet.getMemoryWithoutUpdate().getBoolean(key) &&
56 fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.JUST_TOGGLED_TRANSPONDER)) {
58 fleet.getMemoryWithoutUpdate().set(key,
true, 0.1f);
70 float mult = getPhaseFieldMultBaseProfileAndTotal(fleet,
null, 0f, 0f)[0];
71 if (fleet.isTransponderOn()) mult = 1f;
73 fleet.getDetectedRangeMod().unmodifyMult(MOD_KEY);
75 fleet.getDetectedRangeMod().modifyMult(MOD_KEY, mult,
"Phase ships in fleet");
85 public void addPostDescriptionSection(TooltipMakerAPI tooltip, HullSize hullSize, ShipAPI ship,
float width,
boolean isForModSpec) {
88 Color h = Misc.getHighlightColor();
89 Color bad = Misc.getNegativeHighlightColor();
92 tooltip.addPara(
"In addition, the fleet's detected-at range is reduced by a multiplier based on the total "
93 +
"sensor profile of the %s highest-profile ships in the fleet, and the total sensor strength of the %s "
94 +
"phase ships with the highest sensor strength values. This effect only applies when the "
95 +
"fleet's transponder is turned off.", opad,
97 "" + numProfileShips,
"" + numProfileShips);
99 tooltip.addPara(
"Fleetwide sensor strength increases - such as from High Resolution Sensors - do not factor into "
100 +
"this calculation.", opad);
102 if (isForModSpec || ship ==
null)
return;
107 float [] data = getPhaseFieldMultBaseProfileAndTotal(fleet,
null, 0f, 0f);
108 float [] dataWithOneMore = getPhaseFieldMultBaseProfileAndTotal(fleet,
null,
109 ship.getMutableStats().getSensorProfile().getModifiedValue(),
110 ship.getMutableStats().getSensorStrength().getModifiedValue());
111 float [] dataWithOneLess = getPhaseFieldMultBaseProfileAndTotal(fleet, ship.getFleetMemberId(), 0f, 0f);
113 float mult = data[0];
114 float profile = data[1];
115 float sensors = data[2];
117 tooltip.addPara(
"The sensor profile of the %s top ships in your fleet is %s. The sensor strength of the top %s phase ships "
119 "" + numProfileShips,
120 "" + (
int)Math.round(profile),
121 "" + numProfileShips,
122 "" + (
int)Math.round(sensors)
125 tooltip.addPara(
"The detected-at range multiplier for your fleet is %s. The fleet's transponder must be off "
126 +
"for the multiplier to be applied.",
128 Strings.X + Misc.getRoundedValueFloat(mult),
129 "transponder must be off");
131 float cr = ship.getCurrentCR();
132 for (FleetMemberAPI member :
Global.
getSector().getPlayerFleet().getFleetData().getMembersListCopy()) {
133 if (member.getId().equals(ship.getFleetMemberId())) {
134 cr = member.getRepairTracker().getCR();
139 LabelAPI label = tooltip.addPara(
"This ship's combat readiness is below %s " +
140 "and the phase field's fleetwide effect can not be utilized. Bringing this ship into readiness " +
141 "would improve the multiplier to %s.",
143 "" + (
int) Math.round(MIN_CR * 100f) +
"%",
144 Strings.X + Misc.getRoundedValueFloat(dataWithOneMore[0]));
145 label.setHighlightColors(bad, h);
146 label.setHighlight(
"" + (
int) Math.round(MIN_CR * 100f) +
"%", Strings.X + Misc.getRoundedValueFloat(dataWithOneMore[0]));
148 tooltip.addPara(
"Removing this ship would change the multiplier to %s. Adding another ship with the same sensor strength " +
149 "would improve it to %s.", opad, h,
150 Strings.X + Misc.getRoundedValueFloat(dataWithOneLess[0]),
151 Strings.X + Misc.getRoundedValueFloat(dataWithOneMore[0]));
190 List<FleetMemberAPI> members =
new ArrayList<FleetMemberAPI>();
191 List<FleetMemberAPI> phase =
new ArrayList<FleetMemberAPI>();
192 for (FleetMemberAPI member : fleet.getFleetData().getMembersListCopy()) {
193 if (member.getId().equals(skipId)) {
198 if (member.isMothballed())
continue;
199 if (member.getRepairTracker().getCR() < MIN_CR)
continue;
200 if (member.getVariant().hasHullMod(HullMods.PHASE_FIELD)) {
205 float [] profiles =
new float [members.size()];
206 if (addProfile <= 0) {
207 profiles =
new float [members.size()];
209 profiles =
new float [members.size() + 1];
211 float [] phaseSensors;
212 if (addSensor <= 0) {
213 phaseSensors =
new float [phase.size()];
215 phaseSensors =
new float [phase.size() + 1];
219 for (FleetMemberAPI member : members) {
220 profiles[i] = member.getStats().getSensorProfile().getModifiedValue();
223 if (addProfile > 0) profiles[i] = addProfile;
225 for (FleetMemberAPI member : phase) {
226 phaseSensors[i] = member.getStats().getSensorStrength().getModifiedValue();
229 if (addSensor > 0) phaseSensors[i] = addSensor;
232 int numPhaseShips = numProfileShips;
234 float totalProfile = getTopKValuesSum(profiles, numProfileShips);
235 float totalPhaseSensors = getTopKValuesSum(phaseSensors, numPhaseShips);
237 float total = Math.max(totalProfile + totalPhaseSensors, 1f);
239 float mult = totalProfile / total;
241 if (mult < MIN_FIELD_MULT) mult = MIN_FIELD_MULT;
242 if (mult > 1f) mult = 1f;
244 return new float[] {mult, totalProfile, totalPhaseSensors};
249 k = Math.min(k, arr.length);
251 float kVal = Misc.findKth(arr, arr.length - k);
254 for (
int i = 0; i < arr.length; i++) {
261 total += (k - found) * kVal;
static SettingsAPI getSettings()
static SectorAPI getSector()
static float[] getPhaseFieldMultBaseProfileAndTotal(CampaignFleetAPI fleet, String skipId, float addProfile, float addSensor)
void addPostDescriptionSection(TooltipMakerAPI tooltip, HullSize hullSize, ShipAPI ship, float width, boolean isForModSpec)
static float getTopKValuesSum(float[] arr, int k)
void applyEffectsBeforeShipCreation(HullSize hullSize, MutableShipStatsAPI stats, String id)
boolean withOnFleetSync()
boolean withAdvanceInCampaign()
void advanceInCampaign(CampaignFleetAPI fleet)
void onFleetSync(CampaignFleetAPI fleet)
boolean shouldAddDescriptionToTooltip(HullSize hullSize, ShipAPI ship, boolean isForModSpec)
String getDescriptionParam(int index, HullSize hullSize)
GameState getCurrentState()