Starsector API
Loading...
Searching...
No Matches
FGRaidAction.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.Collections;
6import java.util.Comparator;
7import java.util.List;
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.ai.CampaignFleetAIAPI;
17import com.fs.starfarer.api.campaign.ai.CampaignFleetAIAPI.ActionType;
18import com.fs.starfarer.api.campaign.econ.Industry;
19import com.fs.starfarer.api.campaign.econ.MarketAPI;
20import com.fs.starfarer.api.impl.campaign.MilitaryResponseScript;
21import com.fs.starfarer.api.impl.campaign.MilitaryResponseScript.MilitaryResponseParams;
22import com.fs.starfarer.api.impl.campaign.command.WarSimScript;
23import com.fs.starfarer.api.impl.campaign.econ.impl.OrbitalStation;
24import com.fs.starfarer.api.impl.campaign.fleets.FleetFactoryV3;
25import com.fs.starfarer.api.impl.campaign.fleets.RouteManager;
26import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.OptionalFleetData;
27import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData;
28import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteSegment;
29import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
30import com.fs.starfarer.api.impl.campaign.ids.Tags;
31import com.fs.starfarer.api.impl.campaign.intel.group.GenericRaidFGI.GenericPayloadAction;
32import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseAssignmentAI.FleetActionDelegate;
33import com.fs.starfarer.api.impl.campaign.procgen.themes.WarfleetAssignmentAI;
34import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.MarketCMD;
35import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.MarketCMD.BombardType;
36import com.fs.starfarer.api.util.CountingMap;
37import com.fs.starfarer.api.util.IntervalUtil;
38import com.fs.starfarer.api.util.Misc;
39
40public class FGRaidAction extends FGDurationAction implements FleetActionDelegate, GenericPayloadAction {
41
42 public static enum FGRaidType {
43 CONCURRENT,
44 SEQUENTIAL,
45 }
46
47
48 public static class FGRaidParams {
49 public StarSystemAPI where;
50 public FGRaidType type = FGRaidType.CONCURRENT;
51 public boolean doNotGetSidetracked = true;
52 public boolean tryToCaptureObjectives = true;
53 public boolean allowAnyHostileMarket = false;
54 public float maxDurationIfSpawnedFleetsConcurrent = 90f;
55 public float maxDurationIfSpawnedFleetsPerSequentialStage = 45f;
56 public int maxStabilityLostPerRaid = 3;
57 public int raidsPerColony = 2;
58
59 public String raidApproachText = null;
60 public String raidActionText = null;
61 public String targetTravelText = null;
62 public boolean appendTargetNameToTravelText = true;
63 public String inSystemActionText = null;
64 public BombardType bombardment = null;
65 public List<String> disrupt = new ArrayList<String>();
66
67 public boolean allowNonHostileTargets = false;
68 public List<MarketAPI> allowedTargets = new ArrayList<MarketAPI>();
69
70 public void setBombardment(BombardType type) {
71 this.bombardment = type;
72 raidApproachText = "moving to bombard";
73 raidActionText = "bombarding";
74 raidsPerColony = 1;
75 }
76
77 public void setDisrupt(String ... industries) {
78 for (String id : industries) {
79 disrupt.add(id);
80 }
81 raidsPerColony = Math.min(disrupt.size(), 3);
82 if (raidsPerColony < 1) raidsPerColony = 1;
83 }
84 }
85
86 public static class RaidSubstage {
87 protected boolean started = false;
88 public float maxDuration;
89 //public int raidsPerformed = 0;
90 public List<SectorEntityToken> objectives = new ArrayList<SectorEntityToken>();
91 public List<SectorEntityToken> markets = new ArrayList<SectorEntityToken>();
92 public List<SectorEntityToken> finishedRaiding = new ArrayList<SectorEntityToken>();
93
94 protected Object readResolve() {
95 if (objectives == null) {
96 objectives = new ArrayList<SectorEntityToken>();
97 }
98 if (markets == null) {
99 markets = new ArrayList<SectorEntityToken>();
100 }
101 if (finishedRaiding == null) {
102 finishedRaiding = new ArrayList<SectorEntityToken>();
103 }
104 return this;
105 }
106
107 public boolean allGoalsAchieved(FGRaidAction action) {
108 if (markets.isEmpty()) {
109 for (SectorEntityToken curr : objectives) {
110 if (curr.getFaction() != action.intel.getFaction()) {
111 return false;
112 }
113 }
114 }
115 for (SectorEntityToken curr : markets) {
116 if (action.raidCount.getCount(curr.getMarket()) < action.params.raidsPerColony) {
117 return false;
118 }
119
120 }
121 return true;
122 }
123 }
124
125 protected IntervalUtil interval = new IntervalUtil(0.1f, 0.3f);
126
127
128 protected boolean computedSubstages = false;
129
130 protected FGRaidParams params;
131 protected CountingMap<MarketAPI> raidCount = new CountingMap<MarketAPI>();
132 protected int bombardCount = 0;
133 protected List<RaidSubstage> stages = new ArrayList<FGRaidAction.RaidSubstage>();
134 protected List<MilitaryResponseScript> scripts = new ArrayList<MilitaryResponseScript>();
135 protected float originalDuration = 0f;
136
137 public FGRaidAction(FGRaidParams params, float raidDays) {
138 super(raidDays);
139 originalDuration = raidDays;
140 this.params = params;
141
142 interval.forceIntervalElapsed();
143 }
144
145 public Object readResolve() {
146 if (raidCount == null) {
147 raidCount = new CountingMap<MarketAPI>();
148 }
149 return this;
150 }
151
152 @Override
153 public void addRouteSegment(RouteData route) {
154 RouteSegment segment = new RouteSegment(getDurDays(), params.where.getCenter());
155 route.addSegment(segment);
156 }
157
158
159 @Override
160 public void notifyFleetsSpawnedMidSegment(RouteSegment segment) {
161 super.notifyFleetsSpawnedMidSegment(segment);
162 }
163
164 @Override
165 public void notifySegmentFinished(RouteSegment segment) {
166 super.notifySegmentFinished(segment);
167
168 autoresolve();
169 }
170
171 protected void computeSubstages() {
172 List<CampaignFleetAPI> fleets = intel.getFleets();
173 if (fleets.isEmpty()) return;
174
175// params.maxDurationIfSpawnedFleetsConcurrent = 90f;
176// params.maxDurationIfSpawnedFleetsPerSequentialStage = 45f;
177// params.maxStabilityLostPerRaid = 3;
178// params.raidsPerColony = 2;
179// params.doNotGetSidetracked = true;
180// params.appendTargetNameToTravelText = true;
181// params.type = FGRaidType.SEQUENTIAL;
182// intel.setApproximateNumberOfFleets(5);
183
184
185 for (CampaignFleetAPI fleet : fleets) {
186 if (!fleet.hasScriptOfClass(WarfleetAssignmentAI.class)) {
187 WarfleetAssignmentAI script = new WarfleetAssignmentAI(fleet, true, true);
188 script.setDelegate(this);
189 fleet.addScript(script);
190 }
191 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_WAR_FLEET, true);
192 fleet.getMemoryWithoutUpdate().unset(MemFlags.FLEET_BUSY);
193 //fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_PIRATE, true);
194 }
195
196 List<MarketAPI> sortedTargetMarkets = new ArrayList<MarketAPI>();
197 for (MarketAPI market : Misc.getMarketsInLocation(params.where)) {
198 if (!params.allowAnyHostileMarket && !params.allowedTargets.contains(market)) continue;
199 if (!params.allowNonHostileTargets && !intel.getFaction().isHostileTo(market.getFaction())) continue;
200
201 sortedTargetMarkets.add(market);
202 }
203
204 final Vector2f sortLoc = new Vector2f(fleets.get(0).getLocation());
205 Collections.sort(sortedTargetMarkets, new Comparator<MarketAPI>() {
206 public int compare(MarketAPI o1, MarketAPI o2) {
207 float d1 = Misc.getDistance(sortLoc, o1.getPrimaryEntity().getLocation());
208 float d2 = Misc.getDistance(sortLoc, o2.getPrimaryEntity().getLocation());
209 return (int) Math.signum(d1 - d2);
210 }
211 });
212
213 // otherwise, WasSimScript adds extra MilitaryResponseScripts for objectives and
214 // attacking fleets go there almost to the exclusion of other targets
215 for (SectorEntityToken objective : params.where.getEntitiesWithTag(Tags.OBJECTIVE)) {
216 WarSimScript.setNoFightingForObjective(objective, intel.getFaction(), 1000f);
217 }
218
219 List<SectorEntityToken> objectives = new ArrayList<SectorEntityToken>();
220 float minDist = Float.MAX_VALUE;
221 SectorEntityToken closest = null;
222 for (SectorEntityToken objective : params.where.getEntitiesWithTag(Tags.NAV_BUOY)) {
223 float dist = Misc.getDistance(sortLoc, objective.getLocation());
224 if (dist < minDist) {
225 closest = objective;
226 minDist = dist;
227 }
228 }
229 if (closest != null) {
230 objectives.add(closest);
231 }
232
233
234 minDist = Float.MAX_VALUE;
235 closest = null;
236 for (SectorEntityToken objective : params.where.getEntitiesWithTag(Tags.SENSOR_ARRAY)) {
237 float dist = Misc.getDistance(sortLoc, objective.getLocation());
238 if (dist < minDist) {
239 closest = objective;
240 minDist = dist;
241 }
242 }
243 if (closest != null) {
244 objectives.add(closest);
245 }
246
247 if (!params.tryToCaptureObjectives) {
248 objectives.clear();
249 }
250
251 if (params.type == FGRaidType.CONCURRENT) {
252 RaidSubstage stage = new RaidSubstage();
253 stage.maxDuration = params.maxDurationIfSpawnedFleetsConcurrent;
254 stage.objectives.addAll(objectives);
255 for (MarketAPI market : sortedTargetMarkets) {
256 stage.markets.add(market.getPrimaryEntity());
257 }
258 stages.add(stage);
259 } else {
260 if (!objectives.isEmpty()) {
261 RaidSubstage stage = new RaidSubstage();
262 stage.maxDuration = params.maxDurationIfSpawnedFleetsPerSequentialStage;
263 stage.objectives.addAll(objectives);
264 stages.add(stage);
265 }
266
267 for (MarketAPI market : sortedTargetMarkets) {
268 RaidSubstage stage = new RaidSubstage();
269 stage.maxDuration = params.maxDurationIfSpawnedFleetsConcurrent;
270 stage.markets.add(market.getPrimaryEntity());
271 stages.add(stage);
272 }
273 }
274
275 float totalDur = 0f;
276 for (RaidSubstage stage : stages) {
277 totalDur += stage.maxDuration;
278 }
279 setDurDays(totalDur + 10f);
280
281
282 // system defenders protect targeted markets
283 float responseFraction = 1f / Math.max(1f, sortedTargetMarkets.size());
284 for (MarketAPI market : sortedTargetMarkets) {
285 MilitaryResponseParams defParams = new MilitaryResponseParams(ActionType.HOSTILE,
286 "defRaid_" + market.getId(),
287 market.getFaction(),
288 market.getPrimaryEntity(),
289 responseFraction,
290 getDurDays());
291 MilitaryResponseScript defScript = new MilitaryResponseScript(defParams);
292 params.where.addScript(defScript);
293 scripts.add(defScript);
294 }
295
296 computedSubstages = true;
297 }
298
299 public void removeAggroMilitaryScripts(boolean clearAssignments) {
300 if (clearAssignments) {
301 for (CampaignFleetAPI fleet : intel.getFleets()) {
302 fleet.clearAssignments();
303 }
304 }
305 if (scripts != null) {
306 List<MilitaryResponseScript> remove = new ArrayList<MilitaryResponseScript>();
308 if (s.getParams() != null &&
309 s.getParams().responseReason != null && s.getParams().responseReason.startsWith("raid_")) {
310 s.forceDone();
311 remove.add(s);
312 }
313 }
314 scripts.removeAll(remove);
315 }
316 }
317
318 @Override
319 public void setActionFinished(boolean finished) {
320 if (finished && !this.finished) {
321 List<CampaignFleetAPI> fleets = intel.getFleets();
322 for (CampaignFleetAPI fleet : fleets) {
323 fleet.removeScriptsOfClass(WarfleetAssignmentAI.class);
324 Misc.setFlagWithReason(fleet.getMemoryWithoutUpdate(), MemFlags.FLEET_BUSY, fleet.getId(), true, -1f);
325 }
326
327 if (scripts != null) {
329 s.forceDone();
330 }
331 }
332
333 for (SectorEntityToken objective : params.where.getEntitiesWithTag(Tags.OBJECTIVE)) {
334 WarSimScript.removeNoFightingTimeoutForObjective(objective, intel.getFaction());
335 }
336 }
337 super.setActionFinished(finished);
338 }
339
340
341 @Override
342 public void directFleets(float amount) {
343 super.directFleets(amount);
344 if (isActionFinished()) return;
345
346 if (intel.isSpawning()) return; // could happen if source is in same system as target
347
348 List<CampaignFleetAPI> fleets = intel.getFleets();
349 if (fleets.isEmpty()) {
350 setActionFinished(true);
351 return;
352 }
353
354 if (!computedSubstages) {
356 }
357
358 if (stages.isEmpty()) {
359 setActionFinished(true);
360 return;
361 }
362
363 float days = Global.getSector().getClock().convertToDays(amount);
364
365 RaidSubstage stage = stages.get(0);
366 if (!stage.started) {
367 stage.started = true;
368
370
371 List<SectorEntityToken> targets = new ArrayList<SectorEntityToken>(stage.objectives);
372 targets.addAll(stage.markets);
373
374 orderFleetMovements(targets);
375 }
376
377
378 stage.maxDuration -= days;
379 if (stage.maxDuration <= 0 || stage.allGoalsAchieved(this)) {
380 stages.remove(stage);
381 }
382
383
384 interval.advance(days);
385 if (!interval.intervalElapsed()) return;
386
387 boolean inSpawnRange = RouteManager.isPlayerInSpawnRange(params.where.getCenter());
388 if (!inSpawnRange && elapsed > originalDuration) {
389 autoresolve();
390 return;
391 }
392
393
394 for (SectorEntityToken obj : stage.objectives) {
395 if (obj.getFaction() == intel.getFaction()) {
396 WarSimScript.removeFightOrdersFor(obj, intel.getFaction());
397 }
398 }
399
400 boolean someRaidsFinished = false;
401 for (SectorEntityToken e : stage.markets) {
402 if (stage.finishedRaiding.contains(e)) continue;
403 if (!canRaid(null, e.getMarket())) {
404 someRaidsFinished = true;
405 stage.finishedRaiding.add(e);
406 }
407 }
408
409 if (someRaidsFinished) {
410 for (SectorEntityToken e : stage.markets) {
411 WarSimScript.removeFightOrdersFor(e, intel.getFaction());
412 }
413 List<SectorEntityToken> remaining = new ArrayList<SectorEntityToken>();
414 remaining.addAll(stage.markets);
415 remaining.removeAll(stage.finishedRaiding);
416
417 // if wanted to re-fight for objectives that were lost, would add those here, but don't
418
419 if (!remaining.isEmpty()) {
420 orderFleetMovements(remaining);
421 }
422 }
423
424
425
426 for (CampaignFleetAPI fleet : fleets) {
427 if (params.doNotGetSidetracked) {
428 boolean battleNear = false;
429 for (CampaignFleetAPI other : fleets) {
430 if (other == fleet || other.getBattle() == null) continue;
431 if (other.getContainingLocation() != fleet.getContainingLocation());
432 float dist = Misc.getDistance(fleet, other);
433 if (dist < 1000) {
434 CampaignFleetAIAPI ai = fleet.getAI();
435 if (ai != null && ai.wantsToJoin(other.getBattle(), other.getBattle().isPlayerInvolved())) {
436 battleNear = true;
437 break;
438 }
439 }
440 }
441 if (!battleNear) {
442 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_FLEET_DO_NOT_GET_SIDETRACKED, true, 0.4f);
443 }
444 }
445 }
446 }
447
448
449 protected void orderFleetMovements(List<SectorEntityToken> targets) {
450 float responseFraction = 1f / Math.max(1f, targets.size());
451
452 for (SectorEntityToken target : targets) {
453 if (!target.hasTag(Tags.OBJECTIVE) &&!canRaid(null, target.getMarket())) {
454 continue;
455 }
456
457 float rf = responseFraction;
458 MilitaryResponseParams aggroParams = new MilitaryResponseParams(ActionType.HOSTILE,
459 "raid_" + target.getId(),
461 target,
462 rf,
463 getDurDays());
464 if (params.appendTargetNameToTravelText) {
465 aggroParams.travelText =
466 (params.targetTravelText != null ? params.targetTravelText + " " : "traveling to ") + target.getName();
467 } else if (params.targetTravelText != null) {
468 aggroParams.travelText = params.targetTravelText;
469 }
470
471 if (params.inSystemActionText != null) {
472 aggroParams.actionText = params.inSystemActionText;
473 } else {
474 aggroParams.actionText = "raiding system";
475 }
476
477 MilitaryResponseScript script = new MilitaryResponseScript(aggroParams);
478 params.where.addScript(script);
479 scripts.add(script);
480 }
481 }
482
483 public FGRaidParams getParams() {
484 return params;
485 }
486
487
488 public boolean canRaid(CampaignFleetAPI fleet, MarketAPI market) {
489 if (market == null) return false;
490 if (!market.isInEconomy()) {
491 return false;
492 }
493 if (!params.allowedTargets.contains(market) && !params.allowedTargets.isEmpty() && !params.allowAnyHostileMarket) {
494 return false;
495 }
496 if (raidCount.getCount(market) >= params.raidsPerColony) {
497 return false;
498 }
499
500 if (fleet != null && !intel.getFleets().contains(fleet)) {
501 return false;
502 }
503
504 if (params.bombardment != null && fleet != null) {
505 float fp = fleet.getFleetPoints();
506 for (CampaignFleetAPI other : intel.getFleets()) {
507 if (other == fleet) continue;
508 if (other.getContainingLocation() != fleet.getContainingLocation()) continue;
509 float dist = Misc.getDistance(fleet, other);
510 if (dist > 1000) continue;
511 float otherFP = other.getFleetPoints();
512 if (otherFP > fp * 1.2f) {
513 return false;
514 }
515 }
516 }
517
518 FactionAPI faction = intel.getFaction();
519 if (fleet != null) {
520 faction = fleet.getFaction();
521 }
522 boolean hostile = market.getFaction().isHostileTo(faction);
523 if (fleet != null) {
524 hostile |= Misc.isFleetMadeHostileToFaction(fleet, market.getFaction());
525 }
526 return (params.allowNonHostileTargets || hostile) && !isActionFinished();
527 }
528
529
530 public void performRaid(CampaignFleetAPI fleet, MarketAPI market) {
531 raidCount.add(market);
532
533 FactionAPI faction = intel.getFaction();
534 if (fleet != null) {
535 faction = fleet.getFaction();
536 }
537
538 if (params.bombardment != null) {
539 float cost = MarketCMD.getBombardmentCost(market, fleet);
540 float bombardStr = intel.getRoute().getExtra().getStrengthModifiedByDamage() / intel.getApproximateNumberOfFleets() *
541 Misc.FP_TO_BOMBARD_COST_APPROX_MULT;
542 if (fleet != null) {
543 bombardStr = fleet.getCargo().getMaxFuel() * 0.5f;
544 }
545
546 if (cost <= bombardStr) {
547 new MarketCMD(market.getPrimaryEntity()).doBombardment(intel.getFaction(), params.bombardment);
548 bombardCount++;
549 } else {
550 Misc.setFlagWithReason(market.getMemoryWithoutUpdate(), MemFlags.RECENTLY_BOMBARDED,
551 intel.getFaction().getId(), true, 30f);
552 }
553 } else {
554 float raidStr = intel.getRoute().getExtra().getStrengthModifiedByDamage() / intel.getApproximateNumberOfFleets() *
555 Misc.FP_TO_GROUND_RAID_STR_APPROX_MULT;
556 if (fleet != null) {
557 raidStr = MarketCMD.getRaidStr(fleet);
558 }
559
560 Industry industry = null;
561 int index = raidCount.getCount(market) - 1;
562 if (index < 0) index = 0;
563 if (params.disrupt != null && index < params.disrupt.size()) {
564 int count = 0;
565 for (String industryId : params.disrupt) {
566 if (market.hasIndustry(industryId)) {
567 if (count >= index) {
568 industry = market.getIndustry(industryId);
569 break;
570 }
571 count++;
572 }
573 }
574// String industryId = params.disrupt.get(index);
575// industry = market.getIndustry(industryId);
576 }
577
579 ((GenericRaidFGI)intel).doCustomRaidAction(fleet, market, raidStr);
580 Misc.setFlagWithReason(market.getMemoryWithoutUpdate(), MemFlags.RECENTLY_RAIDED,
581 faction.getId(), true, 30f);
582 Misc.setRaidedTimestamp(market);
583 } else if (industry != null) {
584 float durMult = Global.getSettings().getFloat("punitiveExpeditionDisruptDurationMult");
585 new MarketCMD(market.getPrimaryEntity()).doIndustryRaid(faction, raidStr, industry, durMult);
586 } else {
587 new MarketCMD(market.getPrimaryEntity()).doGenericRaid(faction,
588 raidStr, params.maxStabilityLostPerRaid, params.raidsPerColony > 1);
589 }
590 }
591 }
592
593
594
595 public void autoresolve() {
596 if (isActionFinished()) return;
597
598 float str = WarSimScript.getFactionStrength(intel.getFaction(), params.where);
599 if (!intel.isSpawnedFleets() && intel.getRoute().isExpired()) {
600 // the above doesn't pick it up
601 OptionalFleetData data = intel.getRoute().getExtra();
602 if (data != null) str += data.getStrengthModifiedByDamage();
603 }
604
605 boolean playerTargeted = false;
606 if (intel instanceof GenericRaidFGI) {
607 playerTargeted = ((GenericRaidFGI)intel).getParams().playerTargeted;
608 }
609
610 float enemyStr = WarSimScript.getEnemyStrength(intel.getFaction(), params.where, playerTargeted);
611 float origStr = str;
612 float strMult = 1f;
613 for (MarketAPI target : Misc.getMarketsInLocation(params.where)) {
614 if (!params.allowAnyHostileMarket && !params.allowedTargets.contains(target)) continue;
615 if (!params.allowNonHostileTargets && !intel.getFaction().isHostileTo(target.getFaction())) continue;
616
617 float defensiveStr = enemyStr + WarSimScript.getStationStrength(target.getFaction(), params.where, target.getPrimaryEntity());
618
619 float damage = 0.5f * defensiveStr / Math.max(str, 1f);
620 if (damage > 0.75f) damage = 0.75f;
621 strMult *= (1f - damage);
622
623 if (defensiveStr >= str) {
624 continue;
625 }
626
627 Industry station = Misc.getStationIndustry(target);
628 if (station != null) {
629 OrbitalStation.disrupt(station);
630 station.reapply();
631 }
632
633 for (int i = 0; i < params.raidsPerColony; i++) {
634 performRaid(null, target);
635 }
636
637 //str -= defensiveStr * 0.5f;
638 str = origStr * strMult;
639 }
640
641 if (intel.isSpawnedFleets() && strMult < 1f) {
642 for (CampaignFleetAPI fleet : intel.getFleets()) {
643 FleetFactoryV3.applyDamageToFleet(fleet, 1f - strMult, false, intel.getRandom());
644 }
645 }
646
647 if (!intel.isSpawnedFleets() && strMult < 1) {
648 OptionalFleetData extra = intel.getRoute().getExtra();
649 if (extra != null) {
650 if (extra.damage == null) {
651 extra.damage = 0f;
652 }
653 extra.damage = 1f - (1f - extra.damage) * strMult;
654 //extra.damage = 1f;
655 if (extra.damage > 1f) extra.damage = 1f;
656 }
657 } else if (intel.isSpawnedFleets() && getSuccessFraction() <= 0f) {
658 intel.abort();
659 } else {
660 // if fleets were not spawned and it needs to abort due to the damage taken,
661 // that's handled in FleetGroupIntel
662 }
663
664 setActionFinished(true);
665 }
666
667
668
669 public String getRaidApproachText(CampaignFleetAPI fleet, MarketAPI market) {
670 if (params.raidApproachText != null) {
671 return params.raidApproachText + " " + market.getName();
672 }
673 return null;
674 }
675
676 public String getRaidActionText(CampaignFleetAPI fleet, MarketAPI market) {
677 if (params.raidActionText != null) {
678 return params.raidActionText + " " + market.getName();
679 }
680 return null;
681 }
682
683
684 // not needed and not used by the WarfleetAssignmentAI
685 public String getRaidPrepText(CampaignFleetAPI fleet, SectorEntityToken from) {
686 return null;
687 }
688
689 public String getRaidInSystemText(CampaignFleetAPI fleet) {
690 return null;
691 }
692
693 public String getRaidDefaultText(CampaignFleetAPI fleet) {
694 return null;
695 }
696
697 public CountingMap<MarketAPI> getRaidCount() {
698 return raidCount;
699 }
700
701
702 public float getSuccessFraction() {
703 int totalGoal = params.raidsPerColony * params.allowedTargets.size();
704 if (totalGoal < 1) totalGoal = 1;
705 int achieved = raidCount.getTotal();
706
707 if (params.bombardment != null) {
708 achieved = bombardCount;
709 }
710
711 return Math.max(0f, (float)achieved / (float)totalGoal);
712 }
713
715 MarketAPI largest = null;
716 int max = 0;
717 boolean player = false;
718 for (MarketAPI target : Misc.getMarketsInLocation(params.where)) {
719 if (!params.allowAnyHostileMarket && !params.allowedTargets.contains(target)) continue;
720 if (!params.allowNonHostileTargets && !intel.getFaction().isHostileTo(target.getFaction())) continue;
721
722 int size = target.getSize();
723 if (size > max) {
724 largest = target;
725 max = size;
726 }
727 if (target.isPlayerOwned()) {
728 player = true;
729 }
730 }
731 if (player) return Misc.getBasePlayerColor();
732 if (largest != null) {
733 return largest.getFaction().getBaseUIColor();
734 }
735 return Misc.getTextColor();
736 }
737
738 public StarSystemAPI getWhere() {
739 return params.where;
740 }
741
742}
743
744
745
746
747
748
749
750
static SettingsAPI getSettings()
Definition Global.java:51
static SectorAPI getSector()
Definition Global.java:59
void orderFleetMovements(List< SectorEntityToken > targets)
boolean canRaid(CampaignFleetAPI fleet, MarketAPI market)
String getRaidApproachText(CampaignFleetAPI fleet, MarketAPI market)
String getRaidActionText(CampaignFleetAPI fleet, MarketAPI market)
void performRaid(CampaignFleetAPI fleet, MarketAPI market)
String getRaidPrepText(CampaignFleetAPI fleet, SectorEntityToken from)