Starsector API
Loading...
Searching...
No Matches
HegemonyInspectionIntel.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.intel.inspection;
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.input.Keyboard;
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.ReputationActionResponsePlugin.ReputationAdjustmentResult;
15import com.fs.starfarer.api.campaign.SectorEntityToken;
16import com.fs.starfarer.api.campaign.econ.Industry;
17import com.fs.starfarer.api.campaign.econ.MarketAPI;
18import com.fs.starfarer.api.characters.PersonAPI;
19import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin;
20import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.CustomRepImpact;
21import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActionEnvelope;
22import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActions;
23import com.fs.starfarer.api.impl.campaign.DebugFlags;
24import com.fs.starfarer.api.impl.campaign.fleets.RouteLocationCalculator;
25import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData;
26import com.fs.starfarer.api.impl.campaign.ids.Factions;
27import com.fs.starfarer.api.impl.campaign.ids.Tags;
28import com.fs.starfarer.api.impl.campaign.intel.raid.RaidAssignmentAI;
29import com.fs.starfarer.api.impl.campaign.intel.raid.RaidIntel;
30import com.fs.starfarer.api.impl.campaign.intel.raid.RaidIntel.RaidDelegate;
31import com.fs.starfarer.api.impl.campaign.procgen.themes.RouteFleetAssignmentAI;
32import com.fs.starfarer.api.ui.Alignment;
33import com.fs.starfarer.api.ui.ButtonAPI;
34import com.fs.starfarer.api.ui.IntelUIAPI;
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 HegemonyInspectionIntel extends RaidIntel implements RaidDelegate {
41
42 //public static float DEFAULT_INSPECTION_GROUND_STRENGTH = 1000;
43
44 public static interface InspectionEndedListener {
45 public void notifyInspectionEnded(HegemonyInspectionOutcome outcome);
46 }
47
48 public static enum HegemonyInspectionOutcome {
49 COLONY_NO_LONGER_EXISTS,
50 TASK_FORCE_DESTROYED, // rep hit due to destruction, depends on transponder status and other factors
51 CONFISCATE_CORES, // cores taken, minor rep hit
52 FOUND_EVIDENCE_NO_CORES, // player removed cores - lots of disruption
53 //CORES_HIDDEN, // player invested into hiding cores - costs credits, no rep hit
54 BRIBED, // player paid a lot of bribe money, no rep hit
55 }
56
57 public static enum AntiInspectionOrders {
58 COMPLY,
59 HIDE,
60 BRIBE,
61 RESIST,
62 }
63
64 public static final String BUTTON_CHANGE_ORDERS = "BUTTON_CHANGE_ORDERS";
65
66 public static final Object MADE_HOSTILE_UPDATE = new Object();
67 public static final Object ENTERED_SYSTEM_UPDATE = new Object();
68 public static final Object OUTCOME_UPDATE = new Object();
69
70
72
73 protected AntiInspectionOrders orders = AntiInspectionOrders.COMPLY;
74 protected int investedCredits = 0;
75 protected MarketAPI target;
76 protected FactionAPI targetFaction;
77 protected MarketAPI from;
78
79 protected List<String> expectedCores = new ArrayList<String>();
80 protected boolean enteredSystem = false;
81 protected HegemonyInspectionOutcome outcome;
82 protected Random random = new Random();
83
84 protected InspectionEndedListener listener;
85
86 public HegemonyInspectionIntel(MarketAPI from, MarketAPI target, float inspectionFP) {
87 super(target.getStarSystem(), from.getFaction(), null);
88 this.delegate = this;
89 this.from = from;
90 this.target = target;
91 targetFaction = target.getFaction();
92
93 for (Industry curr : target.getIndustries()) {
94 String id = curr.getAICoreId();
95 if (id != null) {
96 expectedCores.add(id);
97 }
98 }
99 PersonAPI admin = target.getAdmin();
100 if (admin.isAICore()) {
101 expectedCores.add(admin.getAICoreId());
102 }
103
104 float orgDur = 20f + 10f * (float) Math.random();
105 if (Global.getSettings().isDevMode()) {
106 orgDur = 1f;
107 }
108
110 addStage(new HIOrganizeStage(this, from, orgDur));
111
112 SectorEntityToken gather = from.getPrimaryEntity();
113 SectorEntityToken raidJump = RouteLocationCalculator.findJumpPointToUse(getFactionForUIColors(), target.getPrimaryEntity());
114
115 if (gather == null || raidJump == null) {
116 endImmediately();
117 return;
118 }
119
120 float successMult = 0.5f;
121
122 HIAssembleStage assemble = new HIAssembleStage(this, gather);
123 assemble.addSource(from);
124 assemble.setSpawnFP(inspectionFP);
125 assemble.setAbortFP(inspectionFP * successMult);
126 addStage(assemble);
127
128
129
130 HITravelStage travel = new HITravelStage(this, gather, raidJump, false);
131 travel.setAbortFP(inspectionFP * successMult);
132 addStage(travel);
133
134 action = new HIActionStage(this, target);
135 action.setAbortFP(inspectionFP * successMult);
136 addStage(action);
137
138 addStage(new HIReturnStage(this));
139
140 setImportant(true);
141
142 Global.getSector().getIntelManager().addIntel(this);
143 }
144
145 public InspectionEndedListener getListener() {
146 return listener;
147 }
148
149
150 public void setListener(InspectionEndedListener listener) {
151 this.listener = listener;
152 }
153
154
155
156 public Random getRandom() {
157 return random;
158 }
159
160 public MarketAPI getTarget() {
161 return target;
162 }
163
164 public MarketAPI getFrom() {
165 return from;
166 }
167
168 public RouteFleetAssignmentAI createAssignmentAI(CampaignFleetAPI fleet, RouteData route) {
169 RaidAssignmentAI raidAI = new RaidAssignmentAI(fleet, route, action);
170 //raidAI.setDelegate(action);
171 return raidAI;
172 }
173
174 public AntiInspectionOrders getOrders() {
175 return orders;
176 }
177
178 public void setOrders(AntiInspectionOrders orders) {
179 this.orders = orders;
180 }
181
182 public List<String> getExpectedCores() {
183 return expectedCores;
184 }
185
186 public int getInvestedCredits() {
187 return investedCredits;
188 }
189
191 this.investedCredits = investedCredits;
192 }
193
194 public boolean isEnteredSystem() {
195 return enteredSystem;
196 }
197
198 public void setEnteredSystem(boolean enteredSystem) {
199 this.enteredSystem = enteredSystem;
200 }
201
202 public HegemonyInspectionOutcome getOutcome() {
203 return outcome;
204 }
205
206 public void setOutcome(HegemonyInspectionOutcome outcome) {
207 this.outcome = outcome;
208 }
209
210 protected transient String targetOwner = null;
211 @Override
212 protected void advanceImpl(float amount) {
213 super.advanceImpl(amount);
214 if (target != null && targetOwner == null) targetOwner = target.getFactionId();
215 if (failStage < 0 && targetOwner != null && target != null && !targetOwner.equals(target.getFactionId())) {
216 forceFail(false);
217 }
218 }
219
220
221
222
223 protected transient ReputationAdjustmentResult repResult = null;
225 boolean hostile = getFaction().isHostileTo(Factions.PLAYER);
226 if (!hostile) {
227 repResult = Global.getSector().adjustPlayerReputation(
228 new RepActionEnvelope(RepActions.MAKE_HOSTILE_AT_BEST,
229 null, null, null, false, false),
230 Factions.HEGEMONY);
232 }
233 }
234
238
239 public void applyRepPenalty(float delta) {
240 CustomRepImpact impact = new CustomRepImpact();
241 impact.delta = delta;
242 repResult = Global.getSector().adjustPlayerReputation(
243 new RepActionEnvelope(RepActions.CUSTOM,
244 impact, null, null, false, false),
245 getFaction().getId());
246 }
247
251
252 @Override
253 public String getName() {
254 String base = "Hegemony AI Inspection";
255 if (outcome == HegemonyInspectionOutcome.TASK_FORCE_DESTROYED ||
256 outcome == HegemonyInspectionOutcome.COLONY_NO_LONGER_EXISTS) return base + " - Failed";
257 if (outcome != null) return base + " - Completed";
258 return base;
259 }
260
261
262 @Override
263 protected void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode) {
264 //super.addBulletPoints(info, mode);
265
266 Color h = Misc.getHighlightColor();
267 Color g = Misc.getGrayColor();
268 float pad = 3f;
269 float opad = 10f;
270
271 float initPad = pad;
272 if (mode == ListInfoMode.IN_DESC) initPad = opad;
273
274 Color tc = getBulletColorForMode(mode);
275
276 bullet(info);
277 boolean isUpdate = getListInfoParam() != null;
278
279 boolean hostile = getFaction().isHostileTo(Factions.PLAYER);
280 if (hostile) {
281 orders = AntiInspectionOrders.RESIST;
282 }
283
284 if (getListInfoParam() == MADE_HOSTILE_UPDATE) {
285 FactionAPI other = target.getFaction();
286 info.addPara("Target: %s", initPad, tc,
287 other.getBaseUIColor(), target.getName());
288 initPad = 0f;
289 info.addPara("" + faction.getDisplayName() + " forces arrive in-system and encounter resistance", initPad, tc,
290 faction.getBaseUIColor(), faction.getDisplayName());
291 initPad = 0f;
293 null, null, info, tc, isUpdate, initPad);
294 return;
295 }
296
297 if (getListInfoParam() == ENTERED_SYSTEM_UPDATE) {
298 FactionAPI other = target.getFaction();
299 info.addPara("Target: %s", initPad, tc,
300 other.getBaseUIColor(), target.getName());
301 initPad = 0f;
302 info.addPara("Arrived in-system", tc, initPad);
303// info.addPara("" + faction.getDisplayName() + " inspection arrives in-system", initPad, tc,
304// faction.getBaseUIColor(), faction.getDisplayName());
305 return;
306 }
307
308 if (getListInfoParam() == OUTCOME_UPDATE) {
309 int num = getActionStage().getCoresRemoved().size();
310 if (num > 0) {
311 String cores = "cores";
312 if (num == 1) cores = "core";
313 info.addPara("%s AI " + cores + " confiscated", initPad, tc, h, "" + num);
314 initPad = 0f;
315 }
316 if (outcome == HegemonyInspectionOutcome.BRIBED) {
317 info.addPara("No AI cores found", initPad, tc, h, "" + num);
318 } else if (outcome == HegemonyInspectionOutcome.FOUND_EVIDENCE_NO_CORES) {
319 FactionAPI other = target.getFaction();
320 info.addPara("Operations at %s disrupted", initPad, tc,
321 other.getBaseUIColor(), target.getName());
322 //info.addPara("Operations disrupted by inspection", initPad, h, "" + num);
323 } else if (outcome == HegemonyInspectionOutcome.CONFISCATE_CORES) {
324 }
325 initPad = 0f;
326 if (repResult != null) {
328 null, null, info, tc, isUpdate, initPad);
329 }
330 return;
331 }
332
333// if (getListInfoParam() == UPDATE_FAILED) {
334// FactionAPI other = target.getFaction();
335// info.addPara("Target: %s", initPad, tc,
336// other.getBaseUIColor(), target.getName());
337// initPad = 0f;
338// info.addPara("Inspection failed", tc, initPad);
339// return;
340// }
341
342 float eta = getETA();
343
344 FactionAPI other = target.getFaction();
345 info.addPara("Target: %s", initPad, tc,
346 other.getBaseUIColor(), target.getName());
347 initPad = 0f;
348
349 if (eta > 1 && outcome == null) {
350 String days = getDaysString(eta);
351 info.addPara("Estimated %s " + days + " until arrival",
352 initPad, tc, h, "" + (int)Math.round(eta));
353 initPad = 0f;
354
355 if (hostile || orders == AntiInspectionOrders.RESIST) {
356 info.addPara("Defenders will resist", tc, initPad);
357 } else if (orders == AntiInspectionOrders.COMPLY) {
358 info.addPara("Defenders will comply", tc, initPad);
359 } else if (orders == AntiInspectionOrders.BRIBE) {
360 info.addPara("Funds allocated for bribe", tc, initPad);
361 }
362 } else if (outcome == null && action.getElapsed() > 0) {
363 info.addPara("Inspection under way", tc, initPad);
364 initPad = 0f;
365 } else if (outcome != null) {
366 int num = getActionStage().getCoresRemoved().size();
367 if (num > 0) {
368 String cores = "cores";
369 if (num == 1) cores = "core";
370 info.addPara("%s AI " + cores + " confiscated", initPad, tc, h, "" + num);
371 initPad = 0f;
372 } else if (outcome == HegemonyInspectionOutcome.TASK_FORCE_DESTROYED) {
373 //info.addPara("Inspection failed", tc, initPad);
374 }
375// info.addPara("Inspection under way", tc, initPad);
376// initPad = 0f;
377 }
378
379 unindent(info);
380 }
381
383 for (RaidStage stage : stages) {
384 if (stage instanceof HIActionStage) {
385 return (HIActionStage) stage;
386 }
387 }
388 return null;
389// return (HIActionStage) stages.get(2);
390 }
391
392 @Override
393 public void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode) {
394 super.createIntelInfo(info, mode);
395 }
396
397 @Override
398 public void createSmallDescription(TooltipMakerAPI info, float width, float height) {
399 //super.createSmallDescription(info, width, height);
400
401 Color h = Misc.getHighlightColor();
402 Color g = Misc.getGrayColor();
403 Color tc = Misc.getTextColor();
404 float pad = 3f;
405 float opad = 10f;
406
407 info.addImage(getFactionForUIColors().getLogo(), width, 128, opad);
408
409 FactionAPI faction = getFaction();
410 String has = faction.getDisplayNameHasOrHave();
411 String is = faction.getDisplayNameIsOrAre();
412
413 //AssembleStage as = getAssembleStage();
414 //MarketAPI source = as.getSources().get(0);
415
416 String strDesc = getRaidStrDesc();
417 int numFleets = (int) getOrigNumFleets();
418 String fleets = "fleets";
419 if (numFleets == 1) fleets = "fleet";
420
421 LabelAPI label = info.addPara(Misc.ucFirst(faction.getDisplayNameWithArticle()) + " " + is +
422 " targeting %s for an inspection due to the suspected use of AI cores there." +
423 " The task force is projected to be " + strDesc + " and is likely comprised of " +
424 "" + numFleets + " " + fleets + ".",
425 opad, faction.getBaseUIColor(), target.getName());
426 label.setHighlight(faction.getDisplayNameWithArticleWithoutArticle(), target.getName(), strDesc, "" + numFleets);
427 label.setHighlightColors(faction.getBaseUIColor(), target.getFaction().getBaseUIColor(), h, h);
428
429 if (outcome == null) {
430 addStandardStrengthComparisons(info, target, targetFaction, true, false, "inspection", "inspection's");
431 }
432
433 info.addSectionHeading("Status",
434 faction.getBaseUIColor(), faction.getDarkUIColor(), Alignment.MID, opad);
435
436 for (RaidStage stage : stages) {
437 stage.showStageInfo(info);
438 if (getStageIndex(stage) == failStage) break;
439 }
440
441
442 if (outcome == null) {
443 FactionAPI pf = Global.getSector().getPlayerFaction();
444 info.addSectionHeading("Your orders",
445 pf.getBaseUIColor(), pf.getDarkUIColor(), Alignment.MID, opad);
446
447 boolean hostile = getFaction().isHostileTo(Factions.PLAYER);
448 if (hostile) {
449 label = info.addPara(Misc.ucFirst(faction.getDisplayNameWithArticle()) + " " + is +
450 " hostile towards " + pf.getDisplayNameWithArticle() + ". Your forces will attempt to resist the inspection.",
451 opad);
452 label.setHighlight(faction.getDisplayNameWithArticleWithoutArticle(),
453 pf.getDisplayNameWithArticleWithoutArticle());
454 label.setHighlightColors(faction.getBaseUIColor(), pf.getBaseUIColor());
455 } else {
456 switch (orders) {
457 case COMPLY:
458 info.addPara("The authorities at " + target.getName() + " will comply with the inspection. " +
459 "It is certain to find any AI cores currently in use.", opad);
460 break;
461 case BRIBE:
462 info.addPara("You've allocated enough funds to ensure the inspection " +
463 "will produce a satisfactory outcome all around.", opad);
464 break;
465 // case HIDE:
466 // info.addPara("You've allocated funds to improve AI core concealment measures. It is certain that the inspection " +
467 // "can be defeated, but some amount of suspicion will remain.", opad);
468 // break;
469 case RESIST:
470 info.addPara("Your space and ground forces will attempt to resist the inspection.", opad);
471 break;
472 }
473
474 if (!enteredSystem) {
475 ButtonAPI button = info.addButton("Change orders", BUTTON_CHANGE_ORDERS,
476 pf.getBaseUIColor(), pf.getDarkUIColor(),
477 (int)(width), 20f, opad * 2f);
478 button.setShortcut(Keyboard.KEY_T, true);
479 } else {
480 info.addPara("The inspection task force is in-system and there's no time to implement new orders.", opad);
481 }
482 }
483 } else {
484 //addBulletPoints(info, ListInfoMode.IN_DESC);
485 bullet(info);
486 if (repResult != null) {
488 null, null, info, tc, false, opad);
489 }
490 unindent(info);
491 }
492 }
493
494
495
496 @Override
497 public void sendUpdateIfPlayerHasIntel(Object listInfoParam, boolean onlyIfImportant, boolean sendIfHidden) {
498
499 if (listInfoParam == UPDATE_RETURNING) {
500 // we're using sendOutcomeUpdate() to send an end-of-event update instead
501 return;
502 }
503
504 super.sendUpdateIfPlayerHasIntel(listInfoParam, onlyIfImportant, sendIfHidden);
505 }
506
507 @Override
508 public Set<String> getIntelTags(SectorMapAPI map) {
509 //return super.getIntelTags(map);
510
511 Set<String> tags = super.getIntelTags(map);
512 tags.add(Tags.INTEL_MILITARY);
513 tags.add(Tags.INTEL_COLONIES);
514 tags.add(getFaction().getId());
515 return tags;
516 }
517
518
519 public void notifyRaidEnded(RaidIntel raid, RaidStageStatus status) {
520 if (outcome == null && failStage >= 0) {
521 if (!target.isInEconomy() || !target.isPlayerOwned()) {
522 outcome = HegemonyInspectionOutcome.COLONY_NO_LONGER_EXISTS;
523 } else {
524 outcome = HegemonyInspectionOutcome.TASK_FORCE_DESTROYED;
525 }
526 //sendOutcomeUpdate(); // don't do this - base raid sends an UPDATE_FAILED so we're good already
527 }
528 if (listener != null && outcome != null) {
529 listener.notifyInspectionEnded(outcome);
530 }
531 }
532
533
534 public void buttonPressConfirmed(Object buttonId, IntelUIAPI ui) {
535 if (buttonId == BUTTON_CHANGE_ORDERS) {
536 ui.showDialog(null, new HIOrdersInteractionDialogPluginImpl(this, ui));
537 }
538 }
539
540
541 @Override
542 public String getIcon() {
543 return Global.getSettings().getSpriteName("intel", "hegemony_inspection");
544 }
545
546 @Override
547 public SectorEntityToken getMapLocation(SectorMapAPI map) {
548 if (target != null && target.isInEconomy() && target.getPrimaryEntity() != null) {
549 return target.getPrimaryEntity();
550 }
551 return super.getMapLocation(map);
552 }
553}
554
555
556
557
558
559
static SettingsAPI getSettings()
Definition Global.java:51
static SectorAPI getSector()
Definition Global.java:59
static void addAdjustmentMessage(float delta, FactionAPI faction, PersonAPI person, TextPanelAPI panel, TooltipMakerAPI info, Color tc, boolean withCurrent, float pad)
RouteFleetAssignmentAI createAssignmentAI(CampaignFleetAPI fleet, RouteData route)
void sendUpdateIfPlayerHasIntel(Object listInfoParam, boolean onlyIfImportant, boolean sendIfHidden)
void createSmallDescription(TooltipMakerAPI info, float width, float height)
HegemonyInspectionIntel(MarketAPI from, MarketAPI target, float inspectionFP)
String getSpriteName(String category, String id)