Starsector API
Loading...
Searching...
No Matches
BallisticRangefinder.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.hullmods;
2
3import java.awt.Color;
4
5import com.fs.starfarer.api.Global;
6import com.fs.starfarer.api.combat.BaseHullMod;
7import com.fs.starfarer.api.combat.MutableShipStatsAPI;
8import com.fs.starfarer.api.combat.ShipAPI;
9import com.fs.starfarer.api.combat.ShipAPI.HullSize;
10import com.fs.starfarer.api.combat.WeaponAPI;
11import com.fs.starfarer.api.combat.WeaponAPI.AIHints;
12import com.fs.starfarer.api.combat.WeaponAPI.WeaponSize;
13import com.fs.starfarer.api.combat.WeaponAPI.WeaponType;
14import com.fs.starfarer.api.combat.listeners.WeaponBaseRangeModifier;
15import com.fs.starfarer.api.loading.WeaponSlotAPI;
16import com.fs.starfarer.api.ui.Alignment;
17import com.fs.starfarer.api.ui.TooltipMakerAPI;
18import com.fs.starfarer.api.util.Misc;
19
20public class BallisticRangefinder extends BaseHullMod {
21
22 public static float BONUS_MAX_1 = 800;
23 public static float BONUS_MAX_2 = 800;
24 public static float BONUS_MAX_3 = 900;
25 public static float BONUS_SMALL_1 = 100;
26 public static float BONUS_SMALL_2 = 100;
27 public static float BONUS_SMALL_3 = 200;
28 public static float BONUS_MEDIUM_3 = 100;
29
30 public static float HYBRID_MULT = 2f;
31 public static float HYBRID_BONUS_MIN = 100f;
32
33
34 public void applyEffectsBeforeShipCreation(HullSize hullSize, MutableShipStatsAPI stats, String id) {
35 }
36
37 public static WeaponSize getLargestBallisticSlot(ShipAPI ship) {
38 if (ship == null) return null;
39 WeaponSize largest = null;
40 for (WeaponSlotAPI slot : ship.getHullSpec().getAllWeaponSlotsCopy()) {
41 if (slot.isDecorative() ) continue;
42 if (slot.getWeaponType() == WeaponType.BALLISTIC) {
43 if (largest == null || largest.ordinal() < slot.getSlotSize().ordinal()) {
44 largest = slot.getSlotSize();
45 }
46 }
47 }
48 return largest;
49 }
50
51 @Override
52 public void applyEffectsAfterShipCreation(ShipAPI ship, String id) {
53 WeaponSize largest = getLargestBallisticSlot(ship);
54 if (largest == null) return;
55 float small = 0f;
56 float medium = 0f;
57 float max = 0f;
58 switch (largest) {
59 case LARGE:
60 small = BONUS_SMALL_3;
61 medium = BONUS_MEDIUM_3;
62 max = BONUS_MAX_3;
63 break;
64 case MEDIUM:
65 small = BONUS_SMALL_2;
66 max = BONUS_MAX_2;
67 break;
68 case SMALL:
69 small = BONUS_SMALL_1;
70 max = BONUS_MAX_1;
71 break;
72 }
73
74 ship.addListener(new RangefinderRangeModifier(small, medium, max));
75 }
76
77 public static class RangefinderRangeModifier implements WeaponBaseRangeModifier {
78 public float small, medium, max;
79 public RangefinderRangeModifier(float small, float medium, float max) {
80 this.small = small;
81 this.medium = medium;
82 this.max = max;
83 }
84
85 public float getWeaponBaseRangePercentMod(ShipAPI ship, WeaponAPI weapon) {
86 return 0;
87 }
88 public float getWeaponBaseRangeMultMod(ShipAPI ship, WeaponAPI weapon) {
89 return 1f;
90 }
91 public float getWeaponBaseRangeFlatMod(ShipAPI ship, WeaponAPI weapon) {
92// if (weapon.getSlot() == null || weapon.getSlot().getWeaponType() != WeaponType.BALLISTIC) {
93// return 0f;
94// }
95 if (weapon.getSpec() == null) {
96 return 0f;
97 }
98 if (weapon.getSpec().getMountType() != WeaponType.BALLISTIC &&
99 weapon.getSpec().getMountType() != WeaponType.HYBRID) {
100 return 0f;
101 }
102 if (weapon.hasAIHint(AIHints.PD)) {
103 return 0f;
104 }
105
106 float bonus = 0;
107 if (weapon.getSize() == WeaponSize.SMALL) {
108 bonus = small;
109 } else if (weapon.getSize() == WeaponSize.MEDIUM) {
110 bonus = medium;
111 }
112 if (weapon.getSpec().getMountType() == WeaponType.HYBRID) {
113 bonus *= HYBRID_MULT;
114 if (bonus < HYBRID_BONUS_MIN) {
115 bonus = HYBRID_BONUS_MIN;
116 }
117 }
118 if (bonus == 0f) return 0f;
119
120 float base = weapon.getSpec().getMaxRange();
121 if (base + bonus > max) {
122 bonus = max - base;
123 }
124 if (bonus < 0) bonus = 0;
125 return bonus;
126 }
127 }
128
129 public String getDescriptionParam(int index, HullSize hullSize) {
130 //if (index == 0) return "" + (int)RANGE_PENALTY_PERCENT + "%";
131 return null;
132 }
133
134 @Override
135 public boolean shouldAddDescriptionToTooltip(HullSize hullSize, ShipAPI ship, boolean isForModSpec) {
136 return false;
137 }
138
139 @Override
140 public void addPostDescriptionSection(TooltipMakerAPI tooltip, HullSize hullSize, ShipAPI ship, float width, boolean isForModSpec) {
141 float pad = 3f;
142 float opad = 10f;
143 Color h = Misc.getHighlightColor();
144 Color bad = Misc.getNegativeHighlightColor();
145 Color t = Misc.getTextColor();
146 Color g = Misc.getGrayColor();
147
148 WeaponSize largest = getLargestBallisticSlot(ship);
149
150// LabelAPI label = tooltip.addPara("If the largest Ballistic slot on the ship is large:"
151// + " increases the base range of small weapons in Ballistic slots by %s,"
152// + " and of medium weapons by %s, up to %s maximum.", opad, h,
153// "" + (int)BONUS_SMALL_3, "" + (int)BONUS_MEDIUM_3, "" + (int)BONUS_MAX_3);
156// label.setHighlight("" + (int)BONUS_SMALL_3, "" + (int)BONUS_MEDIUM_3, "" + (int)BONUS_MAX_3);
157// label.setHighlightColors(h, h, h);
158// if (largest != null && largest != WeaponSize.LARGE) {
159// label.setColor(Misc.getGrayColor());
160// }
161//
162// label = tooltip.addPara("Otherwise:"
163// + " increases the base range of small weapons in Ballistic slots by %s,"
164// + " up to %s maximum.", opad, h,
165// "" + (int)BONUS_SMALL_1, "" + (int)BONUS_MAX_1);
168// label.setHighlight("" + (int)BONUS_SMALL_1, "" + (int)BONUS_MAX_1);
169// label.setHighlightColors(h, h);
170// if (largest != null && largest == WeaponSize.LARGE) {
171// label.setColor(Misc.getGrayColor());
172// }
173//
177//
178// tooltip.addSectionHeading("Exceptions", Alignment.MID, opad);
179// label = tooltip.addPara("Does not affect point-defense weapons, "
180// + "or Ballistic weapons in Composite, Hybrid, and Universal slots.", opad);
183// label.setHighlight("Composite", "Hybrid", "Universal");
184// label.setHighlightColors(Misc.MOUNT_COMPOSITE, Misc.MOUNT_HYBRID, Misc.MOUNT_UNIVERSAL);
185//
186// label = tooltip.addPara("Hybrid weapons in Ballistic slots receive %s the bonus. "
189// + "In addition, the range bonus for all non-PD Hybrid weapons in Ballistic slots will be at least %s, "
190// + "regardless of size or other factors, but still subject to the maximum.", opad, h,
193// "" + (int)Math.round(HYBRID_MULT) + Strings.X, "" + (int)Math.round(HYBRID_BONUS_MIN));
196// label.setHighlight("Hybrid", "" + (int)Math.round(HYBRID_MULT) + Strings.X, "Hybrid", "" + (int)Math.round(HYBRID_BONUS_MIN));
197// label.setHighlightColors(Misc.MOUNT_HYBRID, h, Misc.MOUNT_HYBRID, h);
198
199
200
201 tooltip.addPara("Utilizes targeting data from the ship's largest ballistic slot "
202 + "to benefit certain weapons, extending the base range of "
203 + "typical ballistic weapons to match similar but larger weapons. "
204 + "Greatly benefits hybrid weapons. Point-defense weapons are unaffected.",
205 opad, h, "ship's largest ballistic slot", "base range", "Greatly benefits hybrid weapons");
206
207 //tooltip.addPara("The maximum range is capped, based on the largest slot.", opad);
208 tooltip.addPara("The range bonus is based on the size of the largest ballistic slot, "
209 + "and the increased base range is capped, but still subject to other modifiers.", opad);
210
211// tooltip.addPara("Affects small and medium ballistic weapons, and all hybrid weapons. "
212// + "Point-defense weapons are not affected.", opad, h,
213// "");
214 //"small and medium", "hybrid", "Point-defense");
215
216 tooltip.addSectionHeading("Ballistic weapon range", Alignment.MID, opad);
217
218
219 tooltip.addPara("Affects small and medium ballistic weapons.", opad);
220
221 float col1W = 120;
222 float colW = (int) ((width - col1W - 12f) / 3f);
223 float lastW = colW;
224
226 20f, true, true,
227 new Object [] {"Largest b. slot", col1W, "Small wpn", colW, "Medium wpn", colW, "Range cap", lastW});
228
229 Color reallyG = g;
231 g = h;
232 }
233
234 Color c = null;
235 if (largest == WeaponSize.SMALL) c = h;
236 else if (largest == WeaponSize.MEDIUM) c = h;
237 else c = g;
238
239
240 tooltip.addRow(Alignment.MID, c, "Small / Medium",
241 Alignment.MID, c, "+" + (int) BONUS_SMALL_1,
242 Alignment.MID, reallyG, "---",
243 Alignment.MID, c, "" + (int)BONUS_MAX_1);
244
245 if (largest == WeaponSize.LARGE) c = h;
246 else c = g;
247 tooltip.addRow(Alignment.MID, c, "Large",
248 Alignment.MID, c, "+" + (int) BONUS_SMALL_3,
249 Alignment.MID, c, "+" + (int) BONUS_MEDIUM_3,
250 Alignment.MID, c, "" + (int)BONUS_MAX_3);
251
252 tooltip.addTable("", 0, opad);
253
254
255 tooltip.addSectionHeading("Hybrid weapon range", Alignment.MID, opad + 7f);
256
257 tooltip.addPara("Affects hybrid weapons (those that can fit into both ballistic and energy slots)"
258 + " of all sizes.", opad);
259
260 col1W = 120;
261 colW = (int) ((width - col1W - lastW - 15f) / 3f);
262
264 20f, true, true,
265 new Object [] {"Largest b. slot", col1W, "Small", colW, "Medium", colW, "Large", colW, "Range cap", lastW});
266
267
268 c = null;
269 if (largest == WeaponSize.SMALL) c = h;
270 else if (largest == WeaponSize.MEDIUM) c = h;
271 else c = g;
272 tooltip.addRow(Alignment.MID, c, "Small / Medium",
273 Alignment.MID, c, "+" + (int) (BONUS_SMALL_1 * HYBRID_MULT),
274 Alignment.MID, c, "+" + (int) HYBRID_BONUS_MIN,
275 Alignment.MID, c, "+" + (int) HYBRID_BONUS_MIN,
276 Alignment.MID, c, "" + (int)BONUS_MAX_1);
277
278 if (largest == WeaponSize.LARGE) c = h;
279 else c = g;
280 tooltip.addRow(Alignment.MID, c, "Large",
281 Alignment.MID, c, "+" + (int) (BONUS_SMALL_3 * HYBRID_MULT),
282 Alignment.MID, c, "+" + (int) (BONUS_MEDIUM_3 * HYBRID_MULT),
283 Alignment.MID, c, "+" + (int) HYBRID_BONUS_MIN,
284 Alignment.MID, c, "" + (int)BONUS_MAX_3);
285
286 tooltip.addTable("", 0, opad);
287
288
289 tooltip.addSectionHeading("Interactions with other modifiers", Alignment.MID, opad + 7f);
290 tooltip.addPara("Since the base range is increased, this modifier"
291 + " - unlike most other flat modifiers - "
292 + "is increased by percentage modifiers from other hullmods and skills.", opad);
293 }
294
295 public float getTooltipWidth() {
296 return 412f;
297 }
298
299 @Override
300 public boolean isApplicableToShip(ShipAPI ship) {
301 WeaponSize largest = getLargestBallisticSlot(ship);
302 if (ship != null && largest == null) {
303 return false;
304 }
305 return getUnapplicableReason(ship) == null;
306 }
307
308 public String getUnapplicableReason(ShipAPI ship) {
309 WeaponSize largest = getLargestBallisticSlot(ship);
310 if (ship != null && largest == null) {
311 return "Ship has no ballistic weapon slots";
312 }
313 if (ship != null &&
314 ship.getHullSize() != HullSize.CAPITAL_SHIP &&
315 ship.getHullSize() != HullSize.DESTROYER &&
316 ship.getHullSize() != HullSize.CRUISER) {
317 return "Can only be installed on destroyer-class hulls and larger";
318 }
319 return null;
320 }
321
322}
323
324
325
326
327
328
329
330
331
static boolean CODEX_TOOLTIP_MODE
Definition Global.java:15
void applyEffectsBeforeShipCreation(HullSize hullSize, MutableShipStatsAPI stats, String id)
void addPostDescriptionSection(TooltipMakerAPI tooltip, HullSize hullSize, ShipAPI ship, float width, boolean isForModSpec)
boolean shouldAddDescriptionToTooltip(HullSize hullSize, ShipAPI ship, boolean isForModSpec)
static Color getTextColor()
Definition Misc.java:839
static Color getNegativeHighlightColor()
Definition Misc.java:802
static Color getBasePlayerColor()
Definition Misc.java:833
static Color getGrayColor()
Definition Misc.java:826
static Color getBrightPlayerColor()
Definition Misc.java:830
static Color getHighlightColor()
Definition Misc.java:792
static Color getDarkPlayerColor()
Definition Misc.java:836
void addListener(Object listener)
List< WeaponSlotAPI > getAllWeaponSlotsCopy()
void addTable(String emptyText, int andMore, float pad)
UIPanelAPI beginTable(FactionAPI faction, float itemHeight, Object ... columns)
LabelAPI addPara(String format, float pad, Color hl, String... highlights)
LabelAPI addSectionHeading(String str, Alignment align, float pad)