Starsector API
Loading...
Searching...
No Matches
FleetGroupIntel.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.intel.group;
2
3import java.awt.Color;
4import java.util.ArrayList;
5import java.util.List;
6import java.util.Random;
7import java.util.Set;
8
9import org.lwjgl.util.vector.Vector2f;
10
11import com.fs.starfarer.api.Global;
12import com.fs.starfarer.api.campaign.CampaignFleetAPI;
13import com.fs.starfarer.api.campaign.FactionAPI;
14import com.fs.starfarer.api.campaign.LocationAPI;
15import com.fs.starfarer.api.campaign.SectorEntityToken;
16import com.fs.starfarer.api.campaign.StarSystemAPI;
17import com.fs.starfarer.api.campaign.econ.Industry;
18import com.fs.starfarer.api.campaign.econ.MarketAPI;
19import com.fs.starfarer.api.campaign.rules.MemoryAPI;
20import com.fs.starfarer.api.impl.campaign.command.WarSimScript;
21import com.fs.starfarer.api.impl.campaign.fleets.RouteLocationCalculator;
22import com.fs.starfarer.api.impl.campaign.fleets.RouteManager;
23import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.OptionalFleetData;
24import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData;
25import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteFleetSpawner;
26import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteSegment;
27import com.fs.starfarer.api.impl.campaign.ids.Conditions;
28import com.fs.starfarer.api.impl.campaign.ids.Factions;
29import com.fs.starfarer.api.impl.campaign.ids.Industries;
30import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
31import com.fs.starfarer.api.impl.campaign.ids.Tags;
32import com.fs.starfarer.api.impl.campaign.intel.BaseIntelPlugin;
33import com.fs.starfarer.api.impl.campaign.missions.FleetCreatorMission;
34import com.fs.starfarer.api.impl.campaign.procgen.themes.RouteFleetAssignmentAI.TravelState;
35import com.fs.starfarer.api.ui.LabelAPI;
36import com.fs.starfarer.api.ui.SectorMapAPI;
37import com.fs.starfarer.api.ui.TooltipMakerAPI;
38import com.fs.starfarer.api.util.CountingMap;
39import com.fs.starfarer.api.util.Misc;
40
55public abstract class FleetGroupIntel extends BaseIntelPlugin implements RouteFleetSpawner {
56
57 public static interface FGIEventListener {
58 public void reportFGIAborted(FleetGroupIntel intel);
59 }
60
61 public static String ABORT_UPDATE = "abort_update";
62 public static String FLEET_LAUNCH_UPDATE = "fleet_launch_update";
63
64 public static final String KEY_SPAWN_FP = "$core_fgiSpawnFP";
65
66 public static final String NEVER_STRAGGLER = "$core_fgiNeverStraggler";
67 public static final String KEY_POTENTIAL_STRAGGLER = "$core_fgiMaybeStraggler";
68 public static final String KEY_STRAGGLER_RETURN_COUNTDOWN = "$core_fgiStragglerReturnCountdown";
69
70
71 public static boolean DEBUG = false;
72
73
74 protected Random random = new Random();
75 protected List<FGAction> actions = new ArrayList<FGAction>();
76 protected RouteData route;
77 protected RouteSegment prevSegment;
78 protected List<CampaignFleetAPI> fleets = new ArrayList<CampaignFleetAPI>();
79 protected boolean spawnedFleets = false;
80
81 protected boolean doIncrementalSpawn = true;
82 protected List<CampaignFleetAPI> spawning = new ArrayList<CampaignFleetAPI>();
83 protected LocationAPI spawnLocation = null;
84 protected float spawnDelay = 0f;
85 protected float elapsed = 0f;
86
87 protected boolean aborted = false;
88 protected float totalFPSpawned = 0f;
89 protected float fleetAbortsMissionFPFraction = 0.33f;
90 protected float groupAbortsMissionFPFraction = 0.33f;
91 protected SectorEntityToken returnLocation;
92 protected FactionAPI faction;
93 protected int approximateNumberOfFleets = 3;
94
95 protected FGIEventListener listener;
96
97 public FleetGroupIntel() {
98 Global.getSector().addScript(this);
99 }
100
101 protected Object readResolve() {
102 if (random == null) {
103 random = new Random();
104 }
105
106 //random = new Random(142343232L);
107 //System.out.println("RNG CHECK 1: " + random.nextLong());
108 return this;
109 }
110
111 public float getETAUntil(String actionId) {
112 return getETAUntil(actionId, false);
113 }
114 public float getETAUntil(String actionId, boolean untilEndOfAction) {
115 float eta = getDelayRemaining();
116 for (FGAction action : actions) {
117 if (action.getId() != null && action.getId().equals(actionId)) {
118 if (untilEndOfAction) {
119 eta += action.getEstimatedDaysToComplete();
120 }
121 return eta;
122 } else {
123 eta += action.getEstimatedDaysToComplete();
124 }
125 }
126 return 0f;
127 }
128
129 @Override
130 protected void notifyEnded() {
131 super.notifyEnded();
132 Global.getSector().removeScript(this);
133 }
134
135
136 protected boolean sourceWasEverMilitaryMarket = false;
137 protected boolean sendFleetLaunchUpdate = false;
139 if (getSource() == null) return false;
140 MarketAPI market = getSource().getMarket();
141 if (market == null || market.isPlanetConditionMarketOnly()) return false;
142
143 if (market.hasCondition(Conditions.DECIVILIZED)) {
144 return false;
145 }
146
147 Industry b = market.getIndustry(Industries.MILITARYBASE);
148 if (b == null) b = market.getIndustry(Industries.HIGHCOMMAND);
149 if (b == null || b.isDisrupted() || !b.isFunctional()) {
150 return false;
151 }
152 return true;
153 }
154
155 public boolean isInPreLaunchDelay() {
156 return route != null && route.getElapsed() <= 0f && route.getDelay() > 0;
157 }
158
163 public void setPreFleetDeploymentDelay(float delay) {
164 if (route != null) {
165 route.setDelay(delay);
166 }
167 }
168
169 public float getDelayRemaining() {
170 if (!isInPreLaunchDelay() || route == null) return 0f;
171 return route.getDelay();
172 }
173
174 public float getElapsed() {
175 return elapsed;
176 }
177
178 public void setElapsed(float elapsed) {
179 this.elapsed = elapsed;
180 }
181
182 @Override
183 public void advance(float amount) {
184 super.advance(amount);
185
186 elapsed += amount;
187
188 if (isEnded() || isEnding() || isAborted()) return;
189 if (route == null) return;
190
191 if (isInPreLaunchDelay()) {
193 boolean mil = isSourceFunctionalMilitaryMarket();
195 if (!mil && sourceWasEverMilitaryMarket) {
196 abort();
197 return;
198 }
199 return;
200 }
201
203 sendFleetLaunchUpdate = false;
205 }
206
207 if (!isSucceeded() && !isEnding() && !isAborted() && shouldAbort()) {
208 abort();
209 return;
210 }
211
212 if (!spawnedFleets) {
213 if (!isSucceeded() && route.getExtra() != null && route.getExtra().damage != null &&
214 1f - route.getExtra().damage < getGroupAbortsMissionFPFraction()) {
215 abort();
216 return;
217 }
218
219 RouteSegment curr = route.getCurrent();
220 if (curr != prevSegment || route.isExpired()) {
221 if (prevSegment != null && prevSegment.custom instanceof FGAction) {
222 FGAction action = (FGAction) prevSegment.custom;
224 actions.remove(action);
225 notifyActionFinished(action);
226
227 if (route.isExpired()) {
228 finish(false);
229 return;
230 }
231 }
232 }
233 prevSegment = curr;
234 } else {
237
238 if (actions.isEmpty()) {
239 finish(false);
240 return;
241 }
242
243 FGAction action = actions.get(0);
244 if (action.isActionFinished()) {
245 actions.remove(0);
246 notifyActionFinished(action);
247 return;
248 }
249
250 action.directFleets(amount);
251
252 //System.out.println(action + " " + action.isActionFinished());
253 if (action.isActionFinished()) {
254 actions.remove(0);
255 notifyActionFinished(action);
256 return;
257 }
258 }
259
260 }
261
262 protected boolean shouldAbort() {
263 return false;
264 }
265
267 // presumably, !isFailed() is correct here but not 100% sure why -am
268 if (action instanceof FGWaitAction && (isAborted() || !isFailed())) {
269 return false;
270 }
271
272 if (action instanceof FGWaitAction) {
273 FGWaitAction wait = (FGWaitAction) action;
274 if (wait.getOrigDurDays() <= 0f) return false;
275 }
276 return action != null && action.getId() != null;
277 }
278
279 protected void notifyActionFinished(FGAction action) {
280 if (action != null && shouldSendIntelUpdateWhenActionFinished(action)) {
282 }
283 }
284
285
287 if (isSucceeded()) {
288 List<CampaignFleetAPI> remove = new ArrayList<CampaignFleetAPI>();
289 for (CampaignFleetAPI fleet : fleets) {
290 if (!fleet.isAlive()) {
291 remove.add(fleet);
292 }
293 }
294 fleets.removeAll(remove);
295 return; // already returning at this point, still clean up destroyed fleets though
296 }
297
299
300 List<CampaignFleetAPI> remove = new ArrayList<CampaignFleetAPI>();
301 float totalFP = 0f;
302 for (CampaignFleetAPI fleet : fleets) {
303 float spawnFP = fleet.getMemoryWithoutUpdate().getFloat(KEY_SPAWN_FP);
304 if (!fleet.isAlive()) {
305 remove.add(fleet);
306 } else if (fleet.getFleetPoints() <= spawnFP * getFleetAbortsMissionFPFraction()) {
307 remove.add(fleet);
309 } else {
310 totalFP += fleet.getFleetPoints();
311 }
312 }
313
314 fleets.removeAll(remove);
315
317 abort();
318 return;
319 }
320
321 }
322
323 protected void checkStragglers() {
324 List<CampaignFleetAPI> remove = new ArrayList<CampaignFleetAPI>();
325 CountingMap<LocationAPI> fleetLocs = new CountingMap<LocationAPI>();
326
327 for (CampaignFleetAPI fleet : fleets) {
328 fleetLocs.add(fleet.getContainingLocation());
329 }
330
331 LocationAPI withMostFleets = null;
332 int maxCount = 0;
333 for (LocationAPI loc : fleetLocs.keySet()) {
334 int count = fleetLocs.getCount(loc);
335 if (count > maxCount) {
336 withMostFleets = loc;
337 maxCount = count;
338 }
339 }
340
341 if (withMostFleets == null) return;
342
343 Vector2f com = new Vector2f();
344 float weight = 0f;
345 for (CampaignFleetAPI fleet : fleets) {
346 if (fleet.getContainingLocation() != withMostFleets) continue;
347 float w = fleet.getFleetPoints();
348 Vector2f loc = new Vector2f(fleet.getLocation());
349 loc.scale(w);
350 Vector2f.add(com, loc, com);
351 weight += w;
352 }
353
354 if (weight < 1f) weight = 1f;
355 com.scale(1f / weight);
356
357 FGAction action = getCurrentAction();
358 boolean canBeStragglers = action != null &&
359 (action instanceof FGTravelAction || action instanceof FGWaitAction);
360
361 int maybeStragglers = 0;
362 for (CampaignFleetAPI fleet : fleets) {
363 boolean potentialStraggler = fleet.getContainingLocation() != withMostFleets;
364 if (!potentialStraggler) {
365 potentialStraggler |= Misc.getDistance(fleet.getLocation(), com) > 4000;
366 }
367 if (fleet.getMemoryWithoutUpdate().getBoolean(NEVER_STRAGGLER) || !canBeStragglers) {
368 potentialStraggler = false;
369 }
370
371 MemoryAPI mem = fleet.getMemoryWithoutUpdate();
372 if (mem.contains(KEY_POTENTIAL_STRAGGLER)) {
373 maybeStragglers++;
374 }
375 if (!potentialStraggler && mem.contains(KEY_POTENTIAL_STRAGGLER)) {
376 mem.unset(KEY_POTENTIAL_STRAGGLER);
378 } else if (mem.contains(KEY_POTENTIAL_STRAGGLER) && !mem.contains(KEY_STRAGGLER_RETURN_COUNTDOWN)) {
379 remove.add(fleet);
380// if (fleet.getName().toLowerCase().contains("tactistar")) {
381// System.out.println("fewfwef23r23r23r");
382// }
384 } else if (potentialStraggler && !mem.contains(KEY_POTENTIAL_STRAGGLER)) {
385 mem.set(KEY_POTENTIAL_STRAGGLER, true);
387 }
388 }
389
390 fleets.removeAll(remove);
391
392 //System.out.println(getClass().getSimpleName() + " maybe stragglers: " + maybeStragglers + ", fleets: " + fleets.size());
393 }
394
396 //if (true) return 0.5f;
397 return 30f;
398 }
399
400 protected boolean failedButNotDefeated = false;
401 public boolean isFailedButNotDefeated() {
403 }
404
406 this.failedButNotDefeated = failedButNotDefeated;
407 }
408
409 public void abort() {
410 finish(true);
411 }
412 public void finish(boolean isAbort) {
413 boolean wasEnding = isEnding();
414 aborted = isAbort;
416
417 if (!isAbort) {
419 }
420
421 if (spawnedFleets && !actions.isEmpty()) {
422 if (!actions.get(0).isActionFinished()) {
423 actions.get(0).setActionFinished(true);
424 }
425 }
426
427 if (route != null) {
428 route.expire();
429 RouteManager.getInstance().removeRoute(route);
430 }
431
433
434 if (!wasEnding && isAbort) {
436
437 if (listener != null) {
438 listener.reportFGIAborted(this);
439 }
440 }
441 }
442
443 public boolean isSpawning() {
444 return spawning != null && !spawning.isEmpty();
445 }
446
447 public boolean isAborted() {
448 return aborted;
449 }
450
451
453 for (CampaignFleetAPI fleet : fleets) {
455 }
456 }
457
458 protected void giveReturnAssignments(CampaignFleetAPI fleet) {
459 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_FLEET_DO_NOT_GET_SIDETRACKED, true);
460 if (returnLocation != null) {
461 Misc.giveStandardReturnAssignments(fleet, returnLocation, null, true);
462 } else {
463 Misc.giveStandardReturnToSourceAssignments(fleet, true);
464 }
465 }
466
467
468 protected void createRoute(String factionId, int approximateTotalDifficultyPoints,
469 int approximateNumberOfFleets, Object custom) {
470 OptionalFleetData extra = new OptionalFleetData();
471 extra.strength = getApproximateStrengthForTotalDifficultyPoints(factionId, approximateTotalDifficultyPoints);
472 extra.factionId = faction.getId(); // needed for WarSimScript etc
473 route = RouteManager.getInstance().addRoute("FGI_" + getClass().getSimpleName(), null,
474 Misc.genRandomSeed(), extra, this, custom);
475
476 for (FGAction action : actions) {
477 int before = route.getSegments().size();
478 action.addRouteSegment(route);
479 int after = route.getSegments().size();
480 for (int i = before; i < after; i++) {
481 route.getSegments().get(i).custom = action;
482 }
483 }
484
485 this.approximateNumberOfFleets = approximateNumberOfFleets;
486 }
487
488 public void setRoute(RouteData route) {
489 this.route = route;
490 }
491
492 public CampaignFleetAPI spawnFleet(RouteData route) {
493 //System.out.println("RNG CHECK 2: " + random.nextLong());
494
495 RouteManager.getInstance().removeRoute(route);
496
497 if (isSpawnedFleets()) return null;
498
499 if (isEnded() || isEnding()) return null;
500 if (route == null || route.getCurrent() == null) {
501 abort();
502 return null;
503 }
504
505 RouteSegment curr = route.getCurrent();
506
507 while (!actions.isEmpty()) {
508 FGAction action = actions.get(0);
509 if (action == curr.custom) {
510 break;
511 }
512 actions.remove(0);
513 }
514
515 if (actions.isEmpty()) {
516 abort();
517 return(null);
518 }
519
521 System.out.println(getClass().getSimpleName() + ": about to spawn fleets");
522 }
523
524 spawnFleets();
525 setSpawnedFleets(true);
526
527 if (doIncrementalSpawn && route.getElapsed() < 0.1f) {
528 spawning.addAll(fleets);
529 fleets.clear();
530 for (CampaignFleetAPI fleet : spawning) {
531 if (spawnLocation == null) {
532 spawnLocation = fleet.getContainingLocation();
533 }
534 fleet.getContainingLocation().removeEntity(fleet);
535 }
537 } else {
538 for (CampaignFleetAPI fleet : fleets) {
539 int fp = fleet.getFleetPoints();
540 fleet.getMemoryWithoutUpdate().set(KEY_SPAWN_FP, fp);
541 totalFPSpawned += fp;
542 }
543 }
544
545
546 actions.get(0).notifyFleetsSpawnedMidSegment(curr);
547
548 // don't return any created fleets - route is removed anyway and we're managing the fleets directly
549 return null;
550 }
551
552 public void setNeverStraggler(CampaignFleetAPI fleet) {
553 if (fleet == null) return;
554 fleet.getMemoryWithoutUpdate().set(NEVER_STRAGGLER, true);
555 }
556
557 public void handleIncrementalSpawning(float amount) {
558 if (spawning == null || spawning.isEmpty() || spawnLocation == null) return;
559 float days = Misc.getDays(amount);
560 spawnDelay -= days;
561
562 if (spawnDelay <= 0) {
563 spawnDelay = 0.25f + (float) Math.random() * 0.25f;
564
565 CampaignFleetAPI fleet = spawning.remove(0);
566 spawnLocation.addEntity(fleet);
567 if (getSource() != null) {
568 fleet.setLocation(getSource().getLocation().x, getSource().getLocation().y);
569 }
570 fleets.add(fleet);
571 int fp = fleet.getFleetPoints();
572 totalFPSpawned += fp;
573
574 if (spawning.isEmpty()) {
575 spawning = null;
576 spawnLocation = null;
577 }
578 }
579 }
580
581
582 public boolean isDoIncrementalSpawn() {
583 return doIncrementalSpawn;
584 }
585
587 this.doIncrementalSpawn = doIncrementalSpawn;
588 }
589
590 public float getTotalFPSpawned() {
591 return totalFPSpawned;
592 }
593
594
596 this.totalFPSpawned = totalFPSpawned;
597 }
598
599 public void setSpawnedFleets(boolean spawnedFleets) {
600 this.spawnedFleets = spawnedFleets;
601 }
602
603 public RouteSegment getSegmentForAction(FGAction action) {
604 for (RouteSegment seg : getRoute().getSegments()) {
605 if (seg.custom == action) return seg;
606 }
607 return null;
608 }
609
610 public void removeAction(String id) {
611 FGAction action = getAction(id);
612 if (action != null) {
613 actions.remove(action);
614 }
615 }
616 public FGAction getAction(String id) {
617 for (FGAction curr : actions) {
618 if (curr.getId() != null && curr.getId().equals(id)) {
619 return curr;
620 }
621 }
622 return null;
623 }
624
625 public boolean isCurrent(String id) {
626 FGAction action = getAction(id);
627 return action != null && action == getCurrentAction();
628 }
629
631 if (actions.isEmpty()) return null;
632 return actions.get(0);
633 }
634
635 public boolean isSpawnedFleets() {
636 return spawnedFleets;
637 }
638
642
644 this.approximateNumberOfFleets = approximateNumberOfFleets;
645 }
646
647 public List<CampaignFleetAPI> getFleets() {
648 return fleets;
649 }
650
651 public static TravelState getTravelState(RouteSegment segment) {
652 if (segment.isInSystem()) {
653 return TravelState.IN_SYSTEM;
654 }
655
656 if (segment.hasLeaveSystemPhase() && segment.getLeaveProgress() < 1f) {
657 return TravelState.LEAVING_SYSTEM;
658 }
659 if (segment.hasEnterSystemPhase() && segment.getEnterProgress() > 0f) {
660 return TravelState.ENTERING_SYSTEM;
661 }
662
663 return TravelState.IN_HYPER_TRANSIT;
664 }
665
666 public static LocationAPI getLocation(RouteSegment segment) {
667 return getLocationForState(segment, getTravelState(segment));
668 }
669
670 public static LocationAPI getLocationForState(RouteSegment segment, TravelState state) {
671 switch (state) {
672 case ENTERING_SYSTEM: {
673 if (segment.to != null) {
674 return segment.to.getContainingLocation();
675 }
676 return segment.from.getContainingLocation();
677 }
678 case IN_HYPER_TRANSIT: return Global.getSector().getHyperspace();
679 case IN_SYSTEM: return segment.from.getContainingLocation();
680 case LEAVING_SYSTEM: return segment.from.getContainingLocation();
681 }
682 return null;
683 }
684
685
686 public static void setLocationAndCoordinates(CampaignFleetAPI fleet, RouteSegment current) {
687 TravelState state = getTravelState(current);
688 if (state == TravelState.LEAVING_SYSTEM) {
689 float p = current.getLeaveProgress();
690 SectorEntityToken jp = RouteLocationCalculator.findJumpPointToUse(fleet, current.from);
691 if (jp == null) jp = current.from;
692 RouteLocationCalculator.setLocation(fleet, p, current.from, jp);
693 }
694 else if (state == TravelState.ENTERING_SYSTEM) {
695 float p = current.getEnterProgress();
696 SectorEntityToken jp = RouteLocationCalculator.findJumpPointToUse(fleet, current.to);
697 if (jp == null) jp = current.to;
698 RouteLocationCalculator.setLocation(fleet, p, jp, current.to);
699 }
700 else if (state == TravelState.IN_SYSTEM) {
701 float p = current.getTransitProgress();
702 RouteLocationCalculator.setLocation(fleet, p,
703 current.from, current.to);
704 }
705 else if (state == TravelState.IN_HYPER_TRANSIT) {
706 float p = current.getTransitProgress();
707 SectorEntityToken t1 = Global.getSector().getHyperspace().createToken(
708 current.from.getLocationInHyperspace().x,
709 current.from.getLocationInHyperspace().y);
710 SectorEntityToken t2 = Global.getSector().getHyperspace().createToken(
711 current.to.getLocationInHyperspace().x,
712 current.to.getLocationInHyperspace().y);
713 RouteLocationCalculator.setLocation(fleet, p, t1, t2);
714 }
715 }
716
717
718 public List<FGAction> getActions() {
719 return actions;
720 }
721
722 public void addAction(FGAction action, String id) {
723 action.setId(id);
724 addAction(action);
725 }
726 public void addAction(FGAction action) {
727 action.setIntel(this);
728 actions.add(action);
729 }
730
731
732 public boolean shouldCancelRouteAfterDelayCheck(RouteData route) {
733 return false;
734 }
735
736 public boolean shouldRepeat(RouteData route) {
737 return false;
738 }
739
741 // should never happen since this class removes the route and never returns the created fleets to the manager
742 }
743
744 public SectorEntityToken getReturnLocation() {
745 return returnLocation;
746 }
747
748 public void setReturnLocation(SectorEntityToken returnLocation) {
749 this.returnLocation = returnLocation;
750 }
751
752
756
758 this.fleetAbortsMissionFPFraction = fleetAbortsMissionFPFraction;
759 }
760
764
766 this.groupAbortsMissionFPFraction = groupAbortsMissionFPFraction;
767 }
768
769 @Override
770 public FactionAPI getFactionForUIColors() {
771 //return super.getFactionForUIColors();
772 return faction;
773 }
774
775 public void setFaction(String factionId) {
776 faction = Global.getSector().getFaction(factionId);
777
778 }
779 public void setFaction(FactionAPI faction) {
780 this.faction = faction;
781 }
782
783 public FactionAPI getFaction() {
784 return faction;
785 }
786
787 public RouteData getRoute() {
788 return route;
789 }
790
791 public static float getApproximateStrengthForTotalDifficultyPoints(String factionId, int points) {
792 float mult = 50f;
793 if (factionId != null) {
794 FactionAPI faction = Global.getSector().getFaction(factionId);
795 if (faction.getCustomBoolean("pirateBehavior")) {
796 mult = 35f;
797 }
798 }
799 return points * mult;
800 }
801
808 public static void computeSampleFleetStrengths() {
809 String factionId = null;
810 factionId = Factions.LUDDIC_CHURCH;
811 factionId = Factions.LUDDIC_PATH;
812 factionId = Factions.TRITACHYON;
813 factionId = Factions.DIKTAT;
814 factionId = Factions.REMNANTS;
815 factionId = Factions.PIRATES;
816 factionId = Factions.PERSEAN;
817 factionId = Factions.HEGEMONY;
818 factionId = Factions.INDEPENDENT;
819
820 System.out.println("---------------------------------");
821 System.out.println("FACTION: " + factionId);
822
823 System.out.println("Difficulty\tStd\tQuality\tQuantity");
824 for (int j = 0; j < 1; j++) {
825 for (int i = 1; i <= 10; i++) {
826
827 Vector2f loc = new Vector2f();
828
829 float strStandard = 0;
830 float strQuality = 0;
831 float strQuantity = 0;
832
833 {
834 FleetCreatorMission m = new FleetCreatorMission(new Random());
835 m.beginFleet();
836 m.createStandardFleet(i, factionId, loc);
837 CampaignFleetAPI fleet = m.createFleet();
838 if (fleet != null) {
839 strStandard = fleet.getEffectiveStrength();
840 }
841 }
842
843 {
844 FleetCreatorMission m = new FleetCreatorMission(new Random());
845 m.beginFleet();
846 m.createQualityFleet(i, factionId, loc);
847 CampaignFleetAPI fleet = m.createFleet();
848 if (fleet != null) {
849 strQuality = fleet.getEffectiveStrength();
850 }
851 }
852
853 {
854 FleetCreatorMission m = new FleetCreatorMission(new Random());
855 m.beginFleet();
856 m.createQuantityFleet(i, factionId, loc);
857 CampaignFleetAPI fleet = m.createFleet();
858 if (fleet != null) {
859 strQuantity = fleet.getEffectiveStrength();
860 }
861 }
862
863
864 System.out.println("" + i + "\t\t" + (int)strStandard + "\t" + (int)strQuality + "\t" + (int)strQuantity);
865 }
866 System.out.println("---------------------------------");
867 }
868 }
869
870 protected abstract boolean isPlayerTargeted();
871 protected abstract void spawnFleets();
872 protected abstract SectorEntityToken getSource();
873 protected abstract SectorEntityToken getDestination();
874 protected abstract String getBaseName();
875
876 protected abstract void addNonUpdateBulletPoints(TooltipMakerAPI info, Color tc, Object param,
877 ListInfoMode mode, float initPad);
878 protected abstract void addUpdateBulletPoints(TooltipMakerAPI info, Color tc, Object param,
879 ListInfoMode mode, float initPad);
880
881 protected void addStatusSection(TooltipMakerAPI info, float width, float height, float opad) {
882
883 }
884 protected void addAssessmentSection(TooltipMakerAPI info, float width, float height, float opad) {
885
886 }
887 protected void addBasicDescription(TooltipMakerAPI info, float width, float height, float opad) {
888
889 }
890
891 @Override
892 public Set<String> getIntelTags(SectorMapAPI map) {
893 Set<String> tags = super.getIntelTags(map);
894 tags.add(Tags.INTEL_MILITARY);
895
896 if (Misc.isHyperspaceAnchor(getDestination())) {
897 StarSystemAPI system = Misc.getStarSystemForAnchor(getDestination());
898 if (system != null &&
899 !Misc.getMarketsInLocation(system, Factions.PLAYER).isEmpty()) {
900 tags.add(Tags.INTEL_COLONIES);
901 }
902 }
903
904 if (getDestination() != null &&
905 getDestination().getContainingLocation() != null &&
906 !Misc.getMarketsInLocation(getDestination().getContainingLocation(), Factions.PLAYER).isEmpty()) {
907 tags.add(Tags.INTEL_COLONIES);
908 }
909 tags.add(getFaction().getId());
910 return tags;
911 }
912
913 public String getSortString() {
914 return "Fleet Group Movement";
915 }
916
917 public String getSuccessPostfix() {
918 return " - Successful";
919 }
920
921 public String getFailurePostfix() {
922 if (isInPreLaunchDelay()) {
923 return " - Aborted";
924 }
926 return " - Failed";
927 }
928 return " - Defeated";
929 }
930
931 public String getName() {
932 String base = getBaseName();
933 if (isSucceeded()) {
934 return base + getSuccessPostfix();
935 } else if (isFailed() || isAborted()) {
936 return base + getFailurePostfix();
937 }
938 //return base + " - Over";
939 return base;
940 }
941
942 public boolean isSucceeded() {
943 return false;
944 }
945 public boolean isFailed() {
946 return isAborted();
947 }
948
949 @Override
950 public void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode) {
951 Color c = getTitleColor(mode);
952
953 info.setParaFontDefault();
954
955 info.addPara(getName(), c, 0f);
956 info.setParaFontDefault();
957 addBulletPoints(info, mode);
958 }
959
960 @Override
961 public String getIcon() {
962 return getFaction().getCrest();
963 }
964
965 public String getSmallDescriptionTitle() {
966 return getName();
967 }
968
969 @Override
970 public IntelSortTier getSortTier() {
971// if (isPlayerTargeted() && false) {
972// return IntelSortTier.TIER_2;
973// }
974 return super.getSortTier();
975 }
976
977 @Override
978 public SectorEntityToken getMapLocation(SectorMapAPI map) {
979 return getDestination();
980 }
981
982 public List<ArrowData> getArrowData(SectorMapAPI map) {
983
984 SectorEntityToken src = getSource();
985 SectorEntityToken dest = getDestination();
986
987 if (src == null || dest == null || src.getContainingLocation() == dest.getContainingLocation()) {
988 return null;
989 }
990
991 List<ArrowData> result = new ArrayList<ArrowData>();
992
993 ArrowData arrow = new ArrowData(src, dest);
994 arrow.color = getFactionForUIColors().getBaseUIColor();
995 arrow.width = 20f;
996 result.add(arrow);
997
998 return result;
999 }
1000
1001 public Random getRandom() {
1002 return random;
1003 }
1004
1005 public void setRandom(Random random) {
1006 this.random = random;
1007 }
1008
1009 protected void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode) {
1010 float pad = 3f;
1011 float opad = 10f;
1012
1013 float initPad = pad;
1014 if (mode == ListInfoMode.IN_DESC) initPad = opad;
1015
1016 Color tc = getBulletColorForMode(mode);
1017
1018
1019 bullet(info);
1020 Object param = getListInfoParam();
1021 boolean isUpdate = param != null;
1022
1023 if (!isUpdate) {
1024 addNonUpdateBulletPoints(info, tc, param, mode, initPad);
1025 } else {
1026 addUpdateBulletPoints(info, tc, param, mode, initPad);
1027 }
1028 unindent(info);
1029 }
1030
1031 protected void addFactionBulletPoint(TooltipMakerAPI info, Color tc, float initPad) {
1032 info.addPara("Faction: " + faction.getDisplayName(), initPad, tc,
1033 faction.getBaseUIColor(), faction.getDisplayName());
1034 }
1035
1036 protected void addArrivedBulletPoint(String destName, Color destHL, TooltipMakerAPI info, Color tc, float initPad) {
1037 LabelAPI label = info.addPara("Arrived at " + destName, tc, initPad);
1038
1039 if (destHL != null) {
1040 String hl = getNameWithNoType(destName);
1041 label.setHighlightColor(destHL);
1042 label.highlightLast(hl);
1043 }
1044 }
1045
1046 public String getNameWithNoType(String systemName) {
1047 String hl = systemName;
1048 if (hl != null) {
1049 if (hl.endsWith(" system")) {
1050 hl = hl.replaceAll(" system", "");
1051 }
1052 if (hl.endsWith(" nebula")) {
1053 hl = hl.replaceAll(" nebula", "");
1054 }
1055 if (hl.endsWith(" star system")) {
1056 hl = hl.replaceAll(" star system", "");
1057 }
1058 }
1059 return hl;
1060 }
1061
1062 public static enum ETAType {
1063 ARRIVING,
1064 RETURNING,
1065 DEPARTURE,
1066 DEPLOYMENT,
1067 }
1068
1069 protected void addETABulletPoints(String destName, Color destHL, boolean withDepartedText, float eta,
1070 ETAType type, TooltipMakerAPI info, Color tc, float initPad) {
1071 Color h = Misc.getHighlightColor();
1072
1073 String hl = getNameWithNoType(destName);
1074
1075 if (type == ETAType.DEPLOYMENT) {
1076 if ((int) eta <= 0) {
1077 info.addPara("Fleet deployment imminent", tc, initPad);
1078 } else {
1079 String days = (int)eta == 1 ? "day" : "days";
1080 info.addPara("Estimated %s " + days + " until fleet deployment",
1081 initPad, tc, h, "" + (int) eta);
1082 }
1083 return;
1084 }
1085
1086 if (type == ETAType.DEPARTURE) {
1087 if ((int) eta <= 0) {
1088 info.addPara("Departure imminent", tc, initPad);
1089 } else {
1090 String days = (int)eta == 1 ? "day" : "days";
1091 info.addPara("Estimated %s " + days + " until departure",
1092 initPad, tc, h, "" + (int) eta);
1093 }
1094 return;
1095 }
1096
1097 LabelAPI label = null;
1098 if (withDepartedText && eta <= 0) {
1099 // operations in same location as the "from"
1100 label = info.addPara("Operating in the " + destName, tc, initPad);
1101
1102 if (destHL != null && label != null) {
1103 label.setHighlightColor(destHL);
1104 label.highlightLast(hl);
1105 }
1106 } else {
1107 if (withDepartedText) {
1108 String pre = "Departed for ";
1109 if (type == ETAType.RETURNING) {
1110 pre = "Returning to ";
1111 }
1112 label = info.addPara(pre + destName, tc, initPad);
1113
1114 if (destHL != null && label != null) {
1115 label.setHighlightColor(destHL);
1116 label.setHighlight(hl);
1117 }
1118 initPad = 0f;
1119 }
1120 if ((int) eta > 0) {
1121 String days = (int)eta == 1 ? "day" : "days";
1122 String post = " until arrival";
1123 if (type == ETAType.RETURNING) {
1124 post = " until return";
1125 }
1126 if (!withDepartedText) {
1127 if (type == ETAType.RETURNING) post += " to " + destName;
1128 else if (type == ETAType.ARRIVING) post += " at " + destName;
1129 }
1130 label = info.addPara("Estimated %s " + days + post, initPad, tc, h, "" + (int) eta);
1131
1132 if (!withDepartedText && destHL != null && label != null) {
1133 label.setHighlightColors(h, destHL);
1134 label.setHighlight("" + (int) eta, hl);
1135 }
1136 } else {
1137 String pre = "Arrival at ";
1138 if (type == ETAType.RETURNING) {
1139 pre = "Return to ";
1140 }
1141 label = info.addPara(pre + destName + " is imminent", tc, initPad);
1142
1143 if (destHL != null && label != null) {
1144 label.setHighlightColor(destHL);
1145 label.highlightLast(hl);
1146 }
1147 }
1148 }
1149 }
1150
1151
1152 @Override
1153 public void createSmallDescription(TooltipMakerAPI info, float width, float height) {
1154 Color h = Misc.getHighlightColor();
1155 Color g = Misc.getGrayColor();
1156 Color tc = Misc.getTextColor();
1157 float pad = 3f;
1158 float opad = 10f;
1159
1160 addBasicDescription(info, width, height, opad);
1161
1162 addAssessmentSection(info, width, height, opad);
1163
1164 addStatusSection(info, width, height, opad);
1165
1166 addBulletPoints(info, ListInfoMode.IN_DESC);
1167 }
1168
1169 protected void showMarketsInDanger(TooltipMakerAPI info, float opad, float width, StarSystemAPI system,
1170 List<MarketAPI> targets, String safeStr, String riskStr, String riskStrHighlight) {
1171
1172 Color h = Misc.getHighlightColor();
1173 float raidStr = getRoute().getExtra().getStrengthModifiedByDamage();
1174 float defenderStr = WarSimScript.getEnemyStrength(getFaction(), system, isPlayerTargeted());
1175
1176 List<MarketAPI> safe = new ArrayList<MarketAPI>();
1177 List<MarketAPI> unsafe = new ArrayList<MarketAPI>();
1178 for (MarketAPI market : targets) {
1179 float defensiveStr = defenderStr + WarSimScript.getStationStrength(market.getFaction(), system, market.getPrimaryEntity());
1180 if (defensiveStr > raidStr * 1.25f) {
1181 safe.add(market);
1182 } else {
1183 unsafe.add(market);
1184 }
1185 }
1186
1187 if (safe.size() == targets.size()) {
1188 info.addPara("However, all colonies " + safeStr + ", " +
1189 "owing to their orbital defenses.", opad);
1190 } else {
1191 info.addPara("The following colonies " + riskStr, opad,
1192 Misc.getNegativeHighlightColor(), riskStrHighlight);
1193
1194 FactionAPI f = Global.getSector().getPlayerFaction();
1195 addMarketTable(info, f.getBaseUIColor(), f.getDarkUIColor(), f.getBrightUIColor(), unsafe, width, opad);
1196 }
1197 }
1198
1206 public int getRelativeFGStrength(StarSystemAPI target) {
1207 float raidStr = getRoute().getExtra().getStrengthModifiedByDamage();
1208 float defenderStr = 0f;
1209 if (target != null) defenderStr = WarSimScript.getEnemyStrength(getFaction(), target, isPlayerTargeted());
1210
1211 if (raidStr < defenderStr * 0.75f) {
1212 return -1;
1213 } else if (raidStr < defenderStr * 1.25f) {
1214 return 0;
1215 } else {
1216 return 1;
1217 }
1218 }
1219
1224 protected boolean addStrengthDesc(TooltipMakerAPI info, float opad, StarSystemAPI system,
1225 String forces, String outcomeFailure, String outcomeUncertain, String outcomeSuccess) {
1226 Color h = Misc.getHighlightColor();
1227
1228 float raidStr = getRoute().getExtra().getStrengthModifiedByDamage();
1229 float defenderStr = 0f;
1230 if (system != null) defenderStr = WarSimScript.getEnemyStrength(getFaction(), system, isPlayerTargeted());
1231
1232 String strDesc = Misc.getStrengthDesc(raidStr);
1233 int numFleets = (int) getApproximateNumberOfFleets();
1234 String fleets = "fleets";
1235 if (numFleets == 1) fleets = "fleet";
1236
1237 String defenderDesc = "";
1238 String defenderHighlight = "";
1239 Color defenderHighlightColor = h;
1240
1241 boolean potentialDanger = false;
1242 String outcome = null;
1243 if (raidStr < defenderStr * 0.75f) {
1244 defenderDesc = "The defending fleets are superior";
1245 defenderHighlightColor = Misc.getPositiveHighlightColor();
1246 defenderHighlight = "superior";
1247 outcome = outcomeFailure;
1248 } else if (raidStr < defenderStr * 1.25f) {
1249 defenderDesc = "The defending fleets are evenly matched";
1250 defenderHighlightColor = h;
1251 defenderHighlight = "evenly matched";
1252 outcome = outcomeUncertain;
1253 potentialDanger = true;
1254 } else {
1255 defenderDesc = "The defending fleets are outmatched";
1256 defenderHighlightColor = Misc.getNegativeHighlightColor();
1257 defenderHighlight = "outmatched";
1258 outcome = outcomeSuccess;
1259 potentialDanger = true;
1260 }
1261
1262 if (outcome != null) {
1263 defenderDesc += ", and " + outcome + ".";
1264 } else {
1265 defenderDesc += ".";
1266 }
1267
1268 defenderDesc = " " + defenderDesc;
1269
1270 if (system == null) defenderDesc = "";
1271
1272
1273 LabelAPI label = info.addPara("The " + forces + " are " +
1274 "projected to be %s and likely comprised of %s " + fleets + "." + defenderDesc,
1275 opad, h, strDesc, "" + numFleets);
1276 label.setHighlight(strDesc, "" + numFleets, defenderHighlight);
1277 label.setHighlightColors(h, h, defenderHighlightColor);
1278
1279 return potentialDanger;
1280 }
1281
1282
1287 protected boolean addStrengthDesc(TooltipMakerAPI info, float opad, MarketAPI target,
1288 String forces, String outcomeFailure, String outcomeUncertain, String outcomeSuccess) {
1289 Color h = Misc.getHighlightColor();
1290
1291 float raidStr = getRoute().getExtra().getStrengthModifiedByDamage();
1292 float defenderStr = 0f;
1293 StarSystemAPI system = target.getStarSystem();
1294 if (system != null) defenderStr = WarSimScript.getEnemyStrength(getFaction(), system, isPlayerTargeted());
1295
1296 defenderStr += WarSimScript.getStationStrength(target.getFaction(), system, target.getPrimaryEntity());
1297
1298 String strDesc = Misc.getStrengthDesc(raidStr);
1299 int numFleets = (int) getApproximateNumberOfFleets();
1300 String fleets = "fleets";
1301 if (numFleets == 1) fleets = "fleet";
1302
1303 String defenderDesc = "";
1304 String defenderHighlight = "";
1305 Color defenderHighlightColor = h;
1306
1307 boolean potentialDanger = false;
1308 String outcome = null;
1309 if (raidStr < defenderStr * 0.75f) {
1310 defenderDesc = "The defending forces are superior";
1311 defenderHighlightColor = Misc.getPositiveHighlightColor();
1312 defenderHighlight = "superior";
1313 outcome = outcomeFailure;
1314 } else if (raidStr < defenderStr * 1.25f) {
1315 defenderDesc = "The defending forces are evenly matched";
1316 defenderHighlightColor = h;
1317 defenderHighlight = "evenly matched";
1318 outcome = outcomeUncertain;
1319 potentialDanger = true;
1320 } else {
1321 defenderDesc = "The defending forces are outmatched";
1322 defenderHighlightColor = Misc.getNegativeHighlightColor();
1323 defenderHighlight = "outmatched";
1324 outcome = outcomeSuccess;
1325 potentialDanger = true;
1326 }
1327
1328 if (outcome != null) {
1329 defenderDesc += ", and " + outcome + ".";
1330 } else {
1331 defenderDesc += ".";
1332 }
1333
1334 defenderDesc = " " + defenderDesc;
1335
1336 if (system == null) defenderDesc = "";
1337
1338
1339 LabelAPI label = info.addPara("The " + forces + " are " +
1340 "projected to be %s and likely comprised of %s " + fleets + "." + defenderDesc,
1341 opad, h, strDesc, "" + numFleets);
1342 label.setHighlight(strDesc, "" + numFleets, defenderHighlight);
1343 label.setHighlightColors(h, h, defenderHighlightColor);
1344
1345 return potentialDanger;
1346 }
1347
1348
1349
1350 public FGIEventListener getListener() {
1351 return listener;
1352 }
1353
1354 public void setListener(FGIEventListener listener) {
1355 this.listener = listener;
1356 }
1357
1358 @Override
1359 public String getCommMessageSound() {
1360 if (isSendingUpdate()) {
1361 return getSoundStandardUpdate();
1362 }
1363 return getSoundMajorPosting();
1364 }
1365
1366
1367}
1368
1369
1370
1371
static SectorAPI getSector()
Definition Global.java:59
static void addMarketTable(TooltipMakerAPI info, Color base, Color dark, Color bright, List< MarketAPI > markets, float width, float pad)
void sendUpdateIfPlayerHasIntel(Object listInfoParam, TextPanelAPI textPanel)
float getETAUntil(String actionId, boolean untilEndOfAction)
void addArrivedBulletPoint(String destName, Color destHL, TooltipMakerAPI info, Color tc, float initPad)
void createRoute(String factionId, int approximateTotalDifficultyPoints, int approximateNumberOfFleets, Object custom)
void setFleetAbortsMissionFPFraction(float fleetAbortsMissionFPFraction)
void addETABulletPoints(String destName, Color destHL, boolean withDepartedText, float eta, ETAType type, TooltipMakerAPI info, Color tc, float initPad)
void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode)
void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode)
abstract void addUpdateBulletPoints(TooltipMakerAPI info, Color tc, Object param, ListInfoMode mode, float initPad)
void showMarketsInDanger(TooltipMakerAPI info, float opad, float width, StarSystemAPI system, List< MarketAPI > targets, String safeStr, String riskStr, String riskStrHighlight)
static LocationAPI getLocationForState(RouteSegment segment, TravelState state)
boolean addStrengthDesc(TooltipMakerAPI info, float opad, StarSystemAPI system, String forces, String outcomeFailure, String outcomeUncertain, String outcomeSuccess)
void setGroupAbortsMissionFPFraction(float groupAbortsMissionFPFraction)
void addFactionBulletPoint(TooltipMakerAPI info, Color tc, float initPad)
static void setLocationAndCoordinates(CampaignFleetAPI fleet, RouteSegment current)
abstract void addNonUpdateBulletPoints(TooltipMakerAPI info, Color tc, Object param, ListInfoMode mode, float initPad)
void addAssessmentSection(TooltipMakerAPI info, float width, float height, float opad)
void addStatusSection(TooltipMakerAPI info, float width, float height, float opad)
void createSmallDescription(TooltipMakerAPI info, float width, float height)
static float getApproximateStrengthForTotalDifficultyPoints(String factionId, int points)
void addBasicDescription(TooltipMakerAPI info, float width, float height, float opad)
boolean addStrengthDesc(TooltipMakerAPI info, float opad, MarketAPI target, String forces, String outcomeFailure, String outcomeUncertain, String outcomeSuccess)