Starsector API
Loading...
Searching...
No Matches
ShipWeaponsGroundRaidObjectivePluginImpl.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.graid;
2
3import java.awt.Color;
4import java.util.Random;
5
6import com.fs.starfarer.api.Global;
7import com.fs.starfarer.api.campaign.CargoAPI;
8import com.fs.starfarer.api.campaign.CargoAPI.CargoItemType;
9import com.fs.starfarer.api.campaign.CargoStackAPI;
10import com.fs.starfarer.api.campaign.FactionAPI;
11import com.fs.starfarer.api.campaign.TextPanelAPI;
12import com.fs.starfarer.api.campaign.econ.CommodityOnMarketAPI;
13import com.fs.starfarer.api.campaign.econ.CommoditySpecAPI;
14import com.fs.starfarer.api.campaign.econ.MarketAPI;
15import com.fs.starfarer.api.combat.WeaponAPI.AIHints;
16import com.fs.starfarer.api.impl.campaign.econ.CommodityIconCounts;
17import com.fs.starfarer.api.impl.campaign.ids.Commodities;
18import com.fs.starfarer.api.impl.campaign.ids.Tags;
19import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.MarketCMD.RaidDangerLevel;
20import com.fs.starfarer.api.loading.FighterWingSpecAPI;
21import com.fs.starfarer.api.loading.HullModSpecAPI;
22import com.fs.starfarer.api.loading.WeaponSpecAPI;
23import com.fs.starfarer.api.ui.IconGroupAPI;
24import com.fs.starfarer.api.ui.IconRenderMode;
25import com.fs.starfarer.api.ui.TooltipMakerAPI;
26import com.fs.starfarer.api.util.Misc;
27import com.fs.starfarer.api.util.WeightedRandomPicker;
28
30
31 public static float CARGO_SPACE_PER_LARGE = 8f;
32 public static float CARGO_SPACE_PER_MEDIUM = 4f;
33 public static float CARGO_SPACE_PER_SMALL = 2f;
34
35 public static float SELL_MULT = Global.getSettings().getFloat("shipWeaponSellPriceMult");
36
37
38 public static float VALUE_NORMAL = 1f;
39 public static float VALUE_EXCESS = 2f;
40 public static float VALUE_DEFICIT = -1f;
41 public static float VALUE_OVERALL = 1000f;
42
44
50
51
52 public void addIcons(IconGroupAPI iconGroup) {
54
55 int deficit = counts.deficit;
56 int available = Math.max(0, counts.available - counts.extra);
57 int extra = counts.extra;
58
59 if (available > 0) {
60 iconGroup.addIconGroup(Commodities.SHIP_WEAPONS, IconRenderMode.NORMAL, available, null);
61 }
62 if (deficit > 0) {
63 iconGroup.addIconGroup(Commodities.SHIP_WEAPONS, IconRenderMode.RED, deficit, null);
64 }
65 if (extra > 0) {
67 }
68 }
69
70// public int getCargoSpaceNeeded() {
71// return (int) getQuantity(getMarinesAssigned());
72// }
73
75 return (int) getQuantity(getMarinesAssigned());
76 }
77
81
82 public RaidDangerLevel getDangerLevel() {
83 RaidDangerLevel danger = getWeaponsCommoditySpec().getBaseDanger();
84
86 if (counts.production >= counts.available) {
87 danger = danger.prev();
88 }
89 if (counts.deficit > 0) {
90 return danger.next();
91 }
92 if (counts.extra > 0) {
93 return danger.prev();
94 }
95
96 if (source != null) {
97 danger = source.adjustCommodityDangerLevel(id, danger);
98 }
99
100 return danger;
101 }
102
103 public float getQuantitySortValue() {
105 float add = 0;
106 if (spec != null) {
107 add = spec.getOrder();
108 }
109 return QUANTITY_SORT_TIER_1 + add;
110 }
111
112 public String getQuantityString(int marines) {
113// int value = (int) getQuantity(Math.max(1, marines));
114// return Misc.getDGSCredits(value);
115 return "";
116 }
117
118 @Override
119 public String getValueString(int marines) {
120 int value = (int) getQuantity(Math.max(1, marines));
121 return Misc.getDGSCredits(value);
122 }
123
124
125 public int getValue(int marines) {
126 return (int) getQuantity(marines);
127 }
128
129 public float getQuantity(int marines) {
130 float base = Math.round(getBaseRaidValue());
131 return base * marines;
132 }
133
134 public float getBaseRaidValue() {
136 float unit = 1f;
137
139
140 float result = 0f;
141
142 result += Math.max(0, counts.available - counts.extra) * unit * VALUE_NORMAL;
143 result += counts.extra * unit * VALUE_EXCESS;
144 result += counts.deficit * unit * VALUE_DEFICIT;
145
146 result *= VALUE_OVERALL;
147
148 if (result < 0) result = 0;
149
150 return result;
151 }
152
153 public String getName() {
155 }
156
158 CargoStackAPI stack = Global.getFactory().createCargoStack(CargoItemType.RESOURCES, Commodities.SHIP_WEAPONS, null);
159 return stack;
160 }
161
163 return com.getId();
164 }
165
167
168 protected float getQMult(int tier) {
169 if (tier <= 0) return 0f;
170 if (tier <= 1) return 0.25f;
171 if (tier <= 2) return 0.5f;
172 return 0.75f;
173 }
174
175 public int performRaid(CargoAPI loot, Random random, float lootMult, TextPanelAPI text) {
176 if (marinesAssigned <= 0) return 0;
177
178 //random = new Random();
179
183
186
187 String factionId = market.getFactionId();
188 float quality = Misc.getShipQuality(market, factionId);
189 FactionAPI faction = Global.getSector().getFaction(factionId);
190
191 int maxTier = 0;
192 if (market.getSize() >= 6) {
193 maxTier = 1;
194 }
196 maxTier = 1000;
197 }
198
199 float numSmall = 0;
200 float numMedium = 0;
201 float numLarge = 0;
202 for (String id : faction.getKnownWeapons()) {
204 switch (spec.getSize()) {
205 case LARGE:
206 numLarge++;
207 break;
208 case MEDIUM:
209 numMedium++;
210 break;
211 case SMALL:
212 numSmall++;
213 break;
214 }
215 }
216 float numTotal = numSmall + numMedium + numLarge + 1f;
217
218 for (String id : faction.getKnownWeapons()) {
220 if (spec.getAIHints().contains(AIHints.SYSTEM)) continue;
221 if (spec.getTier() > maxTier) continue;
222
223 float p = 1f * spec.getRarity() + quality * getQMult(spec.getTier());
224 switch (spec.getSize()) {
225 case LARGE:
226 p *= 1f - numLarge / numTotal;
227 p *= 2f;
228 break;
229 case MEDIUM:
230 p *= 1f - numMedium / numTotal;
231 p *= 3f;
232 break;
233 case SMALL:
234 p *= 1f - numSmall / numTotal;
235 p *= 4f;
236 break;
237 }
238 pickerW.add(spec, p);
239 }
240 for (int i = 0; i < 4 + marinesAssigned; i++) {
241 WeaponSpecAPI spec = pickerW.pick();
242 if (spec != null) {
243 float w = pickerW.getWeight(spec);
244 weaponSubset.add(spec, w);
245 pickerW.remove(spec);
246 }
247 }
248
249 for (String id : faction.getKnownFighters()) {
251 if (spec.getTier() > maxTier) continue;
252
253 float p = 1f * spec.getRarity() + quality * getQMult(spec.getTier());
254 pickerF.add(spec, p);
255 }
256 for (int i = 0; i < 2 + marinesAssigned/2; i++) {
257 FighterWingSpecAPI spec = pickerF.pick();
258 if (spec != null) {
259 float w = pickerF.getWeight(spec);
260 fighterSubset.add(spec, w);
261 pickerF.remove(spec);
262 }
263 }
264
265 for (String id : faction.getKnownHullMods()) {
267 if (spec.isHidden()) continue;
268 if (spec.isAlwaysUnlocked()) continue;
269 if (spec.hasTag(Tags.NO_DROP)) continue;
270 if (spec.getTier() > maxTier) continue;
271
272 float p = 1f * spec.getRarity();
274 p *= 0.2f;
275 }
276 pickerH.add(spec, p);
277 }
278
279
280 float targetValue = getQuantity(marinesAssigned);
281 targetValue *= lootMult;
282 float mult = 0.9f + random.nextFloat() * 0.2f;
283 targetValue *= mult;
284
285 quantityLooted = (int) targetValue;
286
287 float weaponWeight = faction.getDoctrine().getWarships() + faction.getDoctrine().getPhaseShips();
288 float fighterWeight = 1f + faction.getDoctrine().getCarriers();
289 float hullmodWeight = 1f + quality * 1f;
290 float totalWeight = weaponWeight + fighterWeight + hullmodWeight;
291
292 float weaponValue = targetValue * weaponWeight / totalWeight;
293 float fighterValue = targetValue * fighterWeight / totalWeight;
294 float hullmodValue = targetValue * hullmodWeight / totalWeight;
295
296 float totalValue = 0;
297
298 looted.clear();
299
300 int tries = 0;
301 while (weaponValue > 0 && tries < 100) {
302 tries++;
303 WeaponSpecAPI weapon = weaponSubset.pick();
304 if (weapon != null) {
305 int min = 1, max = 2;
306 // don't do this since the odds of rolling large are smaller than medium smaller than small etc
307// switch (weapon.getSize()) {
308// case LARGE: min = 1; max = 2; break;
309// case MEDIUM: min = 1; max = 4; break;
310// case SMALL: min = 2; max = 6; break;
311// }
312 float val = weapon.getBaseValue() * SELL_MULT;
313 int num = min + random.nextInt(max - min + 1);
314 num = (int) Math.min(num, weaponValue / val);
315 if (num == 0) {
316 if (random.nextFloat() < weaponValue / val) num = 1;
317 }
318 if (num > 0) {
319 looted.addWeapons(weapon.getWeaponId(), num);
320 weaponValue -= val * num;
321 totalValue += val * num;
322 } else {
323 break;
324 }
325 } else {
326 break;
327 }
328 }
329
330 fighterValue += Math.max(0, weaponValue);
331
332 tries = 0;
333 while (fighterValue > 0 && tries < 100) {
334 tries++;
335 FighterWingSpecAPI fighter = fighterSubset.pick();
336 if (fighter != null) {
337 int min = 1, max = 2;
338 switch (fighter.getRole()) {
339 case ASSAULT:
340 case BOMBER:
341 case SUPPORT:
342 min = 1; max = 2;
343 break;
344 case FIGHTER:
345 min = 1; max = 3;
346 break;
347 case INTERCEPTOR:
348 min = 1; max = 4;
349 break;
350 }
351 float val = fighter.getBaseValue() * SELL_MULT;
352 int num = min + random.nextInt(max - min + 1);
353 num = (int) Math.min(num, fighterValue / val);
354 if (num == 0) {
355 if (random.nextFloat() < fighterValue / val) num = 1;
356 }
357 if (num > 0) {
358 looted.addFighters(fighter.getId(), num);
359 fighterValue -= val * num;
360 totalValue += val * num;
361 } else {
362 break;
363 }
364 } else {
365 break;
366 }
367 }
368
369 hullmodValue += Math.max(0, fighterValue);
370
371 tries = 0;
372 while (hullmodValue > 0 && tries < 100) {
373 tries++;
374 HullModSpecAPI mod = pickerH.pickAndRemove();
375 if (mod != null) {
376 float val = mod.getBaseValue();
377 int num = 0;
378 if (random.nextFloat() < hullmodValue / val) num = 1;
379 if (num > 0) {
380 looted.addHullmods(mod.getId(), num);
381 hullmodValue -= val * num;
382 totalValue += val * num;
383 } else {
384 break;
385 }
386 } else {
387 break;
388 }
389 }
390
391 loot.addAll(looted);
392
393 xpGained = (int) (totalValue * XP_GAIN_VALUE_MULT);
394 return xpGained;
395 }
396
397
398
399 @Override
400 public boolean hasTooltip() {
401 return true;
402 }
403
404 @Override
405 public void createTooltip(TooltipMakerAPI t, boolean expanded) {
406 float opad = 10f;
407 float pad = 3f;
408 Color h = Misc.getHighlightColor();
409 Color bad = Misc.getNegativeHighlightColor();
410 Color good = Misc.getPositiveHighlightColor();
411
413
414 t.addPara("Ship weapons, fighter LPCs, and hullmod specs. Availability is based on the " +
415 "\"" + com.getCommodity().getName() + "\" commodity.", 0f);
416 t.addPara("The colony faction's doctrine affects the number of weapons vs fighter LPCs acquired. Higher ship quality " +
417 "increases the probability of finding modspecs..", opad);
418 //t.addPara("The \"projected value\" is the typical sell value of the equipment acquired.", opad);
419
422 t.addPara("This colony has heavy industry and high-tier equipment may be found.", good, opad);
423 } else if (Misc.isMilitary(market)) {
424 t.addPara("This colony has a military presence and high-tier equipment may be found.", good, opad);
425 }
426 } else {
427 t.addPara("This colony does not have heavy industry or a military presence and has no access to high-tier ship equipment.", bad, opad);
428 }
429
430 // weapons fighters and hullmods
431 // based on S&W
432 // impact of doctrine
433 // impact of ship quality
434 // how hullmods get rolled
435 // impact of assigning more marines, explain that more marines = more stuff despite "variable"
436 // whether it has military or production, or size >= 6
437 }
438
439
440
441
442
444 return looted;
445 }
446
447
448
449}
450
451
452
453
454
455
456
457
static SettingsAPI getSettings()
Definition Global.java:57
static FactoryAPI getFactory()
Definition Global.java:41
static SectorAPI getSector()
Definition Global.java:65
static String getDGSCredits(float num)
Definition Misc.java:1390
static boolean hasHeavyIndustry(MarketAPI market)
Definition Misc.java:5049
static Color getNegativeHighlightColor()
Definition Misc.java:802
static Color getHighlightColor()
Definition Misc.java:792
static float getShipQuality(MarketAPI market)
Definition Misc.java:4505
static Color getPositiveHighlightColor()
Definition Misc.java:822
static boolean isMilitary(MarketAPI market)
Definition Misc.java:5045
CargoAPI createCargo(boolean unlimitedStacks)
CargoStackAPI createCargoStack(CargoItemType type, Object data, CargoAPI cargo)
HullModSpecAPI getHullModSpec(String modId)
CommoditySpecAPI getCommoditySpec(String commodityId)
FighterWingSpecAPI getFighterWingSpec(String wingId)
WeaponSpecAPI getWeaponSpec(String weaponId)
void addHullmods(String id, int count)
void addWeapons(String id, int count)
void addFighters(String id, int count)
FactionAPI getFaction(String factionId)
RaidDangerLevel adjustCommodityDangerLevel(String commodityId, RaidDangerLevel level)
CommodityOnMarketAPI getCommodityData(String commodityId)
EnumSet< WeaponAPI.AIHints > getAIHints()
void addIconGroup(String commodityId, IconRenderMode mode, int count, Object custom)
LabelAPI addPara(String format, float pad, Color hl, String... highlights)