Starsector API
Loading...
Searching...
No Matches
GenericRaidFGI.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.intel.group;
2
3import java.util.ArrayList;
4import java.util.List;
5import java.util.Random;
6import java.util.Set;
7
8import java.awt.Color;
9
10import org.lwjgl.util.vector.Vector2f;
11
12import com.fs.starfarer.api.Global;
13import com.fs.starfarer.api.campaign.CampaignFleetAPI;
14import com.fs.starfarer.api.campaign.FactionAPI;
15import com.fs.starfarer.api.campaign.SectorEntityToken;
16import com.fs.starfarer.api.campaign.StarSystemAPI;
17import com.fs.starfarer.api.campaign.econ.MarketAPI;
18import com.fs.starfarer.api.impl.campaign.ids.Factions;
19import com.fs.starfarer.api.impl.campaign.intel.group.FGRaidAction.FGRaidParams;
20import com.fs.starfarer.api.impl.campaign.missions.FleetCreatorMission;
21import com.fs.starfarer.api.impl.campaign.missions.FleetCreatorMission.FleetStyle;
22import com.fs.starfarer.api.impl.campaign.missions.hub.BaseHubMission;
23import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers.ComplicationRepImpact;
24import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.MarketCMD.BombardType;
25import com.fs.starfarer.api.ui.Alignment;
26import com.fs.starfarer.api.ui.LabelAPI;
27import com.fs.starfarer.api.ui.SectorMapAPI;
28import com.fs.starfarer.api.ui.TooltipMakerAPI;
29import com.fs.starfarer.api.util.Misc;
30import com.fs.starfarer.api.util.WeightedRandomPicker;
31
32public class GenericRaidFGI extends FleetGroupIntel {
33
34 public static String PREPARE_ACTION = "prepare_action";
35 public static String TRAVEL_ACTION = "travel_action";
36 public static String PAYLOAD_ACTION = "payload_action";
37 public static String RETURN_ACTION = "return_action";
38
39
40 public static interface GenericPayloadAction extends FGAction {
41 Color getSystemNameHighlightColor();
42 float getSuccessFraction();
43 StarSystemAPI getWhere();
44
45 }
46
47 public static class GenericRaidParams {
48 public Random random = new Random();
49 public boolean playerTargeted;
50 public boolean remnant = false;
51 public MarketAPI source;
52 public String factionId;
53 public List<Integer> fleetSizes = new ArrayList<Integer>();
54 public FleetStyle style = FleetStyle.STANDARD;
55 public FGRaidParams raidParams = new FGRaidParams();
56 public float prepDays = 5f;
57 public float payloadDays = 30f;
58 public boolean makeFleetsHostile = true;
59 public ComplicationRepImpact repImpact = ComplicationRepImpact.LOW;
60 public String noun;
61 public String forcesNoun;
62 public Object custom;
63 public String memoryKey = null;
64
65 public GenericRaidParams(Random random, boolean playerTargeted) {
66 this.random = random;
67 this.playerTargeted = playerTargeted;
68 //makeFleetsHostile = playerTargeted; // now supported: making fleets hostile to arbitrary factions
69 }
70
71 }
72
73 protected GenericRaidParams params;
75 protected GenericPayloadAction raidAction;
79
80 public static GenericRaidFGI get(String key) {
82 }
83
84 public GenericRaidFGI(GenericRaidParams params) {
85 if (params != null) {
86 this.params = params;
87 setRandom(params.random);
89
90 if (params.memoryKey != null) {
92 }
93 }
94 }
95
96 @Override
97 protected void notifyEnding() {
98 super.notifyEnding();
99 if (params != null && params.memoryKey != null) {
101 }
102 }
103
104 protected void initActions() {
105 setFaction(params.factionId);
106 waitAction = new FGWaitAction(params.source.getPrimaryEntity(), params.prepDays,
107 "preparing for departure");
109
111
113 raidAction.getWhere().getCenter());
114
117
118 SectorEntityToken returnWhere = params.source.getPrimaryEntity();
119 if (returnWhere.getStarSystem() != null) {
120 returnWhere = returnWhere.getStarSystem().getCenter();
121 }
123 params.source.getPrimaryEntity());
124 returnAction.setTravelText("returning to " + params.source.getPrimaryEntity().getName());
126
127 origin = params.source.getPrimaryEntity();
128
129 int total = 0;
130 for (Integer i : params.fleetSizes) total += i;
131 createRoute(params.factionId, total, params.fleetSizes.size(), null, params);
132 }
133
134 protected GenericPayloadAction createPayloadAction() {
135 return new FGRaidAction(params.raidParams, params.payloadDays);
136 }
137
138 protected void spawnFleets() {
139
140 Float damage = null;
141 if (route != null && route.getExtra() != null) {
142 damage = route.getExtra().damage;
143 }
144 if (damage == null) damage = 0f;
145
147 picker.addAll(params.fleetSizes);
148
149 int total = 0;
150 for (Integer i : params.fleetSizes) total += i;
151
152 float spawnsToSkip = total * damage * 0.5f;
153 float skipped = 0f;
154
155 //FactionAPI faction = Global.getSector().getFaction(params.factionId);
156
157// picker.add(1);
158// picker.add(1);
159
160 while (!picker.isEmpty()) {
161 Integer size = picker.pickAndRemove();
162 if (skipped < spawnsToSkip && getRandom().nextFloat() < damage) {
163 skipped += size;
164 continue;
165 }
166
167 CampaignFleetAPI fleet = createFleet(size, damage);
168
169 if (fleet != null && route != null) {
170 setLocationAndCoordinates(fleet, route.getCurrent());
171 fleets.add(fleet);
172 }
173 }
174 }
175
176 protected CampaignFleetAPI createFleet(int size, float damage) {
177 Vector2f loc = origin.getLocationInHyperspace();
179
181
182 preConfigureFleet(size, m);
183
184 m.beginFleet();
185
186 String factionId = getFleetCreationFactionOverride(size);
187 if (factionId == null) factionId = params.factionId;
188
189 m.createFleet(params.style, size, factionId, loc);
190 m.triggerSetFleetFaction(params.factionId);
191
192 m.setFleetSource(params.source);
194 m.setFleetDamageTaken(damage);
195 if (pirate) {
197 } else {
199 }
200
201 if (params.remnant) {
203 }
204
205 if (params.makeFleetsHostile) {
206 for (MarketAPI market : params.raidParams.allowedTargets) {
208 }
210 if (Factions.LUDDIC_PATH.equals(faction.getId())) {
212 }
213 }
214
215 if (params.repImpact == ComplicationRepImpact.LOW || params.repImpact == null) {
217 } else if (params.repImpact == ComplicationRepImpact.NONE) {
219 }
220
221 if (params.repImpact != ComplicationRepImpact.FULL) {
223 }
224
225 configureFleet(size, m);
226
227 CampaignFleetAPI fleet = m.createFleet();
228 if (fleet != null) {
229 configureFleet(size, fleet);
230 }
231
232 return fleet;
233 }
234
235 protected String getFleetCreationFactionOverride(int size) {
236 return null;
237 }
238
239 protected void preConfigureFleet(int size, FleetCreatorMission m) {
240
241 }
242 protected void configureFleet(int size, FleetCreatorMission m) {
243
244 }
245
246 protected void configureFleet(int size, CampaignFleetAPI fleet) {
247
248 }
249
250 protected void addTargetingBulletPoint(TooltipMakerAPI info, Color tc, Object param, ListInfoMode mode, float initPad) {
251 StarSystemAPI system = raidAction.getWhere();
252 Color s = raidAction.getSystemNameHighlightColor();
253 LabelAPI label = info.addPara("Targeting the " + system.getNameWithLowercaseTypeShort(), tc, initPad);
254 label.setHighlightColors(s);
255 label.setHighlight(system.getNameWithNoType());
256 }
257
258 protected void addNonUpdateBulletPoints(TooltipMakerAPI info, Color tc, Object param, ListInfoMode mode, float initPad) {
259 Color h = Misc.getHighlightColor();
260 Color s = raidAction.getSystemNameHighlightColor();
261 FGAction curr = getCurrentAction();
262 StarSystemAPI system = raidAction.getWhere();
263 String forces = getForcesNoun();
264
265 float untilDeployment = getETAUntil(PREPARE_ACTION);
266 float untilDeparture = getETAUntil(TRAVEL_ACTION);
267 float untilRaid = getETAUntil(PAYLOAD_ACTION);
268 float untilReturn = getETAUntil(RETURN_ACTION, true);
269 if (!isEnding()) {
270 if (mode == ListInfoMode.MESSAGES || getElapsed() <= 0f) { // initial notification only, not updates
271 addTargetingBulletPoint(info, tc, param, mode, initPad);
272 initPad = 0f;
273 }
274 if (untilDeployment > 0) {
275 addETABulletPoints(null, null, false, untilDeployment, ETAType.DEPLOYMENT, info, tc, initPad);
276 initPad = 0f;
277 } else if (untilDeparture > 0) {
278 addETABulletPoints(null, null, false, untilDeparture, ETAType.DEPARTURE, info, tc, initPad);
279 initPad = 0f;
280 }
281 if (untilRaid > 0 && getSource().getContainingLocation() != system) {
282 addETABulletPoints(system.getNameWithLowercaseTypeShort(), s, false, untilRaid, ETAType.ARRIVING,
283 info, tc, initPad);
284 initPad = 0f;
285 }
286 if (untilReturn > 0 && RETURN_ACTION.equals(curr.getId()) && getSource().getContainingLocation() != system &&
287 mode != ListInfoMode.INTEL) {
289
290 addETABulletPoints(from.getNameWithLowercaseTypeShort(), null, false, untilReturn, ETAType.RETURNING,
291 info, tc, initPad);
292 initPad = 0f;
293 }
294 if ((mode == ListInfoMode.INTEL || mode == ListInfoMode.MAP_TOOLTIP)
295 && curr != null && curr.getId().equals(PAYLOAD_ACTION)) {
296 LabelAPI label = info.addPara("Operating in the " + system.getNameWithLowercaseTypeShort(), tc, initPad);
297 label.setHighlightColors(s);
298 label.setHighlight(system.getNameWithNoType());
299 initPad = 0f;
300 }
301 }
302
303 if (mode != ListInfoMode.IN_DESC && isEnding()) {
304 if (!isSucceeded()) {
305 if (!isAborted() && !isFailed()) {
306 info.addPara("The " + forces + " have failed to achieve their objective", tc, initPad);
307 } else {
309 info.addPara("The " + forces + " have failed to achieve their objective", tc, initPad);
310 } else {
311 info.addPara("The " + forces + " have been defeated and scatter", tc, initPad);
312 }
313 }
314 }
315 }
316 }
317
318 protected void addUpdateBulletPoints(TooltipMakerAPI info, Color tc, Object param, ListInfoMode mode, float initPad) {
319 StarSystemAPI system = raidAction.getWhere();
320 String forces = getForcesNoun();
321 String noun = getNoun();
322 Color s = raidAction.getSystemNameHighlightColor();
323 //Color h = Misc.getHighlightColor();
324 if (ABORT_UPDATE.equals(param)) {
325 if (isInPreLaunchDelay()) {
326 info.addPara("The " + noun + " was aborted in the planning stages", tc, initPad);
327 } else {
328 info.addPara("The " + forces + " have been defeated and scatter", tc, initPad);
329 }
330 } else if (FLEET_LAUNCH_UPDATE.equals(param)) {
331 float untilDeparture = getETAUntil(TRAVEL_ACTION);
332 float untilRaid = getETAUntil(PAYLOAD_ACTION);
333 info.addPara("Fleet deployment in progress", tc, initPad);
334 initPad = 0f;
335 if (untilDeparture > 0) {
336 addETABulletPoints(null, null, false, untilDeparture, ETAType.DEPARTURE, info, tc, initPad);
337 }
338 if (untilRaid > 0 && getSource().getContainingLocation() != system) {
339 addETABulletPoints(system.getNameWithLowercaseTypeShort(), s, false, untilRaid, ETAType.ARRIVING,
340 info, tc, initPad);
341 }
342 } else if (PREPARE_ACTION.equals(param)) {
343 float untilRaid = getETAUntil(PAYLOAD_ACTION);
344 addETABulletPoints(system.getNameWithLowercaseTypeShort(), s, true, untilRaid, ETAType.ARRIVING,
345 info, tc, initPad);
346 } else if (TRAVEL_ACTION.equals(param)) {
347 addArrivedBulletPoint(system.getNameWithLowercaseTypeShort(), s, info, tc, initPad);
348 } else if (PAYLOAD_ACTION.equals(param)) {
349 if (isSucceeded()) {
350 info.addPara("The " + forces + " are withdrawing", tc, initPad);
351 } else {
352 if (isAborted()) {
353 info.addPara("The " + forces + " have been defeated and scatter", tc, initPad);
354 } else {
355 info.addPara("The " + forces + " have failed to achieve their objective", tc, initPad);
356 }
357 }
358 }
359 }
360
361 @Override
363 if (RETURN_ACTION.equals(action.getId())) return false;
364 if (PAYLOAD_ACTION.equals(action.getId())) {
365 // if it was aborted, will send an update on abort() instead
366 return isSucceeded() || (isFailed() && !isAborted());
367 }
368 if (TRAVEL_ACTION.equals(action.getId())) {
369 if (action instanceof FGTravelAction && (isAborted() || isFailed())) {
370 return false; // already sent a notification on abort/fail
371 }
372 // no update for "arriving" when traveling from one planet in-system to another
373 return getSource().getContainingLocation() != raidAction.getWhere();
374 }
375
376 return super.shouldSendIntelUpdateWhenActionFinished(action);
377 }
378
379 protected void addBasicDescription(TooltipMakerAPI info, float width, float height, float opad) {
380 info.addImage(getFaction().getLogo(), width, 128, opad);
381
382 StarSystemAPI system = raidAction.getWhere();
383
384 String noun = getNoun();
385
386 //String aOrAn = Misc.getAOrAnFor(noun);
387 //info.addPara(Misc.ucFirst(aOrAn) + " %s " + noun + " against "
388 info.addPara(Misc.ucFirst(faction.getPersonNamePrefixAOrAn()) + " %s " + noun + " against "
389 + "the " + system.getNameWithLowercaseTypeShort() + ".", opad,
391
392
393 }
394
395 protected void addAssessmentSection(TooltipMakerAPI info, float width, float height, float opad) {
396 Color h = Misc.getHighlightColor();
397
399
400 List<MarketAPI> targets = params.raidParams.allowedTargets;
401
402 String noun = getNoun();
403 if (!isEnding() && !isSucceeded() && !isFailed()) {
404 info.addSectionHeading("Assessment",
406 if (targets.isEmpty()) {
407 info.addPara("There are no colonies for the " + noun + " to target in the system.", opad);
408 } else {
409 StarSystemAPI system = raidAction.getWhere();
410
411 String forces = getForcesNoun();
412
413 boolean potentialDanger = addStrengthDesc(info, opad, system, forces,
414 "the " + noun + " is unlikely to find success",
415 "the outcome of the " + noun + " is uncertain",
416 "the " + noun + " is likely to find success");
417
418 if (potentialDanger) {
419 String safe = "should be safe from the " + noun;
420 String risk = "are at risk of being raided and losing stability:";
421 String highlight = "losing stability:";
422 if (params.raidParams.bombardment == BombardType.SATURATION) {
423 risk = "are at risk of suffering a saturation bombardment resulting in catastrophic damage:";
424 highlight = "catastrophic damage";
425 } else if (params.raidParams.bombardment == BombardType.TACTICAL) {
426 risk = "are at risk of suffering a tactical bombardment and having their military infrastructure disrupted:";
427 highlight = "military infrastructure disrupted";
428 } else if (!params.raidParams.disrupt.isEmpty()) {
429 risk = "are at risk of being raided and having their operations severely disrupted";
430 highlight = "operations severely disrupted";
431 }
432 if (getAssessmentRiskStringOverride() != null) {
434 }
437 }
438 showMarketsInDanger(info, opad, width, system, targets,
439 safe, risk, highlight);
440 }
441 }
442 addPostAssessmentSection(info, width, height, opad);
443 }
444 }
445
446 protected void addPostAssessmentSection(TooltipMakerAPI info, float width, float height, float opad) {
447
448 }
449
451 return null;
452 }
454 return null;
455 }
456
457
458 protected void addPayloadActionStatus(TooltipMakerAPI info, float width, float height, float opad) {
459 StarSystemAPI to = raidAction.getWhere();
460 info.addPara("Conducting operations in the " +
461 to.getNameWithLowercaseTypeShort() + ".", opad);
462
463 }
464
465 protected void addStatusSection(TooltipMakerAPI info, float width, float height, float opad) {
466 FGAction curr = getCurrentAction();
467
468 boolean showStatus = curr != null || isEnding() || isSucceeded();
469
470 if (showStatus) {
471 String noun = getNoun();
472 String forces = getForcesNoun();
473 info.addSectionHeading("Status",
475 if (isEnding() && !isSucceeded()) {
476 if (isFailed() || isAborted()) {
478 info.addPara("The " + forces + " are withdrawing.", opad);
479 } else {
480 info.addPara("The " + forces + " have been defeated and any "
481 + "remaining ships are retreating in disarray.", opad);
482 }
483 } else {
484 info.addPara("The " + forces + " are withdrawing.", opad);
485 }
486 } else if (isEnding() || isSucceeded()) {
487 info.addPara("The " + noun + " was successful and the " + forces + " are withdrawing.", opad);
488 } else if (curr != null) {
489 StarSystemAPI to = raidAction.getWhere();
490 if (isInPreLaunchDelay()) {
491 if (getSource().getMarket() != null) {
492 BaseHubMission.addStandardMarketDesc("The " + noun + " is in the planning stages on",
493 getSource().getMarket(), info, opad);
494 boolean mil = isSourceFunctionalMilitaryMarket();
495 if (mil) {
496 info.addPara("Disrupting the military facilities " + getSource().getMarket().getOnOrAt() +
497 " " + getSource().getMarket().getName() + " will abort the " + noun + ".", opad);
498 }
499 }
500 } else if (PREPARE_ACTION.equals(curr.getId())) {
501 if (getSource().getMarket() != null) {
502 BaseHubMission.addStandardMarketDesc("Making preparations in orbit around",
503 getSource().getMarket(), info, opad);
504 } else {
505 info.addPara("Making preparations in orbit around " + getSource().getName() + ".", opad);
506 }
507 } else if (TRAVEL_ACTION.equals(curr.getId())) {
508 if (getSource().getMarket() == null) {
509 info.addPara("Traveling to the " +
510 to.getNameWithLowercaseTypeShort() + ".", opad);
511 } else {
512 info.addPara("Traveling from " + getSource().getMarket().getName() + " to the " +
513 to.getNameWithLowercaseTypeShort() + ".", opad);
514 }
515 } else if (RETURN_ACTION.equals(curr.getId())) {
516 if (getSource().getMarket() == null) {
517 info.addPara("Returning to their port of origin.", opad);
518 } else {
519 info.addPara("Returning to " + getSource().getMarket().getName() + " in the " +
521 }
522 } else if (PAYLOAD_ACTION.equals(curr.getId())) {
523 addPayloadActionStatus(info, width, height, opad);
524 }
525 }
526 }
527 }
528
529 public String getNoun() {
530 if (params.noun != null) return params.noun;
531
532 String noun = "raid";
533 if (params.raidParams.bombardment != null) {
534 noun = "attack";
535 }
536 return noun;
537 }
538
539 public String getForcesNoun() {
540 if (params.forcesNoun != null) return params.forcesNoun;
541
542 String forces = "raiding forces";
543 if (!getNoun().equals("raid")) {
544 forces = "attacking forces";
545 }
546 return forces;
547 }
548
549
550 public String getBaseName() {
551 return Misc.ucFirst(getFaction().getPersonNamePrefix()) + " " + Misc.ucFirst(getNoun());
552 }
553
554 public boolean isSucceeded() {
555 return raidAction.getSuccessFraction() > 0f && raidAction.isActionFinished() && !isAborted();
556 }
557
558 public boolean isFailed() {
559 return isAborted() || (raidAction.getSuccessFraction() <= 0f && raidAction.isActionFinished());
560 }
561
563 return origin;
564 }
565
567 return raidAction.getWhere().getHyperspaceAnchor();
568 }
569
571 return raidAction.getWhere();
572 }
573
574 public GenericPayloadAction getRaidAction() {
575 return raidAction;
576 }
577
579 return travelAction;
580 }
581
583 return returnAction;
584 }
585
587 return waitAction;
588 }
589
590 @Override
591 public String getCommMessageSound() {
592 if (isSendingUpdate()) {
593 return getSoundStandardUpdate();
594 }
595 if (params.playerTargeted) {
596 return getSoundColonyThreat();
597 }
598 return super.getCommMessageSound();
599 }
600
601 public boolean isPlayerTargeted() {
602 return params.playerTargeted;
603 }
604
605
606 @Override
607 public Set<String> getIntelTags(SectorMapAPI map) {
608 return super.getIntelTags(map);
609 }
610
611 @Override
612 public List<ArrowData> getArrowData(SectorMapAPI map) {
613 if (isAborted() || isFailed() || isSucceeded() || isEnded() || isEnding()) {
614 return null;
615 }
616 return super.getArrowData(map);
617 }
618
619 public GenericRaidParams getParams() {
620 return params;
621 }
622
624 this.origin = origin;
625 }
626
627 @Override
629 if (getCurrentAction() != null && GenericRaidFGI.PREPARE_ACTION.equals(getCurrentAction().getId()) ||
630 getDelayRemaining() > 0) {
631 return getSource();
632 }
633 return getDestination();
634 }
635
636 public boolean hasCustomRaidAction() {
637 return false;
638 }
639
640 public void doCustomRaidAction(CampaignFleetAPI fleet, MarketAPI market, float raidStr) {
641
642 }
643
645 if (m == null || route == null || route.getExtra() == null || route.getExtra().quality == null) return;
646 m.getPreviousCreateFleetAction().qualityOverride = route.getExtra().quality;
647 }
648}
649
650
651
652
static SectorAPI getSector()
Definition Global.java:65
void addArrivedBulletPoint(String destName, Color destHL, TooltipMakerAPI info, Color tc, float initPad)
void createRoute(String factionId, int approximateTotalDifficultyPoints, int approximateNumberOfFleets, Object custom)
void addETABulletPoints(String destName, Color destHL, boolean withDepartedText, float eta, ETAType type, TooltipMakerAPI info, Color tc, float initPad)
void showMarketsInDanger(TooltipMakerAPI info, float opad, float width, StarSystemAPI system, List< MarketAPI > targets, String safeStr, String riskStr, String riskStrHighlight)
boolean addStrengthDesc(TooltipMakerAPI info, float opad, StarSystemAPI system, String forces, String outcomeFailure, String outcomeUncertain, String outcomeSuccess)
static void setLocationAndCoordinates(CampaignFleetAPI fleet, RouteSegment current)
void addPayloadActionStatus(TooltipMakerAPI info, float width, float height, float opad)
void addNonUpdateBulletPoints(TooltipMakerAPI info, Color tc, Object param, ListInfoMode mode, float initPad)
void addStatusSection(TooltipMakerAPI info, float width, float height, float opad)
void addPostAssessmentSection(TooltipMakerAPI info, float width, float height, float opad)
void addBasicDescription(TooltipMakerAPI info, float width, float height, float opad)
void addTargetingBulletPoint(TooltipMakerAPI info, Color tc, Object param, ListInfoMode mode, float initPad)
void doCustomRaidAction(CampaignFleetAPI fleet, MarketAPI market, float raidStr)
void addAssessmentSection(TooltipMakerAPI info, float width, float height, float opad)
void addUpdateBulletPoints(TooltipMakerAPI info, Color tc, Object param, ListInfoMode mode, float initPad)
static void addStandardMarketDesc(String prefix, MarketAPI market, TooltipMakerAPI info, float pad)
static String ucFirst(String str)
Definition Misc.java:559
static Color getHighlightColor()
Definition Misc.java:792
void set(String key, Object value)
void setHighlight(int start, int end)
void setHighlightColors(Color ... colors)
void addImage(String spriteName, float pad)
LabelAPI addPara(String format, float pad, Color hl, String... highlights)
LabelAPI addSectionHeading(String str, Alignment align, float pad)