Starsector API
Loading...
Searching...
No Matches
RaidIntel.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.intel.raid;
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.SectorEntityToken;
15import com.fs.starfarer.api.campaign.StarSystemAPI;
16import com.fs.starfarer.api.campaign.comm.IntelInfoPlugin;
17import com.fs.starfarer.api.campaign.econ.MarketAPI;
18import com.fs.starfarer.api.impl.campaign.DebugFlags;
19import com.fs.starfarer.api.impl.campaign.command.WarSimScript;
20import com.fs.starfarer.api.impl.campaign.fleets.FleetFactoryV3;
21import com.fs.starfarer.api.impl.campaign.fleets.FleetParamsV3;
22import com.fs.starfarer.api.impl.campaign.fleets.RouteLocationCalculator;
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.ids.Factions;
27import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
28import com.fs.starfarer.api.impl.campaign.ids.Ranks;
29import com.fs.starfarer.api.impl.campaign.ids.Tags;
30import com.fs.starfarer.api.impl.campaign.intel.BaseIntelPlugin;
31import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseAssignmentAI.FleetActionDelegate;
32import com.fs.starfarer.api.impl.campaign.procgen.themes.RouteFleetAssignmentAI;
33import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.MarketCMD;
34import com.fs.starfarer.api.ui.Alignment;
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.Misc;
39
40public class RaidIntel extends BaseIntelPlugin implements RouteFleetSpawner {
41
42 public static Object UPDATE_FAILED = new Object();
43 public static Object UPDATE_RETURNING = new Object();
44 public static Object ENTERED_SYSTEM_UPDATE = new Object();
45
46 public static enum RaidStageStatus {
47 ONGOING,
48 SUCCESS,
49 FAILURE,
50 }
51
52 public static interface RaidDelegate {
53 void notifyRaidEnded(RaidIntel raid, RaidStageStatus status);
54 }
55
56 public static interface RaidStage {
57 RaidStageStatus getStatus();
58 void advance(float amount);
59 void notifyStarted();
60 float getExtraDaysUsed();
61 void showStageInfo(TooltipMakerAPI info);
62 float getElapsed();
63 float getMaxDays();
64 }
65
66 protected int currentStage = 0;
67 protected int failStage = -1;
68 protected List<RaidStage> stages = new ArrayList<RaidStage>();
69
70 protected String id = Misc.genUID();
71 protected String sid = "raid_" + id;
72
73 protected float extraDays = 60f;
74 protected StarSystemAPI system;
75 protected FactionAPI faction;
76 protected float defenderStr = 0f;
77 protected RaidDelegate delegate;
78
79 public RaidIntel(StarSystemAPI system, FactionAPI faction, RaidDelegate delegate) {
80
81 //RAID_DEBUG = false;
82
83 this.system = system;
84 this.faction = faction;
85 this.delegate = delegate;
86
87 Global.getSector().addScript(this);
88// Global.getSector().getIntelManager().addIntel(this);
89
90
91// List<MarketAPI> targets = new ArrayList<MarketAPI>();
92// for (MarketAPI market : Misc.getMarketsInLocation(system)) {
93// if (market.getFaction().isHostileTo(getFaction())) {
94// targets.add(market);
95// }
96// }
97 defenderStr = WarSimScript.getEnemyStrength(getFaction(), system);
98 }
99
101 //sendUpdateIfPlayerHasIntel(ENTERED_SYSTEM_UPDATE, false);
102 }
103
104 public StarSystemAPI getSystem() {
105 return system;
106 }
107
108
109 public int getCurrentStage() {
110 return currentStage;
111 }
112
113 public int getStageIndex(RaidStage stage) {
114 return stages.indexOf(stage);
115 }
116
117 public int getFailStage() {
118 return failStage;
119 }
120
122 for (RaidStage stage : stages) {
123 if (stage instanceof OrganizeStage) {
124 return (OrganizeStage) stage;
125 }
126 }
127 return null;
128 }
130 for (RaidStage stage : stages) {
131 if (stage instanceof AssembleStage) {
132 return (AssembleStage) stage;
133 }
134 }
135 return null;
136 //return (AssembleStage) stages.get(0);
137 }
138
140 for (RaidStage stage : stages) {
141 if (stage instanceof ActionStage) {
142 return (ActionStage) stage;
143 }
144 }
145 return null;
146 //return (AssembleStage) stages.get(0);
147 }
148
149 public void addStage(RaidStage stage) {
150 stages.add(stage);
151 }
152
153 public String getRouteSourceId() {
154 return sid;
155 }
156
157 public float getExtraDays() {
158 return extraDays;
159 }
160
161 public void setExtraDays(float extraDays) {
162 this.extraDays = extraDays;
163 }
164
165
166
167 @Override
168 public boolean canMakeVisibleToPlayer(boolean playerInRelayRange) {
169 return super.canMakeVisibleToPlayer(playerInRelayRange);
170 }
171
172 public boolean shouldSendUpdate() {
173 if (DebugFlags.SEND_UPDATES_WHEN_NO_COMM || Global.getSector().getIntelManager().isPlayerInRangeOfCommRelay()) {
174 return true;
175 }
176 if (system != null && system == Global.getSector().getCurrentLocation()) {
177 return true;
178 }
179
180 return isPlayerTargeted();
181 }
182
183 public boolean isPlayerTargeted() {
184 ActionStage action = getActionStage();
185 if (action != null && action.isPlayerTargeted()) return true;
186 return false;
187 }
188
189 public String getCommMessageSound() {
190 if (isPlayerTargeted() && !isSendingUpdate()) {
191 return getSoundColonyThreat();
192 }
193
194 if (isSendingUpdate()) {
195 return getSoundStandardUpdate();
196 }
197 return getSoundMajorPosting();
198 }
199
200 @Override
201 protected void advanceImpl(float amount) {
202 super.advanceImpl(amount);
203
204 if (currentStage >= stages.size()) {
206 // do we really need an update after the raiders have returned to their source colonies?
207 // as far as the player is concerned, the raid is really over when they head back, not when they get back
208
209 // actually, the return stage finishes immediately since its updateStatus() sets to SUCCESS right away
210 // so this update gets sent right after the action stage succeeds
211 if (shouldSendUpdate()) {
213 }
214 return;
215 }
216
217 RaidStage stage = stages.get(currentStage);
218
219 stage.advance(amount);
220
221 RaidStageStatus status = stage.getStatus();
222 if (status == RaidStageStatus.SUCCESS) {
223 currentStage++;
224 setExtraDays(Math.max(0, getExtraDays() - stage.getExtraDaysUsed()));
225 if (currentStage < stages.size()) {
226 stages.get(currentStage).notifyStarted();
227 }
228 return;
229 } else if (status == RaidStageStatus.FAILURE) {
230 failedAtStage(stage);
233 if (shouldSendUpdate()) {
235 }
236 }
237 }
238
239 public void forceFail(boolean withUpdate) {
240 int index = currentStage;
241 if (index >= stages.size()) index = stages.size() - 1;
242 failedAtStage(stages.get(index));
245 if (withUpdate && shouldSendUpdate()) {
247 }
248 }
249
250 protected void failedAtStage(RaidStage stage) {
251
252 }
253
254
255 @Override
256 protected void notifyEnded() {
257 super.notifyEnded();
258 Global.getSector().removeScript(this);
259 }
260
261 @Override
262 protected void notifyEnding() {
263 super.notifyEnding();
264
265 if (delegate != null) {
266 RaidStageStatus status = RaidStageStatus.SUCCESS;
267 if (failStage >= 0) {
268 status = RaidStageStatus.FAILURE;
269 }
270 delegate.notifyRaidEnded(this, status);
271 }
272 }
273
274
275 public float getETA() {
276 int curr = getCurrentStage();
277 float eta = 0f;
278 for (RaidStage stage : stages) {
279 if (stage instanceof ActionStage) {
280 break;
281 }
282 //RouteLocationCalculator.getTravelDays(((TravelStage)stage).from, ((TravelStage)stage).to)
283 int index = getStageIndex(stage);
284 if (index < curr) {
285 continue;
286 }
287 if (stage instanceof OrganizeStage) {
288 eta += Math.max(0f, stage.getMaxDays() - stage.getElapsed());
289 } else if (stage instanceof AssembleStage) {
290 eta += Math.max(0f, 20f - stage.getElapsed());
291 } else if (stage instanceof TravelStage) {
292 float travelDays = RouteLocationCalculator.getTravelDays(getAssembleStage().gatheringPoint, system.getHyperspaceAnchor());
293 eta += Math.max(0f, travelDays - stage.getElapsed());
294 }
295 }
296 return eta;
297 }
298
299 protected void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode) {
300
301 Color h = Misc.getHighlightColor();
302 Color g = Misc.getGrayColor();
303 float pad = 3f;
304 float opad = 10f;
305
306 float initPad = pad;
307 if (mode == ListInfoMode.IN_DESC) initPad = opad;
308
309 Color tc = getBulletColorForMode(mode);
310
311 bullet(info);
312 boolean isUpdate = getListInfoParam() != null;
313
314 float eta = getETA();
315
316 info.addPara("Faction: " + faction.getDisplayName(), initPad, tc,
317 faction.getBaseUIColor(), faction.getDisplayName());
318 initPad = 0f;
319
320 int max = 0;
321 MarketAPI target = null;
322 for (MarketAPI other : Misc.getMarketsInLocation(system)) {
323 if (!other.getFaction().isHostileTo(faction)) continue;
324 int size = other.getSize();
325 if (size > max || (size == max && other.getFaction().isPlayerFaction())) {
326 max = size;
327 target = other;
328 }
329 }
330
331
332 if (target != null) {
333 FactionAPI other = target.getFaction();
334 info.addPara("Target: " + other.getDisplayName(), initPad, tc,
335 other.getBaseUIColor(), other.getDisplayName());
336 }
337
338 if (isUpdate) {
340 info.addPara("Arrived in-system", tc, initPad);
341 } else {
342 if (failStage < 0) {
343 info.addPara("Colonies in the " + system.getNameWithLowercaseType() + " have been raided",
344 tc, initPad);
345 } else {
346 info.addPara("The raid on the " + system.getNameWithLowercaseType() + " has failed",
347 tc, initPad);
348 }
349 }
350 } else {
351 info.addPara(system.getNameWithLowercaseType(),
352 tc, initPad);
353 }
354 initPad = 0f;
355 if (eta > 1 && failStage < 0 && getListInfoParam() != ENTERED_SYSTEM_UPDATE) {
356 String days = getDaysString(eta);
357 info.addPara("Estimated %s " + days + " until arrival",
358 initPad, tc, h, "" + (int)Math.round(eta));
359 initPad = 0f;
360 }
361
362 unindent(info);
363 }
364
365 @Override
366 public void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode) {
367 Color c = getTitleColor(mode);
368
369 if (isPlayerTargeted() && false) {
370 info.setParaSmallInsignia();
371 } else {
372 info.setParaFontDefault();
373 }
374
375 info.addPara(getName(), c, 0f);
376 info.setParaFontDefault();
377 addBulletPoints(info, mode);
378 }
379
380 protected MarketAPI getFirstSource() {
382 if (as == null) return null;
383 if (as.getSources() == null || as.getSources().isEmpty()) return null;
384 return as.getSources().get(0);
385 }
386
387 @Override
388 public void createSmallDescription(TooltipMakerAPI info, float width, float height) {
389 Color h = Misc.getHighlightColor();
390 Color g = Misc.getGrayColor();
391 Color tc = Misc.getTextColor();
392 float pad = 3f;
393 float opad = 10f;
394
395 info.addImage(getFactionForUIColors().getLogo(), width, 128, opad);
396
397 FactionAPI faction = getFaction();
398 String has = faction.getDisplayNameHasOrHave();
399 String is = faction.getDisplayNameIsOrAre();
400
402 MarketAPI source = getFirstSource();
403
404 //float raidStr = as.getSpawnFP();
405 float raidStr = as.getOrigSpawnFP();
406 raidStr = Misc.getAdjustedStrength(raidStr, source);
407
408// String strDesc = "";
409// // fp, multiplied by roughly 0.25 to 4, depending on quality, colony size, doctrine
410// if (raidStr < 150) {
411// strDesc = "very weak";
412// } else if (raidStr < 300) {
413// strDesc = "somewhat weak";
414// } else if (raidStr < 500) {
415// strDesc = "fairly strong";
416// } else if (raidStr < 1000) {
417// strDesc = "strong";
418// } else {
419// strDesc = "very strong";
420// }
421
422 String strDesc = getRaidStrDesc();
423 int numFleets = (int) getOrigNumFleets();
424 String fleets = "fleets";
425 if (numFleets == 1) fleets = " large fleet, or several smaller ones";
426
427 LabelAPI label = info.addPara(Misc.ucFirst(faction.getDisplayNameWithArticle()) + " " + is +
428 " conducting a raid of the " + system.getName() + ". The raiding forces are " +
429 "projected to be " + strDesc +
430 " and likely comprised of " + numFleets + " " + fleets + ".",
431 opad, faction.getBaseUIColor(), faction.getDisplayNameWithArticleWithoutArticle());
432 label.setHighlight(faction.getDisplayNameWithArticleWithoutArticle(), strDesc, "" + numFleets);
433 label.setHighlightColors(faction.getBaseUIColor(), h, h);
434
435 List<MarketAPI> targets = new ArrayList<MarketAPI>();
436 for (MarketAPI market : Misc.getMarketsInLocation(system)) {
437 if (market.getFaction().isHostileTo(faction)) {
438 targets.add(market);
439 }
440 }
441
442 defenderStr = WarSimScript.getEnemyStrength(getFaction(), system);
443
444 List<MarketAPI> safe = new ArrayList<MarketAPI>();
445 List<MarketAPI> unsafe = new ArrayList<MarketAPI>();
446 for (MarketAPI market : targets) {
447 float defensiveStr = defenderStr + WarSimScript.getStationStrength(market.getFaction(), system, market.getPrimaryEntity());
448 if (defensiveStr > raidStr * 1.25f) {
449 safe.add(market);
450 } else {
451 unsafe.add(market);
452 }
453 }
454
455 if (!isEnding()) {
456 if (targets.isEmpty()) {
457 info.addPara("There are no colonies for the raid to target in the system.", opad);
458 } else {
459 boolean showSafe = false;
460 if (raidStr < defenderStr * 0.75f) {
461 info.addPara("The raiding forces should be outmatched by fleets defending the system. In the absence of " +
462 "other factors, the raid is unlikely to find success.", opad);
463 } else if (raidStr < defenderStr * 1.25f) {
464 info.addPara("The raiding forces are evenly matched with fleets defending the system.", opad);
465 showSafe = true;
466 } else {
467 info.addPara("The raiding forces are superior to the fleets defending the system.", opad);
468 showSafe = true;
469 }
470 if (showSafe) {
471 if (safe.size() == targets.size()) {
472 info.addPara("However, all colonies should be safe from the raid, " +
473 "owing to their orbital defenses.", opad);
474 } else {
475 info.addPara("Considering orbital defenses (if any), the following colonies are " +
476 "at risk from the raid:", opad);
477 float initPad = opad;
478 for (MarketAPI market : unsafe) {
479 addMarketToList(info, market, initPad, tc);
480 initPad = 0f;
481 }
482
483 // info.addPara("Unless the raid is stopped, these colonies " +
484 // "may suffer " +
485 // "reduced stability, infrastructure damage, and a possible loss of stockpiled resources.", opad);
486
487 }
488 }
489 }
490 }
491
492 info.addSectionHeading("Status",
493 faction.getBaseUIColor(), faction.getDarkUIColor(), Alignment.MID, opad);
494
495 for (RaidStage stage : stages) {
496 stage.showStageInfo(info);
497 if (getStageIndex(stage) == failStage) break;
498 }
499 }
500
501
502
503 @Override
504 public String getIcon() {
505 return faction.getCrest();
506 }
507
508 @Override
509 public Set<String> getIntelTags(SectorMapAPI map) {
510 Set<String> tags = super.getIntelTags(map);
511 tags.add(Tags.INTEL_MILITARY);
512 if (!Misc.getMarketsInLocation(system, Factions.PLAYER).isEmpty()) {
513 tags.add(Tags.INTEL_COLONIES);
514 }
515 tags.add(getFaction().getId());
516 return tags;
517 }
518
519 public String getSortString() {
520 return "Raid";
521 }
522
523 public String getName() {
524 String base = Misc.ucFirst(getFaction().getPersonNamePrefix()) + " Raid";
525 if (isEnding()) {
526 if (isSendingUpdate() && failStage >= 0) {
527 return base + " - Failed";
528 }
529 for (RaidStage stage : stages) {
530 if (stage instanceof ActionStage && stage.getStatus() == RaidStageStatus.SUCCESS) {
531 return base + " - Successful";
532 }
533 }
534 return base + " - Over";
535 }
536 return base;
537 }
538
539 public boolean isFailed() {
540 return failStage >= 0;
541 }
542
543 public boolean isSucceeded() {
544 for (RaidStage stage : stages) {
545 if (stage instanceof ActionStage && stage.getStatus() == RaidStageStatus.SUCCESS) {
546 return true;
547 }
548 }
549 return false;
550 }
551
552
553 @Override
554 public FactionAPI getFactionForUIColors() {
555 return getFaction();
556 }
557
558 public FactionAPI getFaction() {
559 return faction;
560 }
561
562 public String getSmallDescriptionTitle() {
563 return getName();
564 }
565
566 @Override
567 public SectorEntityToken getMapLocation(SectorMapAPI map) {
568 return system.getHyperspaceAnchor();
569 }
570
571 public List<ArrowData> getArrowData(SectorMapAPI map) {
573 if (as == null || !as.isSourceKnown()) return null;
574
575
576 SectorEntityToken from = as.gatheringPoint;
577 if (system == null|| system == from.getContainingLocation()) return null;
578
579 List<ArrowData> result = new ArrayList<ArrowData>();
580
581 SectorEntityToken entityFrom = from;
582 if (map != null && delegate instanceof IntelInfoPlugin && delegate != this) {
583 SectorEntityToken iconEntity = map.getIntelIconEntity((IntelInfoPlugin)delegate);
584 if (iconEntity != null) {
585 entityFrom = iconEntity;
586 }
587 }
588
589 ArrowData arrow = new ArrowData(entityFrom, system.getCenter());
590 arrow.color = getFactionForUIColors().getBaseUIColor();
591 arrow.width = 20f;
592 result.add(arrow);
593
594 return result;
595 }
596
597 public boolean shouldCancelRouteAfterDelayCheck(RouteData route) {
598 return false;
599 }
600
601 public boolean shouldRepeat(RouteData route) {
602 return false;
603 }
604
605 public void reportAboutToBeDespawnedByRouteManager(RouteData route) {
606 }
607
608
609
610 public CampaignFleetAPI spawnFleet(RouteData route) {
611
612 Random random = route.getRandom();
613
614 MarketAPI market = route.getMarket();
615 CampaignFleetAPI fleet = createFleet(market.getFactionId(), route, market, null, random);
616
617 if (fleet == null || fleet.isEmpty()) return null;
618
619 //fleet.addEventListener(this);
620
621 market.getContainingLocation().addEntity(fleet);
622 fleet.setFacing((float) Math.random() * 360f);
623 // this will get overridden by the patrol assignment AI, depending on route-time elapsed etc
624 fleet.setLocation(market.getPrimaryEntity().getLocation().x, market.getPrimaryEntity().getLocation().x);
625
626 fleet.addScript(createAssignmentAI(fleet, route));
627
628 return fleet;
629 }
630
631 public RouteFleetAssignmentAI createAssignmentAI(CampaignFleetAPI fleet, RouteData route) {
632 ActionStage action = getActionStage();
633 FleetActionDelegate delegate = null;
634 if (action instanceof FleetActionDelegate) {
635 delegate = (FleetActionDelegate) action;
636 }
637 return new RaidAssignmentAI(fleet, route, delegate);
638 }
639
640 public CampaignFleetAPI createFleet(String factionId, RouteData route, MarketAPI market, Vector2f locInHyper, Random random) {
641 if (random == null) random = new Random();
642
643 OptionalFleetData extra = route.getExtra();
644
645 float combat = extra.fp;
646 float tanker = extra.fp * (0.1f + random.nextFloat() * 0.05f);
647 float transport = extra.fp * (0.1f + random.nextFloat() * 0.05f);
648 float freighter = 0f;
649 combat -= tanker;
650 combat -= transport;
651
652 FleetParamsV3 params = new FleetParamsV3(
653 market,
654 locInHyper,
655 factionId,
656 route == null ? null : route.getQualityOverride(),
657 extra.fleetType,
658 combat, // combatPts
659 freighter, // freighterPts
660 tanker, // tankerPts
661 transport, // transportPts
662 0f, // linerPts
663 0f, // utilityPts
664 0f // qualityMod, won't get used since routes mostly have quality override set
665 );
666 //params.ignoreMarketFleetSizeMult = true; // already accounted for in extra.fp
667// if (DebugFlags.RAID_DEBUG) {
668// params.qualityOverride = 1f;
669// }
670 if (route != null) {
671 params.timestamp = route.getTimestamp();
672 }
673 params.random = random;
674 CampaignFleetAPI fleet = FleetFactoryV3.createFleet(params);
675
676 if (fleet == null || fleet.isEmpty()) return null;
677
678 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_WAR_FLEET, true);
679 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_RAIDER, true);
680
681 if (fleet.getFaction().getCustomBoolean(Factions.CUSTOM_PIRATE_BEHAVIOR)) {
682 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_PIRATE, true);
683 }
684
685 String postId = Ranks.POST_PATROL_COMMANDER;
686 String rankId = Ranks.SPACE_COMMANDER;
687
688 fleet.getCommander().setPostId(postId);
689 fleet.getCommander().setRankId(rankId);
690
691 return fleet;
692 }
693
694
695 public float getRaidFPAdjusted() {
696 //AssembleStage as = getAssembleStage();
697 //MarketAPI source = as.getSources().get(0);
698 MarketAPI source = getFirstSource();
699 float raidFP = getRaidFP();
700
701 // fp, multiplied by roughly 0.25 to 4, depending on quality, colony size, doctrine
702 float raidStr = Misc.getAdjustedFP(raidFP, source);
703 return raidStr;
704 }
705
706 public float getRaidFP() {
708 float raidStr = 0f;
709 for (RouteData route : as.getRoutes()) {
710 CampaignFleetAPI fleet = route.getActiveFleet();
711 if (fleet != null) {
712 float mult = Misc.getAdjustedFP(1f, route.getMarket());
713 if (mult < 1) mult = 1f;
714 raidStr += fleet.getFleetPoints() / mult;
715 } else {
716 raidStr += route.getExtra().fp;
717 }
718 }
719 if (raidStr <= 0 || as.getSpawnFP() > 0) {
720 raidStr = Math.max(as.getOrigSpawnFP(), raidStr);
721 }
722 float raidFP = raidStr;
723 return raidFP;
724 }
725
726 public float getNumFleets() {
728 float num = as.getRoutes().size();
729 if (as.getSpawnFP() > 0) {
730 num = Math.max(num, as.getOrigSpawnFP() / as.getLargeSize(false));
731 }
732 if (num < 1) num = 1;
733 return num;
734 }
735
736 public float getOrigNumFleets() {
738 float num = (float) Math.ceil(as.getOrigSpawnFP() / as.getLargeSize(false));
739 if (num < 1) num = 1;
740 return num;
741 }
742
743 public float getRaidStr() {
744// AssembleStage as = getAssembleStage();
745// MarketAPI source = as.getSources().get(0);
746 MarketAPI source = getFirstSource();
747 float raidFP = getRaidFP();
748
749 // fp, multiplied by roughly 0.25 to 4, depending on quality, colony size, doctrine
750 float raidStr = Misc.getAdjustedStrength(raidFP, source);
751 return raidStr;
752 }
753
754 protected String getRaidStrDesc() {
755 return Misc.getStrengthDesc(getRaidStr());
756 }
757
758 public void addStandardStrengthComparisons(TooltipMakerAPI info,
759 MarketAPI target, FactionAPI targetFaction,
760 boolean withGround, boolean withBombard,
761 String raid, String raids) {
762 Color h = Misc.getHighlightColor();
763 float opad = 10f;
764
765 //AssembleStage as = getAssembleStage();
766 //MarketAPI source = as.getSources().get(0);
767 float raidFP = getRaidFPAdjusted() / getNumFleets();
768 float raidStr = getRaidStr();
769
770 //float defenderStr = WarSimScript.getEnemyStrength(getFaction(), system);
771 float defenderStr = WarSimScript.getFactionStrength(targetFaction, system);
772 float defensiveStr = defenderStr + WarSimScript.getStationStrength(targetFaction, system, target.getPrimaryEntity());
773
774 float assumedRaidGroundStr = raidFP * Misc.FP_TO_GROUND_RAID_STR_APPROX_MULT;
775 float re = MarketCMD.getRaidEffectiveness(target, assumedRaidGroundStr);
776
777 String spaceStr = "";
778 String groundStr = "";
779 String outcomeDesc = null;
780 boolean even = false;
781 if (raidStr < defensiveStr * 0.75f) {
782 spaceStr = "outmatched";
783 if (outcomeDesc == null) outcomeDesc = "The " + raid + " is likely to be defeated in orbit";
784 } else if (raidStr < defensiveStr * 1.25f) {
785 spaceStr = "evenly matched";
786 if (outcomeDesc == null) outcomeDesc = "The " + raids + " outcome is uncertain";
787 even = true;
788 } else {
789 spaceStr = "superior";
790 if (!withGround && !withBombard) {
791 if (outcomeDesc == null) outcomeDesc = "The " + raid + " is likely to be successful";
792 }
793 }
794
795 if (withGround) {
796 if (re < 0.33f) {
797 groundStr = "outmatched";
798 if (outcomeDesc == null || even) outcomeDesc = "The " + raid + " is likely to be largely repelled by the ground defences";
799 } else if (re < 0.66f) {
800 groundStr = "evenly matched";
801 if (outcomeDesc == null) outcomeDesc = "The " + raids + " outcome is uncertain";
802 } else {
803 groundStr = "superior";
804 if (outcomeDesc == null) outcomeDesc = "The " + raid + " is likely to be successful";
805 }
806 //info.addPara("Compared to the defenses of " + target.getName() + ", the " + raids + " space forces are %s " +
807 info.addPara("Compared to the defenses, the " + raids + " space forces are %s " +
808 "and its ground forces are %s." +
809 " " + outcomeDesc + ".", opad, h, spaceStr, groundStr);
810 } else if (withBombard) {
811 float required = MarketCMD.getBombardmentCost(target, null);
812 float available = raidFP * Misc.FP_TO_BOMBARD_COST_APPROX_MULT;
813
814 if (required * .67 > available) {
815 groundStr = "outmatched";
816 if (outcomeDesc == null) outcomeDesc = "The bombardment is likely to be countered by the ground defences";
817 } else if (required * 1.33f > available) {
818 groundStr = "evenly matched";
819 if (outcomeDesc == null) outcomeDesc = "The bombardment's outcome is uncertain";
820 } else {
821 groundStr = "superior";
822 if (outcomeDesc == null) outcomeDesc = "The bombardment is likely to be successful";
823 }
824 //info.addPara("Compared to the defenses of " + target.getName() + ", the " + raids + " space forces are %s " +
825 info.addPara("Compared to the defenses, the " + raids + " space forces are %s. " +
826 "" + outcomeDesc + ".", opad, h, spaceStr, groundStr);
827
828 } else {
829 info.addPara("Compared to the defenses of " + target.getName() + ", " +
830 "the " + raids + " space forces are %s." +
831 " " + outcomeDesc + ".", opad, h, spaceStr, groundStr);
832 }
833 }
834
835 @Override
836 public IntelSortTier getSortTier() {
837 if (isPlayerTargeted() && false) {
838 return IntelSortTier.TIER_2;
839 }
840 return super.getSortTier();
841 }
842}
843
844
845
846
847
848
849
static SectorAPI getSector()
Definition Global.java:59
void sendUpdateIfPlayerHasIntel(Object listInfoParam, TextPanelAPI textPanel)
static void addMarketToList(TooltipMakerAPI info, MarketAPI market, float pad)
void createSmallDescription(TooltipMakerAPI info, float width, float height)
SectorEntityToken getMapLocation(SectorMapAPI map)
RaidIntel(StarSystemAPI system, FactionAPI faction, RaidDelegate delegate)
List< ArrowData > getArrowData(SectorMapAPI map)
CampaignFleetAPI createFleet(String factionId, RouteData route, MarketAPI market, Vector2f locInHyper, Random random)
void addStandardStrengthComparisons(TooltipMakerAPI info, MarketAPI target, FactionAPI targetFaction, boolean withGround, boolean withBombard, String raid, String raids)
boolean canMakeVisibleToPlayer(boolean playerInRelayRange)
void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode)
void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode)
RouteFleetAssignmentAI createAssignmentAI(CampaignFleetAPI fleet, RouteData route)