Starsector API
Loading...
Searching...
No Matches
BaseSkillEffectDescription.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.skills;
2
3import java.awt.Color;
4import java.util.ArrayList;
5import java.util.Collections;
6import java.util.Comparator;
7import java.util.HashSet;
8import java.util.List;
9import java.util.Set;
10
11import com.fs.starfarer.api.GameState;
12import com.fs.starfarer.api.Global;
13import com.fs.starfarer.api.campaign.AICoreOfficerPlugin;
14import com.fs.starfarer.api.campaign.CampaignFleetAPI;
15import com.fs.starfarer.api.campaign.FleetDataAPI;
16import com.fs.starfarer.api.characters.CustomSkillDescription;
17import com.fs.starfarer.api.characters.FleetTotalItem;
18import com.fs.starfarer.api.characters.MutableCharacterStatsAPI;
19import com.fs.starfarer.api.characters.MutableCharacterStatsAPI.SkillLevelAPI;
20import com.fs.starfarer.api.characters.PersonAPI;
21import com.fs.starfarer.api.characters.SkillSpecAPI;
22import com.fs.starfarer.api.combat.MutableShipStatsAPI;
23import com.fs.starfarer.api.combat.ShipHullSpecAPI.ShipTypeHints;
24import com.fs.starfarer.api.combat.ShipVariantAPI;
25import com.fs.starfarer.api.fleet.FleetMemberAPI;
26import com.fs.starfarer.api.impl.campaign.ids.HullMods;
27import com.fs.starfarer.api.impl.campaign.intel.BaseIntelPlugin;
28import com.fs.starfarer.api.impl.hullmods.Automated;
29import com.fs.starfarer.api.ui.BaseTooltipCreator;
30import com.fs.starfarer.api.ui.TooltipMakerAPI;
31import com.fs.starfarer.api.ui.TooltipMakerAPI.TooltipCreator;
32import com.fs.starfarer.api.util.Misc;
33
34public class BaseSkillEffectDescription implements CustomSkillDescription {
35
36 public static float TOOLTIP_WIDTH = 450;
37
38 public static float FIGHTER_BAYS_THRESHOLD = 8;
39 public static float OP_THRESHOLD = 1000;
40 public static float OP_LOW_THRESHOLD = 500;
41 public static float OP_ALL_LOW_THRESHOLD = 500;
42 public static float OP_ALL_THRESHOLD = 1000;
43 public static float PHASE_OP_THRESHOLD = 150;
44 public static float MILITARIZED_OP_THRESHOLD = 50;
45
46 public static float AUTOMATED_POINTS_THRESHOLD = 200;
47
48 public static boolean USE_RECOVERY_COST = true;
49
50 //public static String RECOVERY_COST = "recovery cost";
51 public static String RECOVERY_COST = "deployment point cost";
52
53 static {
55 // working off 60% of the default battle size of 300 for these, which is 180
56 OP_THRESHOLD = 240;
57 OP_LOW_THRESHOLD = 120;
59 OP_ALL_THRESHOLD = 240;
60// OP_THRESHOLD = 150;
61// OP_LOW_THRESHOLD = 75;
62// OP_ALL_LOW_THRESHOLD = 50;
63
64
68 }
69 }
70
71
72 public static enum ThresholdBonusType {
73 OP,
74 OP_LOW,
75 OP_ALL,
76 OP_ALL_LOW,
77 MILITARIZED_OP,
78 PHASE_OP,
79 FIGHTER_BAYS,
80 AUTOMATED_POINTS,
81 }
82
83 protected Color tc;
84 protected Color dtc;
85 protected Color hc;
86 protected Color dhc;
87 protected String indent;
88 protected int alpha;
89
90 public void init(MutableCharacterStatsAPI stats, SkillSpecAPI skill) {
91 indent = BaseIntelPlugin.BULLET;
92 tc = Misc.getTextColor();
93 hc = Misc.getHighlightColor();
94 dhc = Misc.setAlpha(hc, 155);
95 alpha = 255;
96 float level = stats.getSkillLevel(skill.getId());
97 if (level <= 0) {
98 tc = Misc.getGrayColor();
99 hc = dhc;
100 alpha = 155;
101 }
102 dtc = Misc.getGrayColor();
103 }
104
105 public void initElite(MutableCharacterStatsAPI stats, SkillSpecAPI skill) {
106 indent = BaseIntelPlugin.BULLET;
107 tc = Misc.getTextColor();
108 hc = Misc.getHighlightColor();
109 dhc = Misc.setAlpha(hc, 155);
110 alpha = 255;
111 float level = stats.getSkillLevel(skill.getId());
112 if (level <= 1) {
113 tc = Misc.getGrayColor();
114 hc = dhc;
115 alpha = 155;
116 }
117 dtc = Misc.getGrayColor();
118 }
119
120 public void addFighterBayThresholdInfo(TooltipMakerAPI info, FleetDataAPI data) {
121 if (isInCampaign()) {
122 int bays = Math.round(getNumFighterBays(data));
123 String baysStr = "fighter bays";
124 if (bays == 1) baysStr = "fighter bay";
125 //baysStr = "";
126 info.addPara(indent + "Maximum at %s or less fighter bays in fleet, your fleet has %s " + baysStr,
127 0f, tc, hc,
128 "" + (int) FIGHTER_BAYS_THRESHOLD,
129 "" + bays);
130 } else {
131 info.addPara(indent + "Maximum at %s or less fighter bays in fleet",
132 0f, tc, hc,
133 "" + (int) FIGHTER_BAYS_THRESHOLD);
134 }
135 }
136
137 public void addOPThresholdInfo(TooltipMakerAPI info, FleetDataAPI data, MutableCharacterStatsAPI cStats) {
138 addOPThresholdInfo(info, data, cStats, OP_THRESHOLD);
139 }
140 public void addOPThresholdInfo(TooltipMakerAPI info, FleetDataAPI data, MutableCharacterStatsAPI cStats, float threshold) {
141 if (USE_RECOVERY_COST) {
142 if (isInCampaign()) {
143 float op = getTotalCombatOP(data, cStats);
144 info.addPara(indent + "Maximum at %s or less total combat ship " + RECOVERY_COST + ", your fleet's total is %s",
145 0f, tc, hc,
146 "" + (int) threshold,
147 "" + (int)Math.round(op));
148 } else {
149 info.addPara(indent + "Maximum at %s or less total combat ship " + RECOVERY_COST + " for fleet",
150 0f, tc, hc,
151 "" + (int) threshold);
152 }
153 return;
154 }
155 if (isInCampaign()) {
156 float op = getTotalCombatOP(data, cStats);
157 String opStr = "points";
158 if (op == 1) opStr = "point";
159 info.addPara(indent + "Maximum at %s or less total combat ship ordnance points in fleet, your fleet has %s " + opStr,
160 0f, tc, hc,
161 "" + (int) threshold,
162 "" + (int)Math.round(op));
163 } else {
164 info.addPara(indent + "Maximum at %s or less total combat ship ordnance points in fleet",
165 0f, tc, hc,
166 "" + (int) threshold);
167 }
168 }
169
170 public void addOPThresholdAll(TooltipMakerAPI info, FleetDataAPI data, MutableCharacterStatsAPI cStats, float threshold) {
171 if (USE_RECOVERY_COST) {
172 if (isInCampaign()) {
173 float op = getTotalOP(data, cStats);
174 info.addPara(indent + "Maximum at %s or less total " + RECOVERY_COST + ", your fleet's total is %s",
175 0f, tc, hc,
176 "" + (int) threshold,
177 "" + (int)Math.round(op));
178 } else {
179 info.addPara(indent + "Maximum at %s or less total " + RECOVERY_COST + " for fleet",
180 0f, tc, hc,
181 "" + (int) threshold);
182 }
183 return;
184 }
185 if (isInCampaign()) {
186 float op = getTotalOP(data, cStats);
187// String opStr = "combat ship ordnance points";
188// if (op == 1) opStr = "combat ship ordnance point";
189 String opStr = "points";
190 if (op == 1) opStr = "point";
191 info.addPara(indent + "Maximum at %s or less total ordnance points in fleet, your fleet has %s " + opStr,
192 0f, tc, hc,
193 "" + (int) threshold,
194 "" + (int)Math.round(op));
195 } else {
196 info.addPara(indent + "Maximum at %s or less total ordnance points in fleet",
197 0f, tc, hc,
198 "" + (int) threshold);
199 }
200 }
201
202 public void addPhaseOPThresholdInfo(TooltipMakerAPI info, FleetDataAPI data, MutableCharacterStatsAPI cStats) {
203 if (USE_RECOVERY_COST) {
204 if (isInCampaign()) {
205 float op = getPhaseOP(data, cStats);
206 info.addPara(indent + "Maximum at %s or less total combat phase ship " + RECOVERY_COST + ", your fleet's total is %s",
207 0f, tc, hc,
208 "" + (int) PHASE_OP_THRESHOLD,
209 "" + (int)Math.round(op));
210 } else {
211 info.addPara(indent + "Maximum at %s or less total combat phase ship " + RECOVERY_COST + " for fleet",
212 0f, tc, hc,
213 "" + (int) PHASE_OP_THRESHOLD);
214 }
215
216 return;
217 }
218 if (isInCampaign()) {
219 float op = getPhaseOP(data, cStats);
220 String opStr = "points";
221 if (op == 1) opStr = "point";
222 info.addPara(indent + "Maximum at %s or less total combat phase ship ordnance points in fleet, your fleet has %s " + opStr,
223 0f, tc, hc,
224 "" + (int) PHASE_OP_THRESHOLD,
225 "" + (int)Math.round(op));
226 } else {
227 info.addPara(indent + "Maximum at %s or less total combat phase ship ordnance points in fleet",
228 0f, tc, hc,
229 "" + (int) PHASE_OP_THRESHOLD);
230 }
231 }
232
233 public void addAutomatedThresholdInfo(TooltipMakerAPI info, FleetDataAPI data, MutableCharacterStatsAPI cStats) {
234 if (USE_RECOVERY_COST) {
235 if (isInCampaign()) {
236 float op = getAutomatedPoints(data, cStats);
237 info.addPara(indent + "Maximum at %s or less total automated ship points*, your fleet's total is %s ",
238 0f, tc, hc,
240 "" + (int)Math.round(op));
241 } else {
242 info.addPara(indent + "Maximum at %s or less total automated ship points* for fleet",
243 0f, tc, hc,
244 "" + (int) AUTOMATED_POINTS_THRESHOLD);
245 }
246 return;
247 }
248 if (isInCampaign()) {
249 float op = getAutomatedPoints(data, cStats);
250 String opStr = "points";
251 if (op == 1) opStr = "point";
252 info.addPara(indent + "Maximum at %s or less total automated ship points* in fleet, your fleet has %s " + opStr,
253 0f, tc, hc,
255 "" + (int)Math.round(op));
256 } else {
257 info.addPara(indent + "Maximum at %s or less total automated ship points* in fleet",
258 0f, tc, hc,
259 "" + (int) AUTOMATED_POINTS_THRESHOLD);
260 }
261 }
262
263 public void addMilitarizedOPThresholdInfo(TooltipMakerAPI info, FleetDataAPI data, MutableCharacterStatsAPI cStats) {
264 if (USE_RECOVERY_COST) {
265 if (isInCampaign()) {
266 float op = getMilitarizedOP(data, cStats);
267 info.addPara(indent + "Maximum at %s or less total " + RECOVERY_COST + " for ships with Militarized Subsystems, your fleet's total is %s",
268 0f, tc, hc,
269 "" + (int) MILITARIZED_OP_THRESHOLD,
270 "" + (int)Math.round(op));
271 } else {
272 info.addPara(indent + "Maximum at %s or less total " + RECOVERY_COST + " for ships with Militarized Subsystems for fleet",
273 0f, tc, hc,
274 "" + (int) MILITARIZED_OP_THRESHOLD);
275 }
276 return;
277 } else {
278 if (isInCampaign()) {
279 float op = getMilitarizedOP(data, cStats);
280 String opStr = "points";
281 if (op == 1) opStr = "point";
282 info.addPara(indent + "Maximum at %s or less total ordnance points for ships with Militarized Subsystems, your fleet has %s " + opStr,
283 0f, tc, hc,
284 "" + (int) MILITARIZED_OP_THRESHOLD,
285 "" + (int)Math.round(op));
286 } else {
287 info.addPara(indent + "Maximum at %s or less total ordnance points for ships with Militarized Subsystems",
288 0f, tc, hc,
289 "" + (int) MILITARIZED_OP_THRESHOLD);
290 }
291 }
292 }
293
294 protected float computeAndCacheThresholdBonus(MutableShipStatsAPI stats,
295 String key, float maxBonus, ThresholdBonusType type) {
296 FleetDataAPI data = getFleetData(stats);
297 MutableCharacterStatsAPI cStats = getCommanderStats(stats);
298 return computeAndCacheThresholdBonus(data, cStats, key, maxBonus, type);
299 }
300 protected float computeAndCacheThresholdBonus(FleetDataAPI data, MutableCharacterStatsAPI cStats,
301 String key, float maxBonus, ThresholdBonusType type) {
302// if (key.equals("pc_peak")) {
303// System.out.println("efwfwefwe");
304// }
305 if (data == null) return maxBonus;
306 if (cStats.getFleet() == null) return maxBonus;
307
308 Float bonus = (Float) data.getCacheClearedOnSync().get(key);
309 if (bonus != null) return bonus;
310
311 float currValue = 0f;
312 float threshold = 1f;
313
314 if (type == ThresholdBonusType.FIGHTER_BAYS) {
315 currValue = getNumFighterBays(data);
316 threshold = FIGHTER_BAYS_THRESHOLD;
317 } else if (type == ThresholdBonusType.OP) {
318 currValue = getTotalCombatOP(data, cStats);
319 threshold = OP_THRESHOLD;
320 } else if (type == ThresholdBonusType.OP_LOW) {
321 currValue = getTotalCombatOP(data, cStats);
322 threshold = OP_LOW_THRESHOLD;
323 } else if (type == ThresholdBonusType.OP_ALL_LOW) {
324 currValue = getTotalOP(data, cStats);
325 threshold = OP_ALL_LOW_THRESHOLD;
326 } else if (type == ThresholdBonusType.OP_ALL) {
327 currValue = getTotalOP(data, cStats);
328 threshold = OP_ALL_THRESHOLD;
329 } else if (type == ThresholdBonusType.MILITARIZED_OP) {
330 currValue = getMilitarizedOP(data, cStats);
331 threshold = MILITARIZED_OP_THRESHOLD;
332 } else if (type == ThresholdBonusType.PHASE_OP) {
333 currValue = getPhaseOP(data, cStats);
334 threshold = PHASE_OP_THRESHOLD;
335 } else if (type == ThresholdBonusType.AUTOMATED_POINTS) {
336 currValue = getAutomatedPoints(data, cStats);
337 threshold = AUTOMATED_POINTS_THRESHOLD;
338 }
339
340 bonus = getThresholdBasedRoundedBonus(maxBonus, currValue, threshold);
341
342 data.getCacheClearedOnSync().put(key, bonus);
343 return bonus;
344 }
345// refitData.addOrUpdate(0, 0, indent + "Combat ship ordnance points", "" + (int)totalOP);
346// refitData.addOrUpdate(0, 1, indent + "Phase ship ordnance points", "" + (int)phaseOP);
347// refitData.addOrUpdate(0, 2, indent + "Fighter bays", "" + (int)bays);
348// float totalOP = BaseSkillEffectDescription.getTotalOP(fleet.getFleetData(), Global.getSector().getPlayerStats());
349// float phaseOP = BaseSkillEffectDescription.getPhaseOP(fleet.getFleetData(), Global.getSector().getPlayerStats());
350
351 public FleetTotalItem getOPTotal() {
352 final CampaignFleetAPI fleet = Global.getSector().getPlayerFleet();
353 final MutableCharacterStatsAPI stats = Global.getSector().getPlayerStats();
354 FleetTotalItem item = new FleetTotalItem();
355 item.label = "Total ordnance points";
356 if (USE_RECOVERY_COST) {
357 item.label = "All ships";
358 }
359 item.value = "" + (int) getTotalOP(fleet.getFleetData(), stats);
360 item.sortOrder = 50;
361
362 item.tooltipCreator = getTooltipCreator(new TooltipCreatorSkillEffectPlugin() {
363 public void addDescription(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) {
364 float opad = 10f;
365 tooltip.addPara("The total deployment points of all the ships in your fleet.", 0f);
366 }
367 public List<FleetMemberPointContrib> getContributors() {
368 return getTotalOPDetail(fleet.getFleetData(), stats);
369 }
370 });
371
372 return item;
373 }
374
375 public FleetTotalItem getCombatOPTotal() {
376 final CampaignFleetAPI fleet = Global.getSector().getPlayerFleet();
377 final MutableCharacterStatsAPI stats = Global.getSector().getPlayerStats();
378 FleetTotalItem item = new FleetTotalItem();
379 item.label = "Combat ship ordnance points";
380 if (USE_RECOVERY_COST) {
381 item.label = "Combat ships";
382 }
383 item.value = "" + (int) BaseSkillEffectDescription.getTotalCombatOP(fleet.getFleetData(), stats);
384 item.sortOrder = 100;
385
386 item.tooltipCreator = getTooltipCreator(new TooltipCreatorSkillEffectPlugin() {
387 public void addDescription(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) {
388 float opad = 10f;
389 tooltip.addPara("The total deployment points of all the combat ships in your fleet.", 0f);
390 }
391 public List<FleetMemberPointContrib> getContributors() {
392 return getTotalCombatOPDetail(fleet.getFleetData(), stats);
393 }
394 });
395
396 return item;
397 }
398
399 public FleetTotalItem getAutomatedPointsTotal() {
400 final CampaignFleetAPI fleet = Global.getSector().getPlayerFleet();
401 final MutableCharacterStatsAPI stats = Global.getSector().getPlayerStats();
402 FleetTotalItem item = new FleetTotalItem();
403 item.label = "Automated ships";
404 item.value = "" + (int) BaseSkillEffectDescription.getAutomatedPoints(fleet.getFleetData(), stats);
405 item.sortOrder = 350;
406
407 item.tooltipCreator = getTooltipCreator(new TooltipCreatorSkillEffectPlugin() {
408 public void addDescription(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) {
409 float opad = 10f;
410 tooltip.addPara("The total deployment points of all the automated ships in your fleet, "
411 + "with additional points for ships controlled by AI cores.", 0f);
412 }
413 public List<FleetMemberPointContrib> getContributors() {
414 return getAutomatedPointsDetail(fleet.getFleetData(), stats);
415 }
416 });
417
418 return item;
419 }
420
421 public FleetTotalItem getPhaseOPTotal() {
422 final CampaignFleetAPI fleet = Global.getSector().getPlayerFleet();
423 final MutableCharacterStatsAPI stats = Global.getSector().getPlayerStats();
424 FleetTotalItem item = new FleetTotalItem();
425 item.label = "Phase ship ordnance points";
426 if (USE_RECOVERY_COST) {
427 item.label = "Phase ships";
428 }
429 item.value = "" + (int) BaseSkillEffectDescription.getPhaseOP(fleet.getFleetData(), stats);
430 item.sortOrder = 200;
431
432 item.tooltipCreator = getTooltipCreator(new TooltipCreatorSkillEffectPlugin() {
433 public void addDescription(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) {
434 float opad = 10f;
435 tooltip.addPara("The total deployment points of all the non-civilian phase ships in your fleet.", 0f);
436 }
437 public List<FleetMemberPointContrib> getContributors() {
438 return getPhaseOPDetail(fleet.getFleetData(), stats);
439 }
440 });
441 return item;
442 }
443
444 public FleetTotalItem getMilitarizedOPTotal() {
445 final CampaignFleetAPI fleet = Global.getSector().getPlayerFleet();
446 final MutableCharacterStatsAPI stats = Global.getSector().getPlayerStats();
447 FleetTotalItem item = new FleetTotalItem();
448 item.label = "Militarized ship ordnance points";
449 if (USE_RECOVERY_COST) {
450 item.label = "Militarized ships";
451 }
452 item.value = "" + (int) BaseSkillEffectDescription.getMilitarizedOP(fleet.getFleetData(), stats);
453 item.sortOrder = 300;
454
455 item.tooltipCreator = getTooltipCreator(new TooltipCreatorSkillEffectPlugin() {
456 public void addDescription(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) {
457 float opad = 10f;
458 tooltip.addPara("The total deployment points of all the ships in your fleet that have "
459 + "the \"Militarized Subsystems\" hullmod.", 0f);
460 }
461 public List<FleetMemberPointContrib> getContributors() {
462 return getMilitarizedOPDetail(fleet.getFleetData(), stats);
463 }
464 });
465
466 return item;
467 }
468
469 public FleetTotalItem getFighterBaysTotal() {
470 final CampaignFleetAPI fleet = Global.getSector().getPlayerFleet();
471 FleetTotalItem item = new FleetTotalItem();
472 item.label = "Fighter bays";
473 item.value = "" + (int) BaseSkillEffectDescription.getNumFighterBays(fleet.getFleetData());
474 item.sortOrder = 400;
475
476 item.tooltipCreator = getTooltipCreator(new TooltipCreatorSkillEffectPlugin() {
477 public void addDescription(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) {
478 float opad = 10f;
479 tooltip.addPara("The total number of fighter bays in your fleet. Both empty and filled "
480 + "fighter bays are counted. Built-in fighter bays can be removed from a ship by "
481 + "installing the \"Converted Fighter Bay\" hullmod.", 0f);
482 }
483 public List<FleetMemberPointContrib> getContributors() {
484 return getNumFighterBaysDetail(fleet.getFleetData());
485 }
486 });
487
488 return item;
489 }
490
492 void addDescription(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam);
493 List<FleetMemberPointContrib> getContributors();
494 }
495 public TooltipCreator getTooltipCreator(final TooltipCreatorSkillEffectPlugin plugin) {
496 return new BaseTooltipCreator() {
497 public float getTooltipWidth(Object tooltipParam) {
498 return TOOLTIP_WIDTH;
499 }
500 @SuppressWarnings("unchecked")
501 public void createTooltip(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) {
502 float pad = 3f;
503 float opad = 10f;
504
505 plugin.addDescription(tooltip, expanded, tooltipParam);
506
507 tooltip.addPara("Certain skills will have reduced effects if this value exceeds a "
508 + "skill-specific threshold; see the specific skill for details. Mothballed "
509 + "ships are not counted towards the total.", opad);
510
511 tooltip.addPara("Skills using this value:", opad);
512 tooltip.setBulletedListMode(BaseIntelPlugin.INDENT);
513 List<SkillLevelAPI> skills = (List<SkillLevelAPI>) tooltipParam;
514 Set<SkillLevelAPI> seen = new HashSet<MutableCharacterStatsAPI.SkillLevelAPI>();
515
516 float initPad = opad;
517 //initPad = pad;
518 for (SkillLevelAPI skill : skills) {
519 if (seen.contains(skill)) continue;
520 seen.add(skill);
521 String label = skill.getSkill().getName() + " (" + skill.getSkill().getGoverningAptitudeName() + ")";
522 label = skill.getSkill().getGoverningAptitudeName() + " - " + skill.getSkill().getName();
523 tooltip.addPara(label,
524 skill.getSkill().getGoverningAptitudeColor(), initPad);
525 initPad = pad;
526 }
527 tooltip.setBulletedListMode(null);
528
529 List<FleetMemberPointContrib> members = plugin.getContributors();
530 Collections.sort(members, new Comparator<FleetMemberPointContrib>() {
531 public int compare(FleetMemberPointContrib o1, FleetMemberPointContrib o2) {
532 return o2.points - o1.points;
533 }
534 });
535
536 tooltip.addPara("Ships contributing to this value:", opad);
537 initPad = opad;
538 //initPad = pad;
539 if (members.isEmpty()) {
540 tooltip.setBulletedListMode(BaseIntelPlugin.INDENT);
541 tooltip.addPara("None", initPad);
542 tooltip.setBulletedListMode(null);
543 }
544 float gridWidth = 450f;
545 //tooltip.beginGrid(gridWidth, 1);
546 tooltip.beginGridFlipped(gridWidth, 1, 40f, opad);
547 int i = 0;
548 int max = 20;
549 if (members.size() == max + 1) {
550 max = members.size();
551 }
552 for (FleetMemberPointContrib member : members) {
553// String label = tooltip.shortenString(BaseIntelPlugin.INDENT + getValueLabelForMember(member.member),
554// gridWidth);
555 String label = tooltip.shortenString(getValueLabelForMember(member.member),
556 gridWidth - 60f);
557 tooltip.addToGrid(0, i++, label, "+" + member.points);
558 if (i >= max) break;
559 }
560 tooltip.addGrid(opad);
561 if (members.size() > max) {
562 tooltip.addPara("And %s other ships with a smaller contribution.", opad,
563 Misc.getHighlightColor(), "" + (members.size() - max));
564 }
565
566 }
567 };
568 }
569
570 public static String getValueLabelForMember(FleetMemberAPI member) {
571 String str = "";
572 if (!member.isFighterWing()) {
573 str += member.getShipName() + ", ";
574 str += member.getHullSpec().getHullNameWithDashClass();
575 } else {
576 str += member.getVariant().getFullDesignationWithHullName();
577 }
578 if (member.isMothballed()) {
579 str += " (mothballed)";
580 }
581 return str;
582 }
583
584
585 public float getThresholdBasedBonus(float maxBonus, float value, float threshold) {
586 float bonus = maxBonus * threshold / Math.max(value, threshold);
587 return bonus;
588 }
589 public float getThresholdBasedRoundedBonus(float maxBonus, float value, float threshold) {
590 float bonus = maxBonus * threshold / Math.max(value, threshold);
591 if (bonus > 0 && bonus < 1) bonus = 1;
592 if (maxBonus > 1f) {
593 if (bonus < maxBonus) {
594 bonus = Math.min(bonus, maxBonus - 1f);
595 }
596 bonus = (float) Math.round(bonus);
597 }
598 return bonus;
599 }
600
601 public static boolean isMilitarized(MutableShipStatsAPI stats) {
602 if (stats == null || stats.getFleetMember() == null) return false;
603 return isMilitarized(stats.getFleetMember());
604 }
605 public static boolean isMilitarized(FleetMemberAPI member) {
606 if (member == null) return false;
607 MutableShipStatsAPI stats = member.getStats();
608 return stats != null && stats.getVariant() != null &&
609 stats.getVariant().hasHullMod(HullMods.MILITARIZED_SUBSYSTEMS);
610 }
611
612 public static boolean isCivilian(MutableShipStatsAPI stats) {
613 if (stats == null || stats.getFleetMember() == null) return false;
614 return isCivilian(stats.getFleetMember());
615 }
616
617 public static boolean isCivilian(FleetMemberAPI member) {
618 if (member == null) return false;
619 MutableShipStatsAPI stats = member.getStats();
620 return stats != null && stats.getVariant() != null &&
621 ((stats.getVariant().hasHullMod(HullMods.CIVGRADE) &&
622 !stats.getVariant().hasHullMod(HullMods.MILITARIZED_SUBSYSTEMS)) ||
623 (!stats.getVariant().hasHullMod(HullMods.CIVGRADE) &&
624 stats.getVariant().getHullSpec().getHints().contains(ShipTypeHints.CIVILIAN)));// &&
626 }
627
628 public static boolean hasFighterBays(MutableShipStatsAPI stats) {
629 if (stats == null || stats.getFleetMember() == null) return false;
630 return hasFighterBays(stats.getFleetMember());
631 }
632
633 public static boolean hasFighterBays(FleetMemberAPI member) {
634 if (member == null) return false;
635 MutableShipStatsAPI stats = member.getStats();
636 return stats != null && stats.getNumFighterBays().getModifiedInt() > 0;
637 }
638
639// public static float getTotalOP(MutableShipStatsAPI stats) {
640// FleetDataAPI data = getFleetData(stats);
641// MutableCharacterStatsAPI cStats = getCommanderStats(stats);
642// if (data == null) return 0;
643// return getTotalOP(data, cStats);
644// }
645
646 protected static float getPoints(FleetMemberAPI member, MutableCharacterStatsAPI stats) {
647 if (USE_RECOVERY_COST) {
648 return member.getDeploymentPointsCost();
649 }
650 return member.getHullSpec().getOrdnancePoints(stats);
651 }
652
653 public static class FleetMemberPointContrib {
654 public FleetMemberAPI member;
655 public int points;
656 public FleetMemberPointContrib(FleetMemberAPI member, int points) {
657 super();
658 this.member = member;
659 this.points = points;
660 }
661 }
662
663
664 public static float getTotalOP(FleetDataAPI data, MutableCharacterStatsAPI stats) {
665 float op = 0;
666 for (FleetMemberAPI curr : data.getMembersListCopy()) {
667 if (curr.isMothballed()) continue;
668 op += getPoints(curr, stats);
669 }
670 return Math.round(op);
671 }
672
673 public static List<FleetMemberPointContrib> getTotalOPDetail(FleetDataAPI data, MutableCharacterStatsAPI stats) {
674 List<FleetMemberPointContrib> result = new ArrayList<BaseSkillEffectDescription.FleetMemberPointContrib>();
675 for (FleetMemberAPI curr : data.getMembersListCopy()) {
676 if (curr.isMothballed()) continue;
677 int pts = (int) Math.round(getPoints(curr, stats));
678 result.add(new FleetMemberPointContrib(curr, pts));
679 }
680 return result;
681 }
682
683 public static float getTotalCombatOP(FleetDataAPI data, MutableCharacterStatsAPI stats) {
684 float op = 0;
685 for (FleetMemberAPI curr : data.getMembersListCopy()) {
686 if (curr.isMothballed()) continue;
687 if (isCivilian(curr)) continue;
688 op += getPoints(curr, stats);
689 }
690 return Math.round(op);
691 }
692
693 public static List<FleetMemberPointContrib> getTotalCombatOPDetail(FleetDataAPI data, MutableCharacterStatsAPI stats) {
694 List<FleetMemberPointContrib> result = new ArrayList<BaseSkillEffectDescription.FleetMemberPointContrib>();
695 for (FleetMemberAPI curr : data.getMembersListCopy()) {
696 if (curr.isMothballed()) continue;
697 if (isCivilian(curr)) continue;
698 int pts = (int) Math.round(getPoints(curr, stats));
699 result.add(new FleetMemberPointContrib(curr, pts));
700 }
701 return result;
702 }
703
704 public static float getPhaseOP(FleetDataAPI data, MutableCharacterStatsAPI stats) {
705 float op = 0;
706 for (FleetMemberAPI curr : data.getMembersListCopy()) {
707 if (curr.isMothballed()) continue;
708 if (curr.isPhaseShip()) {
709 if (isCivilian(curr)) continue;
710 op += getPoints(curr, stats);
711 }
712 }
713 return Math.round(op);
714 }
715
716 public static List<FleetMemberPointContrib> getPhaseOPDetail(FleetDataAPI data, MutableCharacterStatsAPI stats) {
717 List<FleetMemberPointContrib> result = new ArrayList<BaseSkillEffectDescription.FleetMemberPointContrib>();
718 for (FleetMemberAPI curr : data.getMembersListCopy()) {
719 if (curr.isMothballed()) continue;
720 if (curr.isPhaseShip()) {
721 if (isCivilian(curr)) continue;
722 int pts = (int) Math.round(getPoints(curr, stats));
723 result.add(new FleetMemberPointContrib(curr, pts));
724 }
725 }
726 return result;
727 }
728
729 public static float getMilitarizedOP(FleetDataAPI data, MutableCharacterStatsAPI stats) {
730 float op = 0;
731 for (FleetMemberAPI curr : data.getMembersListCopy()) {
732 if (curr.isMothballed()) continue;
733 if (!isMilitarized(curr)) continue;
734 op += getPoints(curr, stats);
735 }
736 return Math.round(op);
737 }
738
739 public static List<FleetMemberPointContrib> getMilitarizedOPDetail(FleetDataAPI data, MutableCharacterStatsAPI stats) {
740 List<FleetMemberPointContrib> result = new ArrayList<BaseSkillEffectDescription.FleetMemberPointContrib>();
741 for (FleetMemberAPI curr : data.getMembersListCopy()) {
742 if (curr.isMothballed()) continue;
743 if (!isMilitarized(curr)) continue;
744 int pts = (int) Math.round(getPoints(curr, stats));
745 result.add(new FleetMemberPointContrib(curr, pts));
746 }
747 return result;
748 }
749
750 public static float getNumFighterBays(FleetDataAPI data) {
751 if (data == null) return FIGHTER_BAYS_THRESHOLD;
752 float bays = 0;
753 for (FleetMemberAPI curr : data.getMembersListCopy()) {
754 if (curr.isMothballed()) continue;
755 bays += getNumBaysIncludingModules(curr);
756 //bays += curr.getNumFlightDecks();
757 }
758 return bays;
759 }
760
761 public static float getNumBaysIncludingModules(FleetMemberAPI member) {
762 float bays = 0f;
763 bays += member.getNumFlightDecks();
764 if (member.getVariant().getModuleSlots() != null) {
765 for (String slotId : member.getVariant().getModuleSlots()) {
766 if (slotId == null) continue;
767 ShipVariantAPI variant = member.getVariant().getModuleVariant(slotId);
768 if (variant == null) continue;
769 bays += variant.getHullSpec().getFighterBays();
770 }
771 }
772 return bays;
773 }
774
775 public static List<FleetMemberPointContrib> getNumFighterBaysDetail(FleetDataAPI data) {
776 List<FleetMemberPointContrib> result = new ArrayList<BaseSkillEffectDescription.FleetMemberPointContrib>();
777 for (FleetMemberAPI curr : data.getMembersListCopy()) {
778 if (curr.isMothballed()) continue;
779 //int pts = curr.getNumFlightDecks();
780 int pts = (int)Math.round(getNumBaysIncludingModules(curr));
781 if (pts <= 0) continue;
782 result.add(new FleetMemberPointContrib(curr, pts));
783 }
784 return result;
785 }
786
787 public static float getAutomatedPoints(FleetDataAPI data, MutableCharacterStatsAPI stats) {
788 float points = 0;
789 for (FleetMemberAPI curr : data.getMembersListCopy()) {
790 if (curr.isMothballed()) continue;
791 if (!Misc.isAutomated(curr)) continue;
792 if (Automated.isAutomatedNoPenalty(curr)) continue;
793 float mult = 1f;
794 //if (curr.getCaptain().isAICore()) {
795 points += curr.getCaptain().getMemoryWithoutUpdate().getFloat(AICoreOfficerPlugin.AUTOMATED_POINTS_VALUE);
796 mult = curr.getCaptain().getMemoryWithoutUpdate().getFloat(AICoreOfficerPlugin.AUTOMATED_POINTS_MULT);
797 if (mult == 0) mult = 1;
798 //}
799 points += Math.round(getPoints(curr, stats) * mult);
800 }
801 return Math.round(points);
802 }
803
804 public static List<FleetMemberPointContrib> getAutomatedPointsDetail(FleetDataAPI data, MutableCharacterStatsAPI stats) {
805 List<FleetMemberPointContrib> result = new ArrayList<BaseSkillEffectDescription.FleetMemberPointContrib>();
806 for (FleetMemberAPI curr : data.getMembersListCopy()) {
807 if (curr.isMothballed()) continue;
808 if (!Misc.isAutomated(curr)) continue;
809 if (Automated.isAutomatedNoPenalty(curr)) continue;
810 float mult = 1f;
811 int pts = (int) Math.round(getPoints(curr, stats));
812 //if (curr.getCaptain().isAICore()) {
813 pts += (int) Math.round(curr.getCaptain().getMemoryWithoutUpdate().getFloat(AICoreOfficerPlugin.AUTOMATED_POINTS_VALUE));
814 mult = curr.getCaptain().getMemoryWithoutUpdate().getFloat(AICoreOfficerPlugin.AUTOMATED_POINTS_MULT);
815 if (mult == 0) mult = 1;
816 //}
817 result.add(new FleetMemberPointContrib(curr, Math.round(pts * mult)));
818 }
819 return result;
820 }
821
822 public static boolean isInCampaign() {
823 return Global.getCurrentState() == GameState.CAMPAIGN &&
824 Global.getSector() != null &&
825 Global.getSector().getPlayerFleet() != null;
826 }
827
828 public static MutableCharacterStatsAPI getCommanderStats(MutableShipStatsAPI stats) {
829 if (stats == null) {
830 if (isInCampaign()) {
831 return Global.getSector().getPlayerStats();
832 }
833 return null;
834 }
835
836 FleetMemberAPI member = stats.getFleetMember();
837 if (member == null) return null;
838 PersonAPI commander = member.getFleetCommanderForStats();
839 if (commander == null) {
840 boolean orig = false;
841 if (member.getFleetData() != null) {
842 orig = member.getFleetData().isForceNoSync();
843 member.getFleetData().setForceNoSync(true);
844 }
845 commander = member.getFleetCommander();
846 if (member.getFleetData() != null) {
847 member.getFleetData().setForceNoSync(orig);
848 }
849 }
850 if (commander != null) {
851 return commander.getStats();
852 }
853 return null;
854 }
855
856 public static FleetDataAPI getFleetData(MutableShipStatsAPI stats) {
857 if (stats == null) {
858 if (isInCampaign()) {
859 return Global.getSector().getPlayerFleet().getFleetData();
860 }
861 return null;
862 }
863 FleetMemberAPI member = stats.getFleetMember();
864 if (member == null) return null;
865 FleetDataAPI data = member.getFleetDataForStats();
866 if (data == null) data = member.getFleetData();
867 return data;
868 }
869
870
871 public boolean hasCustomDescription() {
872 return true;
873 }
874
875 public void createCustomDescription(MutableCharacterStatsAPI stats, SkillSpecAPI skill,
876 TooltipMakerAPI info, float width) {
877 }
878
879 public String getEffectDescription(float level) {
880 return null;
881 }
882
884 return null;
885 }
886
887 public ScopeDescription getScopeDescription() {
888 return null;
889 }
890
891}
static GameState getCurrentState()
Definition Global.java:21
static SectorAPI getSector()
Definition Global.java:59
void createCustomDescription(MutableCharacterStatsAPI stats, SkillSpecAPI skill, TooltipMakerAPI info, float width)
static List< FleetMemberPointContrib > getAutomatedPointsDetail(FleetDataAPI data, MutableCharacterStatsAPI stats)
void addOPThresholdInfo(TooltipMakerAPI info, FleetDataAPI data, MutableCharacterStatsAPI cStats)
static MutableCharacterStatsAPI getCommanderStats(MutableShipStatsAPI stats)
void addPhaseOPThresholdInfo(TooltipMakerAPI info, FleetDataAPI data, MutableCharacterStatsAPI cStats)
static float getTotalOP(FleetDataAPI data, MutableCharacterStatsAPI stats)
static float getPhaseOP(FleetDataAPI data, MutableCharacterStatsAPI stats)
static List< FleetMemberPointContrib > getPhaseOPDetail(FleetDataAPI data, MutableCharacterStatsAPI stats)
void addAutomatedThresholdInfo(TooltipMakerAPI info, FleetDataAPI data, MutableCharacterStatsAPI cStats)
static List< FleetMemberPointContrib > getMilitarizedOPDetail(FleetDataAPI data, MutableCharacterStatsAPI stats)
static List< FleetMemberPointContrib > getTotalOPDetail(FleetDataAPI data, MutableCharacterStatsAPI stats)
static float getMilitarizedOP(FleetDataAPI data, MutableCharacterStatsAPI stats)
void init(MutableCharacterStatsAPI stats, SkillSpecAPI skill)
float computeAndCacheThresholdBonus(MutableShipStatsAPI stats, String key, float maxBonus, ThresholdBonusType type)
TooltipCreator getTooltipCreator(final TooltipCreatorSkillEffectPlugin plugin)
float getThresholdBasedBonus(float maxBonus, float value, float threshold)
static List< FleetMemberPointContrib > getNumFighterBaysDetail(FleetDataAPI data)
void addOPThresholdInfo(TooltipMakerAPI info, FleetDataAPI data, MutableCharacterStatsAPI cStats, float threshold)
float getThresholdBasedRoundedBonus(float maxBonus, float value, float threshold)
static float getTotalCombatOP(FleetDataAPI data, MutableCharacterStatsAPI stats)
void addMilitarizedOPThresholdInfo(TooltipMakerAPI info, FleetDataAPI data, MutableCharacterStatsAPI cStats)
void initElite(MutableCharacterStatsAPI stats, SkillSpecAPI skill)
void addOPThresholdAll(TooltipMakerAPI info, FleetDataAPI data, MutableCharacterStatsAPI cStats, float threshold)
float computeAndCacheThresholdBonus(FleetDataAPI data, MutableCharacterStatsAPI cStats, String key, float maxBonus, ThresholdBonusType type)
static float getPoints(FleetMemberAPI member, MutableCharacterStatsAPI stats)
static float getAutomatedPoints(FleetDataAPI data, MutableCharacterStatsAPI stats)
static List< FleetMemberPointContrib > getTotalCombatOPDetail(FleetDataAPI data, MutableCharacterStatsAPI stats)
void addDescription(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam)