1package com.fs.starfarer.api.impl.campaign.intel.punitive;
4import java.util.Random;
7import org.lwjgl.input.Keyboard;
8import org.lwjgl.util.vector.Vector2f;
10import com.fs.starfarer.api.Global;
11import com.fs.starfarer.api.campaign.CampaignFleetAPI;
12import com.fs.starfarer.api.campaign.FactionAPI;
13import com.fs.starfarer.api.campaign.ReputationActionResponsePlugin.ReputationAdjustmentResult;
14import com.fs.starfarer.api.campaign.SectorEntityToken;
15import com.fs.starfarer.api.campaign.econ.CommoditySpecAPI;
16import com.fs.starfarer.api.campaign.econ.Industry;
17import com.fs.starfarer.api.campaign.econ.MarketAPI;
18import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin;
19import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.CustomRepImpact;
20import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActionEnvelope;
21import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActions;
22import com.fs.starfarer.api.impl.campaign.DebugFlags;
23import com.fs.starfarer.api.impl.campaign.fleets.FleetFactoryV3;
24import com.fs.starfarer.api.impl.campaign.fleets.FleetParamsV3;
25import com.fs.starfarer.api.impl.campaign.fleets.RouteLocationCalculator;
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.ids.Factions;
29import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
30import com.fs.starfarer.api.impl.campaign.ids.Ranks;
31import com.fs.starfarer.api.impl.campaign.ids.Tags;
32import com.fs.starfarer.api.impl.campaign.intel.punitive.PunitiveExpeditionManager.PunExData;
33import com.fs.starfarer.api.impl.campaign.intel.punitive.PunitiveExpeditionManager.PunExGoal;
34import com.fs.starfarer.api.impl.campaign.intel.punitive.PunitiveExpeditionManager.PunExReason;
35import com.fs.starfarer.api.impl.campaign.intel.punitive.PunitiveExpeditionManager.PunExType;
36import com.fs.starfarer.api.impl.campaign.intel.raid.RaidAssignmentAI;
37import com.fs.starfarer.api.impl.campaign.intel.raid.RaidIntel;
38import com.fs.starfarer.api.impl.campaign.intel.raid.RaidIntel.RaidDelegate;
39import com.fs.starfarer.api.impl.campaign.procgen.themes.RouteFleetAssignmentAI;
40import com.fs.starfarer.api.ui.Alignment;
41import com.fs.starfarer.api.ui.ButtonAPI;
42import com.fs.starfarer.api.ui.IntelUIAPI;
43import com.fs.starfarer.api.ui.LabelAPI;
44import com.fs.starfarer.api.ui.SectorMapAPI;
45import com.fs.starfarer.api.ui.TooltipMakerAPI;
46import com.fs.starfarer.api.util.Misc;
53 public static enum PunExOutcome {
55 COLONY_NO_LONGER_EXISTS,
71 protected Random
random =
new Random();
78 float expeditionFP,
float organizeDuration,
80 super(
target.getStarSystem(), faction,
null);
89 SectorEntityToken gather =
from.getPrimaryEntity();
90 SectorEntityToken raidJump = RouteLocationCalculator.findJumpPointToUse(getFactionForUIColors(),
target.getPrimaryEntity());
92 if (gather ==
null || raidJump ==
null) {
98 float orgDur = organizeDuration;
103 float successMult = 0.5f;
105 assemble.addSource(
from);
106 assemble.setSpawnFP(expeditionFP);
107 assemble.setAbortFP(expeditionFP * successMult);
112 travel.setAbortFP(expeditionFP * successMult);
116 action.setAbortFP(expeditionFP * successMult);
129 protected transient ReputationAdjustmentResult
repResult =
null;
131 CustomRepImpact impact =
new CustomRepImpact();
134 new RepActionEnvelope(RepActions.CUSTOM,
135 impact,
null,
null,
false,
false),
136 getFaction().getId());
157 RaidAssignmentAI raidAI =
new RaidAssignmentAI(fleet, route,
action);
165 super.advanceImpl(amount);
184 String base = Misc.ucFirst(faction.getPersonNamePrefix()) +
" Expedition";
186 if (
outcome == PunExOutcome.AVERTED) {
187 return base +
" - Averted";
189 if (isSendingUpdate() && isFailed()) {
190 return base +
" - Failed";
192 if (isSucceeded() ||
outcome == PunExOutcome.SUCCESS) {
193 return base +
" - Successful";
195 if (
outcome == PunExOutcome.RAID_FAIL ||
196 outcome == PunExOutcome.BOMBARD_FAIL ||
197 outcome == PunExOutcome.COLONY_NO_LONGER_EXISTS ||
198 outcome == PunExOutcome.TASK_FORCE_DEFEATED) {
199 return base +
" - Failed";
210 Color h = Misc.getHighlightColor();
211 Color g = Misc.getGrayColor();
216 if (mode == ListInfoMode.IN_DESC) initPad = opad;
218 Color tc = getBulletColorForMode(mode);
221 boolean isUpdate = getListInfoParam() !=
null;
233 FactionAPI other =
target.getFaction();
234 info.addPara(
"Target: %s", initPad, tc,
235 other.getBaseUIColor(),
target.getName());
237 info.addPara(
"Arrived in-system", tc, initPad);
243 null,
null, info, tc, isUpdate, initPad);
251 if (
outcome == PunExOutcome.TASK_FORCE_DEFEATED) {
252 info.addPara(
"Expeditionary force defeated", tc, initPad);
253 }
else if (
outcome == PunExOutcome.COLONY_NO_LONGER_EXISTS) {
254 info.addPara(
"Expedition aborted", tc, initPad);
255 }
else if (
outcome == PunExOutcome.AVERTED) {
256 info.addPara(
"Expedition planning disrupted", initPad, tc, other.getBaseUIColor(),
target.getName());
257 }
else if (
outcome == PunExOutcome.BOMBARD_FAIL) {
258 info.addPara(
"Bombardment of %s failed", initPad, tc, other.getBaseUIColor(),
target.getName());
259 }
else if (
outcome == PunExOutcome.RAID_FAIL) {
260 info.addPara(
"Raid of %s failed", initPad, tc, other.getBaseUIColor(),
target.getName());
261 }
else if (
outcome == PunExOutcome.SUCCESS) {
262 if (
goal == PunExGoal.BOMBARD) {
263 if (!
target.isInEconomy()) {
264 info.addPara(
"%s destroyed by bombardment", initPad, tc, other.getBaseUIColor(),
target.getName());
266 info.addPara(
"Bombardment of %s successful", initPad, tc, other.getBaseUIColor(),
target.getName());
269 info.addPara(
targetIndustry.getCurrentName() +
" disrupted for %s days",
270 initPad, tc, h,
"" + (
int)Math.round(
targetIndustry.getDisruptedDays()));
277 null,
null, info, tc, isUpdate, initPad);
283 info.addPara(
"Target: %s", initPad, tc,
284 other.getBaseUIColor(),
target.getName());
287 if (
goal == PunExGoal.BOMBARD) {
288 String goalStr =
"saturation bombardment";
289 info.addPara(
"Goal: %s", initPad, tc, Misc.getNegativeHighlightColor(), goalStr);
292 float eta = getETA();
293 if (eta > 1 && !isEnding()) {
294 String days = getDaysString(eta);
295 info.addPara(
"Estimated %s " + days +
" until arrival",
296 initPad, tc, h,
"" + (
int)Math.round(eta));
298 }
else if (!isEnding() &&
action.getElapsed() > 0) {
299 info.addPara(
"Currently in-system", tc, initPad);
306 null,
null, info, tc, isUpdate, initPad);
313 for (RaidStage stage : stages) {
324 super.createIntelInfo(info, mode);
329 Color h = Misc.getHighlightColor();
332 FactionAPI faction = getFaction();
333 String is = faction.getDisplayNameIsOrAre();
335 String goalDesc =
"";
337 Color goalColor = Misc.getTextColor();
339 case RAID_PRODUCTION:
340 goalDesc =
"disrupting the colony's " +
targetIndustry.getCurrentName();
343 goalDesc =
"raiding the colony's " +
targetIndustry.getCurrentName() +
" to disrupt its operations";
346 goalDesc =
"a saturation bombardment of the colony";
347 goalHL =
"saturation bombardment of the colony";
348 goalColor = Misc.getNegativeHighlightColor();
352 String strDesc = getRaidStrDesc();
353 int numFleets = (int) getOrigNumFleets();
354 String fleets =
"fleets";
355 if (numFleets == 1) fleets =
"fleet";
358 LabelAPI label = info.addPara(Misc.ucFirst(faction.getDisplayNameWithArticle()) +
" " + is +
359 " targeting %s with a " + strDesc +
" expeditionary force, projected to be comprised of " +
360 numFleets +
" " + fleets +
". " +
361 "Its likely goal is " + goalDesc +
".",
362 initPad, faction.getBaseUIColor(),
target.getName());
363 label.setHighlight(faction.getDisplayNameWithArticleWithoutArticle(),
target.getName(), strDesc,
"" + numFleets, goalHL);
364 label.setHighlightColors(faction.getBaseUIColor(),
targetFaction.getBaseUIColor(), h, h, goalColor);
366 LabelAPI label = info.addPara(Misc.ucFirst(faction.getDisplayNameWithArticle()) +
" " + is +
367 " targeting %s with an expeditionary force. " +
368 "Its likely goal is " + goalDesc +
".",
369 initPad, faction.getBaseUIColor(),
target.getName());
370 label.setHighlight(faction.getDisplayNameWithArticleWithoutArticle(),
target.getName(), goalHL);
371 label.setHighlightColors(faction.getBaseUIColor(),
targetFaction.getBaseUIColor(), goalColor);
379 Color h = Misc.getHighlightColor();
380 Color g = Misc.getGrayColor();
381 Color tc = Misc.getTextColor();
385 info.addImage(getFactionForUIColors().getLogo(), width, 128, opad);
387 FactionAPI faction = getFaction();
388 String has = faction.getDisplayNameHasOrHave();
389 String is = faction.getDisplayNameIsOrAre();
395 info.addPara(
"The primary reason for the expedition is the colony's market share " +
396 "in the exports of " + spec.getName() +
".", opad);
397 }
else if (
bestReason.type == PunExType.ANTI_FREE_PORT) {
398 info.addPara(
"The primary reason for the expedition is the colony's \"free port\" " +
399 "status, and the concomitant export of illegal goods alongside it being a haven for " +
400 "various undesirables.", opad);
401 }
else if (
bestReason.type == PunExType.TERRITORIAL) {
402 info.addPara(
"The primary reason for the expedition is the colony being established in " +
403 "space claimed by " + faction.getDisplayNameWithArticle() +
".", opad);
408 "expedition",
"expedition's");
411 info.addSectionHeading(
"Status",
412 faction.getBaseUIColor(), faction.getDarkUIColor(), Alignment.MID, opad);
414 for (RaidStage stage : stages) {
415 stage.showStageInfo(info);
416 if (getStageIndex(stage) == failStage)
break;
419 if (getCurrentStage() == 0 && !isFailed()) {
421 ButtonAPI button = info.addButton(
"Avert",
BUTTON_AVERT,
422 pf.getBaseUIColor(), pf.getDarkUIColor(),
423 (int)(width), 20f, opad * 2f);
424 button.setShortcut(Keyboard.KEY_T,
true);
439 LabelAPI label = info.addPara(
"This operation is being carried " +
440 "without an open declaration of war. Defeating the " +
441 "expeditionary force will only result in a small reputation reduction with " + faction.getDisplayNameWithArticle() +
442 ".", Misc.getGrayColor(),
444 label.setHighlight(faction.getDisplayNameWithArticleWithoutArticle());
445 label.setHighlightColors(faction.getBaseUIColor());
454 if (listInfoParam == UPDATE_RETURNING) {
459 if (listInfoParam == UPDATE_FAILED) {
463 super.sendUpdateIfPlayerHasIntel(listInfoParam, onlyIfImportant, sendIfHidden);
470 Set<String> tags = super.getIntelTags(map);
471 tags.add(Tags.INTEL_MILITARY);
472 tags.add(Tags.INTEL_COLONIES);
473 tags.add(getFaction().getId());
479 if (
outcome ==
null && failStage >= 0) {
481 outcome = PunExOutcome.COLONY_NO_LONGER_EXISTS;
483 outcome = PunExOutcome.TASK_FORCE_DEFEATED;
489 if (
outcome == PunExOutcome.SUCCESS) {
498 return faction.getCrest();
519 Random
random = route.getRandom();
521 MarketAPI market = route.getMarket();
522 CampaignFleetAPI fleet =
createFleet(market.getFactionId(), route, market,
null,
random);
524 if (fleet ==
null || fleet.isEmpty())
return null;
528 market.getContainingLocation().addEntity(fleet);
529 fleet.setFacing((
float) Math.random() * 360f);
531 fleet.setLocation(market.getPrimaryEntity().getLocation().x, market.getPrimaryEntity().getLocation().x);
538 public CampaignFleetAPI
createFleet(String factionId, RouteData route, MarketAPI market, Vector2f locInHyper, Random
random) {
541 OptionalFleetData extra = route.getExtra();
543 float combat = extra.fp;
544 float tanker = extra.fp * (0.1f +
random.nextFloat() * 0.05f);
545 float transport = extra.fp * (0.1f +
random.nextFloat() * 0.05f);
546 float freighter = 0f;
548 if (
goal == PunExGoal.BOMBARD) {
551 transport += tanker / 2f;
559 FleetParamsV3 params =
new FleetParamsV3(
563 route ==
null ?
null : route.getQualityOverride(),
576 params.timestamp = route.getTimestamp();
579 CampaignFleetAPI fleet = FleetFactoryV3.createFleet(params);
581 if (fleet ==
null || fleet.isEmpty())
return null;
583 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_WAR_FLEET,
true);
584 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_RAIDER,
true);
586 if (fleet.getFaction().getCustomBoolean(Factions.CUSTOM_PIRATE_BEHAVIOR)) {
587 fleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_PIRATE,
true);
590 String postId = Ranks.POST_PATROL_COMMANDER;
591 String rankId = Ranks.SPACE_COMMANDER;
593 fleet.getCommander().setPostId(postId);
594 fleet.getCommander().setRankId(rankId);
596 Misc.makeNoRepImpact(fleet,
"punex");
597 Misc.makeHostile(fleet);
614 return bestReason !=
null && bestReason.type == PunExType.TERRITORIAL;
620 return target.getPrimaryEntity();
622 return super.getMapLocation(map);
static SettingsAPI getSettings()
static SectorAPI getSector()
static void addAdjustmentMessage(float delta, FactionAPI faction, PersonAPI person, TextPanelAPI panel, TooltipMakerAPI info, Color tc, boolean withCurrent, float pad)
static boolean PUNITIVE_EXPEDITION_DEBUG
static boolean FAST_RAIDS
void buttonPressConfirmed(Object buttonId, IntelUIAPI ui)
PunitiveExpeditionIntel(FactionAPI faction, MarketAPI from, MarketAPI target, float expeditionFP, float organizeDuration, PunExGoal goal, Industry targetIndustry, PunExReason bestReason)
void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode)
SectorEntityToken getMapLocation(SectorMapAPI map)
static final String BUTTON_AVERT
void addInitialDescSection(TooltipMakerAPI info, float initPad)
CampaignFleetAPI createFleet(String factionId, RouteData route, MarketAPI market, Vector2f locInHyper, Random random)
PunExReason getBestReason()
Industry getTargetIndustry()
transient String targetOwner
void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode)
void sendEnteredSystemUpdate()
Set< String > getIntelTags(SectorMapAPI map)
static final Object OUTCOME_UPDATE
RouteFleetAssignmentAI createAssignmentAI(CampaignFleetAPI fleet, RouteData route)
static final Object ENTERED_SYSTEM_UPDATE
void sendUpdateIfPlayerHasIntel(Object listInfoParam, boolean onlyIfImportant, boolean sendIfHidden)
void advanceImpl(float amount)
transient ReputationAdjustmentResult repResult
CampaignFleetAPI spawnFleet(RouteData route)
void createSmallDescription(TooltipMakerAPI info, float width, float height)
void setOutcome(PunExOutcome outcome)
PEActionStage getActionStage()
void notifyRaidEnded(RaidIntel raid, RaidStageStatus status)
FactionAPI getTargetFaction()
PunExOutcome getOutcome()
PunExData getDataFor(FactionAPI faction)
static PunitiveExpeditionManager getInstance()
CommoditySpecAPI getCommoditySpec(String commodityId)