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