Starsector API
Loading...
Searching...
No Matches
PirateRaidActionStage.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.HashSet;
6import java.util.List;
7import java.util.Set;
8
9import com.fs.starfarer.api.campaign.CampaignFleetAPI;
10import com.fs.starfarer.api.campaign.FactionAPI;
11import com.fs.starfarer.api.campaign.SectorEntityToken;
12import com.fs.starfarer.api.campaign.StarSystemAPI;
13import com.fs.starfarer.api.campaign.ai.CampaignFleetAIAPI.ActionType;
14import com.fs.starfarer.api.campaign.econ.Industry;
15import com.fs.starfarer.api.campaign.econ.MarketAPI;
16import com.fs.starfarer.api.impl.campaign.MilitaryResponseScript;
17import com.fs.starfarer.api.impl.campaign.MilitaryResponseScript.MilitaryResponseParams;
18import com.fs.starfarer.api.impl.campaign.command.WarSimScript;
19import com.fs.starfarer.api.impl.campaign.econ.impl.OrbitalStation;
20import com.fs.starfarer.api.impl.campaign.fleets.RouteManager;
21import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData;
22import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteSegment;
23import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
24import com.fs.starfarer.api.impl.campaign.intel.BaseIntelPlugin;
25import com.fs.starfarer.api.impl.campaign.intel.raid.RaidIntel.RaidStageStatus;
26import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseAssignmentAI.FleetActionDelegate;
27import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.MarketCMD;
28import com.fs.starfarer.api.ui.TooltipMakerAPI;
29import com.fs.starfarer.api.util.Misc;
30import com.fs.starfarer.api.util.Pair;
31import com.fs.starfarer.api.util.WeightedRandomPicker;
32
33public class PirateRaidActionStage extends ActionStage implements FleetActionDelegate {
34
35 public static class RaidActionSubStage {
36 public List<Pair<SectorEntityToken, Float>> targets = new ArrayList<Pair<SectorEntityToken,Float>>();
37 public float duration = 30f;
38 }
39
41
42 protected float untilNextStage = 0f;
43 protected List<MilitaryResponseScript> scripts = new ArrayList<MilitaryResponseScript>();
44 protected List<RaidActionSubStage> steps = new ArrayList<RaidActionSubStage>();
45 protected List<MarketAPI> targets = new ArrayList<MarketAPI>();
46 protected boolean playerTargeted = false;
47
49 super(raid);
50
51 this.system = system;
52
53 for (MarketAPI target : getTargets()) {
54 if (target.isPlayerOwned()) {
55 playerTargeted = true;
56 }
57 }
58 }
59
60 @Override
61 public void advance(float amount) {
62 super.advance(amount);
63
64 float days = Misc.getDays(amount);
65 untilNextStage -= days;
66
67 if (!steps.isEmpty() && untilNextStage <= 0) {
69
70 RaidActionSubStage step = steps.remove(0);
71 untilNextStage = step.duration;
72
73 // scripts get removed anyway so we don't care about when they expire naturally
74 // just make sure they're around for long enough
75 float duration = 100f;
76
77 for (Pair<SectorEntityToken, Float> curr : step.targets) {
78 MilitaryResponseParams params = new MilitaryResponseParams(ActionType.HOSTILE,
79 "raid_" + curr.one.getId(),
81 curr.one,
82 curr.two,
83 duration);
85 curr.one.getContainingLocation().addScript(script);
86 scripts.add(script);
87
88 MilitaryResponseParams defParams = new MilitaryResponseParams(ActionType.HOSTILE,
89 "defRaid_" + curr.one.getId(),
90 curr.one.getFaction(),
91 curr.one,
92 curr.two,
93 duration);
94 MilitaryResponseScript defScript = new MilitaryResponseScript(defParams);
95 curr.one.getContainingLocation().addScript(defScript);
96 scripts.add(defScript);
97 }
98 }
99 }
100
101 protected void removeMilScripts() {
102 if (scripts != null) {
104 s.forceDone();
105 }
106 }
107 }
108
109 @Override
110 protected void updateStatus() {
111// if (true) {
112// status = RaidStageStatus.SUCCESS;
113// return;
114// }
115
117 if (status != RaidStageStatus.ONGOING) return;
118
119 if (getTargets().isEmpty()) {
120 status = RaidStageStatus.FAILURE;
123 return;
124 }
125
126 if (steps.isEmpty()) {
127 boolean inSpawnRange = RouteManager.isPlayerInSpawnRange(system.getCenter());
128 if (!inSpawnRange && elapsed > maxDays) {
129 autoresolve();
130 return;
131 }
132
133 boolean someUnraided = false;
134 boolean someRaided = false;
135 for (MarketAPI market : targets) {
136 if (!market.getFaction().isHostileTo(intel.getFaction())) {
137 someUnraided = true;
138 continue;
139 }
140 if (Misc.flagHasReason(market.getMemoryWithoutUpdate(),
142 someRaided = true;
143 } else {
144 someUnraided = true;
145 }
146 }
147 if (targets.isEmpty()) {
148 someUnraided = true;
149 }
150
151 if (!someUnraided || (elapsed > maxDays && someRaided)) {
152 status = RaidStageStatus.SUCCESS;
154 return;
155 }
156
157 if (elapsed > maxDays && !someRaided) {
158 status = RaidStageStatus.FAILURE;
161 return;
162 }
163 }
164 }
165
166
167 protected List<MarketAPI> getTargets() {
168 List<MarketAPI> targets = new ArrayList<MarketAPI>();
169 for (MarketAPI market : Misc.getMarketsInLocation(system)) {
170 if (market.getFaction().isHostileTo(intel.getFaction())) {
171 targets.add(market);
172 }
173 }
174 return targets;
175 }
176
177 protected void updateRoutes() {
178 resetRoutes();
179
180 if (playerTargeted) {
182 }
183
184
185 FactionAPI faction = intel.getFaction();
186
188
189 for (RouteData route : routes) {
190 route.addSegment(new RouteSegment(1000f, system.getCenter()));
191 }
192
193 List<MarketAPI> targets = getTargets();
194 if (targets.isEmpty()) return;
195
197 for (MarketAPI target : targets) {
198 picker.add(target, target.getSize() * target.getSize());
199 }
200
201 float str = WarSimScript.getFactionStrength(faction, system);
202 float enemyStr = 0;
203 Set<String> seen = new HashSet<String>();
204 for (MarketAPI market : targets) {
205 if (seen.contains(market.getFactionId())) continue;
206 seen.add(market.getFactionId());
207 enemyStr += WarSimScript.getFactionStrength(market.getFaction(), system);
208 }
209 if (str < 1) str = 1;
210 if (enemyStr < 1) enemyStr = 1;
211
212 boolean concurrent = false;
213 int numRaids = 1;
214 if (str > enemyStr * 2 && (float) Math.random() > 0.5f) {
215 numRaids = 2;
216 }
217 if (str > enemyStr * 4) {
218 concurrent = true;
219 numRaids++;
220 }
221
222 if (!concurrent) {
223 for (int i = 0; i < numRaids && !picker.isEmpty(); numRaids++) {
224 MarketAPI target = picker.pickAndRemove();
225
226 float defensiveStr = enemyStr + WarSimScript.getStationStrength(target.getFaction(), system, target.getPrimaryEntity());
227 if (defensiveStr > str) {
228 continue;
229 }
230
231 RaidActionSubStage step = new RaidActionSubStage();
232 step.duration = 20f + 10f * (float) Math.random();
233
234 float weight = 1f;
235 Industry station = Misc.getStationIndustry(target);
236 if (station != null && station.getDisruptedDays() < step.duration) {
237 step.duration += 10f + (float) Math.random() * 5f;
238 weight += 1f;
239 }
240
241
242 step.targets.add(new Pair<SectorEntityToken, Float>(target.getPrimaryEntity(), weight));
243 steps.add(step);
244
245 this.targets.add(target);
246 }
247
248 maxDays = 0f;
249 for (RaidActionSubStage step : steps) {
250 maxDays += step.duration;
251 }
252 } else {
253 RaidActionSubStage step = new RaidActionSubStage();
254 boolean stationPresent = false;
255 for (int i = 0; i < numRaids && !picker.isEmpty(); numRaids++) {
256 MarketAPI target = picker.pickAndRemove();
257
258 float defensiveStr = enemyStr + WarSimScript.getStationStrength(target.getFaction(), system, target.getPrimaryEntity());
259 if (defensiveStr > str) {
260 continue;
261 }
262
263 float weight = 1f;
264 Industry station = Misc.getStationIndustry(target);
265 if (station != null && station.getDisruptedDays() < 20f) {
266 stationPresent = true;
267 weight += 1f;
268 }
269
270
271 step.targets.add(new Pair<SectorEntityToken, Float>(target.getPrimaryEntity(), weight));
272
273 this.targets.add(target);
274 }
275
276 steps.add(step);
277
278 step.duration = 20f + 10f * (float) Math.random();
279 if (stationPresent) {
280 step.duration += 10f + (float) Math.random() * 5f;
281 }
282
283 maxDays = step.duration;
284 }
285
286 if (this.targets.isEmpty()) {
287 steps.clear();
288 maxDays = 0f;
289 return;
290 }
291 }
292
293
294 public void showStageInfo(TooltipMakerAPI info) {
295 int curr = intel.getCurrentStage();
296 int index = intel.getStageIndex(this);
297
298 Color h = Misc.getHighlightColor();
299 Color g = Misc.getGrayColor();
300 Color tc = Misc.getTextColor();
301 float pad = 3f;
302 float opad = 10f;
303
304 if (status == RaidStageStatus.FAILURE) {
305 info.addPara("The raiding forces have been defeated by the defenders of the " +
306 intel.getSystem().getNameWithLowercaseType() + ". The raid is now over.", opad);
307 } else if (status == RaidStageStatus.SUCCESS) {
308 List<MarketAPI> raided = new ArrayList<MarketAPI>();
309 for (MarketAPI market : targets) {
310 if (!market.getFaction().isHostileTo(intel.getFaction())) {
311 continue;
312 }
313 if (Misc.flagHasReason(market.getMemoryWithoutUpdate(),
315 raided.add(market);
316 }
317 }
318 if (!raided.isEmpty()) {
319 info.addPara("The raiding forces have been successful in raiding the following colonies:", opad);
320 float initPad = opad;
321 for (MarketAPI market : raided) {
322 BaseIntelPlugin.addMarketToList(info, market, initPad, tc);
323 initPad = 0f;
324 }
325 }
326 } else if (curr == index) {
327 info.addPara("The raiding forces are currently operating in the " +
329
330 }
331 }
332
333 @Override
334 public boolean isPlayerTargeted() {
335 return playerTargeted;
336 }
337
338
339
340 protected void autoresolve() {
342
344
345 status = RaidStageStatus.FAILURE;
346 for (MarketAPI target : targets) {
347 if (!target.getFaction().isHostileTo(intel.getFaction())) continue;
348
349 float defensiveStr = enemyStr + WarSimScript.getStationStrength(target.getFaction(), system, target.getPrimaryEntity());
350 if (defensiveStr >= str) {
351 continue;
352 }
353
354 Industry station = Misc.getStationIndustry(target);
355 if (station != null) {
356 OrbitalStation.disrupt(station);
357 }
358
359// float raidStr = intel.getRaidFP() / intel.getNumFleets() * Misc.FP_TO_GROUND_RAID_STR_APPROX_MULT;
360// new MarketCMD(target.getPrimaryEntity()).doGenericRaid(intel.getFaction(), raidStr);
361 performRaid(null, target);
362
363 str -= defensiveStr * 0.5f;
364 status = RaidStageStatus.SUCCESS;
365 }
366
368 }
369
370 public String getRaidActionText(CampaignFleetAPI fleet, MarketAPI market) {
371 return "raiding " + market.getName();
372 }
373
374 public String getRaidApproachText(CampaignFleetAPI fleet, MarketAPI market) {
375 return "moving in to raid " + market.getName();
376 }
377
378
379 public void performRaid(CampaignFleetAPI fleet, MarketAPI market) {
381 if (fleet != null) {
382 raidStr = MarketCMD.getRaidStr(fleet);
383 }
384
385 float maxPenalty = 3f;
386// if (fleet == null) {
387// maxPenalty += (intel.getNumFleets() - 1);
388// }
389
390 new MarketCMD(market.getPrimaryEntity()).doGenericRaid(intel.getFaction(), raidStr, maxPenalty);
391
392// float re = MarketCMD.getRaidEffectiveness(market, raidStr);
393// MarketCMD.applyRaidStabiltyPenalty(market, Misc.ucFirst(intel.getFaction().getPersonNamePrefix()) + " raid", re);
394// //RecentUnrest.get(market).add(3, Misc.ucFirst(faction.getPersonNamePrefix()) + " raid");
395//
396// Misc.setFlagWithReason(market.getMemoryWithoutUpdate(), MemFlags.RECENTLY_RAIDED,
397// faction.getId(), true, 30f);
398 }
399
400
401
402 public boolean canRaid(CampaignFleetAPI fleet, MarketAPI market) {
405 return false;
406 }
407 return market.getFaction().isHostileTo(fleet.getFaction());
408 }
409
411 return "preparing for raid";
412 }
413
415 return "raiding";
416 }
417
419 return "raiding";
420 }
421
422}
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
static float getFactionStrength(String factionId, StarSystemAPI system)
static float getStationStrength(FactionAPI faction, StarSystemAPI system, SectorEntityToken from)
static float getEnemyStrength(String factionId, StarSystemAPI system)
static boolean isPlayerInSpawnRange(SectorEntityToken from)
static void addMarketToList(TooltipMakerAPI info, MarketAPI market, float pad)
void giveReturnOrdersToStragglers(List< RouteData > stragglers)
String getRaidActionText(CampaignFleetAPI fleet, MarketAPI market)
String getRaidApproachText(CampaignFleetAPI fleet, MarketAPI market)
String getRaidPrepText(CampaignFleetAPI fleet, SectorEntityToken from)
void doGenericRaid(FactionAPI faction, float attackerStr)
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 getGrayColor()
Definition Misc.java:826
static float getDays(float amount)
Definition Misc.java:4663
static boolean flagHasReason(MemoryAPI memory, String flagKey, String reason)
Definition Misc.java:1453
static Color getHighlightColor()
Definition Misc.java:792
static Industry getStationIndustry(MarketAPI market)
Definition Misc.java:4617
boolean isHostileTo(FactionAPI other)
LabelAPI addPara(String format, float pad, Color hl, String... highlights)