Starsector API
Loading...
Searching...
No Matches
PEActionStage.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.intel.punitive;
2
3import java.awt.Color;
4import java.util.ArrayList;
5import java.util.List;
6
7import com.fs.starfarer.api.Global;
8import com.fs.starfarer.api.campaign.CampaignFleetAPI;
9import com.fs.starfarer.api.campaign.SectorEntityToken;
10import com.fs.starfarer.api.campaign.ai.CampaignFleetAIAPI.ActionType;
11import com.fs.starfarer.api.campaign.econ.Industry;
12import com.fs.starfarer.api.campaign.econ.MarketAPI;
13import com.fs.starfarer.api.impl.campaign.DebugFlags;
14import com.fs.starfarer.api.impl.campaign.MilitaryResponseScript;
15import com.fs.starfarer.api.impl.campaign.MilitaryResponseScript.MilitaryResponseParams;
16import com.fs.starfarer.api.impl.campaign.command.WarSimScript;
17import com.fs.starfarer.api.impl.campaign.econ.impl.OrbitalStation;
18import com.fs.starfarer.api.impl.campaign.fleets.RouteManager;
19import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData;
20import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteSegment;
21import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
22import com.fs.starfarer.api.impl.campaign.intel.punitive.PunitiveExpeditionIntel.PunExOutcome;
23import com.fs.starfarer.api.impl.campaign.intel.punitive.PunitiveExpeditionManager.PunExGoal;
24import com.fs.starfarer.api.impl.campaign.intel.raid.ActionStage;
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.impl.campaign.rulecmd.salvage.MarketCMD.BombardType;
29import com.fs.starfarer.api.ui.TooltipMakerAPI;
30import com.fs.starfarer.api.util.Misc;
31
32public class PEActionStage extends ActionStage implements FleetActionDelegate {
33
34 protected MarketAPI target;
35 protected boolean playerTargeted = false;
36 protected List<MilitaryResponseScript> scripts = new ArrayList<MilitaryResponseScript>();
37 protected boolean gaveOrders = true; // will be set to false in updateRoutes()
38 protected float untilAutoresolve = 30f;
39
41 super(raid);
42 this.target = target;
43 playerTargeted = target.isPlayerOwned();
44
45 untilAutoresolve = 15f + 5f * (float) Math.random();
46 }
47
48
49 @Override
50 public void advance(float amount) {
51 super.advance(amount);
52
53 float days = Misc.getDays(amount);
54 untilAutoresolve -= days;
56 untilAutoresolve -= days * 100f;
57 }
58
59 if (!gaveOrders) {
60 gaveOrders = true;
61
63
64 // getMaxDays() is always 1 here
65 // scripts get removed anyway so we don't care about when they expire naturally
66 // just make sure they're around for long enough
67 float duration = 100f;
68
69 MilitaryResponseParams params = new MilitaryResponseParams(ActionType.HOSTILE,
70 "PE_" + Misc.genUID() + target.getId(),
71 intel.getFaction(),
72 target.getPrimaryEntity(),
73 1f,
74 duration);
76 target.getContainingLocation().addScript(script);
77 scripts.add(script);
78
79 MilitaryResponseParams defParams = new MilitaryResponseParams(ActionType.HOSTILE,
80 "defPE_" + Misc.genUID() + target.getId(),
81 target.getFaction(),
82 target.getPrimaryEntity(),
83 1f,
84 duration);
85 MilitaryResponseScript defScript = new MilitaryResponseScript(defParams);
86 target.getContainingLocation().addScript(defScript);
87 scripts.add(defScript);
88 }
89 }
90
91 protected void removeMilScripts() {
92 if (scripts != null) {
94 s.forceDone();
95 }
96 }
97 }
98
99 @Override
100 protected void updateStatus() {
101// if (true) {
102// status = RaidStageStatus.SUCCESS;
103// return;
104// }
105
106 abortIfNeededBasedOnFP(true);
107 if (status != RaidStageStatus.ONGOING) return;
108
109 boolean inSpawnRange = RouteManager.isPlayerInSpawnRange(target.getPrimaryEntity());
110 if (!inSpawnRange && untilAutoresolve <= 0){
111 autoresolve();
112 return;
113 }
114
115 if (!target.isInEconomy() || !target.isPlayerOwned()) {
116 status = RaidStageStatus.FAILURE;
118 giveReturnOrdersToStragglers(getRoutes());
119 return;
120 }
121
122 }
123
124 public String getRaidActionText(CampaignFleetAPI fleet, MarketAPI market) {
126 PunExGoal goal = intel.getGoal();
127 if (goal == PunExGoal.BOMBARD) {
128 return "bombarding " + market.getName();
129 }
130 return "raiding " + market.getName();
131 }
132
133 public String getRaidApproachText(CampaignFleetAPI fleet, MarketAPI market) {
135 PunExGoal goal = intel.getGoal();
136 if (goal == PunExGoal.BOMBARD) {
137 return "moving in to bombard " + market.getName();
138 }
139 return "moving in to raid " + market.getName();
140 }
141
142 public void performRaid(CampaignFleetAPI fleet, MarketAPI market) {
144
146 PunExGoal goal = intel.getGoal();
147
148 status = RaidStageStatus.SUCCESS;
149
150 if (goal == PunExGoal.BOMBARD) {
151 float cost = MarketCMD.getBombardmentCost(market, fleet);
152 //float maxCost = intel.getAssembleStage().getOrigSpawnFP() * Misc.FP_TO_BOMBARD_COST_APPROX_MULT;
153 float maxCost = intel.getRaidFP() / intel.getNumFleets() * Misc.FP_TO_BOMBARD_COST_APPROX_MULT;
154 if (fleet != null) {
155 maxCost = fleet.getCargo().getMaxFuel() * 0.25f;
156 }
157
158 if (cost <= maxCost) {
159 new MarketCMD(market.getPrimaryEntity()).doBombardment(intel.getFaction(), BombardType.SATURATION);
160 intel.setOutcome(PunExOutcome.SUCCESS);
161 } else {
162 intel.setOutcome(PunExOutcome.BOMBARD_FAIL);
163 status = RaidStageStatus.FAILURE;
164
165 Misc.setFlagWithReason(market.getMemoryWithoutUpdate(), MemFlags.RECENTLY_BOMBARDED,
166 intel.getFaction().getId(), true, 30f);
167 }
168 } else {
169 //float str = intel.getAssembleStage().getOrigSpawnFP() * Misc.FP_TO_GROUND_RAID_STR_APPROX_MULT;
170 float str = intel.getRaidFPAdjusted() / intel.getNumFleets() * Misc.FP_TO_GROUND_RAID_STR_APPROX_MULT;
171
172 if (fleet != null) str = MarketCMD.getRaidStr(fleet);
173 //float re = MarketCMD.getRaidEffectiveness(target, str);
174
175 //str = 10f;
176
177 float durMult = Global.getSettings().getFloat("punitiveExpeditionDisruptDurationMult");
178 boolean raidSuccess = new MarketCMD(market.getPrimaryEntity()).doIndustryRaid(intel.getFaction(), str, intel.targetIndustry, durMult);
179
180 if (raidSuccess) {
181 intel.setOutcome(PunExOutcome.SUCCESS);
182 } else {
183 intel.setOutcome(PunExOutcome.RAID_FAIL);
184 status = RaidStageStatus.FAILURE;
185
186 Misc.setFlagWithReason(market.getMemoryWithoutUpdate(), MemFlags.RECENTLY_RAIDED,
187 intel.getFaction().getId(), true, 30f);
188 Misc.setRaidedTimestamp(market);
189 }
190 }
191
192// // so it doesn't keep trying to raid/bombard
193// if (fleet != null) {
194// fleet.getMemoryWithoutUpdate().unset(MemFlags.MEMORY_KEY_RAIDER);
195// }
196
197 // when FAILURE, gets sent by RaidIntel
198 if (intel.getOutcome() != null) {
199 if (status == RaidStageStatus.SUCCESS) {
200 intel.sendOutcomeUpdate();
201 } else {
203 giveReturnOrdersToStragglers(getRoutes());
204 }
205 }
206 }
207
208
209 protected void autoresolve() {
210 float str = WarSimScript.getFactionStrength(intel.getFaction(), target.getStarSystem());
211 float enemyStr = WarSimScript.getFactionStrength(target.getFaction(), target.getStarSystem());
212
213 float defensiveStr = enemyStr + WarSimScript.getStationStrength(target.getFaction(),
214 target.getStarSystem(), target.getPrimaryEntity());
215 if (defensiveStr >= str) {
216 status = RaidStageStatus.FAILURE;
218 giveReturnOrdersToStragglers(getRoutes());
219
220 // not strictly necessary, I think, but shouldn't hurt
221 // otherwise would get set in PunitiveExpeditionIntel.notifyRaidEnded()
223 intel.setOutcome(PunExOutcome.TASK_FORCE_DEFEATED);
224 return;
225 }
226
227 Industry station = Misc.getStationIndustry(target);
228 if (station != null) {
229 OrbitalStation.disrupt(station);
230 }
231
232 performRaid(null, target);
233 }
234
235
236 protected void updateRoutes() {
237 resetRoutes();
238
239 gaveOrders = false;
240
241 ((PunitiveExpeditionIntel)intel).sendEnteredSystemUpdate();
242
243 List<RouteData> routes = RouteManager.getInstance().getRoutesForSource(intel.getRouteSourceId());
244 for (RouteData route : routes) {
245 if (target.getStarSystem() != null) { // so that fleet may spawn NOT at the target
246 route.addSegment(new RouteSegment(Math.min(5f, untilAutoresolve), target.getStarSystem().getCenter()));
247 }
248 route.addSegment(new RouteSegment(1000f, target.getPrimaryEntity()));
249 }
250 }
251
252
253 public void showStageInfo(TooltipMakerAPI info) {
254 int curr = intel.getCurrentStage();
255 int index = intel.getStageIndex(this);
256
257 Color h = Misc.getHighlightColor();
258 Color g = Misc.getGrayColor();
259 Color tc = Misc.getTextColor();
260 float pad = 3f;
261 float opad = 10f;
262
263 if (curr < index) return;
264
265 if (status == RaidStageStatus.ONGOING && curr == index) {
266 info.addPara("The expedition forces are currently in-system.", opad);
267 return;
268 }
269
271 if (intel.getOutcome() != null) {
272 switch (intel.getOutcome()) {
273 case BOMBARD_FAIL:
274 info.addPara("The ground defenses of " + target.getName() + " were sufficient to prevent bombardment.", opad);
275 break;
276 case RAID_FAIL:
277 info.addPara("The raiding forces have been repelled by the ground defenses of " + target.getName() + ".", opad);
278 break;
279 case SUCCESS:
280 if (intel.goal == PunExGoal.BOMBARD) {
281 if (!target.isInEconomy()) {
282 info.addPara("The expeditionary force has successfully bombarded " + target.getName() + ", destroying the colony outright.", opad);
283 } else {
284 info.addPara("The expeditionary force has successfully bombarded " + target.getName() + ".", opad);
285 }
286 } else if (intel.getTargetIndustry() != null) {
287 info.addPara("The expeditionary force has disrupted " +
288 intel.getTargetIndustry().getCurrentName() + " operations for %s days.",
289 opad, h, "" + (int)Math.round(intel.getTargetIndustry().getDisruptedDays()));
290 }
291 break;
292 case TASK_FORCE_DEFEATED:
293 info.addPara("The expeditionary force has been defeated by the defenders of " +
294 target.getName() + ".", opad);
295 break;
296 case COLONY_NO_LONGER_EXISTS:
297 info.addPara("The expedition has been aborted.", opad);
298 break;
299
300 }
301 } else if (status == RaidStageStatus.SUCCESS) {
302 info.addPara("The expeditionary force has succeeded.", opad); // shouldn't happen?
303 } else {
304 info.addPara("The expeditionary force has failed.", opad); // shouldn't happen?
305 }
306 }
307
308 public boolean canRaid(CampaignFleetAPI fleet, MarketAPI market) {
310 if (intel.getOutcome() != null) return false;
311 return market == target;
312 }
313
314 public String getRaidPrepText(CampaignFleetAPI fleet, SectorEntityToken from) {
315 return "orbiting " + from.getName();
316 }
317
318 public String getRaidInSystemText(CampaignFleetAPI fleet) {
319 return "traveling";
320 }
321
322 public String getRaidDefaultText(CampaignFleetAPI fleet) {
323 return "traveling";
324 }
325
326 @Override
327 public boolean isPlayerTargeted() {
328 return playerTargeted;
329 }
330}
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
static SettingsAPI getSettings()
Definition Global.java:51
String getRaidApproachText(CampaignFleetAPI fleet, MarketAPI market)
String getRaidPrepText(CampaignFleetAPI fleet, SectorEntityToken from)
void performRaid(CampaignFleetAPI fleet, MarketAPI market)
PEActionStage(PunitiveExpeditionIntel raid, MarketAPI target)
String getRaidActionText(CampaignFleetAPI fleet, MarketAPI market)
boolean canRaid(CampaignFleetAPI fleet, MarketAPI market)