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;
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
143 }
144
145 public Object readResolve() {
146 if (raidCount == null) {
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)) {
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;
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)) {
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()) {
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) {
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() *
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 {
551 intel.getFaction().getId(), true, 30f);
552 }
553 } else {
554 float raidStr = intel.getRoute().getExtra().getStrengthModifiedByDamage() / intel.getApproximateNumberOfFleets() *
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
578 if (intel instanceof GenericRaidFGI && ((GenericRaidFGI)intel).hasCustomRaidAction()) {
579 ((GenericRaidFGI)intel).doCustomRaidAction(fleet, market, raidStr);
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
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
686 return null;
687 }
688
690 return null;
691 }
692
694 return null;
695 }
696
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
739 return params.where;
740 }
741
742}
743
744
745
746
747
748
749
750
static SettingsAPI getSettings()
Definition Global.java:57
static SectorAPI getSector()
Definition Global.java:65
static float getFactionStrength(String factionId, StarSystemAPI system)
static float getStationStrength(FactionAPI faction, StarSystemAPI system, SectorEntityToken from)
static void removeNoFightingTimeoutForObjective(SectorEntityToken objective, FactionAPI faction)
static void setNoFightingForObjective(SectorEntityToken objective, FactionAPI faction, float timeout)
static void removeFightOrdersFor(SectorEntityToken target, FactionAPI faction)
static float getEnemyStrength(String factionId, StarSystemAPI system)
static void applyDamageToFleet(CampaignFleetAPI fleet, float damage, boolean damageRemainingShips, Random random)
static boolean isPlayerInSpawnRange(SectorEntityToken from)
static final String MEMORY_KEY_FLEET_DO_NOT_GET_SIDETRACKED
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)
boolean doIndustryRaid(FactionAPI faction, float attackerStr, Industry industry, float durMult)
void doBombardment(FactionAPI faction, BombardType type)
void doGenericRaid(FactionAPI faction, float attackerStr)
static int getBombardmentCost(MarketAPI market, CampaignFleetAPI fleet)
static Color getTextColor()
Definition Misc.java:839
static float FP_TO_GROUND_RAID_STR_APPROX_MULT
Definition Misc.java:227
static List< MarketAPI > getMarketsInLocation(LocationAPI location, String factionId)
Definition Misc.java:936
static Color getBasePlayerColor()
Definition Misc.java:833
static boolean isFleetMadeHostileToFaction(CampaignFleetAPI fleet, FactionAPI faction)
Definition Misc.java:1508
static float getDistance(SectorEntityToken from, SectorEntityToken to)
Definition Misc.java:599
static boolean setFlagWithReason(MemoryAPI memory, String flagKey, String reason, boolean value, float expire)
Definition Misc.java:1439
static Industry getStationIndustry(MarketAPI market)
Definition Misc.java:4617
static float FP_TO_BOMBARD_COST_APPROX_MULT
Definition Misc.java:226
static void setRaidedTimestamp(MarketAPI market)
Definition Misc.java:5816
boolean isHostileTo(FactionAPI other)
List< SectorEntityToken > getEntitiesWithTag(String tag)
void addScript(EveryFrameScript script)
boolean wantsToJoin(BattleAPI battle, boolean playerInvolved)