Starsector API
Loading...
Searching...
No Matches
FleetInteractionDialogPluginImpl.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign;
2
3import java.awt.Color;
4import java.util.ArrayList;
5import java.util.HashMap;
6import java.util.List;
7import java.util.Map;
8import java.util.Random;
9
10import org.lwjgl.input.Keyboard;
11
12import com.fs.starfarer.api.Global;
13import com.fs.starfarer.api.campaign.BattleAPI;
14import com.fs.starfarer.api.campaign.BattleAPI.BattleSide;
15import com.fs.starfarer.api.campaign.CampaignFleetAPI;
16import com.fs.starfarer.api.campaign.CargoAPI;
17import com.fs.starfarer.api.campaign.CoreInteractionListener;
18import com.fs.starfarer.api.campaign.EngagementResultForFleetAPI;
19import com.fs.starfarer.api.campaign.FactionAPI;
20import com.fs.starfarer.api.campaign.FleetEncounterContextPlugin.DataForEncounterSide;
21import com.fs.starfarer.api.campaign.FleetEncounterContextPlugin.DisengageHarryAvailability;
22import com.fs.starfarer.api.campaign.FleetEncounterContextPlugin.EngagementOutcome;
23import com.fs.starfarer.api.campaign.FleetEncounterContextPlugin.PursueAvailability;
24import com.fs.starfarer.api.campaign.FleetEncounterContextPlugin.Status;
25import com.fs.starfarer.api.campaign.FleetMemberPickerListener;
26import com.fs.starfarer.api.campaign.InteractionDialogAPI;
27import com.fs.starfarer.api.campaign.InteractionDialogPlugin;
28import com.fs.starfarer.api.campaign.OptionPanelAPI;
29import com.fs.starfarer.api.campaign.RuleBasedDialog;
30import com.fs.starfarer.api.campaign.SectorEntityToken;
31import com.fs.starfarer.api.campaign.SectorEntityToken.VisibilityLevel;
32import com.fs.starfarer.api.campaign.TextPanelAPI;
33import com.fs.starfarer.api.campaign.VisualPanelAPI;
34import com.fs.starfarer.api.campaign.ai.CampaignFleetAIAPI;
35import com.fs.starfarer.api.campaign.ai.CampaignFleetAIAPI.EncounterOption;
36import com.fs.starfarer.api.campaign.ai.CampaignFleetAIAPI.InitialBoardingResponse;
37import com.fs.starfarer.api.campaign.ai.CampaignFleetAIAPI.PursuitOption;
38import com.fs.starfarer.api.campaign.events.CampaignEventPlugin;
39import com.fs.starfarer.api.campaign.listeners.ListenerUtil;
40import com.fs.starfarer.api.campaign.rules.MemKeys;
41import com.fs.starfarer.api.campaign.rules.MemoryAPI;
42import com.fs.starfarer.api.campaign.rules.RuleAPI;
43import com.fs.starfarer.api.campaign.rules.RulesAPI;
44import com.fs.starfarer.api.characters.PersonAPI;
45import com.fs.starfarer.api.combat.BattleCreationContext;
46import com.fs.starfarer.api.combat.CombatReadinessPlugin;
47import com.fs.starfarer.api.combat.EngagementResultAPI;
48import com.fs.starfarer.api.fleet.CrewCompositionAPI;
49import com.fs.starfarer.api.fleet.FleetGoal;
50import com.fs.starfarer.api.fleet.FleetMemberAPI;
51import com.fs.starfarer.api.impl.campaign.FleetEncounterContext.BoardingResult;
52import com.fs.starfarer.api.impl.campaign.FleetEncounterContext.EngageBoardableOutcome;
53import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
54import com.fs.starfarer.api.impl.campaign.ids.Sounds;
55import com.fs.starfarer.api.impl.campaign.intel.BaseIntelPlugin;
56import com.fs.starfarer.api.impl.campaign.rulecmd.DumpMemory;
57import com.fs.starfarer.api.impl.campaign.rulecmd.FireBest;
58import com.fs.starfarer.api.impl.campaign.rulecmd.SetStoryOption;
59import com.fs.starfarer.api.impl.campaign.rulecmd.SetStoryOption.BaseOptionStoryPointActionDelegate;
60import com.fs.starfarer.api.impl.campaign.rulecmd.SetStoryOption.StoryOptionParams;
61import com.fs.starfarer.api.impl.campaign.skills.BaseSkillEffectDescription;
62import com.fs.starfarer.api.impl.combat.CRPluginImpl;
63import com.fs.starfarer.api.ui.LabelAPI;
64import com.fs.starfarer.api.ui.TooltipMakerAPI;
65import com.fs.starfarer.api.util.Misc;
66import com.fs.starfarer.api.util.Pair;
67
68public class FleetInteractionDialogPluginImpl implements InteractionDialogPlugin, RuleBasedDialog {
69
70 public static float EMERGENCY_REPAIRS_MAX_DP = Global.getSettings().getFloat("emergencyRepairsMaxDPValue");
71
72 public static interface FIDConfigGen {
73 FIDConfig createConfig();
74 }
75
76 public static class FIDConfig {
77 public boolean showCommLinkOption = true;
78 public boolean leaveAlwaysAvailable = false;
79 public boolean showWarningDialogWhenNotHostile = true;
80 public boolean showTransponderStatus = true;
81 public boolean showFleetAttitude = true;
82 public boolean showEngageText = true;
83 public boolean alwaysAttackVsAttack = false;
84 public boolean alwaysPursue = false;
85 public boolean dismissOnLeave = true;
86 public boolean withSalvage = true;
87 public boolean lootCredits = true;
88
89 public boolean showVictoryText = true;
90
91 //public boolean postLootLeaveHasShortcut = true;
92
93 public boolean impactsEnemyReputation = true;
94 public boolean impactsAllyReputation = true;
95
96 public boolean pullInAllies = true;
97 public boolean pullInEnemies = true;
98 public boolean pullInStations = true;
99
100 //public String postLootLeaveOptionText = null;
101 public String noSalvageLeaveOptionText = null;
102 public String firstTimeEngageOptionText = null;
103 public String afterFirstTimeEngageOptionText = null;
104
105 public FIDDelegate delegate = null;
106 public boolean printXPToDialog = false;
107
108 public boolean justShowFleets = false;
109 public boolean showPullInText = true;
110
111 public boolean straightToEngage = false;
112 public boolean playerAttackingStation = false;
113 public boolean playerDefendingStation = false;
114
115
116 public Random salvageRandom = null;
117 }
118
119 public static interface FIDDelegate {
120 public void postPlayerSalvageGeneration(InteractionDialogAPI dialog, FleetEncounterContext context, CargoAPI salvage);
121 public void battleContextCreated(InteractionDialogAPI dialog, BattleCreationContext bcc);
122 public void notifyLeave(InteractionDialogAPI dialog);
123 }
124
125 public static class BaseFIDDelegate implements FIDDelegate {
126 public void battleContextCreated(InteractionDialogAPI dialog, BattleCreationContext bcc) {}
127 public void notifyLeave(InteractionDialogAPI dialog) {}
128 public void postPlayerSalvageGeneration(InteractionDialogAPI dialog, FleetEncounterContext context, CargoAPI salvage) {}
129 }
130
131
132
133
134 protected static enum VisualType {
135 FLEET_INFO,
136 OTHER,
137 }
138
139
140 public static enum OptionId {
141 INIT,
142 PRINT_ONGOING_BATTLE_INFO,
143 BEGIN_FLEET_ENCOUNTER_2,
144 OPEN_COMM,
145 CUT_COMM,
146 ENGAGE,
147 FORCE_ENGAGE,
148 ATTEMPT_TO_DISENGAGE,
149 DISENGAGE,
150 CLEAN_DISENGAGE,
151 SCUTTLE,
152 PURSUE,
153 AUTORESOLVE_PURSUE,
154 HARRY_PURSUE,
155 LET_THEM_GO,
156 LEAVE,
157 LOOT_THEN_LEAVE,
158 CONTINUE_LEAVE,
159 CONTINUE,
160 GO_TO_MAIN,
161 GO_TO_PRE_BATTLE,
162 RECOVERY_SELECT,
163 RECOVERY_CONTINUE,
164 CONTINUE_FROM_VICTORY_TRIGGERS,
165 CONTINUE_LOOT,
166 CONTINUE_INTO_BATTLE,
167
168 CONTINUE_INTO_BOARDING,
169 BOARDING_ACTION,
170 SELECT_FLAGSHIP,
171 CRASH_MOTHBALL,
172 ENGAGE_BOARDABLE,
173 ABORT_BOARDING_ACTION,
174 HARD_DOCK,
175 LAUNCH_ASSAULT_TEAMS,
176 LET_IT_GO,
177
178 SELECTOR_MARINES,
179 SELECTOR_CREW,
180
181 REINIT_CONTINUE,
182
183 INITIATE_BATTLE,
184 JOIN_ONGOING_BATTLE,
185 CONTINUE_ONGOING_BATTLE,
186
187 EMERGENCY_REPAIRS,
188
189 DEV_MODE_ESCAPE,
190 }
191
192
193 protected InteractionDialogAPI dialog;
194 protected TextPanelAPI textPanel;
195 protected OptionPanelAPI options;
196 protected VisualPanelAPI visual;
197
198 protected CampaignFleetAPI playerFleet;
199 protected CampaignFleetAPI otherFleet;
200
201 protected FleetGoal playerGoal = FleetGoal.ATTACK;
202 protected FleetGoal otherGoal = FleetGoal.ATTACK;
203
204 protected VisualType currVisualType = VisualType.FLEET_INFO;
205
207
208 protected static final Color HIGHLIGHT_COLOR = Global.getSettings().getColor("buttonShortcut");
209 protected static final Color FRIEND_COLOR = Global.getSettings().getColor("textFriendColor");
210 protected static final Color ENEMY_COLOR = Misc.getNegativeHighlightColor();
211
213 protected boolean ongoingBattle = false;
214 protected boolean firstEngagement = true;
215 protected boolean joinedBattle = false;
216
217 protected boolean forceEngage = false;
218
219 protected boolean shownTooLargeToRetreatMessage = false;
220
221 public static boolean inConversation = false;
222 public static boolean directToComms = false;
223
224 protected FIDConfig config;
225
226// public static class FleetMemberPreEncounterData {
227// public int indexInFleet;
228// public PersonAPI officer;
229// }
230 protected List<FleetMemberAPI> membersInOrderPreEncounter = new ArrayList<FleetMemberAPI>();
231
233 this(null);
234 }
235 public FleetInteractionDialogPluginImpl(FIDConfig params) {
236 this.config = params;
237
238 if (origFlagship == null) {
239 origFlagship = Global.getSector().getPlayerFleet().getFlagship();
240 }
241 if (origCaptains.isEmpty()) {
242 for (FleetMemberAPI member : Global.getSector().getPlayerFleet().getFleetData().getMembersListCopy()) {
243 origCaptains.put(member, member.getCaptain());
244 }
245 membersInOrderPreEncounter = new ArrayList<FleetMemberAPI>(Global.getSector().getPlayerFleet().getFleetData().getMembersListCopy());
246 }
247 }
248
249 public Map<String, MemoryAPI> getMemoryMap() {
251 }
252
253 private boolean skipAttitudeOnInit = false;
254 public void reinit(boolean withContinueOnRuleFound) {
255 RulesAPI rules = Global.getSector().getRules();
256 RuleAPI rule = rules.getBestMatching(null, "BeginFleetEncounter", dialog, conversationDelegate.getMemoryMap());
257 if (rule == null || !withContinueOnRuleFound) {
259 } else {
260 options.clearOptions();
261 options.addOption("Continue", OptionId.REINIT_CONTINUE, null);
262 if (Global.getSettings().isDevMode()) {
264 }
265 }
266 }
267
268 public void reinitPostContinue() {
269 //init(dialog);
270 inConversation = false;
271 directToComms = false;
272
273 boolean cont = conversationDelegate.getMemoryMap().get(MemKeys.LOCAL).getBoolean("$fidpi_addContinue");
274 conversationDelegate.getMemoryMap().get(MemKeys.LOCAL).unset("$fidpi_addContinue");
275
276 if (cont) {
277 conversationDelegate.fireBest("BeginFleetEncounter2");
278 } else {
279 conversationDelegate.fireBest("BeginFleetEncounter");
280 }
281 if (conversationDelegate.getMemoryMap().get(MemKeys.LOCAL).getBoolean("$fidpi_addContinue")) {
282 options.clearOptions();
283 options.addOption("Continue", OptionId.BEGIN_FLEET_ENCOUNTER_2);
284 } else {
285 if (directToComms) {
286 optionSelected(null, OptionId.OPEN_COMM);
287 } else {
288 //skipAttitudeOnInit = true;
289 optionSelected(null, OptionId.INIT);
290 }
291 }
292 }
293
294 public void init(InteractionDialogAPI dialog) {
295 this.dialog = dialog;
296
297 if (this.config == null) {
298 MemoryAPI memory = dialog.getInteractionTarget().getMemoryWithoutUpdate();
299// if (memory.contains(MemFlags.FLEET_INTERACTION_DIALOG_CONFIG_OVERRIDE)) {
300// this.config = (FIDConfig) memory.get(MemFlags.FLEET_INTERACTION_DIALOG_CONFIG_OVERRIDE);
301// } else
302 if (memory.contains(MemFlags.FLEET_INTERACTION_DIALOG_CONFIG_OVERRIDE_GEN)) {
303 this.config = ((FIDConfigGen) memory.get(MemFlags.FLEET_INTERACTION_DIALOG_CONFIG_OVERRIDE_GEN)).createConfig();
304 } else {
305 this.config = new FIDConfig();
306 }
307 }
308
309
310
311// boolean sampling = true;
312// while (sampling) {
313 if (Global.getSettings().isDevMode()) {
314 dialog.setOptionOnEscape("dev mode exit", OptionId.DEV_MODE_ESCAPE);
315 dialog.setOptionOnConfirm("dev mode exit", OptionId.DEV_MODE_ESCAPE);
316 }
317
318 textPanel = dialog.getTextPanel();
319 options = dialog.getOptionPanel();
320 visual = dialog.getVisualPanel();
321
322 playerFleet = Global.getSector().getPlayerFleet();
323 if (playerFleet != null) {
324 playerFleet.getFleetData().ensureHasFlagship();
325 }
326 otherFleet = (CampaignFleetAPI) (dialog.getInteractionTarget());
327
328// playerFleet.getFleetData().takeSnapshot();
329// otherFleet.getFleetData().takeSnapshot();
330
331 if (context.getBattle() == null) {
332 if (otherFleet.getBattle() == null || otherFleet.getBattle().isDone()) {
333 ongoingBattle = false;
334 BattleAPI battle = Global.getFactory().createBattle(playerFleet, otherFleet);
335 context.setBattle(battle);
337 } else {
338 ongoingBattle = true;
339 context.setBattle(otherFleet.getBattle());
340 if (context.getBattle().canJoin(playerFleet)) {
341 //context.getBattle().join(playerFleet);
343 }
344 }
345 }
346
347 for (CampaignFleetAPI fleet : context.getBattle().getBothSides()) {
348 fleet.inflateIfNeeded();
349 }
350 context.getBattle().genCombined();
351
352 visual.setVisualFade(0.25f, 0.25f);
353 if (!config.straightToEngage) {
354 if (ongoingBattle && !joinedBattle) {
355 BattleAPI b = context.getBattle();
356 String titleOne = b.getPrimary(b.getSideOne()).getNameWithFactionKeepCase();
357 if (b.getSideOne().size() > 1) titleOne += ", with allies";
358 String titleTwo = b.getPrimary(b.getSideTwo()).getNameWithFactionKeepCase();
359 if (b.getSideTwo().size() > 1) titleTwo += ", with allies";
360 visual.showPreBattleJoinInfo(null, playerFleet, Misc.ucFirst(titleOne), Misc.ucFirst(titleTwo), context);
361 } else {
362 //visual.showFleetInfo((String)null, playerFleet, (String)null, otherFleet, context);
364 }
365 }
366
367 inConversation = false;
368 directToComms = false;
372
373// }
374
375 if (!config.justShowFleets) {
376 // if (ongoingBattle) {
377 conversationDelegate.getMemoryMap().get(MemKeys.LOCAL).set("$ongoingBattle", ongoingBattle, 0);
378 boolean cont = conversationDelegate.getMemoryMap().get(MemKeys.LOCAL).getBoolean("$fidpi_addContinue");
379 conversationDelegate.getMemoryMap().get(MemKeys.LOCAL).unset("$fidpi_addContinue");
380 if (!ongoingBattle && !config.straightToEngage) {
381 if (cont) {
382 conversationDelegate.fireBest("BeginFleetEncounter2");
383 } else {
384 conversationDelegate.fireBest("BeginFleetEncounter");
385 }
386 }
387 // } else {
388 // conversationDelegate.fireBest("OngoingBattleEncounter");
389 // }
390
391 if (conversationDelegate.getMemoryMap().get(MemKeys.LOCAL).getBoolean("$fidpi_addContinue")) {
392 options.clearOptions();
393 options.addOption("Continue", OptionId.BEGIN_FLEET_ENCOUNTER_2);
394 } else {
395 if (directToComms) {
396 optionSelected(null, OptionId.OPEN_COMM);
397 } else {
398 optionSelected(null, OptionId.INIT);
399 }
400 }
401
402 if (config.straightToEngage) {
403 if (ongoingBattle) {
404 optionSelected(null, OptionId.JOIN_ONGOING_BATTLE);
405 } else {
406 optionSelected(null, OptionId.ENGAGE);
407 }
408 }
409 } else {
410// if (config.showPullInText) {
411// optionSelected(null, OptionId.PRINT_ONGOING_BATTLE_INFO);
412// }
413 }
414 }
415
417 optionSelected(null, OptionId.PRINT_ONGOING_BATTLE_INFO);
418 }
419
420
421 protected List<CampaignFleetAPI> pulledIn = new ArrayList<CampaignFleetAPI>();
422 protected void pullInNearbyFleets() {
423 BattleAPI b = context.getBattle();
424 if (!ongoingBattle) {
425 b.join(Global.getSector().getPlayerFleet());
426 }
427
428 BattleSide playerSide = b.pickSide(Global.getSector().getPlayerFleet());
429
430 boolean hostile = otherFleet.getAI() != null && otherFleet.getAI().isHostileTo(playerFleet);
431 if (ongoingBattle) hostile = true;
432
433 //canDecline = otherFleet.getAI() != null && other
434
435// boolean someJoined = false;
436 CampaignFleetAPI actualPlayer = Global.getSector().getPlayerFleet();
437 CampaignFleetAPI actualOther = (CampaignFleetAPI) (dialog.getInteractionTarget());
438
439 //textPanel.addParagraph("Projecting nearby fleet movements:");
440 //textPanel.addParagraph("You encounter a ");
441 pulledIn.clear();
442
443 if (config.pullInStations && !b.isStationInvolved()) {
444 SectorEntityToken closestEntity = null;
445 CampaignFleetAPI closest = null;
446 Pair<SectorEntityToken, CampaignFleetAPI> p = Misc.getNearestStationInSupportRange(actualOther);
447 if (p != null) {
448 closestEntity = p.one;
449 closest = p.two;
450 }
451
452 if (closest != null) {
453 BattleSide joiningSide = b.pickSide(closest, true);
454 boolean canJoin = joiningSide != BattleSide.NO_JOIN;
455 if (!config.pullInAllies && joiningSide == playerSide) {
456 canJoin = false;
457 }
458 if (!config.pullInEnemies && joiningSide != playerSide) {
459 canJoin = false;
460 }
461 if (b == closest.getBattle()) {
462 canJoin = false;
463 }
464 if (closest.getBattle() != null) {
465 canJoin = false;
466 }
467
468 if (canJoin) {
469 if (closestEntity != null) {
470 closestEntity.getMarket().reapplyIndustries(); // need to pick up station CR value, in some cases
471 }
472 b.join(closest);
473 pulledIn.add(closest);
474
475 if (!config.straightToEngage && config.showPullInText) {
476 if (b.getSide(playerSide) == b.getSideFor(closest)) {
477 textPanel.addParagraph(
478 Misc.ucFirst(closest.getNameWithFactionKeepCase()) + ": supporting your forces.");//, FRIEND_COLOR);
479 } else {
480 if (hostile) {
481 textPanel.addParagraph(Misc.ucFirst(closest.getNameWithFactionKeepCase()) + ": supporting the enemy.");//, ENEMY_COLOR);
482 } else {
483 textPanel.addParagraph(Misc.ucFirst(closest.getNameWithFactionKeepCase()) + ": supporting the opposing side.");
484 }
485 }
486 textPanel.highlightFirstInLastPara(closest.getNameWithFactionKeepCase() + ":", closest.getFaction().getBaseUIColor());
487 }
488 }
489 }
490 }
491
492
493 for (CampaignFleetAPI fleet : actualPlayer.getContainingLocation().getFleets()) {
494 if (b == fleet.getBattle()) continue;
495 if (fleet.getBattle() != null) continue;
496
497 if (fleet.isStationMode()) continue;
498
499 float dist = Misc.getDistance(actualOther.getLocation(), fleet.getLocation());
500 dist -= actualOther.getRadius();
501 dist -= fleet.getRadius();
502// if (dist < Misc.getBattleJoinRange()) {
503// System.out.println("Checking: " + fleet.getNameWithFaction());
504// }
505
506 if (fleet.getFleetData().getNumMembers() <= 0) continue;
507
508 float baseSensorRange = playerFleet.getBaseSensorRangeToDetect(fleet.getSensorProfile());
509 boolean visible = fleet.isVisibleToPlayerFleet();
510 VisibilityLevel level = fleet.getVisibilityLevelToPlayerFleet();
511// if (dist < Misc.getBattleJoinRange() &&
512// (dist < baseSensorRange || (visible && level != VisibilityLevel.SENSOR_CONTACT))) {
513// System.out.println("2380dfwef");
514// }
515 float joinRange = Misc.getBattleJoinRange();
516 if (fleet.getFaction().isPlayerFaction() && !fleet.isStationMode()) {
517 joinRange += Global.getSettings().getFloat("battleJoinRangePlayerFactionBonus");
518 }
519 if (dist < joinRange &&
520 (dist < baseSensorRange || (visible && level != VisibilityLevel.SENSOR_CONTACT)) &&
521 ((fleet.getAI() != null && fleet.getAI().wantsToJoin(b, true)) || fleet.isStationMode())) {
522
523 boolean ignore = fleet.getMemoryWithoutUpdate() != null &&
524 fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.FLEET_IGNORES_OTHER_FLEETS);
525 if (ignore) continue;
526
527 BattleSide joiningSide = b.pickSide(fleet, true);
528 if (!config.pullInAllies && joiningSide == playerSide) continue;
529 if (!config.pullInEnemies && joiningSide != playerSide) continue;
530
531 b.join(fleet);
532 pulledIn.add(fleet);
533 //if (b.isPlayerSide(b.getSideFor(fleet))) {
534 if (!config.straightToEngage && config.showPullInText) {
535 if (b.getSide(playerSide) == b.getSideFor(fleet)) {
536 textPanel.addParagraph(Misc.ucFirst(fleet.getNameWithFactionKeepCase()) + ": supporting your forces.");//, FRIEND_COLOR);
537 } else {
538 if (hostile) {
539 textPanel.addParagraph(Misc.ucFirst(fleet.getNameWithFactionKeepCase()) + ": joining the enemy.");//, ENEMY_COLOR);
540 } else {
541 textPanel.addParagraph(Misc.ucFirst(fleet.getNameWithFactionKeepCase()) + ": supporting the opposing side.");
542 }
543 }
544 textPanel.highlightFirstInLastPara(fleet.getNameWithFactionKeepCase() + ":", fleet.getFaction().getBaseUIColor());
545 }
546// someJoined = true;
547 }
548 }
549
550 if (otherFleet != null) otherFleet.inflateIfNeeded();
551 for (CampaignFleetAPI curr : pulledIn) {
552 curr.inflateIfNeeded();
553 }
554
555// if (!someJoined) {
556// addText("No nearby fleets will join the battle.");
557// }
558 if (!ongoingBattle) {
559 b.genCombined();
560 b.takeSnapshots();
561 playerFleet = b.getPlayerCombined();
562 otherFleet = b.getNonPlayerCombined();
563 if (!config.straightToEngage) {
565 }
566 }
567
568 }
569
570
571 protected EngagementResultAPI lastResult = null;
572 public void backFromEngagement(EngagementResultAPI result) {
573
574 // failsafe
575 if (playerGoal == null && otherGoal == null) {
576 EngagementResultForFleetAPI player = result.didPlayerWin() ? result.getWinnerResult() : result.getLoserResult();
577 EngagementResultForFleetAPI other = result.didPlayerWin() ? result.getLoserResult() : result.getWinnerResult();
578 if (player.getDeployed().isEmpty()) {
579 playerGoal = FleetGoal.ATTACK;
580 otherGoal = FleetGoal.ATTACK;
581 } else {
582 playerGoal = FleetGoal.ATTACK;
583 otherGoal = FleetGoal.ATTACK;
584 }
585 player.setGoal(playerGoal);
586 other.setGoal(otherGoal);
587 }
588
589 if (!ongoingBattle) {
590 if (!otherFleet.getMemoryWithoutUpdate().contains(MemFlags.MEMORY_KEY_IGNORE_PLAYER_COMMS)) {
591 otherFleet.getMemoryWithoutUpdate().set(MemFlags.MEMORY_KEY_IGNORE_PLAYER_COMMS, true, 0);
592 }
593 }
594
595 result.setBattle(context.getBattle());
596
598 lastResult = result;
599
600 boolean startedWithAllies = false;
601 if (context.getBattle() != null) {
602 startedWithAllies = context.getBattle().getPlayerSideSnapshot().size() > 1;
603 }
604 if (!Global.getSector().getPlayerFleet().isValidPlayerFleet() &&
605 startedWithAllies && context.getBattle().getPlayerSide().size() > 1) {
608 addText(getString("battleFleetLost"));
609 addText(getString("finalOutcomeNoShipsLeft"));
610 options.clearOptions();
611 options.addOption("Leave", OptionId.LEAVE, null);
612 options.setShortcut(OptionId.LEAVE, Keyboard.KEY_ESCAPE, false, false, false, true);
613 return;
614 }
615
617 if (origFlagship != null) {
618 if (selectedFlagship != null) {
619 PersonAPI captain = origFlagship.getCaptain();
620 if (captain != null && !captain.isPlayer()) {
621 selectedFlagship.setCaptain(captain);
622 }
623 }
624 Global.getSector().getPlayerFleet().getFleetData().setFlagship(origFlagship);
625// origFlagship = null;
626// selectedFlagship = null;
627
628 }
629
630 if (context.getLastEngagementOutcome() == null) {
631 return; // failsafe
632 }
633
634 boolean totalDefeat = !playerFleet.isValidPlayerFleet();
635 boolean mutualDestruction = context.getLastEngagementOutcome() == EngagementOutcome.MUTUAL_DESTRUCTION;
636
637 DataForEncounterSide playerSide = context.getDataFor(playerFleet);
638 CrewCompositionAPI crewLosses = playerSide.getCrewLossesDuringLastEngagement();
639 if ((int)crewLosses.getCrewInt() + (int)crewLosses.getMarines() > 0 && !totalDefeat && !mutualDestruction) {
640 addText(getString("casualtyReport"));
641
642 DataForEncounterSide data = context.getDataFor(playerFleet);
643 int crewLost = (int) (data.getCrewLossesDuringLastEngagement().getCrewInt());
644 int marinesLost = (int) (data.getCrewLossesDuringLastEngagement().getMarines());
645 String crewLostStr = getApproximate(crewLost);
646 if (crewLostStr.equals("no")) crewLostStr = "";
647 if (crewLostStr.indexOf(" ") >= 0) {
648 crewLostStr = crewLostStr.substring(crewLostStr.indexOf(" ") + 1);
649 }
650 String marinesLostStr = getApproximate(marinesLost);
651 if (marinesLostStr.equals("no")) marinesLostStr = "";
652 if (marinesLostStr.indexOf(" ") >= 0) {
653 marinesLostStr = marinesLostStr.substring(marinesLostStr.indexOf(" ") + 1);
654 }
655 textPanel.highlightInLastPara(HIGHLIGHT_COLOR, crewLostStr, marinesLostStr);
656 }
657
658 boolean showFleetInfo = false;
659
661 case PURSUIT_PLAYER_OUT_FIRST_WIN:
662 addText(getString("playerOutFirstPursuitWin"));
663 showFleetInfo = true;
664 break;
665 case PURSUIT_PLAYER_OUT_FIRST_LOSS:
666 addText(getString("playerOutFirstPursuitLoss"));
667 showFleetInfo = true;
668 break;
669 case BATTLE_PLAYER_OUT_FIRST_WIN:
670 addText(getString("playerOutFirstEngageWin"));
671 showFleetInfo = true;
672 break;
673 case BATTLE_PLAYER_OUT_FIRST_LOSS:
674 addText(getString("playerOutFirstEngageLoss"));
675 showFleetInfo = true;
676 break;
677 case ESCAPE_PLAYER_OUT_FIRST_WIN:
678 addText(getString("playerOutFirstEscapeWin"));
679 showFleetInfo = true;
680 break;
681 case ESCAPE_PLAYER_OUT_FIRST_LOSS:
682 addText(getString("playerOutFirstEscapeLoss"));
683 showFleetInfo = true;
684 break;
685 case BATTLE_ENEMY_WIN:
686 addText(getString("battleDefeat"));
687 showFleetInfo = true;
688 //enemyHasPostCombatOptions = true;
689 break;
690 case BATTLE_ENEMY_WIN_TOTAL:
691 addText(getString("battleTotalDefeat"));
692 showFleetInfo = true;
693 break;
694 case BATTLE_PLAYER_WIN:
695 if (config.showVictoryText) {
696 addText(getString("battleVictory"));
697 }
698 showFleetInfo = true;
699 break;
700 case BATTLE_PLAYER_WIN_TOTAL:
701 if (config.showVictoryText) {
702 addText(getString("battleTotalVictory"));
703 }
704 showFleetInfo = true;
705 break;
706 case ESCAPE_ENEMY_LOSS_TOTAL:
707 if (config.showVictoryText) {
708 addText(getString("pursuitTotalVictory"));
709 }
710 showFleetInfo = true;
711 break;
712 case ESCAPE_ENEMY_SUCCESS:
713 if (result.getLoserResult().getDisabled().isEmpty() && result.getLoserResult().getDestroyed().isEmpty()) {
714 addText(getString("pursuitVictoryNoLosses"));
715 } else {
716 addText(getString("pursuitVictoryLosses"));
717 }
718 showFleetInfo = true;
719 break;
720 case ESCAPE_ENEMY_WIN:
721 addText(getString("pursuitDefeat"));
722 showFleetInfo = true;
723 break;
724 case ESCAPE_ENEMY_WIN_TOTAL:
725 addText(getString("pursuitTotalDefeat"));
726 showFleetInfo = true;
727 break;
728 case ESCAPE_PLAYER_LOSS_TOTAL:
729 addText(getString("escapeTotalDefeat"));
730 showFleetInfo = true;
731 break;
732 case ESCAPE_PLAYER_SUCCESS:
733 addText(getString("escapeDefeat"));
734 showFleetInfo = true;
735 break;
736 case ESCAPE_PLAYER_WIN:
737 addText(getString("escapeVictory"));
738 showFleetInfo = true;
739 break;
740 case ESCAPE_PLAYER_WIN_TOTAL:
741 addText(getString("escapeTotalVictory"));
742 showFleetInfo = true;
743 break;
744 case MUTUAL_DESTRUCTION:
745 addText(getString("engagementMutualDestruction"));
746 // bit of a hack. this'll make it so that the player's ships have a chance to be repaired
747 // in the event of mutual destruction by adding them to the enemy fleet side's "disabled enemy ships" list.
748 // it'll work by using the existing vs-player boarding path
749 if (mutualDestruction) {
750 DataForEncounterSide otherData = context.getDataFor(otherFleet);
751 for (FleetMemberAPI member : result.getLoserResult().getDisabled()) {
752 otherData.addEnemy(member, Status.DISABLED);
753 }
754 }
755 }
756
757 EngagementOutcome last = context.getLastEngagementOutcome();
758 if (last == EngagementOutcome.BATTLE_PLAYER_OUT_FIRST_LOSS ||
759 last == EngagementOutcome.BATTLE_PLAYER_OUT_FIRST_WIN) {
760 float recoveryFraction = context.performPostEngagementRecoveryBoth(result);
761 if (recoveryFraction > 0) {
762 addText(getString("bothRecovery"));
763 }
764 } else {
765 float recoveryFraction = context.performPostVictoryRecovery(result);
766 if (recoveryFraction > 0) {
768 addText(getString("playerRecovery"));
769 } else {
770 addText(getString("enemyRecovery"));
771 }
772 }
773 }
774
775 if (showFleetInfo) {
776 //visual.showFleetInfo((String)null, playerFleet, (String)null, otherFleet, context);
778 }
779
781
782
783 if (config.straightToEngage) {
784 //optionSelected(null, OptionId.LEAVE);
786 } else {
787 if (ongoingBattle) {
788 options.clearOptions();
790 } else {
791 updateMainState(true);
792 }
793 }
794
795 if (isFightingOver()) {
799 }
800 }
801 }
802
803 protected void addPostBattleAttitudeText() {
804 if (!config.showFleetAttitude) return;
805
806 if (!ongoingBattle) {
808 boolean otherWantsToRun = otherFleetWantsToDisengage() && otherCanDisengage();
809 if (!otherWantsToRun) {
811 addText(getString("cleanDisengageOpportunity"), getString("highlightCleanDisengage"), Misc.getPositiveHighlightColor());
812 } else if (didEnoughToDisengage(playerFleet)) {
813 addText(getString("playerDisruptedEnemy"), getString("highlghtDisruptedEnemy"), Misc.getPositiveHighlightColor());
814 }
815 }
816 }
817 }
818 if (!isFightingOver()) {
819 String side = "";
820 if (context.getBattle() != null && context.getBattle().getNonPlayerSide().size() > 1) {
821 side = "Side";
822 }
824 addText(getString("postBattleAggressive" + side));
825 } else if (otherFleetWantsToDisengage()) {
826 if (!otherCanDisengage()) {
827 addText(getString("postBattleAggressive" + side));
828 } else {
829 addText(getString("postBattleDisengage" + side));
830 }
831 } else {
833 addText(getString("postBattleHoldVsStrongerEnemy" + side));
834 } else {
835 addText(getString("postBattleNeutral" + side));
836 }
837 }
838 }
839 }
840
841 public List<FleetMemberAPI> getPursuitCapablePlayerShips() {
842 List<FleetMemberAPI> members = new ArrayList<FleetMemberAPI>();
843 for (FleetMemberAPI member : playerFleet.getFleetData().getMembersListCopy()) {
844 if (member.isAlly()) continue;
845 if (member.isCivilian()) continue;
846 members.add(member);
847 }
848 return members;
849 }
850
851 public void optionSelected(String text, Object optionData) {
852 if (optionData == null) return;
853
854 // might not be a string if it's the dev-mode "escape to leave" option
855 if (inConversation && optionData instanceof String) {
856 conversationDelegate.optionSelected(text, optionData);
857 if (!inConversation) {
858 //optionSelected(null, OptionId.CUT_COMM);
859 //optionSelected(null, OptionId.INIT);
860 }
861 return;
862 }
863
864 if (optionData == DumpMemory.OPTION_ID) {
865 //new DumpMemory().execute(null, dialog, null, conversationDelegate.getMemoryMap());
866 new DumpMemory().execute(null, dialog, null, getMemoryMap());
867 return;
868 } else if (DevMenuOptions.isDevOption(optionData)) {
869 DevMenuOptions.execute(dialog, (String) optionData);
870 return;
871 }
872
873 if (optionData instanceof String) {
874 //??? failsafe
875 optionSelected(null, OptionId.CUT_COMM);
876 return;
877 }
878
879 OptionId option = (OptionId) optionData;
880
881// if (option == OptionId.OPEN_COMM) {
882// textPanel.clear();
883// }
884
885 if (text != null) {
886 //textPanel.addParagraph(text, Global.getSettings().getColor("buttonText"));
887 dialog.addOptionSelectedText(option);
888 }
889
890 switch (option) {
891 case PRINT_ONGOING_BATTLE_INFO:
892 if (ongoingBattle) {
893 if (!config.straightToEngage) addText(getString("ongoingBattleEncounter"));
894 BattleAPI b = context.getBattle();
895 b.genCombined();
896
897 BattleSide side = b.pickSide(playerFleet);
898 BattleSide sideAssumingTransponderOn = b.pickSide(playerFleet, false);
899
900 if (!config.straightToEngage) {
901 if (side == sideAssumingTransponderOn && side == BattleSide.NO_JOIN) {
902 addText(getString("ongoingBattleNoJoin"));
903 } else if (side != sideAssumingTransponderOn && side == BattleSide.NO_JOIN) {
904 addText(getString("ongoingBattleNoJoinTransponder"));
905 } else {
906 addText(getString("ongoingBattleShareIFF"));
907 }
908 }
909 }
910 break;
911 case INIT:
912 if (ongoingBattle) {
913 if (!config.straightToEngage) addText(getString("ongoingBattleEncounter"));
914 BattleAPI b = context.getBattle();
915 b.genCombined();
916
917 BattleSide side = b.pickSide(playerFleet);
918 BattleSide sideAssumingTransponderOn = b.pickSide(playerFleet, false);
919
920 if (!config.straightToEngage) {
921 if (side == sideAssumingTransponderOn && side == BattleSide.NO_JOIN) {
922 addText(getString("ongoingBattleNoJoin"));
923 } else if (side != sideAssumingTransponderOn && side == BattleSide.NO_JOIN) {
924 addText(getString("ongoingBattleNoJoinTransponder"));
925 } else {
926 addText(getString("ongoingBattleShareIFF"));
927 }
928 }
929// if (context.getBattle().canJoin(playerFleet)) {
930// BattleSide playerSide = b.pickSide(playerFleet);
931// CampaignFleetAPI prePlayerAllies = b.getCombined(playerSide);
932// CampaignFleetAPI enemies = b.getOtherSideCombined(playerSide);
933// }
934 } else {
935 boolean hostile = otherFleet.getAI() != null && otherFleet.getAI().isHostileTo(playerFleet);
936 hostile |= context.isEngagedInHostilities();
937 if (!skipAttitudeOnInit) {
938 String side = "";
939 if (context.getBattle() != null && context.getBattle().getNonPlayerSide().size() > 1) {
940 side = "Side";
941 }
942 if (config.showFleetAttitude) {
943 boolean hasStation = false;
944 boolean allStation = true;
945 for (CampaignFleetAPI curr : context.getBattle().getSideFor(otherFleet)) {
946 allStation &= curr.isStationMode();
947 hasStation |= curr.isStationMode();
948 }
949 if (otherFleetWantsToFight() && !canDisengage() && hasStation && !allStation) {
950 addText(getString("initialWithStationVsLargeFleet"));
951 } else if (otherFleetWantsToFight()) {
952 addText(getString("initialAggressive" + side));
953 } else if (otherFleetWantsToDisengage()) {
954 if (!otherCanDisengage()) {
955 if (hostile) {
956 addText(getString("initialNeutral" + side));
957 } else {
958 addText(getString("initialNeutral" + side));
959 }
960 } else {
961 if (hostile) {
962 addText(getString("initialDisengage" + side));
963 } else {
964 addText(getString("initialCareful" + side));
965 }
966 }
967 } else {
969 addText(getString("initialHoldVsStrongerEnemy" + side));
970 } else {
971 addText(getString("initialNeutral" + side));
972 }
973 }
974 }
975 }
976 if (!shownKnownStatus && config.showTransponderStatus && !otherFleet.getFaction().isNeutralFaction()) {
977 shownKnownStatus = true;
978 String side = "";
979 if (context.getBattle() != null && context.getBattle().getNonPlayerSide().size() > 1) {
980 side = "Side";
981 }
982 if (!otherFleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_SKIP_TRANSPONDER_STATUS_INFO)) {
983 //boolean knows = otherFleet.knowsWhoPlayerIs();
984 boolean knows = context.getBattle() != null && context.getBattle().getNonPlayerSide() != null &&
985 context.getBattle().knowsWhoPlayerIs(context.getBattle().getNonPlayerSide());
986 if (!knows) {
987 addText(getString("initialDoesntKnow" + side));
988 } else {
989 CampaignFleetAPI actualPlayer = Global.getSector().getPlayerFleet();
990 if (actualPlayer.isTransponderOn()) {
991 addText(getString("initialKnows" + side));
992 } else {
993 if (actualPlayer.hasShipsWithUniqueSig()) {
994 addText(getString("initialKnowsUnique" + side));
995 } else {
996 addText(getString("initialKnowsTOff" + side));
997 }
998 }
999 }
1000 }
1001 }
1002 //textPanel.highlightFirstInLastPara("neutral posture", HIGHLIGHT_COLOR);
1003 }
1004 updateMainState(true);
1005 break;
1006 case REINIT_CONTINUE:
1008 break;
1009 case INITIATE_BATTLE:
1010 {
1011// BattleAPI b = context.getBattle();
1012// b.join(Global.getSector().getPlayerFleet());
1013//
1014// boolean someJoined = false;
1015// CampaignFleetAPI actualPlayer = Global.getSector().getPlayerFleet();
1016// for (CampaignFleetAPI fleet : actualPlayer.getContainingLocation().getFleets()) {
1017// if (b == fleet.getBattle()) continue;
1018//
1019// float dist = Misc.getDistance(actualPlayer.getLocation(), fleet.getLocation());
1020// dist -= actualPlayer.getRadius();
1021// dist -= fleet.getRadius();
1022// if (dist < 200 && fleet.getAI() != null && fleet.getAI().wantsToJoin(b)) {
1023// b.join(fleet);
1024// addText(Misc.ucFirst(fleet.getNameWithFaction()) + " will join the battle.");
1025// textPanel.highlightFirstInLastPara(fleet.getNameWithFaction(), fleet.getFaction().getBaseUIColor());
1026// someJoined = true;
1027// }
1028// }
1029// if (!someJoined) {
1030// addText("No nearby fleets will join the battle.");
1031// }
1032//
1033// b.genCombined();
1034//
1035// showFleetInfo();
1036//
1037// playerFleet = b.getPlayerCombined();
1038// otherFleet = b.getNonPlayerCombined();
1039
1040 //updateEngagementChoice(true);
1041 updateMainState(true);
1042 }
1043 break;
1044 case JOIN_ONGOING_BATTLE:
1045 if (context.getBattle().canJoin(playerFleet)) {
1046 BattleAPI b = context.getBattle();
1047 for (CampaignFleetAPI fleet : b.getBothSides()) {
1048 fleet.inflateIfNeeded();
1049 }
1050 b.genCombined();
1051
1052 BattleSide playerSide = b.pickSide(playerFleet);
1053 CampaignFleetAPI prePlayerAllies = b.getCombined(playerSide);
1054 CampaignFleetAPI enemies = b.getOtherSideCombined(playerSide);
1055
1056 boolean alliedWantsToFightBefore = fleetWantsToFight(prePlayerAllies, enemies);
1057 boolean alliedWantsToDisengageBefore = fleetWantsToDisengage(prePlayerAllies, enemies) && fleetCanDisengage(prePlayerAllies);
1058 boolean alliedHoldingBefore = fleetHoldingVsStrongerEnemy(prePlayerAllies, enemies);
1059 boolean otherWantsToFightBefore = fleetWantsToFight(enemies, prePlayerAllies);
1060 boolean otherWantsToDisengageBefore = fleetWantsToDisengage(enemies, prePlayerAllies) && fleetCanDisengage(enemies);
1061 boolean otherHoldingBefore = fleetHoldingVsStrongerEnemy(enemies, prePlayerAllies);
1062
1063 //System.out.println("Ships before: " + prePlayerAllies.getFleetData().getMembersListCopy().size());
1064
1065 b.join(playerFleet);
1066 b.genCombined();
1067
1068 showFleetInfo();
1069 joinedBattle = true;
1070
1071 playerFleet = b.getPlayerCombined();
1072 otherFleet = b.getNonPlayerCombined();
1073
1074 //System.out.println("Ships after: " + playerFleet.getFleetData().getMembersListCopy().size());
1075 boolean alliedWantsToFight = alliedFleetWantsToFight();
1076 boolean alliedWantsToDisengage = alliedFleetWantsToDisengage() && alliedCanDisengage();
1077 boolean alliedHolding = alliedFleetHoldingVsStrongerEnemy();
1078
1079 boolean otherWantsToFight = otherFleetWantsToFight();
1080 boolean otherWantsToDisengage = otherFleetWantsToDisengage() && otherCanDisengage();
1081 boolean otherHolding = otherFleetHoldingVsStrongerEnemy();
1082
1083 b.takeSnapshots();
1084
1085 options.clearOptions();
1089 }
1090 } else {
1091 addText("Failed to join battle; shouldn't happen.");
1092 updateMainState(true);
1093 }
1094 break;
1095 case CONTINUE_ONGOING_BATTLE:
1097 break;
1098 case FORCE_ENGAGE:
1099 if (config.showEngageText) {
1100 addText(getString("engageForce"));
1101 }
1102 case ENGAGE:
1103 //visual.showImagePortion("illustrations", "hound_hangar", 350, 75, 800, 800, 0, 0, 400, 400);
1104 boolean forceEngage = option == OptionId.FORCE_ENGAGE;
1106 playerGoal = FleetGoal.ATTACK;
1107 otherGoal = FleetGoal.ESCAPE;
1108 if (config.showEngageText) {
1109 addText(getString("engagePursuit"));
1110 }
1111 } else {
1112 playerGoal = FleetGoal.ATTACK;
1113 otherGoal = FleetGoal.ATTACK;
1114 if (config.showEngageText) {
1115 addText(getString("engageMutual"));
1116 }
1117 }
1119 break;
1120 case CONTINUE_INTO_BATTLE:
1121// if (context.getBattle() == null) {
1122// if (otherFleet.getBattle() != null) {
1123// context.setBattle(otherFleet.getBattle());
1124// } else {
1125// BattleAPI battle = Global.getFactory().createBattle(playerFleet, otherFleet);
1126// context.setBattle(battle);
1127// }
1128// }
1129
1130 BattleCreationContext bcc;
1131 if (config.alwaysAttackVsAttack){
1132 playerGoal = FleetGoal.ATTACK;
1133 otherGoal = FleetGoal.ATTACK;
1134 }
1135
1136 if (context.getBattle() != null) {
1137 BattleAPI b = context.getBattle();
1138
1139 if (b.isStationInvolved()) {
1140 boolean regen = false;
1141 if (b.isStationInvolvedOnPlayerSide()) {
1142 if (otherGoal == FleetGoal.ESCAPE) {
1143 regen = true;
1144 }
1145 } else {
1146 if (playerGoal == FleetGoal.ESCAPE) {
1147 regen = true;
1148 }
1149 }
1150
1151 if (regen) {
1152 b.genCombined(false);
1153 }
1154 }
1155
1156 CampaignFleetAPI combinedPlayer = b.getPlayerCombined();
1157 CampaignFleetAPI combinedEnemy = b.getNonPlayerCombined();
1158
1159// playerGoal = null;
1160// otherGoal = null;
1161
1162 bcc = new BattleCreationContext(combinedPlayer, playerGoal, combinedEnemy, otherGoal);
1163 bcc.setPlayerCommandPoints((int) Global.getSector().getPlayerFleet().getCommanderStats().getCommandPoints().getModifiedValue());
1164
1165 if (b.isStationInvolved() && playerGoal != FleetGoal.ESCAPE && otherGoal != FleetGoal.ESCAPE) {
1166 bcc.objectivesAllowed = false;
1167 }
1168 if (config.delegate != null) {
1169 config.delegate.battleContextCreated(dialog, bcc);
1170 }
1171
1172 if (firstEngagement) {
1173 if (playerGoal != FleetGoal.ESCAPE && ongoingBattle) {
1174 bcc.setInitialStepSize(1.5f);
1175 bcc.setInitialNumSteps(10 + (float) Math.random() * 30);
1176 }
1177 firstEngagement = false;
1178 } else {
1179 if (playerGoal != FleetGoal.ESCAPE && ongoingBattle) {
1180 bcc.setInitialStepSize(1.5f);
1181 bcc.setInitialNumSteps(5 + (float) Math.random() * 5);
1182 }
1183 }
1184 } else {
1185 bcc = new BattleCreationContext(playerFleet, playerGoal, otherFleet, otherGoal);
1186 bcc.setPlayerCommandPoints((int) Global.getSector().getPlayerFleet().getCommanderStats().getCommandPoints().getModifiedValue());
1187 if (config.delegate != null) {
1188 config.delegate.battleContextCreated(dialog, bcc);
1189 }
1190 }
1191
1192 if (playerGoal == FleetGoal.ESCAPE) {
1193 //DataForEncounterSide data = context.getDataFor(otherFleet);
1194 CampaignFleetAIAPI ai = playerFleet.getAI();
1195 if (ai != null) {
1196 ai.performCrashMothballingPriorToEscape(context, otherFleet);
1197 }
1198 } else if (otherGoal == FleetGoal.ESCAPE) {
1199 //DataForEncounterSide data = context.getDataFor(playerFleet);
1200 CampaignFleetAIAPI ai = otherFleet.getAI();
1201 if (ai != null) {
1202 ai.performCrashMothballingPriorToEscape(context, playerFleet);
1203 }
1204 }
1205
1206 visual.fadeVisualOut();
1207 dialog.startBattle(bcc);
1208 break;
1209 case CLEAN_DISENGAGE:
1210 case DISENGAGE:
1211// CampaignFleetAIAPI ai = otherFleet.getAI();
1212// PursuitOption po = otherFleet.getAI().pickPursuitOption(context, playerFleet);
1213 PursuitOption po = pickPursuitOption(otherFleet, playerFleet, context);
1215 po = PursuitOption.LET_THEM_GO;
1216 }
1217
1219 context.getDataFor(playerFleet).setDisengaged(true);
1220 context.getDataFor(otherFleet).setDisengaged(false);
1221 switch (po) {
1222 case PURSUE:
1223 // shouldn't happen here, or we'd be in ATTEMPT_TO_DISENGAGE
1224 case HARRY:
1225 context.applyPursuitOption(otherFleet, playerFleet, PursuitOption.HARRY);
1226 addText(getString("enemyHarass"));
1227 context.setEngagedInHostilities(true); // this was commented out, why?
1229 context.getDataFor(playerFleet).setDisengaged(true);
1230 context.getDataFor(otherFleet).setDisengaged(false);
1231 break;
1232 case LET_THEM_GO:
1234 context.setEngagedInHostilities(true); // so that other fleets stand down and don't insta-pursue
1235 addText(getString("enemyUnableToPursue"));
1236 } else {
1237 addText(getString("enemyDecidesNotToPursue"));
1238 }
1239 break;
1240 }
1241 updateMainState(true);
1242 break;
1243 case ATTEMPT_TO_DISENGAGE:
1244 boolean letGo = true;
1245 if (otherFleetWantsToFight()) {
1246 //PursuitOption pursuitOption = otherFleet.getAI().pickPursuitOption(context, playerFleet);
1247 PursuitOption pursuitOption = pickPursuitOption(otherFleet, playerFleet, context);
1248 if (pursuitOption == PursuitOption.PURSUE) {
1249 playerGoal = FleetGoal.ESCAPE;
1250 otherGoal = FleetGoal.ATTACK;
1251 addText(getString("enemyPursuit"));
1252 letGo = false;
1254 } else if (pursuitOption == PursuitOption.HARRY) {
1255 context.applyPursuitOption(otherFleet, playerFleet, PursuitOption.HARRY);
1256 addText(getString("enemyHarass"));
1258 //context.getDataFor(playerFleet).setDisengaged(!context.isEngagedInHostilities());
1259 context.getDataFor(playerFleet).setDisengaged(true);
1260 context.getDataFor(otherFleet).setDisengaged(false);
1261 updateMainState(true);
1262 letGo = false;
1263 } else {
1264 letGo = true;
1265 }
1266 }
1267 if (letGo) {
1268 //PursueAvailability pa = context.getPursuitAvailability(otherFleet, playerFleet);
1269 PursueAvailability pa = getPursuitAvailability(otherFleet);
1270 DisengageHarryAvailability dha = context.getDisengageHarryAvailability(otherFleet, playerFleet);
1271 if (dha == DisengageHarryAvailability.AVAILABLE || pa == PursueAvailability.AVAILABLE) {
1272 addText(getString("enemyDecidesNotToPursue"));
1273 } else {
1274 addText(getString("enemyUnableToPursue"));
1275 }
1276 context.getDataFor(playerFleet).setDisengaged(true);
1278 updateMainState(true);
1279 }
1280
1281// String name = "Corvus III";
1282// SectorEntityToken planet = Global.getSector().getStarSystem("Corvus").getEntityByName(name);
1283// //planet = Global.getSector().getStarSystem("Corvus").getStar();
1284// if (planet != null) {
1285// addText("Incoming visual feed from " + name + ".");
1286// visual.showPlanetInfo(planet);
1287// } else {
1288// addText("Planet " + name + " not found in the Corvus system.");
1289// }
1290// dialog.showTextPanel();
1291 //dialog.hideTextPanel();
1292 //dialog.setXOffset(-200);
1293 break;
1294 case BEGIN_FLEET_ENCOUNTER_2:
1296 break;
1297 case OPEN_COMM:
1298 CampaignFleetAPI actualOther = (CampaignFleetAPI) (dialog.getInteractionTarget());
1299 dialog.showTextPanel();
1300 dialog.flickerStatic(0.1f, 0.1f);
1301
1302 inConversation = true;
1306
1307 dialog.getInteractionTarget().setActivePerson(actualOther.getCommander());
1309
1310 boolean otherWantsToRun = otherFleetWantsToDisengage() && otherCanDisengage();
1311 MemoryAPI mem = conversationDelegate.getMemoryMap().get(MemKeys.LOCAL);
1312 if (otherWantsToRun) {
1313 mem.unset("$weakerThanPlayerButHolding");
1314 }
1315
1316 if (!conversationDelegate.fireBest("OpenCommLink")) {
1317 addText("You try to establish a comm link, but only get static.");
1318 dialog.getInteractionTarget().setActivePerson(null);
1320 inConversation = false;
1321 }
1322 if (inConversation && !visual.isShowingPersonInfo(actualOther.getCommander())) {
1323 visual.showPersonInfo(actualOther.getCommander());
1324 }
1325 break;
1326 case CUT_COMM:
1327 dialog.showTextPanel();
1328 dialog.flickerStatic(0.1f, 0.1f);
1329
1330// addText(getString("cutComm"));
1331// visual.showFleetInfo((String)null, playerFleet, (String)null, otherFleet, context);
1332// updateMainState();
1333
1334 inConversation = false;
1335// addText(getString("cutComm"));
1336 //visual.showFleetInfo((String)null, playerFleet, (String)null, otherFleet, context);
1337 showFleetInfo();
1338 optionSelected(null, OptionId.INIT);
1339
1340 break;
1341 case PURSUE:
1342 playerGoal = FleetGoal.ATTACK;
1343 otherGoal = FleetGoal.ESCAPE;
1344 addText(getString("pursue"));
1346 break;
1347 case AUTORESOLVE_PURSUE:
1348 List<FleetMemberAPI> members = getPursuitCapablePlayerShips();
1349// List<FleetMemberAPI> members = new ArrayList<FleetMemberAPI>();
1350// for (FleetMemberAPI member : playerFleet.getFleetData().getMembersListCopy()) {
1351// if (member.isAlly()) continue;
1352// if (member.isCivilian()) continue;
1353// members.add(member);
1354// }
1355 dialog.showFleetMemberPickerDialog("Select craft to send in pursuit", "Ok", "Cancel",
1356 4, 8, 58f, false, true, members,
1357 new FleetMemberPickerListener() {
1358 public void pickedFleetMembers(List<FleetMemberAPI> members) {
1359 if (members != null && !members.isEmpty()) {
1361 resolver.resolvePlayerPursuit(context, members);
1362 if (resolver.getResult() != null) {
1363 addText(getString("pursuitAutoresolve"));
1364 if (context.getBattle() != null) {
1365 CampaignFleetAPI player = Global.getSector().getPlayerFleet();
1366 CampaignFleetAPI ally = null;
1367 float alliedFP = 0;
1368 for (CampaignFleetAPI curr : context.getBattle().getPlayerSide()) {
1369 if (!curr.isPlayerFleet() && !curr.getFleetData().getMembersListCopy().isEmpty() &&
1370 !curr.isStationMode()) {
1371 if (ally == null) ally = curr;
1372 alliedFP += ally.getFleetPoints();
1373 }
1374 }
1375 float playerFP = 0f;
1376 for (FleetMemberAPI member : members) {
1377 playerFP += member.getFleetPointCost();
1378 }
1379 float damage = 0f;
1380 for (FleetMemberAPI member : resolver.getResult().getLoserResult().getDisabled()) {
1381 damage += member.getFleetPointCost();
1382 }
1383 for (FleetMemberAPI member : resolver.getResult().getLoserResult().getDestroyed()) {
1384 damage += member.getFleetPointCost();
1385 }
1386 float total = playerFP + alliedFP;
1387 if (total < 1) total = 1;
1389 if (ally != null && alliedFP > 0) {
1391 }
1392 }
1393 backFromEngagement(resolver.getResult());
1394 }
1395 }
1396 }
1397 public void cancelledFleetMemberPicking() {
1398
1399 }
1400 });
1401 break;
1402 case CRASH_MOTHBALL:
1403 List<FleetMemberAPI> choices = getCrashMothballable(playerFleet.getFleetData().getCombatReadyMembersListCopy());
1404 dialog.showFleetMemberPickerDialog("Select craft to crash-mothball", "Ok", "Cancel",
1405 3, 7, 58f, false, true, choices,
1406 new FleetMemberPickerListener() {
1407 public void pickedFleetMembers(List<FleetMemberAPI> members) {
1408 for (FleetMemberAPI member : playerFleet.getFleetData().getMembersListCopy()) {
1409 member.getRepairTracker().setCrashMothballed(false);
1410 }
1411 if (members != null && !members.isEmpty()) {
1412 for (FleetMemberAPI member : members) {
1413 member.getRepairTracker().setCrashMothballed(true);
1414 }
1415
1417 if (members.size() == 1) {
1418 addText(getString("crashMothballSelectedOneShip"));
1419 } else {
1420 addText(getString("crashMothballSelectedMultiple"));
1421 }
1422 }
1423 }
1424 public void cancelledFleetMemberPicking() {
1425
1426 }
1427 });
1428 break;
1429 case SCUTTLE:
1430 break;
1431 case GO_TO_PRE_BATTLE:
1433 break;
1434 case GO_TO_MAIN:
1435 if (config.straightToEngage) {
1436 optionSelected(null, OptionId.LEAVE);
1437 break;
1438 }
1439 List<CampaignFleetAPI> playerSide = context.getBattle().getPlayerSide();
1440 List<CampaignFleetAPI> otherSide = context.getBattle().getNonPlayerSide();
1441 //context.getBattle().leave(playerFleet);
1442 if (joinedBattle) {
1443 //context.getBattle().leave(otherFleet);
1444 joinedBattle = false;
1445 }
1446 if (ongoingBattle) {
1447 playerFleet = Global.getSector().getPlayerFleet();
1448 otherFleet = (CampaignFleetAPI) (dialog.getInteractionTarget());
1450 BattleAPI b = context.getBattle();
1451 String titleOne = b.getPrimary(b.getSideOne()).getNameWithFactionKeepCase();
1452 if (b.getSideOne().size() > 1) titleOne += ", with allies";
1453 String titleTwo = b.getPrimary(b.getSideTwo()).getNameWithFactionKeepCase();
1454 if (b.getSideTwo().size() > 1) titleTwo += ", with allies";
1455 visual.showPreBattleJoinInfo(null, playerFleet, Misc.ucFirst(titleOne), Misc.ucFirst(titleTwo), context);
1456 } else {
1457// context.getBattle().uncombine();
1458// if (playerSide != null) {
1459// for (CampaignFleetAPI curr : new ArrayList<CampaignFleetAPI>(playerSide)) {
1460// if (curr != playerFleet) {
1461// context.getBattle().leave(curr);
1462// }
1463// }
1464// }
1465// if (otherSide != null) {
1466// for (CampaignFleetAPI curr : new ArrayList<CampaignFleetAPI>(otherSide)) {
1467// if (curr != otherFleet) {
1468// context.getBattle().leave(curr);
1469// }
1470// }
1471// }
1472// showFleetInfo();
1473 }
1474 updateMainState(false);
1475 break;
1476 case CONTINUE:
1477 visual.showCustomPanel(810, 400, new ExampleCustomUIPanel());
1478 dialog.hideTextPanel();
1479 break;
1480 case DEV_MODE_ESCAPE:
1482
1483 BattleAPI b = context.getBattle();
1484 if (b.isPlayerInvolved()) {
1485 cleanUpBattle();
1486 }
1487 case LOOT_THEN_LEAVE:
1488 //goToEncounterEndPath();
1489 winningPath();
1490 break;
1491 case LEAVE:
1492 case CONTINUE_LEAVE:
1493 if (option != OptionId.CONTINUE_LEAVE) {
1494 if (context.adjustPlayerReputation(dialog, getString("friendlyFireRepLoss"),
1495 config.impactsAllyReputation, config.impactsEnemyReputation)) {
1496 options.clearOptions();
1497 options.addOption("Continue", OptionId.CONTINUE_LEAVE, null);
1498 if (!config.straightToEngage) {
1499 options.setShortcut(OptionId.CONTINUE_LEAVE, Keyboard.KEY_ESCAPE, false, false, false, true);
1500 }
1501 break;
1502 }
1503 }
1504 if (isFightingOver()) {
1505 if (!context.hasWinnerAndLoser()) {
1506 if (context.getDataFor(playerFleet).isWonLastEngagement()) {
1507 context.getDataFor(playerFleet).setDisengaged(false);
1508 context.getDataFor(otherFleet).setDisengaged(true);
1509 } else {
1510 context.getDataFor(playerFleet).setDisengaged(true);
1511 context.getDataFor(otherFleet).setDisengaged(false);
1512 }
1513 }
1514 } else {
1516 context.getDataFor(playerFleet).setDisengaged(true);
1517 context.getDataFor(otherFleet).setDisengaged(false);
1518 } else {
1519 context.getDataFor(playerFleet).setDisengaged(true);
1520 context.getDataFor(otherFleet).setDisengaged(true);
1521 }
1522 }
1523
1524 if (config.printXPToDialog) {
1526 textPanel.setFontSmallInsignia();
1527 }
1530 textPanel.setFontInsignia();
1531
1532// if (config.dismissOnLeave) {
1533// Global.getSector().getCampaignUI().addMessage("Game paused");
1534// }
1535
1536 cleanUpBattle();
1537// context.getBattle().leave(Global.getSector().getPlayerFleet());
1538// if (!ongoingBattle) {
1539// context.getBattle().finish();
1540// }
1541
1542 if (config.dismissOnLeave) {
1543 dialog.dismiss();
1544 } else {
1545 //options.clearOptions();
1546 dialog.setOptionOnEscape("", null);
1547 dialog.setOptionOnConfirm("", null);
1548 }
1549 if (config.delegate != null) {
1550 config.delegate.notifyLeave(dialog);
1551 }
1552 break;
1553 case HARRY_PURSUE:
1554 addText(getString("playerHarass"));
1555 context.applyPursuitOption(playerFleet, otherFleet, PursuitOption.HARRY);
1557 context.getDataFor(playerFleet).setDisengaged(false);
1558 context.getDataFor(otherFleet).setDisengaged(true);
1561 break;
1562 case LET_THEM_GO:
1563 addText(getString("playerLetGo"));
1564 //context.getDataFor(playerFleet).setDisengaged(!context.isEngagedInHostilities());
1565 context.getDataFor(playerFleet).setDisengaged(false);
1566 context.getDataFor(otherFleet).setDisengaged(true);
1568 break;
1569 case RECOVERY_CONTINUE:
1571 break;
1572 case RECOVERY_SELECT:
1573 if (!recoverableShips.isEmpty() || !storyRecoverableShips.isEmpty()) {
1574 dialog.showFleetMemberRecoveryDialog("Select ships to recover",
1575 recoverableShips, storyRecoverableShips,
1576 new FleetMemberPickerListener() {
1577 public void pickedFleetMembers(List<FleetMemberAPI> members) {
1578 if (members != null && !members.isEmpty()) {
1579 recoveredShips.clear();
1580 recoveredShips.addAll(members);
1582
1583 ListenerUtil.reportShipsRecovered(members, dialog);
1584
1585 CampaignFleetAPI player = Global.getSector().getPlayerFleet();
1587 player.getFleetData().sortToMatchOrder(membersInOrderPreEncounter);
1588
1589
1590 showFleetInfo();
1591 winningPath();
1592 }
1593 }
1594 public void cancelledFleetMemberPicking() {
1595 }
1596 });
1597 }
1598 break;
1599 case CONTINUE_FROM_VICTORY_TRIGGERS:
1600 winningPath();
1601 break;
1602 case CONTINUE_LOOT:
1603 visual.setVisualFade(0, 0);
1604 dialog.hideTextPanel();
1605 dialog.hideVisualPanel();
1606
1607 Global.getSector().reportEncounterLootGenerated(context, context.getLoot());
1608
1609 visual.showLoot("Salvaged", context.getLoot(), true, new CoreInteractionListener() {
1610 public void coreUIDismissed() {
1611 if (config.printXPToDialog) {
1613 textPanel.setFontSmallInsignia();
1614 }
1617 textPanel.setFontInsignia();
1618// context.getBattle().uncombine();
1619// context.getBattle().leave(Global.getSector().getPlayerFleet());
1620 cleanUpBattle();
1621
1622 if (config.dismissOnLeave) {
1623 dialog.dismiss();
1624 dialog.hideTextPanel();
1625 dialog.hideVisualPanel();
1626 } else {
1627 dialog.showTextPanel();
1628 dialog.showVisualPanel();
1629 //options.clearOptions();
1630 dialog.setOptionOnEscape("", null);
1631 dialog.setOptionOnConfirm("", null);
1632 }
1633 if (config.delegate != null) {
1634 config.delegate.notifyLeave(dialog);
1635 }
1636 }
1637 });
1638 options.clearOptions();
1639 dialog.setPromptText("");
1640 //options.addOption("Leave", OptionId.LEAVE, null);
1641 break;
1642 case CONTINUE_INTO_BOARDING:
1644 break;
1645 case BOARDING_ACTION:
1646 boardingPhase++;
1647 CampaignFleetAPI sourceFleet = context.getBattle().getSourceFleet(toBoard);
1648 boardingResult = context.boardShip(toBoard, Global.getSector().getPlayerFleet(), sourceFleet);
1649 //boardingResult = context.boardShip(toBoard, Global.getSector().getPlayerFleet(), otherFleet);
1651 break;
1652 case SELECT_FLAGSHIP:
1653 members = new ArrayList<FleetMemberAPI>();
1654 for (FleetMemberAPI member : playerFleet.getFleetData().getMembersListCopy()) {
1655// if (member.isFighterWing()) continue;
1656// if (member.isAlly()) continue;
1657 if (!isValidTransferCommandTarget(member)) continue;
1658 members.add(member);
1659 }
1660 if (!members.isEmpty()) {
1661 dialog.showFleetMemberPickerDialog("Select flagship for this engagement", "Ok", "Cancel",
1662 3, 7, 58f, false, false, members,
1663 new FleetMemberPickerListener() {
1664 public void pickedFleetMembers(List<FleetMemberAPI> members) {
1665 if (members != null && !members.isEmpty()) {
1666// if (origFlagship == null) {
1667// origFlagship = Global.getSector().getPlayerFleet().getFlagship();
1668// if (origCaptains.isEmpty()) {
1669// //origCaptains.clear();
1670// for (FleetMemberAPI member : Global.getSector().getPlayerFleet().getFleetData().getMembersListCopy()) {
1671// origCaptains.put(member, member.getCaptain());
1672// }
1673// }
1674// }
1675 if (!members.get(0).isFlagship()) {
1677
1678 selectedFlagship = members.get(0);
1679 PersonAPI captain = selectedFlagship.getCaptain();
1680 Global.getSector().getPlayerFleet().getFleetData().setFlagship(selectedFlagship);
1681 if (origFlagship != null && captain != null && !captain.isPlayer()) {
1682 origFlagship.setCaptain(captain);
1683 }
1684 addText(getString("selectedFlagship"));
1685 }
1686 }
1687 }
1688 public void cancelledFleetMemberPicking() {
1689
1690 }
1691 });
1692 }
1693 break;
1694 case ENGAGE_BOARDABLE:
1695 EngageBoardableOutcome outcome = context.engageBoardableShip(toBoard, otherFleet, playerFleet);
1696 switch (outcome) {
1697 case DESTROYED:
1698 addText(getString("engageBoardableDestroyed"));
1699 break;
1700 case DISABLED:
1701 addText(getString("engageBoardableDisabled"));
1702 break;
1703 case ESCAPED:
1704 addText(getString("engageBoardableEscaped"));
1705 break;
1706 }
1707 toBoard = null;
1709 break;
1710 case LET_IT_GO:
1712 addText(getString("letBoardableGo"));
1713 toBoard = null;
1715 break;
1716// case ABORT_BOARDING_ACTION:
1717// context.letBoardableGo(toBoard, otherFleet, playerFleet);
1718// addText(getString("letBoardableGo"));
1719// toBoard = null;
1720// goToEncounterEndPath();
1721// break;
1722// case HARD_DOCK:
1723// initBoardingParty();
1724// if (boardingParty != null) {
1725// boardingAttackType = BoardingAttackType.SHIP_TO_SHIP;
1726// boardingResult = context.boardShip(toBoard, boardingParty, boardingAttackType, boardingTaskForce, Global.getSector().getPlayerFleet(), otherFleet);
1727// goToEncounterEndPath();
1728// }
1729// break;
1730// case LAUNCH_ASSAULT_TEAMS:
1731// initBoardingParty();
1732// if (boardingParty != null) {
1733// boardingAttackType = BoardingAttackType.LAUNCH_FROM_DISTANCE;
1734// boardingResult = context.boardShip(toBoard, boardingParty, boardingAttackType, boardingTaskForce, Global.getSector().getPlayerFleet(), otherFleet);
1735// goToEncounterEndPath();
1736// }
1737// break;
1738 }
1739 }
1740
1741 protected void rememberWasBeaten() {
1742 if (context.getBattle() == null) return;
1743
1744 for (CampaignFleetAPI other : context.getBattle().getNonPlayerSide()) {
1745 MemoryAPI mem = other.getMemoryWithoutUpdate();
1746 if (!mem.getBoolean(MemFlags.MEMORY_KEY_RECENTLY_DEFEATED_BY_PLAYER)) {
1747 mem.set(MemFlags.MEMORY_KEY_RECENTLY_DEFEATED_BY_PLAYER, true, 0.5f);
1748 }
1749 }
1750 }
1751
1752 protected void restoreOrigCaptains() {
1753 if (origCaptains != null) {
1754 for (FleetMemberAPI member : origCaptains.keySet()) {
1755 PersonAPI captain = origCaptains.get(member);
1756 if (captain != null) {
1757 member.setCaptain(captain);
1758 }
1759 }
1760 }
1761 }
1762
1763 protected boolean cleanedUp = false;
1764 public void cleanUpBattle() {
1765 if (cleanedUp) return;
1766 cleanedUp = true;
1767
1768 BattleAPI b = context.getBattle();
1769
1770 DataForEncounterSide enemyData = context.getDataFor(b.getNonPlayerCombined());
1771 DataForEncounterSide playerData = context.getDataFor(b.getPlayerCombined());
1772 if (enemyData != null && playerData != null && enemyData.disengaged() && !playerData.disengaged()) {
1774 }
1775
1776
1778
1779 BattleSide playerSide = b.getPlayerSide() == b.getSideOne() ? BattleSide.ONE : BattleSide.TWO;
1780 BattleSide otherSide = b.getPlayerSide() == b.getSideOne() ? BattleSide.TWO : BattleSide.ONE;
1781
1782 BattleSide winner = context.didPlayerWinMostRecentBattleOfEncounter() ? playerSide : otherSide;
1783 if (!context.isEngagedInHostilities() && !context.isOtherFleetHarriedPlayer()) winner = BattleSide.NO_JOIN;
1784
1785 if (!ongoingBattle) {
1787 Global.getSector().getPlayerFleet().getFleetData().setSyncNeeded();
1788 Global.getSector().getPlayerFleet().getFleetData().syncIfNeeded();
1789 } else if (ongoingBattle) {
1790 EngagementOutcome last = context.getLastEngagementOutcome();
1791 boolean finished = false;
1792 if (last == EngagementOutcome.BATTLE_PLAYER_WIN_TOTAL) {
1793 List<CampaignFleetAPI> other = b.getSide(otherSide);
1794 if (other != null && other.size() == 1) {
1795 CampaignFleetAPI f = other.get(0);
1796 if (f != null && f.isStationMode()) {
1797 b.finish(winner, true);
1798 finished = true;
1799 }
1800 }
1801 }
1802 if (!finished) {
1803 if (last == EngagementOutcome.ESCAPE_ENEMY_SUCCESS ||
1804 last == EngagementOutcome.ESCAPE_PLAYER_SUCCESS ||
1808 b.finish(winner, true);
1809 } else {
1810 for (CampaignFleetAPI curr : pulledIn) {
1812 }
1813 }
1814 }
1815 }
1817 b.applyVisibilityMod(Global.getSector().getPlayerFleet());
1818 }
1819
1820 }
1821
1822
1823 protected boolean okToLeave = false;
1824 protected boolean didRepairs = false;
1825 protected boolean didBoardingCheck = false;
1826 protected boolean didRecoveryCheck = false;
1827 protected boolean pickedMemberToBoard = false;
1828 protected FleetMemberAPI toBoard = null;
1829 protected String repairedShipList = null;
1830 //protected String boardingTaskForceList = null;
1831 //protected List<FleetMemberAPI> boardingTaskForce = null;
1832 protected int boardingPhase = 0;
1833 protected float boardingPercentSuccess = 0;
1834
1835 protected String crashMothballList = null;
1836 protected CrewCompositionAPI maxBoardingParty = null;
1837 protected CrewCompositionAPI boardingParty = null;
1838 //protected BoardingAttackType boardingAttackType = null;
1839 protected BoardingResult boardingResult = null;
1840 protected FleetMemberAPI selectedFlagship = null;
1841 protected FleetMemberAPI origFlagship = null;
1842 protected Map<FleetMemberAPI, PersonAPI> origCaptains = new HashMap<FleetMemberAPI, PersonAPI>();
1843
1844 protected InitialBoardingResponse aiBoardingResponse = null;
1845
1846 protected boolean shownKnownStatus = false;
1847
1848 protected void goToEncounterEndPath() {
1849// boolean otherWantsToRun = otherFleetWantsToDisengage() && otherCanDisengage();
1850// if (context.didPlayerWinEncounter() ||
1851// (config.straightToEngage &&
1852// context.getLastEngagementOutcome() == EngagementOutcome.BATTLE_PLAYER_WIN) ||
1853// (otherWantsToRun &&
1854// context.getLastEngagementOutcome() == EngagementOutcome.BATTLE_PLAYER_WIN)) {
1855// winningPath();
1857 (config.straightToEngage &&
1858 context.getLastEngagementOutcome() == EngagementOutcome.BATTLE_PLAYER_WIN)) {
1859 winningPath();
1860 } else {
1861 losingPath();
1862 }
1863 }
1864
1865 protected void losingPath() {
1866 options.clearOptions();
1867
1868 context.getDataFor(playerFleet).setDisengaged(true);
1869
1870 if (!recoveredCrew) {
1871 recoveredCrew = true;
1873 }
1874
1875 boolean playerHasReadyShips = !playerFleet.getFleetData().getCombatReadyMembersListCopy().isEmpty();
1876 boolean otherHasReadyShips = !otherFleet.getFleetData().getCombatReadyMembersListCopy().isEmpty();
1877 boolean totalDefeat = !playerFleet.isValidPlayerFleet();
1878 boolean mutualDestruction = context.getLastEngagementOutcome() == EngagementOutcome.MUTUAL_DESTRUCTION;
1879// if (!didBoardingCheck) {
1880// didBoardingCheck = true;
1881// toBoard = context.pickShipToBoard(otherFleet, playerFleet);
1882// if (toBoard != null) {
1883// pickedMemberToBoard = true;
1884// options.addOption("Continue", OptionId.CONTINUE_INTO_BOARDING, null);
1885// return;
1886// }
1887// }
1888
1889 if (toBoard != null && aiBoardingResponse == null) {
1890 visual.showFleetMemberInfo(toBoard);
1891
1892 if (mutualDestruction) {
1893 addText(getString("mutualDestructionRepairs"));
1894 aiBoardingResponse = InitialBoardingResponse.LET_IT_GO;
1895 } else {
1896 if (totalDefeat) {
1897 addText(getString("lastFriendlyShipRepairs"));
1898 } else {
1899 addText(getString("friendlyShipBoardable"));
1900 }
1901 aiBoardingResponse = otherFleet.getAI().pickBoardingResponse(context, toBoard, playerFleet);
1902 }
1903
1904 if (!otherHasReadyShips) {
1905 aiBoardingResponse = InitialBoardingResponse.LET_IT_GO;
1906 }
1907
1908 options.addOption("Continue", OptionId.CONTINUE_INTO_BOARDING, null);
1909 return;
1910 }
1911
1912 if (toBoard != null && aiBoardingResponse != null) {
1913 switch (aiBoardingResponse) {
1914 case BOARD:
1915 break;
1916 case ENGAGE:
1917 EngageBoardableOutcome outcome = context.engageBoardableShip(toBoard, playerFleet, otherFleet);
1918 switch (outcome) {
1919 case DESTROYED:
1920 if (totalDefeat) {
1921 addText(getString("lastFriendlyBoardableDestroyed"));
1922 } else {
1923 addText(getString("engageFriendlyBoardableDestroyed"));
1924 }
1925 break;
1926 case DISABLED:
1927 if (totalDefeat) {
1928 addText(getString("lastFriendlyBoardableDisabled"));
1929 } else {
1930 addText(getString("engageFriendlyBoardableDisabled"));
1931 }
1932 break;
1933 case ESCAPED:
1934 if (totalDefeat) {
1935 addText(getString("lastFriendlyBoardableEscaped"));
1936 } else {
1937 addText(getString("engageFriendlyBoardableEscaped"));
1938 }
1939 break;
1940 }
1941 break;
1942 case LET_IT_GO:
1944 if (!mutualDestruction) {
1945 if (totalDefeat) {
1946 addText(getString("engageFriendlyBoardableLetGo"));
1947 } else {
1948 addText(getString("lastFriendlyBoardableLetGo"));
1949 }
1950 }
1951 break;
1952 }
1953 }
1954
1955 totalDefeat = !playerFleet.isValidPlayerFleet();
1956 if (totalDefeat) {
1957 addText(getString("finalOutcomeNoShipsLeft"));
1958 }
1959
1960 if (pickedMemberToBoard) {
1961 //visual.showFleetInfo((String)null, playerFleet, (String)null, otherFleet, context);
1962 showFleetInfo();
1963 }
1964
1965 if (config.salvageRandom != null) {
1966 context.setSalvageRandom(config.salvageRandom);
1967 }
1968 context.generateLoot(null, config.lootCredits);
1969 context.autoLoot();
1970 //context.repairShips();
1971 String leave = "Leave";
1972 if (config.straightToEngage) {
1973 leave = "Continue";
1974 }
1975 options.addOption(leave, OptionId.LEAVE, null);
1976 if (!config.straightToEngage) {
1977 options.setShortcut(OptionId.LEAVE, Keyboard.KEY_ESCAPE, false, false, false, true);
1978 } else {
1979 optionSelected(null, OptionId.LEAVE);
1980 }
1981 }
1982
1983 protected boolean recoveredCrew = false;
1984 protected boolean lootedCredits = false;
1985 protected boolean firedVictoryTriggers = false;
1986 protected String creditsLooted = null;
1987 protected void winningPath() {
1988 options.clearOptions();
1989 DataForEncounterSide playerData = context.getDataFor(playerFleet);
1990 context.getDataFor(otherFleet).setDisengaged(true);
1991
1992 if (!firedVictoryTriggers && context.getBattle() != null && context.getBattle().getNonPlayerSideSnapshot() != null) {
1993
1994 SectorEntityToken prev = dialog.getInteractionTarget();
1996 plugin.setEmbeddedMode(true);
1997 //plugin.init(dialog);
1998 dialog.setPlugin(plugin);
1999 BattleAPI battle = context.getBattle();
2000 boolean firedAnyTriggers = false;
2001
2002 //for (CampaignFleetAPI other : battle.getNonPlayerSide()) {
2003 for (CampaignFleetAPI other : battle.getNonPlayerSideSnapshot()) {
2004 dialog.setInteractionTarget(other);
2005 plugin.init(dialog);
2006
2007 MemoryAPI mem = other.getMemoryWithoutUpdate();
2008 List<FleetMemberAPI> losses = Misc.getSnapshotMembersLost(other);
2009 List<FleetMemberAPI> remaining = other.getFleetData().getMembersListCopy();
2010
2011 int fpTotal = 0;
2012 int fpLost = 0;
2013 int fpRemaining = 0;
2014 for (FleetMemberAPI curr : losses) {
2015 fpLost += curr.getFleetPointCost();
2016 fpTotal += curr.getFleetPointCost();
2017 }
2018 for (FleetMemberAPI curr : remaining) {
2019 fpRemaining += curr.getFleetPointCost();
2020 fpTotal += curr.getFleetPointCost();
2021 }
2022
2023 mem.set("$someShipsDestroyed", !losses.isEmpty(), 0);
2024 mem.set("$fpLost", fpLost, 0);
2025 mem.set("$fpRemaining", fpRemaining, 0);
2026 mem.set("$fpLostFraction", (float) fpLost / Math.max(1, fpTotal), 0);
2027 mem.set("$battle", battle, 0);
2028
2029 List<String> triggers = Misc.getDefeatTriggers(other, false);
2030 if (triggers != null) {
2031 //DebugFlags.PRINT_RULES_DEBUG_INFO = true;
2032 for (String trigger : new ArrayList<String>(triggers)) {
2033 boolean fired = FireBest.fire(null, dialog, plugin.getMemoryMap(), trigger);
2034 if (fired) {
2035 triggers.remove(trigger);
2036 firedAnyTriggers = true;
2037 }
2038 }
2039 }
2040 Misc.clearDefeatTriggersIfNeeded(other);
2041 }
2042
2043 dialog.setInteractionTarget(prev);
2044 dialog.setPlugin(this);
2045 firedVictoryTriggers = true;
2046
2047 if (firedAnyTriggers) {
2048 options.addOption("Continue", OptionId.CONTINUE_FROM_VICTORY_TRIGGERS, null);
2049 return;
2050 }
2051 }
2052
2053 if (!recoveredCrew) {
2054 recoveredCrew = true;
2055 if ((int)playerData.getRecoverableCrewLosses().getCrewInt() + (int)playerData.getRecoverableCrewLosses().getMarines() > 0) {
2056 addText(getString("recoveryReport"));
2057 DataForEncounterSide data = context.getDataFor(playerFleet);
2058 int crewRecovered = (int) data.getRecoverableCrewLosses().getCrew();
2059 int marinesRecovered = (int) data.getRecoverableCrewLosses().getMarines();
2060 String crewRecStr = "" + crewRecovered;
2061 if (crewRecovered <= 0) {
2062 crewRecStr = "";
2063 }
2064 String marinesRecStr = "" + marinesRecovered;
2065 if (marinesRecovered <= 0) {
2066 marinesRecStr = "";
2067 }
2068 //if (crewRecStr != null && marinesRecStr != null) {
2069 textPanel.highlightInLastPara(HIGHLIGHT_COLOR, crewRecStr, marinesRecStr);
2070 //} else if (crewRecStr != null) {
2071 //textPanel.highlightInLastPara(HIGHLIGHT_COLOR, crewRecStr);
2072 //} else if (marinesRecStr != null) {
2073 //textPanel.highlightInLastPara(HIGHLIGHT_COLOR, marinesRecStr);
2074 //}
2075
2077 }
2078 }
2079
2080 CampaignFleetAPI actualPlayer = Global.getSector().getPlayerFleet();
2081
2082 boolean playerHasPersonnel = actualPlayer.getCargo().getMarines() > 0;
2083 boolean playerHasReadyShips = !actualPlayer.getFleetData().getCombatReadyMembersListCopy().isEmpty();
2084
2085
2086 if (!didRecoveryCheck) {
2087 didRecoveryCheck = true;
2089 storyRecoverableShips = context.getStoryRecoverableShips();
2090
2091 if (recoverableShips == null) recoverableShips = new ArrayList<FleetMemberAPI>();
2092 if (storyRecoverableShips == null) storyRecoverableShips = new ArrayList<FleetMemberAPI>();
2093
2094 if (!recoverableShips.isEmpty() || !storyRecoverableShips.isEmpty()) {
2095 int crew = actualPlayer.getCargo().getCrew();
2096 int needed = (int)actualPlayer.getFleetData().getMinCrew();
2097
2098 int num = recoverableShips.size() + storyRecoverableShips.size();
2099 String numString = "several ships disabled or destroyed";
2100 if (num == 1) numString = "a ship disabled";
2101 String pre = "The salvage chief reports that " + numString + " during the battle " +
2102 "can be restored to basic functionalty. Recovering ships instead of breaking " +
2103 "them for salvage will greatly reduce the salvage gained from these ships.";
2104 textPanel.addParagraph(pre);
2105// if (extra > 0) {
2106// textPanel.addPara(pre +
2107// "You have %s extra crew available, beyond what's " +
2108// "already required to operate your current ships.", Misc.getHighlightColor(), "" + extra);
2109// } else {
2110// textPanel.addParagraph(pre +
2111// "You have no extra crew available for any recovered vessels, beyond what's " +
2112// "already required to operate your current ships.");
2113// }
2114
2115 boolean playerShipsRecoverable = false;
2116 for (FleetMemberAPI member : recoverableShips) {
2117 if (member.getOwner() == 0 && !member.isAlly()) {
2118 playerShipsRecoverable = true;
2119 break;
2120 }
2121 }
2122 for (FleetMemberAPI member : storyRecoverableShips) {
2123 if (member.getOwner() == 0 && !member.isAlly()) {
2124 playerShipsRecoverable = true;
2125 break;
2126 }
2127 }
2128
2129 boolean onlyDifficultRecovery = recoverableShips.isEmpty() && !storyRecoverableShips.isEmpty();
2130 if (playerShipsRecoverable) {
2131 textPanel.setFontSmallInsignia();
2132 textPanel.addParagraph( "Disabled ships from your fleet are available for recovery", Misc.getHighlightColor());
2133 textPanel.setFontInsignia();
2134 options.addOption("Consider ship recovery", OptionId.RECOVERY_SELECT, Misc.getHighlightColor(),
2135 "Disabled ships from your fleet are available for recovery.");
2136 } else {
2137 Color color = Misc.getButtonTextColor();
2138 if (onlyDifficultRecovery) {
2139 color = Misc.getStoryOptionColor();
2140 }
2141 options.addOption("Consider ship recovery", OptionId.RECOVERY_SELECT, color, null);
2142 }
2143
2144 options.addOption("Continue", OptionId.RECOVERY_CONTINUE, null);
2145 if (playerShipsRecoverable) {
2146 options.addOptionConfirmation(OptionId.RECOVERY_CONTINUE,
2147 "Disabled ships from your fleet are available for recovery.\n\nIf you proceed without recovering them, "
2148 + "they will be lost permanently.", "Proceed", "Cancel");
2149 }
2150
2151 return;
2152 }
2153 }
2154
2155
2156
2157 context.adjustPlayerReputation(dialog, getString("friendlyFireRepLoss"),
2158 config.impactsAllyReputation, config.impactsEnemyReputation);
2159
2160
2161// "noSalvageReport":"There's no salvage to be had.",
2162// "noSalvageReportPlayerDidNothing":"Your $fleetOrShip does not participate in salvage operations due to its limited contributions throughout the encounter.",
2163// "salvageReportPlayer":"Your $fleetOrShip is able to participate in salvage operations due to its contributions throughout the encounter.",
2164 boolean validFleet = playerFleet.isValidPlayerFleet();
2165 BattleAPI battle = context.getBattle();
2166 boolean hasAllies = false;
2167 boolean startedWithAllies = false;
2168 if (battle != null) {
2169 hasAllies = context.getBattle().getPlayerSide().size() <= 1;
2170 startedWithAllies = context.getBattle().getPlayerSideSnapshot().size() > 1;
2171 }
2172
2173 if (!lootedCredits && config.withSalvage) {
2174 Random resetSalvageRandomTo = null;
2175
2176 if (config.salvageRandom != null) {
2177 context.setSalvageRandom(config.salvageRandom);
2178 resetSalvageRandomTo = Misc.getRandom(config.salvageRandom.nextLong(), 11);
2179 }
2180
2181 context.generateLoot(recoveredShips, config.lootCredits);
2182
2183 if (resetSalvageRandomTo != null) {
2184 config.salvageRandom = resetSalvageRandomTo;
2185 }
2186 if (config.delegate != null) {
2187 config.delegate.postPlayerSalvageGeneration(dialog, context, context.getLoot());
2188 }
2189 lootedCredits = true;
2190
2191 float credits = context.getCreditsLooted();
2193 if (validFleet) {
2194 if (credits <= 0 && context.getLoot().isEmpty()) {
2195 if (startedWithAllies) {
2196 addText(getString("noSalvageReportPlayerDidNothing"));
2197 } else {
2198 addText(getString("noSalvageReport"));
2199 }
2200 } else {
2201 if (startedWithAllies) {
2202 addText(getString("salvageReportPlayer"));
2203 }
2204 }
2205 }
2206 }
2207
2208 //creditsLooted = "" + (int) credits;
2209 creditsLooted = Misc.getWithDGS((int)credits);
2210 if (credits > 0 && validFleet) {
2211 addText(getString("creditsLootedReport"));
2212 textPanel.highlightLastInLastPara(creditsLooted, HIGHLIGHT_COLOR);
2213 Global.getSector().getPlayerFleet().getCargo().getCredits().add(credits);
2214
2215// PromoteOfficerIntel intel = new PromoteOfficerIntel(textPanel);
2216// Global.getSector().getIntelManager().addIntel(intel, false, textPanel);
2217 }
2218 }
2219
2220 if (!context.getLoot().isEmpty() && validFleet) {
2221 options.addOption("Pick through the wreckage", OptionId.CONTINUE_LOOT, null);
2222 } else {
2223 if (!validFleet) {
2224 addText(getString("finalOutcomeNoShipsLeft"));
2225 }
2226 String leave = "Leave";
2227 boolean withEscape = true;
2228 if (config.noSalvageLeaveOptionText != null && validFleet && context.getLoot().isEmpty()) {
2229 leave = config.noSalvageLeaveOptionText;
2230 withEscape = false;
2231 }
2232 options.addOption(leave, OptionId.LEAVE, null);
2233 if (withEscape) {
2234 options.setShortcut(OptionId.LEAVE, Keyboard.KEY_ESCAPE, false, false, false, true);
2235 }
2236 }
2237 }
2238
2239 protected List<FleetMemberAPI> getCrashMothballable(List<FleetMemberAPI> all) {
2240 List<FleetMemberAPI> result = new ArrayList<FleetMemberAPI>();
2241 CombatReadinessPlugin crPlugin = Global.getSettings().getCRPlugin();
2242 for (FleetMemberAPI member : all) {
2243 if (member.isAlly()) continue;
2244 if (!member.isFighterWing() && member.getRepairTracker().getCR() < crPlugin.getMalfunctionThreshold(member.getStats())) {
2245 result.add(member);
2246 }
2247 }
2248 return result;
2249 }
2250
2251
2252 protected OptionId lastOptionMousedOver = null;
2253 public void optionMousedOver(String optionText, Object optionData) {
2254
2255 if (inConversation) {
2256 conversationDelegate.optionMousedOver(optionText, optionData);
2257 return;
2258 }
2259
2260 if (optionData instanceof String) return;
2261
2262 if (optionData == null) {
2263 if (currVisualType != VisualType.FLEET_INFO) {
2264 showFleetInfo();
2265 currVisualType = VisualType.FLEET_INFO;
2266 }
2267 lastOptionMousedOver = null;
2268 return;
2269 }
2270 OptionId option = (OptionId) optionData;
2271 if (option == lastOptionMousedOver) return;
2272 lastOptionMousedOver = option;
2273 }
2274
2275 protected void showFleetInfo() {
2276 BattleAPI b = context.getBattle();
2277 if (b != null && b.isPlayerInvolved()) {
2278 String titleOne = "Your forces";
2279 if (b.isPlayerInvolved() && b.getPlayerSide().size() > 1) {
2280 titleOne += ", with allies";
2281 }
2282 if (!Global.getSector().getPlayerFleet().isValidPlayerFleet() && b.getPlayerSide().size() > 1) {
2283 titleOne = "Allied forces";
2284 }
2285 String titleTwo = null;
2286 if (b.getPrimary(b.getNonPlayerSide()) != null) {
2287 titleTwo = b.getPrimary(b.getNonPlayerSide()).getNameWithFactionKeepCase();
2288 }
2289 if (b.getNonPlayerSide().size() > 1) titleTwo += ", with allies";
2290 visual.showFleetInfo(titleOne, b.getPlayerCombined(), Misc.ucFirst(titleTwo), b.getNonPlayerCombined(), context);
2291 } else {
2292 visual.showFleetInfo((String)null, playerFleet, (String)null, otherFleet, context);
2293 }
2294 }
2295
2296 public void advance(float amount) {
2297
2298 }
2299
2300 protected void addText(String text) {
2301 textPanel.addParagraph(text);
2302 }
2303 protected void addText(String text, Color color) {
2304 textPanel.addParagraph(text, color);
2305 }
2306 protected void addText(String text, String hl, Color hlColor) {
2307 LabelAPI label = textPanel.addParagraph(text);
2308 label.setHighlight(hl);
2309 label.setHighlightColor(hlColor);
2310 }
2311
2312 protected void appendText(String text) {
2313 textPanel.appendToLastParagraph(" " + text);
2314 }
2315
2316 protected void updateDialogState() {
2317 options.clearOptions();
2318 options.addOption("Cut the comm link", OptionId.CUT_COMM, null);
2319 }
2320
2321 protected boolean isValidTransferCommandTarget(FleetMemberAPI member) {
2322 if (member.isFighterWing() || member.isAlly()) return false;
2323 if (Misc.isAutomated(member)) return false;
2324 if (Misc.isUnremovable(member.getCaptain())) return false;
2325 return true;
2326 }
2327
2328 protected void updatePreCombat() {
2329
2332 }
2333 float diff = context.getDifficulty();
2334 if (diff >= 1f) {
2335 String percent = "+" + (int) Math.round((diff - 1f) * 100f) + "%";
2336 textPanel.setFontSmallInsignia();
2337 textPanel.addPara("Additional XP due to overall battle difficulty: %s",
2338 Misc.getGrayColor(), Misc.getHighlightColor(), percent);
2339 textPanel.setFontInsignia();
2340 }
2341
2342
2343 options.clearOptions();
2344
2345 //playerFleet.updateCounts();
2346 //int nonFighters = playerFleet.getFleetData().getMembersListCopy().size() - playerFleet.getNumFighters();
2347 boolean canTransfer = false;
2348 for (FleetMemberAPI member : playerFleet.getFleetData().getMembersListCopy()) {
2349// if (member.isFighterWing() || member.isAlly()) continue;
2350 if (member.isFlagship()) continue;
2351 if (!isValidTransferCommandTarget(member)) continue;
2352 canTransfer = true;
2353 break;
2354 }
2355 if (playerGoal == FleetGoal.ATTACK && otherGoal == FleetGoal.ESCAPE) {
2356 String tooltipText = getString("tooltipPursueAutoresolve");
2357 options.addOption("Order your second-in-command to handle it", OptionId.AUTORESOLVE_PURSUE, tooltipText);
2358 options.addOption("Transfer command for this engagement", OptionId.SELECT_FLAGSHIP, getString("tooltipSelectFlagship"));
2359 //if (nonFighters <= 1) {
2360 if (!canTransfer) {
2361 options.setEnabled(OptionId.SELECT_FLAGSHIP, false);
2362 }
2363 options.addOption("Take command of the action", OptionId.CONTINUE_INTO_BATTLE, null);
2364 } else {
2365 options.addOption("Transfer command for this engagement", OptionId.SELECT_FLAGSHIP, getString("tooltipSelectFlagship"));
2366 //if (nonFighters <= 1) {
2367 if (!canTransfer) {
2368 options.setEnabled(OptionId.SELECT_FLAGSHIP, false);
2369 }
2370 if (playerGoal == FleetGoal.ESCAPE) {
2371 List<FleetMemberAPI> choices = getCrashMothballable(playerFleet.getFleetData().getCombatReadyMembersListCopy());
2372
2373 options.addOption("Crash-mothball some of your ships to prevent malfunctions", OptionId.CRASH_MOTHBALL, null);
2374 if (choices.isEmpty()) {
2375 options.setEnabled(OptionId.CRASH_MOTHBALL, false);
2376 options.setTooltip(OptionId.CRASH_MOTHBALL, getString("tooltipCrashMothballUnavailable"));
2377 } else {
2378 options.setTooltip(OptionId.CRASH_MOTHBALL, getString("tooltipCrashMothball"));
2379 }
2380 }
2381 if (config.straightToEngage) {
2382 options.addOption("Continue into battle", OptionId.CONTINUE_INTO_BATTLE, null);
2383 } else {
2384 options.addOption("Continue", OptionId.CONTINUE_INTO_BATTLE, null);
2385 }
2386 }
2387
2388 boolean canGoBack = ongoingBattle || otherGoal == FleetGoal.ESCAPE || Global.getSettings().isDevMode();
2389 if (canGoBack) {
2390 options.addOption("Go back", OptionId.GO_TO_MAIN, null);
2391 options.setShortcut(OptionId.GO_TO_MAIN, Keyboard.KEY_ESCAPE, false, false, false, true);
2392 }
2393// if (ongoingBattle) {
2394// options.addOption("Go back", OptionId.GO_TO_MAIN, null);
2395// options.setShortcut(OptionId.GO_TO_MAIN, Keyboard.KEY_ESCAPE, false, false, false, true);
2396// }
2397 if (Global.getSettings().isDevMode()) {
2398// if (ongoingBattle) {
2401// } else {
2402// options.addOption("Go back", OptionId.GO_TO_MAIN, null);
2403// options.setShortcut(OptionId.GO_TO_MAIN, Keyboard.KEY_ESCAPE, false, false, false, true);
2404// }
2406 }
2407 }
2408
2409 protected String createShipNameListString(List<FleetMemberAPI> members) {
2410 String str = "";
2411 int fighters = 0;
2412 int ships = 0;
2413 for (FleetMemberAPI member : members) {
2414 boolean last = members.indexOf(member) == members.size() - 1;
2415 boolean secondToLast = members.indexOf(member) == members.size() - 2;
2416 boolean fighter = member.isFighterWing();
2417 if (fighter) {
2418 fighters++;
2419 } else {
2420 ships++;
2421 if (last && fighters == 0 && ships > 1) {
2422 if (members.size() > 2) {
2423 str += ", and the " + member.getShipName();
2424 } else {
2425 str += " and the " + member.getShipName();
2426 }
2427 } else {
2428 str += "the " + member.getShipName();
2429 }
2430 }
2431 if (!last && !secondToLast && !fighter) {
2432 str += ", ";
2433 }
2434
2435 if (last && fighters > 0) {
2436 if (fighters == 1) {
2437 if (ships == 0) {
2438 str += "a fighter wing";
2439 } else {
2440 if (ships > 1) {
2441 str += ", and a fighter wing";
2442 } else {
2443 str += " and a fighter wing";
2444 }
2445 }
2446 } else {
2447 if (ships == 0) {
2448 str += "several fighter wings";
2449 } else {
2450 if (ships > 1) {
2451 str += ", and several fighter wings";
2452 } else {
2453 str += " and several fighter wings";
2454 }
2455 }
2456 }
2457 }
2458 }
2459 return str;
2460 }
2461
2462 protected void updateMainState(boolean withText) {
2463 options.clearOptions();
2464
2465 if (isFightingOver()) {
2467 return;
2468 }
2469
2470 if (ongoingBattle) {
2471 BattleAPI battle = context.getBattle();
2472 boolean playerHasReadyShips = false;
2473 for (FleetMemberAPI member : playerFleet.getFleetData().getCombatReadyMembersListCopy()) {
2474 if (!member.isAlly()) {
2475 playerHasReadyShips = true;
2476 }
2477 }
2478 if (!joinedBattle && battle.canJoin(playerFleet)) {
2479 options.addOption("Join the battle", OptionId.JOIN_ONGOING_BATTLE, null);
2480
2481 BattleSide side = battle.pickSide(playerFleet);
2482 if (side != null) {
2483 List<CampaignFleetAPI> otherSide = battle.getOtherSide(side);
2484 if (otherSide != null) {
2485 boolean knows = battle.knowsWhoPlayerIs(otherSide);
2486 boolean lowImpact = false;
2487 CampaignFleetAPI otherPrimary = battle.getPrimary(otherSide);
2488 if (otherPrimary != null) {
2489 lowImpact |= otherPrimary.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_LOW_REP_IMPACT) == true;
2490 lowImpact |= otherPrimary.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_NO_REP_IMPACT) == true;
2491 }
2492 FactionAPI nonHostile = getNonHostileOtherFaction(otherSide);
2493 if (nonHostile != null && knows && !lowImpact && !context.isEngagedInHostilities() &&
2494 config.showWarningDialogWhenNotHostile) {
2495 options.addOptionConfirmation(OptionId.JOIN_ONGOING_BATTLE, "The " + nonHostile.getDisplayNameLong() + " " + nonHostile.getDisplayNameIsOrAre() + " not currently hostile, and you have been positively identified. Are you sure you want to engage in hostilities with one of their fleets?", "Yes", "Never mind");
2496 }
2497 }
2498 }
2499
2500 if (!playerHasReadyShips) {
2501 options.setEnabled(OptionId.JOIN_ONGOING_BATTLE, false);
2502 }
2503 }
2504
2505 options.addOption("Leave", OptionId.LEAVE, null);
2506 options.setShortcut(OptionId.LEAVE, Keyboard.KEY_ESCAPE, false, false, false, true);
2507 if (Global.getSettings().isDevMode()) {
2509 }
2510 } else {
2511 if (config.showCommLinkOption) {
2512 if (otherFleet.getMemoryWithoutUpdate().is("$hailing", true)) {
2513 options.addOption("Accept the comm request", OptionId.OPEN_COMM, Misc.getHighlightedOptionColor(), null);
2514 otherFleet.getMemoryWithoutUpdate().unset("$hailing");
2515 } else if (otherFleet.getMemoryWithoutUpdate().is("$highlightComms", true)) {
2516 options.addOption("Open a comm link", OptionId.OPEN_COMM, Misc.getHighlightedOptionColor(), null);
2517 otherFleet.getMemoryWithoutUpdate().unset("$highlightComms");
2518 } else {
2519 options.addOption("Open a comm link", OptionId.OPEN_COMM, null);
2520 }
2521 }
2522
2523 boolean smuggler = otherFleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_SMUGGLER);
2524 if (otherFleet.getFaction().isPlayerFaction() && !smuggler) {
2525 options.addOption("Leave", OptionId.LEAVE, null);
2526 options.setShortcut(OptionId.LEAVE, Keyboard.KEY_ESCAPE, false, false, false, true);
2527 } else {
2528 updateEngagementChoice(withText);
2529 }
2530 }
2531
2532 }
2533
2534
2535 protected boolean allyEngagementChoiceNoBattle = false;
2536 protected boolean harryEndedBattle = false;
2537 private List<FleetMemberAPI> recoverableShips;
2538 private List<FleetMemberAPI> storyRecoverableShips;
2539 private List<FleetMemberAPI> recoveredShips = new ArrayList<FleetMemberAPI>();
2540 protected void updateEngagementChoice(boolean withText) {
2542 //options.clearOptions();
2543 if (isFightingOver()) {
2545 return;
2546 }
2547 //options.clearOptions();
2548
2549 BattleAPI b = context.getBattle();
2550
2551 if (ongoingBattle && b.getPlayerSide() != null && b.getPlayerSide().size() <= 1) {
2552 //if (ongoingBattle && b.getPlayerSide() != null && b.isPlayerPrimary()) {
2553 ongoingBattle = false;
2554 if (config.showCommLinkOption) {
2555 options.addOption("Open a comm link", OptionId.OPEN_COMM, null);
2556 }
2557 }
2558
2559 playerGoal = null;
2560 otherGoal = null;
2561
2562 boolean alliedWantsToFight = alliedFleetWantsToFight();
2563 boolean alliedWantsToRun = alliedFleetWantsToDisengage() && alliedCanDisengage();
2564 boolean alliedHolding = alliedFleetHoldingVsStrongerEnemy();
2565 boolean otherWantsToFight = otherFleetWantsToFight();
2566 boolean otherWantsToRun = otherFleetWantsToDisengage() && otherCanDisengage();
2567 //otherWantsToRun = otherFleetWantsToDisengage() && otherCanDisengage();
2568 boolean otherHolding = otherFleetHoldingVsStrongerEnemy();
2569
2570 //boolean otherWantsToRun = otherFleetWantsToDisengage() && otherCanDisengage();
2571 boolean playerHasReadyShips = false;
2572 boolean allyHasReadyShips = false;
2573 for (FleetMemberAPI member : playerFleet.getFleetData().getCombatReadyMembersListCopy()) {
2574 if (member.isAlly() && !member.isStation()) {
2575 allyHasReadyShips = true;
2576 } else {
2577 playerHasReadyShips = true;
2578 }
2579 }
2580
2581 if (otherWantsToRun && canDisengageCleanly(otherFleet)) {
2582// if (didEnoughToDisengage(otherFleet)) {
2583// if (context.getBattle().getPlayerSide().size() > 1) {
2584// if (withText) addText(getString("enemyDisruptedPlayerSide"), Misc.getNegativeHighlightColor());
2585// } else {
2586// if (withText) addText(getString("enemyDisruptedPlayer"), Misc.getNegativeHighlightColor());
2587// }
2588// } else {
2589 if (context.getBattle().getPlayerSide().size() > 1) {
2590 if (withText) addText(getString("enemyCleanDisengageSide"));
2591 } else {
2592 if (withText) addText(getString("enemyCleanDisengage"));
2593 }
2594// }
2596 } else if (otherWantsToRun) {
2597 String pursueTooltip = "tooltipPursue";
2598 String harassTooltip = "tooltipHarassRetreat";
2599 String letThemGoTooltip = "tooltipLetThemGo";
2601 letThemGoTooltip = "tooltipLetThemGoNoPenalty";
2602 }
2603
2604 boolean canPursue = false;
2605 boolean canHasass = false;
2606 //PursueAvailability pa = context.getPursuitAvailability(playerFleet, otherFleet);
2607 PursueAvailability pa = getPursuitAvailability(playerFleet);
2608 //List<FleetMemberAPI> members = getPursuitCapablePlayerShips();
2609 //if (members.isEmpty()) pa = PursueAvailability.NO_READY_SHIPS;
2610
2611 DisengageHarryAvailability dha = context.getDisengageHarryAvailability(playerFleet, otherFleet);
2612
2613 switch (pa) {
2614 case AVAILABLE:
2615 canPursue = true;
2616 break;
2617 case LOST_LAST_ENGAGEMENT:
2618 pursueTooltip = "tooltipPursueLostLast";
2619 break;
2620 case NO_READY_SHIPS:
2621 pursueTooltip = "tooltipNoReadyShips";
2622 break;
2623 case TOOK_SERIOUS_LOSSES:
2624 if (context.getBattle().getPlayerSide().size() > 1) {
2625 if (withText) addText(getString("enemyDisruptedPlayerSide"), getString("highlightDisruptedPlayer"), Misc.getNegativeHighlightColor());
2626 } else {
2627 if (withText) addText(getString("enemyDisruptedPlayer"), getString("highlightDisruptedPlayer"), Misc.getNegativeHighlightColor());
2628 }
2629 pursueTooltip = "tooltipPursueSeriousLosses";
2630 break;
2631 case TOO_SLOW:
2632 pursueTooltip = "tooltipPursueTooSlow";
2633 break;
2634 }
2635
2636 switch (dha) {
2637 case AVAILABLE:
2638 canHasass = true;
2639 break;
2640 case NO_READY_SHIPS:
2641 harassTooltip = "tooltipNoReadyShips";
2642 break;
2643 }
2644
2645 if (ongoingBattle) {
2646 boolean station = false;
2647 if (playerFleet != null) {
2648 for (FleetMemberAPI member : playerFleet.getFleetData().getMembersListCopy()) {
2649 if (member.isStation()) {
2650 station = true;
2651 break;
2652 }
2653 }
2654 }
2655
2656 //boolean letGo = (!canPursue && !canHasass) || !allyHasReadyShips || station;
2657 boolean letGo = (!canPursue && !canHasass) || !allyHasReadyShips;// || station;
2658 if (station) { // make it so the player can decide to pursue
2659 letGo = false;
2660 alliedWantsToFight = true;
2661 }
2662 //if (!letGo) {
2663 //PursuitOption po = playerFleet.getAI().pickPursuitOption(context, otherFleet);
2664 PursuitOption po = pickPursuitOption(playerFleet, otherFleet, context);
2665 po = PursuitOption.PURSUE;
2666 if (alliedWantsToRun || alliedHolding || !alliedWantsToFight || letGo) {
2667 po = PursuitOption.LET_THEM_GO;
2668 }
2669 if (!canPursue && canHasass) {
2670 po = PursuitOption.HARRY;
2671 }
2672 //po = PursuitOption.LET_THEM_GO;
2673 //po = PursuitOption.HARRY;
2674 switch (po) {
2675 case PURSUE:
2676 if (withText) addText(getString("ongoingBattlePursue"));
2677 playerGoal = FleetGoal.ATTACK;
2678 otherGoal = FleetGoal.ESCAPE;
2679 options.addOption("Join the pursuit", OptionId.CONTINUE_ONGOING_BATTLE, getString(pursueTooltip));
2680 if (!canPursue || !playerHasReadyShips) {
2681 options.setEnabled(OptionId.CONTINUE_ONGOING_BATTLE, false);
2682 }
2683 break;
2684 case HARRY:
2685 // CR loss from harrying
2687
2688 if (withText) addText(getString("ongoingBattleHarass"));
2690 context.getDataFor(playerFleet).setDisengaged(false);
2691 context.getDataFor(otherFleet).setDisengaged(true);
2693 harryEndedBattle = true;
2694 //rememberWasBeaten();
2695 break;
2696 case LET_THEM_GO:
2697 letGo = true;
2699 context.getDataFor(playerFleet).setDisengaged(false);
2700 context.getDataFor(otherFleet).setDisengaged(true);
2701 }
2703 //rememberWasBeaten();
2704 break;
2705 }
2706 //}
2707 if (letGo) {
2708 if (withText) addText(getString("ongoingBattleLetGo"));
2710 }
2711
2714 } else {
2716 options.addOption("Perform a salvage operation, then leave", OptionId.LOOT_THEN_LEAVE, null);
2717 options.setShortcut(OptionId.LOOT_THEN_LEAVE, Keyboard.KEY_ESCAPE, false, false, false, true);
2718 } else {
2719 options.addOption("Leave", OptionId.LEAVE, null);
2720 options.setShortcut(OptionId.LEAVE, Keyboard.KEY_ESCAPE, false, false, false, true);
2721 }
2722 }
2723 } else {
2724 CampaignFleetAIAPI ai = otherFleet.getAI();
2725 boolean hostile = false;
2726 if (ai != null) {
2727 hostile = ai.isHostileTo(playerFleet) || context.isEngagedInHostilities();
2728 }
2729
2730 options.addOption("Pursue them", OptionId.PURSUE, getString(pursueTooltip));
2731
2732 if (playerHasReadyShips) {
2733 options.addOption("Maneuver to force a pitched battle", OptionId.FORCE_ENGAGE, "Outmaneuver the opposing fleet, forcing them to fight you head on.");
2734 boolean knows = context.getBattle() != null && context.getBattle().getNonPlayerSide() != null &&
2735 context.getBattle().knowsWhoPlayerIs(context.getBattle().getNonPlayerSide());
2736 boolean lowImpact = context.isLowRepImpact() || context.isNoRepImpact();
2737 FactionAPI nonHostile = getNonHostileOtherFaction();
2738 //if (!playerFleet.getFaction().isHostileTo(otherFleet.getFaction()) && knows && !context.isEngagedInHostilities()) {
2739 if (nonHostile != null && knows && !lowImpact && !context.isEngagedInHostilities() &&
2740 config.showWarningDialogWhenNotHostile) {
2741 options.addOptionConfirmation(OptionId.FORCE_ENGAGE, "The " + nonHostile.getDisplayNameLong() + " " + nonHostile.getDisplayNameIsOrAre() + " not currently hostile, and you have been positively identified. Are you sure you want to engage one of their fleets?", "Yes", "Never mind");
2742 }
2743 } else {
2744 options.addOption("Maneuver to force a pitched battle", OptionId.ENGAGE, getString("tooltipNoReadyShips"));
2745 options.setEnabled(OptionId.FORCE_ENGAGE, false);
2746 }
2747 SetStoryOption.set(dialog, 1, OptionId.FORCE_ENGAGE, "forceBattle", Sounds.STORY_POINT_SPEND_COMBAT,
2748 "Maneuvered to force pitched battle with " + otherFleet.getNameWithFactionKeepCase());
2749
2750 options.addOption("Harry their retreat", OptionId.HARRY_PURSUE, getString(harassTooltip));
2751 boolean knows = context.getBattle() != null && context.getBattle().getNonPlayerSide() != null &&
2752 context.getBattle().knowsWhoPlayerIs(context.getBattle().getNonPlayerSide());
2753 boolean lowImpact = context.isLowRepImpact() || context.isNoRepImpact();
2754 FactionAPI nonHostile = getNonHostileOtherFaction();
2755 //if (!playerFleet.getFaction().isHostileTo(otherFleet.getFaction()) && knows && !context.isEngagedInHostilities()) {
2756 if (nonHostile != null && knows && !lowImpact && !context.isEngagedInHostilities() &&
2757 config.showWarningDialogWhenNotHostile) {
2758 options.addOptionConfirmation(OptionId.HARRY_PURSUE, "The " + nonHostile.getDisplayNameLong() + " " + nonHostile.getDisplayNameIsOrAre() + " not currently hostile, and you have been positively identified. Are you sure you want to engage in hostilities with one of their fleets?", "Yes", "Never mind");
2759 options.addOptionConfirmation(OptionId.PURSUE, "The " + nonHostile.getDisplayNameLong() + " " + nonHostile.getDisplayNameIsOrAre() + " not currently hostile, and you have been positively identified. Are you sure you want to engage in hostilities with one of their fleets?", "Yes", "Never mind");
2760 }
2761 if (hostile) {
2762 options.addOption("Let them go", OptionId.LET_THEM_GO, getString(letThemGoTooltip));
2763 } else {
2764 options.addOption("Leave", OptionId.LEAVE, null);
2765 options.setShortcut(OptionId.LEAVE, Keyboard.KEY_ESCAPE, false, false, false, true);
2766// options.addOption("Go back", OptionId.GO_TO_MAIN, null);
2767// options.setShortcut(OptionId.GO_TO_MAIN, Keyboard.KEY_ESCAPE, false, false, false, true);
2768 }
2769
2770 if (!canPursue || !playerHasReadyShips) {
2771 options.setEnabled(OptionId.PURSUE, false);
2772 }
2773 if (!canHasass || !playerHasReadyShips) {
2774 options.setEnabled(OptionId.HARRY_PURSUE, false);
2775 }
2776 }
2777 } else {
2778 if (ongoingBattle) {
2779 if (alliedWantsToRun) {
2780 if (withText && !config.straightToEngage) addText(getString("ongoingBattleDisengage"));
2781 playerGoal = FleetGoal.ESCAPE;
2782 otherGoal = FleetGoal.ATTACK;
2783 options.addOption("Join the disengage attempt", OptionId.CONTINUE_ONGOING_BATTLE, null);
2784 } else {
2785 boolean station = false;
2786 if (playerFleet != null) {
2787 for (FleetMemberAPI member : playerFleet.getFleetData().getMembersListCopy()) {
2788 if (member.isStation()) {
2789 station = true;
2790 break;
2791 }
2792 }
2793 }
2794
2795 if (withText && !config.straightToEngage) {
2796 if (station) {
2797 addText(getString("ongoingBattleStation"));
2798 } else {
2799 addText(getString("ongoingBattleEngage"));
2800 }
2801 }
2802 playerGoal = FleetGoal.ATTACK;
2803 otherGoal = FleetGoal.ATTACK;
2804
2805 if (playerHasReadyShips) {
2806 options.addOption("Join the engagement", OptionId.CONTINUE_ONGOING_BATTLE, null);
2807 } else {
2808 options.addOption("Join the engagement", OptionId.CONTINUE_ONGOING_BATTLE, getString("tooltipNoReadyShips"));
2809 options.setEnabled(OptionId.CONTINUE_ONGOING_BATTLE, false);
2810 }
2811
2812 options.addOption("Leave", OptionId.LEAVE, null);
2813 options.setShortcut(OptionId.LEAVE, Keyboard.KEY_ESCAPE, false, false, false, true);
2814 }
2815 } else {
2816 String engageText = "Move in to engage";
2817 if (config.firstTimeEngageOptionText != null && !context.isEngagedInHostilities()) {
2818 engageText = config.firstTimeEngageOptionText;
2819 }
2820 if (config.afterFirstTimeEngageOptionText != null && context.isEngagedInHostilities()) {
2821 engageText = config.afterFirstTimeEngageOptionText;
2822 }
2823 if (playerHasReadyShips) {
2824 options.addOption(engageText, OptionId.ENGAGE, getString("tooltipEngage"));
2825 boolean knows = context.getBattle() != null && context.getBattle().getNonPlayerSide() != null &&
2826 context.getBattle().knowsWhoPlayerIs(context.getBattle().getNonPlayerSide());
2827 boolean lowImpact = context.isLowRepImpact() || context.isNoRepImpact();
2828 FactionAPI nonHostile = getNonHostileOtherFaction();
2829 //if (!playerFleet.getFaction().isHostileTo(otherFleet.getFaction()) && knows && !context.isEngagedInHostilities()) {
2830 if (nonHostile != null && knows && !lowImpact && !context.isEngagedInHostilities() &&
2831 config.showWarningDialogWhenNotHostile) {
2832 options.addOptionConfirmation(OptionId.ENGAGE, "The " + nonHostile.getDisplayNameLong() + " " + nonHostile.getDisplayNameIsOrAre() + " not currently hostile, and you have been positively identified. Are you sure you want to engage one of their fleets?", "Yes", "Never mind");
2833 }
2834 } else {
2835 options.addOption(engageText, OptionId.ENGAGE, getString("tooltipNoReadyShips"));
2836 options.setEnabled(OptionId.ENGAGE, false);
2837 }
2838 CampaignFleetAIAPI ai = otherFleet.getAI();
2839 boolean hostile = false;
2840 if (ai != null) {
2841 hostile = ai.isHostileTo(playerFleet) || context.isEngagedInHostilities();
2842 }
2843 if (!config.leaveAlwaysAvailable &&
2844 (otherFleetWantsToFight() || (hostile && !otherFleetWantsToDisengage()))) {
2846 options.addOption("Disengage", OptionId.DISENGAGE, getString("tooltipCleanDisengage"));
2848 options.addOption("Disengage", OptionId.DISENGAGE, getString("tooltipHarrassableDisengage"));
2849 } else {
2851 options.addOption("Leave", OptionId.LEAVE, null);
2852 options.setShortcut(OptionId.LEAVE, Keyboard.KEY_ESCAPE, false, false, false, true);
2853// options.addOption("Go back", OptionId.GO_TO_MAIN, null);
2854// options.setShortcut(OptionId.GO_TO_MAIN, Keyboard.KEY_ESCAPE, false, false, false, true);
2855 } else {
2856 boolean addSPDisengage = true;
2857 if (canDisengage() || !playerHasReadyShips) {
2858 options.addOption("Attempt to disengage", OptionId.ATTEMPT_TO_DISENGAGE, getString("tootipAttemptToDisengage"));
2859
2860 addSPDisengage = true;
2861
2862 } else {
2863 boolean hasStation = false;
2864 boolean allStation = true;
2865 for (CampaignFleetAPI curr : context.getBattle().getSideFor(otherFleet)) {
2866 allStation &= curr.isStationMode();
2867 hasStation |= curr.isStationMode();
2868 }
2869
2870 if (hasStation) {
2871 if (allStation) {
2872 options.addOption("Disengage", OptionId.DISENGAGE, getString("tooltipCleanDisengage"));
2873 } else {
2874 options.addOption("Disengage", OptionId.DISENGAGE, getString("tooltipHarrassableDisengage"));
2875 }
2876 addSPDisengage = false;
2877 } else {
2878 if (withText && !shownTooLargeToRetreatMessage) {
2880 //addText(getString("playerTooLargeToDisengage"), getString("highlightTooLarge"), Misc.getNegativeHighlightColor());
2881 //addText(getString("playerTooLargeCanFightToDisengage"), getString("highlightCanFight"), Misc.getHighlightColor());
2882 LabelAPI label = textPanel.addParagraph(getString("playerTooLargeToDisengage"));
2883 label.setHighlight(getString("highlightTooLarge"), getString("highlightDisengage"));
2884 label.setHighlightColors(Misc.getNegativeHighlightColor(), Misc.getHighlightColor());
2885 }
2886 }
2887 }
2888 if (addSPDisengage) {
2889 //options.addOption("Execute a series of special maneuvers, allowing you to disengage cleanly", OptionId.DISENGAGE);
2890 options.addOption("Disengage by executing a series of special maneuvers", OptionId.CLEAN_DISENGAGE,
2891 "Allows your fleet to disengage without being pursued.");
2892 SetStoryOption.set(dialog, 1, OptionId.CLEAN_DISENGAGE, "cleanDisengage", Sounds.STORY_POINT_SPEND_COMBAT,
2893 "Maneuvered to disengage from " + otherFleet.getNameWithFactionKeepCase());
2894
2896 }
2897 }
2898 }
2899 } else {
2900 options.addOption("Leave", OptionId.LEAVE, null);
2901 options.setShortcut(OptionId.LEAVE, Keyboard.KEY_ESCAPE, false, false, false, true);
2902// options.addOption("Go back", OptionId.GO_TO_MAIN, null);
2903// options.setShortcut(OptionId.GO_TO_MAIN, Keyboard.KEY_ESCAPE, false, false, false, true);
2904 }
2905 }
2906 }
2907
2908 if (playerOutBeforeAllies()) {
2909 if (!options.hasOption(OptionId.LEAVE) &&
2910 !options.hasOption(OptionId.LET_THEM_GO) &&
2911 !options.hasOption(OptionId.DISENGAGE)) {
2912 options.addOption("Leave", OptionId.LEAVE, null);
2913 options.setShortcut(OptionId.LEAVE, Keyboard.KEY_ESCAPE, false, false, false, true);
2914 }
2915 }
2916
2917 if (Global.getSettings().isDevMode()) {
2919 }
2920
2921 // if it's an ongoing battle, this will all get cleared out by a subsequent call to updatePreCombat()
2922// if (!options.hasOption(OptionId.GO_TO_MAIN)) {
2923// options.addOption("Go back", OptionId.GO_TO_MAIN, null);
2924// options.setShortcut(OptionId.GO_TO_MAIN, Keyboard.KEY_ESCAPE, false, false, false, true);
2925// }
2926
2927// if (Global.getSettings().isDevMode()) {
2928// DevMenuOptions.addOptions(dialog);
2929// }
2930 }
2931
2932 //addSPDisengage
2933 protected void addEmergencyRepairsOption() {
2934 if (didRepairs) return;
2935
2936 final CampaignFleetAPI fleet = Global.getSector().getPlayerFleet();
2937 final List<FleetMemberAPI> members = new ArrayList<FleetMemberAPI>();
2938
2939 final float crThreshold = CRPluginImpl.MALFUNCTION_START;
2940 final float hullThreshold = 0.4f;
2941 final float bonusRepairAmount = 0.1f; // threshold + this = repair level
2942
2943 FleetMemberAPI flagship = fleet.getFlagship();
2944 if (flagship != null && !flagship.isMothballed()) {
2945 if (flagship.getStatus().getHullFraction() < hullThreshold ||
2946 flagship.getRepairTracker().getBaseCR() < crThreshold) {
2947 members.add(flagship);
2948 }
2949 }
2950
2951 for (FleetMemberAPI curr : fleet.getFleetData().getMembersListCopy()) {
2952 if (curr == flagship) continue;
2953 if (curr.isMothballed()) continue;
2954 if (!curr.getCaptain().isDefault()) {
2955 if (curr.getStatus().getHullFraction() < hullThreshold ||
2956 curr.getRepairTracker().getBaseCR() < crThreshold) {
2957 members.add(curr);
2958 }
2959 }
2960 if (members.size() > 12) break; // just in case, since these are listed in the dialog w/o a limit check
2961 }
2962
2963// for (FleetMemberAPI curr : fleet.getFleetData().getMembersListCopy()) {
2964// if (curr == flagship) continue;
2965// if (curr.isMothballed()) continue;
2966// if (!members.contains(curr)) {
2967// if (curr.getStatus().getHullFraction() < hullThreshold ||
2968// curr.getRepairTracker().getBaseCR() < crThreshold) {
2969// members.add(curr);
2970// }
2971// }
2972// if (members.size() > 12) break; // just in case, since these are listed in the dialog w/o a limit check
2973// }
2974//
2975 if (members.isEmpty()) return;
2976
2977 options.addOption("Perform limited emergency repairs", OptionId.EMERGENCY_REPAIRS,
2978 "Brings your flagship and a few officer-controlled ships back up to reasonable " +
2979 "combat readiness and repairs some hull damage.");
2980 StoryOptionParams params = new StoryOptionParams(OptionId.EMERGENCY_REPAIRS,
2981 1, "emergencyRepairs", Sounds.STORY_POINT_SPEND_COMBAT,
2982 "Performed emergency repairs when facing " + otherFleet.getNameWithFactionKeepCase());
2983
2984 SetStoryOption.set(dialog, params,
2985 new BaseOptionStoryPointActionDelegate(dialog, params) {
2986 @Override
2987 public void confirm() {
2988 float dpUsed = 0f;
2989 for (FleetMemberAPI member : members) {
2990 float dpRemaining = EMERGENCY_REPAIRS_MAX_DP - dpUsed;
2991 float shipDP = member.getDeploymentPointsCost();
2992 dpUsed += shipDP;
2993
2994 float fraction = dpRemaining / shipDP;
2995 if (fraction >= 0.99f) fraction = 1f;
2996
2997 float baseRepairCRLevel = crThreshold + bonusRepairAmount * (float) Math.random();
2998 float baseRepairHullLevel = hullThreshold + bonusRepairAmount * (float) Math.random();
2999
3000 float cr = member.getRepairTracker().getBaseCR();
3001 float repairedCR = cr + (baseRepairCRLevel - cr) * fraction;
3002 if (cr < repairedCR) {
3003 //member.getRepairTracker().setCR(cr + (repairedCR - cr) * fraction);
3004 member.getRepairTracker().applyCREvent(repairedCR - cr, "Emergency repairs");
3005 }
3006 float hull = member.getStatus().getHullFraction();
3007 float repairedHull = hull + (baseRepairHullLevel - hull) * fraction;
3008 if (hull < repairedHull) {
3009 member.getStatus().setHullFraction(repairedHull);
3010 }
3011
3012 String str = BaseSkillEffectDescription.getValueLabelForMember(member);
3013 textPanel.setFontSmallInsignia();
3014 textPanel.addPara(str + " performed emergency repairs", Misc.getPositiveHighlightColor());
3015 textPanel.highlightFirstInLastPara(str, Misc.getHighlightColor());
3016 textPanel.setFontInsignia();
3017
3018 if (fraction < 1f) {
3019 break;
3020 }
3021 }
3022 didRepairs = true;
3023 playerFleet.getFleetData().setSyncNeeded();
3024 playerFleet.getFleetData().syncIfNeeded();
3025 dialog.getOptionPanel().setEnabled(OptionId.EMERGENCY_REPAIRS, false);
3026 }
3027
3028 @Override
3029 public void createDescription(TooltipMakerAPI info) {
3030 super.createDescription(info);
3031 info.setParaFontDefault();
3032 float opad = 10f;
3033 float pad = 3f;
3034 info.addPara("Will bring up to %s deployment points worth of ships up " +
3035 "to approximately %s combat readiness and %s hull integrity. Starts with the " +
3036 "flagship and then goes on to officer-controlled ships, in the " +
3037 "order they are placed in the fleet. " +
3038 "Does not affect other ships.",
3039 0f, Misc.getHighlightColor(),
3040 "" + (int) EMERGENCY_REPAIRS_MAX_DP,
3041 "" + (int) Math.round((crThreshold + bonusRepairAmount) * 100f) + "%",
3042 "" + (int) Math.round((hullThreshold + bonusRepairAmount) * 100f) + "%"
3043 );
3044
3045 info.addPara("The repairs will affect:", opad);
3046 info.setBulletedListMode(BaseIntelPlugin.INDENT);
3047 float initPad = 10f;
3048
3049 float dpUsed = 0f;
3050 for (FleetMemberAPI member : members) {
3051 float dpRemaining = EMERGENCY_REPAIRS_MAX_DP - dpUsed;
3052 float shipDP = member.getDeploymentPointsCost();
3053 dpUsed += shipDP;
3054
3055 dpUsed += shipDP;
3056
3057 float fraction = dpRemaining / shipDP;
3058 if (fraction >= 0.99f) fraction = 1f;
3059
3060 String str = BaseSkillEffectDescription.getValueLabelForMember(member);
3061
3062 String post = " (full effect)";
3063 if (fraction < 1) post = " (partial effect)";
3064
3065 info.addPara(str + post, initPad);
3066 initPad = 0f;
3067
3068 if (dpUsed >= EMERGENCY_REPAIRS_MAX_DP) break;
3069 }
3070 info.setBulletedListMode(null);
3071 info.addSpacer(20f);
3072 }
3073 });
3074// SetStoryOption.set(dialog, 1, OptionId.EMERGENCY_REPAIRS, "emergencyRepairs", Sounds.STORY_POINT_SPEND_COMBAT,
3075// "Performed emergency repairs when facing " + otherFleet.getNameWithFactionKeepCase());
3076 }
3077
3078 protected PursuitOption pickPursuitOption(CampaignFleetAPI fleet, CampaignFleetAPI other, FleetEncounterContext context) {
3080
3081 if (fleet.getAI() == null) return PursuitOption.LET_THEM_GO;
3082
3083 if (config.alwaysPursue) {
3084 return PursuitOption.PURSUE;
3085 }
3086
3087 boolean allStation = false;
3088 boolean hasStation = false;
3089 if (context.getBattle() != null) {
3090 allStation = true;
3091 for (CampaignFleetAPI curr : context.getBattle().getSideFor(fleet)) {
3092// if (curr.isStationMode()) {
3093// return PursuitOption.HARRY;
3094// }
3095 allStation &= curr.isStationMode();
3096 hasStation |= curr.isStationMode();
3097 }
3098 //if (allStation) {
3099 }
3100
3101 PursuitOption option = fleet.getAI().pickPursuitOption(context, other);
3102 if (hasStation && option == PursuitOption.HARRY) {
3104 return PursuitOption.LET_THEM_GO;
3105 }
3106 return option;
3107 }
3108
3109 public FactionAPI getNonHostileOtherFaction() {
3110 if (context.getBattle() == null) return null;
3111
3112 //BattleSide playerSide = context.getBattle().pickSide(Global.getSector().getPlayerFleet());
3113
3114 //List<CampaignFleetAPI> otherSide = context.getBattle().getSideFor(otherFleet);
3115 List<CampaignFleetAPI> otherSide = context.getBattle().getNonPlayerSide();
3116 return getNonHostileOtherFaction(otherSide);
3117 }
3118
3119 public FactionAPI getNonHostileOtherFaction(List<CampaignFleetAPI> otherSide) {
3120 FactionAPI player = Global.getSector().getPlayerFaction();
3121 int max = -1;
3122 CampaignFleetAPI result = null;
3123
3124 if (otherSide != null) {
3125 for (CampaignFleetAPI other : otherSide) {
3126 if (!player.isHostileTo(other.getFaction()) && other.getFleetPoints() > max) {
3127 result = other;
3128 max = other.getFleetPoints();
3129 }
3130 }
3131 }
3132 return result == null ? null : result.getFaction();
3133 }
3134
3135 protected boolean playerOutBeforeAllies() {
3136 EngagementOutcome last = context.getLastEngagementOutcome();
3137 if (last == EngagementOutcome.BATTLE_PLAYER_OUT_FIRST_WIN ||
3138 last == EngagementOutcome.BATTLE_PLAYER_OUT_FIRST_LOSS ||
3139 last == EngagementOutcome.PURSUIT_PLAYER_OUT_FIRST_WIN ||
3140 last == EngagementOutcome.PURSUIT_PLAYER_OUT_FIRST_LOSS ||
3141 last == EngagementOutcome.ESCAPE_PLAYER_OUT_FIRST_WIN ||
3142 last == EngagementOutcome.ESCAPE_PLAYER_OUT_FIRST_LOSS
3143 ) {
3144 return true;
3145 }
3146 return false;
3147 }
3148
3149 public static boolean canDisengage() {
3150 CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet();
3151 float total = 0f;
3152 for (FleetMemberAPI member : playerFleet.getFleetData().getMembersListCopy()) {
3153 if (member.canBeDeployedForCombat()) {
3154 total += member.getDeploymentPointsCost();
3155 }
3156 }
3157 return total <= getDisengageSize();
3158 }
3159
3160 protected boolean otherCanDisengage() {
3162 }
3163
3164 protected boolean alliedCanDisengage() {
3166 }
3167
3168 protected boolean fleetCanDisengage(CampaignFleetAPI fleet) {
3169 float total = 0f;
3170 for (FleetMemberAPI member : fleet.getFleetData().getMembersListCopy()) {
3171 if (member.canBeDeployedForCombat()) {
3172 total += member.getDeploymentPointsCost();
3173 }
3174 }
3175 return total <= getDisengageSize();
3176 }
3177
3178 public static float getDisengageSize() {
3179 float abs = Global.getSettings().getFloat("maxDisengageSize");
3180 float fraction = Global.getSettings().getFloat("maxDisengageFraction") * Global.getSettings().getBattleSize();
3181 return Math.min(abs, fraction);
3182 }
3183
3184 protected boolean didEnoughToDisengage(CampaignFleetAPI fleet) {
3185 DataForEncounterSide data = context.getDataFor(fleet);
3186 return data.isDidEnoughToDisengage();
3187 }
3188
3189 protected boolean canDisengageCleanly(CampaignFleetAPI fleet) {
3190 //if (wasEnemyDisrupted(fleet)) return true;
3191 DataForEncounterSide data = context.getDataFor(fleet);
3192 if (data.isWonLastEngagement()) return true;
3193
3194 if (data.isDidEnoughToDisengage()) return true;
3195
3196 if (fleet == playerFleet) {
3197 for (FleetMemberAPI member : fleet.getFleetData().getMembersListCopy()) {
3198 if (member.isStation()) return true;
3199 }
3200 }
3201
3202 EngagementOutcome last = context.getLastEngagementOutcome();
3203 if (fleet == playerFleet && !ongoingBattle &&
3204 (last == EngagementOutcome.BATTLE_PLAYER_OUT_FIRST_WIN ||
3205 last == EngagementOutcome.BATTLE_PLAYER_OUT_FIRST_LOSS ||
3206 last == EngagementOutcome.PURSUIT_PLAYER_OUT_FIRST_WIN ||
3207 last == EngagementOutcome.PURSUIT_PLAYER_OUT_FIRST_LOSS ||
3208 last == EngagementOutcome.ESCAPE_PLAYER_OUT_FIRST_WIN ||
3209 last == EngagementOutcome.ESCAPE_PLAYER_OUT_FIRST_LOSS)) {
3210 return true;
3211 }
3212
3213 return false;
3214 }
3215 protected boolean canDisengageWithoutPursuit(CampaignFleetAPI fleet) {
3216 CampaignFleetAPI other = playerFleet;
3217 if (other == fleet) other = otherFleet;
3218 PursueAvailability pa = getPursuitAvailability(other);
3219 return pa != PursueAvailability.AVAILABLE;
3220 }
3221
3222 protected PursueAvailability getPursuitAvailability(CampaignFleetAPI fleet) {
3223 CampaignFleetAPI other = playerFleet;
3224 if (other == fleet) other = otherFleet;
3225 PursueAvailability pa = context.getPursuitAvailability(fleet, other);
3226 if (pa == PursueAvailability.TOO_SLOW && fleet == playerFleet) {
3227 pa = PursueAvailability.AVAILABLE;
3228 }
3229 return pa;
3230 }
3231
3232 protected String getString(String id) {
3233 String str = Global.getSettings().getString("fleetInteractionDialog", id);
3234
3235 String faction = otherFleet.getFaction().getEntityNamePrefix();
3236 if (faction == null || faction.isEmpty()) {
3237 faction = otherFleet.getFaction().getDisplayName();
3238 }
3239
3240 if (otherFleet.getFaction().isNeutralFaction()) {
3241 faction = "opposing";
3242 }
3243
3244 String fleetName = otherFleet.getName();
3245 String firstName = otherFleet.getCommander().getName().getFirst();
3246 String lastName = otherFleet.getCommander().getName().getLast();
3247 String fleetOrShip = "fleet";
3248 if (otherFleet.getFleetData().getMembersListCopy().size() == 1) {
3249 fleetOrShip = "ship";
3250 if (otherFleet.getFleetData().getMembersListCopy().get(0).isFighterWing()) {
3251 fleetOrShip = "fighter wing";
3252 }
3253 }
3254 String playerFleetOrShip = "fleet";
3255 if (playerFleet.getFleetData().getMembersListCopy().size() == 1) {
3256 playerFleetOrShip = "ship";
3257 if (playerFleet.getFleetData().getMembersListCopy().get(0).isFighterWing()) {
3258 playerFleetOrShip = "fighter wing";
3259 }
3260 }
3261
3262 DataForEncounterSide data = context.getDataFor(playerFleet);
3263 if (data != null) {
3264 int crewLost = (int) (data.getCrewLossesDuringLastEngagement().getCrewInt());
3265 String crewLostStr = getApproximate(crewLost);
3266
3267 int marinesLost = (int) (data.getCrewLossesDuringLastEngagement().getMarines());
3268 String marinesLostStr = getApproximate(marinesLost);
3269
3270 int crewRecovered = (int) data.getRecoverableCrewLosses().getCrewInt();
3271 int marinesRecovered = (int) data.getRecoverableCrewLosses().getMarines();
3272
3273 String crewRecStr = "" + crewRecovered;
3274 if (crewRecovered <= 0) {
3275 crewRecStr = "no";
3276 }
3277 String marinesRecStr = "" + marinesRecovered;
3278 if (marinesRecovered <= 0) {
3279 marinesRecStr = "no";
3280 }
3281
3282 str = str.replaceAll("\\$crewLost", crewLostStr);
3283 str = str.replaceAll("\\$marinesLost", marinesLostStr);
3284 str = str.replaceAll("\\$crewLost", crewLostStr);
3285 str = str.replaceAll("\\$crewRecovered", crewRecStr);
3286 str = str.replaceAll("\\$marinesRecovered", marinesRecStr);
3287 }
3288
3289 if (toBoard != null) {
3290 int numLifeSigns = (int) (toBoard.getCrewComposition().getCrew() + toBoard.getCrewComposition().getMarines());
3291 str = str.replaceAll("\\$numLifeSigns", getApproximate(numLifeSigns));
3292
3293 str = str.replaceAll("\\$boardableShipName", toBoard.getShipName());
3294 }
3295
3296 str = str.replaceAll("\\$faction", faction);
3297 str = str.replaceAll("\\$fleetName", fleetName);
3298 str = str.replaceAll("\\$firstName", firstName);
3299 str = str.replaceAll("\\$lastName", lastName);
3300 str = str.replaceAll("\\$fleetOrShip", fleetOrShip);
3301 str = str.replaceAll("\\$playerFleetOrShip", playerFleetOrShip);
3302
3303 if (selectedFlagship != null) {
3304 str = str.replaceAll("\\$flagship", "the " + selectedFlagship.getShipName());
3305 }
3306
3307 str = str.replaceAll("\\$creditsLooted", creditsLooted);
3308
3309 if (crashMothballList != null) {
3310 str = str.replaceAll("\\$crashMothballList", crashMothballList);
3311 }
3312
3313 if (repairedShipList != null) {
3314 str = str.replaceAll("\\$repairedShipList", repairedShipList);
3315 }
3316
3317 int marines = Global.getSector().getPlayerFleet().getCargo().getMarines();
3318 str = str.replaceAll("\\$marines", "" + marines);
3319
3320 str = str.replaceAll("\\$boardingSuccessChance", "" + (int) boardingPercentSuccess + "%");
3321
3322 if (boardingResult != null) {
3323 str = str.replaceAll("\\$boardingCrewLost", getIntOrNo(boardingResult.getAttackerLosses().getCrew()));
3324 str = str.replaceAll("\\$boardingMarinesLost", getIntOrNo(boardingResult.getAttackerLosses().getMarines()));
3325 str = str.replaceAll("\\$boardingEnemyCrewLost", getIntOrNo(boardingResult.getDefenderLosses().getCrew()));
3326 str = str.replaceAll("\\$boardingEnemyMarinesLost", getIntOrNo(boardingResult.getDefenderLosses().getMarines()));
3327 }
3328
3329// # $alliedFactionAndTheirAllies "Hegemony forces and their allies"
3330// # $enemyFactionAndTheirAllies "Hegemony forces and their allies"
3331// # $yourForcesWereOrYourSideWas
3332 BattleAPI b = context.getBattle();
3333 if (b != null) {
3334 BattleSide playerSide = b.pickSide(Global.getSector().getPlayerFleet());
3335 CampaignFleetAPI sideOnePrimary = b.getPrimary(b.getSideOne());
3336 CampaignFleetAPI sideTwoPrimary = b.getPrimary(b.getSideTwo());
3337 if (playerSide != BattleSide.NO_JOIN) {
3338 sideOnePrimary = b.getPrimary(b.getSide(playerSide));
3339 sideTwoPrimary = b.getPrimary(b.getOtherSide(playerSide));
3340 }
3341
3342 if (sideOnePrimary != null) {
3343 String strOne = sideOnePrimary.getFaction().getEntityNamePrefix() + " forces";
3344 if (strOne.startsWith(" ")) {
3345 strOne = sideOnePrimary.getFaction().getDisplayName() + " forces";
3346 }
3347// if (b.isStationInvolved(b.getSideFor(sideOnePrimary))) {
3348// strOne = strOne.replaceFirst(" forces", " station");
3349// }
3350 for (CampaignFleetAPI fleet : b.getSideFor(sideOnePrimary)) {
3351 if (fleet.getFaction() != sideOnePrimary.getFaction()) {
3352 if (fleet.isPlayerFleet()) continue;
3353 strOne += " and their allies";
3354 break;
3355 }
3356 }
3357 str = str.replaceAll("\\$alliedFactionAndTheirAllies", strOne);
3358 }
3359 if (sideTwoPrimary != null) {
3360 String strTwo = sideTwoPrimary.getFaction().getEntityNamePrefix() + " forces";
3361 if (strTwo.startsWith(" ")) {
3362 strTwo = sideTwoPrimary.getFaction().getDisplayName() + " forces";
3363 }
3364// if (b.isStationInvolved(b.getSideFor(sideTwoPrimary))) {
3365// strTwo = strTwo.replaceFirst(" forces", " station");
3366// }
3367 for (CampaignFleetAPI fleet : b.getSideFor(sideTwoPrimary)) {
3368 if (fleet.getFaction() != sideTwoPrimary.getFaction()) {
3369 if (fleet.isPlayerFleet()) continue;
3370 strTwo += " and their allies";
3371 break;
3372 }
3373 }
3374 str = str.replaceAll("\\$enemyFactionAndTheirAllies", strTwo);
3375 }
3376
3377 //$yourForcesWereOrYourSideWas
3378 String yourForcesWere = "Your forces were";
3379 if (b.getPlayerSide() != null && b.getPlayerSide().size() > 1) {
3380 yourForcesWere = "Your side was";
3381 }
3382 str = str.replaceAll("\\$yourForcesWereOrYourSideWas", yourForcesWere);
3383 }
3384
3385
3386// float recoveryFraction = context.getStandDownRecoveryFraction();
3387// str = str.replaceAll("\\$standDownRecovery", "" + (int) (recoveryFraction * 100f));
3388
3389 return str;
3390 }
3391
3392 protected String getIntOrNo(float value) {
3393 if (value < 1) {
3394 return "no";
3395 }
3396 return "" + (int) value;
3397 }
3398
3399 protected String getApproximate(float value) {
3400 int v = (int) value;
3401 String str = "multiple";
3402 if (v <= 0) {
3403 str = "no";
3404 } else if (v < 10) {
3405 str = "" + v;
3406 } else if (v < 100) {
3407 v = (int) Math.round((float) v/10f) * 10;
3408 str = "approximately " + v;
3409 } else if (v < 1000) {
3410 v = (int) Math.round((float) v/10f) * 10;
3411 str = "approximately " + v;
3412 } else {
3413 v = (int) Math.round((float) v/100f) * 100;
3414 str = "" + v;
3415 }
3416 return str;
3417 }
3418
3419 protected String getApproximateNumOnly(float value) {
3420 int v = (int) value;
3421 String str = "";
3422 if (v <= 0) {
3423 str = "asdasd";
3424 } else if (v < 10) {
3425 str = "" + v;
3426 } else if (v < 100) {
3427 v = (int) Math.round((float) v/10f) * 10;
3428 str = "" + v;
3429 } else if (v < 1000) {
3430 v = (int) Math.round((float) v/10f) * 10;
3431 str = "" + v;
3432 } else {
3433 v = (int) Math.round((float) v/100f) * 100;
3434 str = "" + v;
3435 }
3436 return str;
3437 }
3438
3439
3440 protected boolean isFightingOver() {
3441 return context.isBattleOver() ||
3442 (context.getDataFor(otherFleet).disengaged() && context.getDataFor(playerFleet).disengaged());
3443// return context.getDataFor(playerFleet).getLastGoal() == FleetGoal.ESCAPE ||
3444// context.getDataFor(otherFleet).getLastGoal() == FleetGoal.ESCAPE;
3445 //return context.getWinnerData().getLastGoal() == FleetGoal.ESCAPE || context.getLoserData().getLastGoal() == FleetGoal.ESCAPE;
3446 }
3447
3448 public boolean alliedFleetWantsToFight() {
3450 }
3451 public boolean otherFleetWantsToFight() {
3453 }
3454 public boolean otherFleetWantsToFight(boolean assumeHostile) {
3455 return fleetWantsToFight(otherFleet, playerFleet, assumeHostile);
3456 }
3457 protected boolean fleetWantsToFight(CampaignFleetAPI fleet, CampaignFleetAPI other) {
3458 return fleetWantsToFight(fleet, other, false);
3459 }
3460 protected boolean fleetWantsToFight(CampaignFleetAPI fleet, CampaignFleetAPI other, boolean assumeHostile) {
3461 if (config.alwaysAttackVsAttack) return true;
3462
3463 boolean hasNonCivReserves = false;
3464 for (FleetMemberAPI member : context.getDataFor(fleet).getInReserveDuringLastEngagement()) {
3465 if (!member.isCivilian()) {
3466 hasNonCivReserves = true;
3467 break;
3468 }
3469 }
3471 !context.getDataFor(fleet).isWonLastEngagement() &&
3472 !hasNonCivReserves) {
3473 return false;
3474 }
3475
3476 CampaignFleetAIAPI ai = fleet.getAI();
3477 if (ai == null) return false;
3478 EncounterOption option = ai.pickEncounterOption(context, other);
3479
3480 if (fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_MAKE_ALLOW_DISENGAGE)) return false;
3481
3482 return (ai.isHostileTo(other) || context.isEngagedInHostilities() || assumeHostile ||
3483 fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_MAKE_PREVENT_DISENGAGE) //||
3484 // "aggressive" just means "always engage IF already hostile"
3485 //fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_MAKE_AGGRESSIVE)
3486 ) &&
3487 (option == EncounterOption.ENGAGE || (option == EncounterOption.HOLD && ongoingBattle));
3488 }
3489
3490
3491
3496// if (otherFleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_MAKE_HOLD_VS_STRONGER_COMBAT_ONLY)) {
3497// return true;
3498// }
3500 }
3501 protected boolean fleetHoldingVsStrongerEnemy(CampaignFleetAPI fleet, CampaignFleetAPI other) {
3502 CampaignFleetAIAPI ai = fleet.getAI();
3503 if (ai == null) return false;
3504 boolean hostile = ai.isHostileTo(other) || (other.getAI() != null && other.getAI().isHostileTo(fleet)) || context.isEngagedInHostilities();
3505 if (!hostile) return false;
3506
3507 if (ai.pickEncounterOption(context, other) == EncounterOption.HOLD_VS_STRONGER) return true;
3508
3509 return fleetWantsToDisengage(fleet, other) && !fleetCanDisengage(fleet);
3510 }
3511
3515
3516 protected boolean otherFleetWantsToDisengage() {
3518 }
3519 protected boolean fleetWantsToDisengage(CampaignFleetAPI fleet, CampaignFleetAPI other) {
3520 if (config.alwaysAttackVsAttack) return false;
3521
3522 boolean hasNonCivReserves = false;
3523 for (FleetMemberAPI member : context.getDataFor(fleet).getInReserveDuringLastEngagement()) {
3524 if (!member.isCivilian()) {
3525 hasNonCivReserves = true;
3526 break;
3527 }
3528 }
3530 !context.getDataFor(fleet).isWonLastEngagement() &&
3531 !hasNonCivReserves) {
3532 return true;
3533 }
3534
3535 CampaignFleetAIAPI ai = fleet.getAI();
3536 if (ai == null) return false;
3537 return ai.pickEncounterOption(context, other) == EncounterOption.DISENGAGE;
3538 }
3539
3540 public Object getContext() {
3541 return context;
3542 }
3543
3544 public void updateMemory() {
3545 if (conversationDelegate != null) {
3547 }
3548 }
3549
3555
3556 public void setActiveMission(CampaignEventPlugin mission) {
3557 if (mission == null) {
3558 conversationDelegate.getMemoryMap().remove(MemKeys.MISSION);
3559 } else {
3560 MemoryAPI memory = mission.getMemory();
3561 if (memory != null) {
3562 conversationDelegate.getMemoryMap().put(MemKeys.MISSION, memory);
3563 } else {
3564 conversationDelegate.getMemoryMap().remove(MemKeys.MISSION);
3565 }
3566 }
3567 }
3568 public void setPlayerFleet(CampaignFleetAPI playerFleet) {
3569 this.playerFleet = playerFleet;
3570 }
3571
3572
3573}
3574
3575
3576
static SettingsAPI getSettings()
Definition Global.java:51
static FactoryAPI getFactory()
Definition Global.java:35
static SectorAPI getSector()
Definition Global.java:59
void resolvePlayerPursuit(FleetEncounterContext context, List< FleetMemberAPI > playerShipsToDeploy)
static void execute(InteractionDialogAPI dialog, String option)
static boolean isDevOption(Object optionData)
static void addOptions(InteractionDialogAPI dialog)
List< FleetMemberAPI > getRecoverableShips(BattleAPI battle, CampaignFleetAPI winningFleet, CampaignFleetAPI otherFleet)
void generateLoot(List< FleetMemberAPI > recoveredShips, boolean withCredits)
boolean adjustPlayerReputation(InteractionDialogAPI dialog, String ffText)
void applyPursuitOption(CampaignFleetAPI pursuingFleet, CampaignFleetAPI otherFleet, PursuitOption pursuitOption)
BoardingResult boardShip(FleetMemberAPI member, CampaignFleetAPI attacker, CampaignFleetAPI defender)
DataForEncounterSide getDataFor(CampaignFleetAPI participantOrCombined)
static void recoverShips(List< FleetMemberAPI > ships, FleetEncounterContext context, CampaignFleetAPI winningFleet, CampaignFleetAPI otherFleet)
PursueAvailability getPursuitAvailability(CampaignFleetAPI fleet, CampaignFleetAPI otherFleet)
EngageBoardableOutcome engageBoardableShip(FleetMemberAPI toBoard, CampaignFleetAPI fleetItBelongsTo, CampaignFleetAPI attackingFleet)
void setPlayerFPHullDamageToEnemies(float playerFPHullDamageToEnemies)
DisengageHarryAvailability getDisengageHarryAvailability(CampaignFleetAPI fleet, CampaignFleetAPI otherFleet)
void letBoardableGo(FleetMemberAPI toBoard, CampaignFleetAPI fleetItBelongsTo, CampaignFleetAPI attackingFleet)
boolean fleetHoldingVsStrongerEnemy(CampaignFleetAPI fleet, CampaignFleetAPI other)
boolean fleetWantsToFight(CampaignFleetAPI fleet, CampaignFleetAPI other, boolean assumeHostile)
PursuitOption pickPursuitOption(CampaignFleetAPI fleet, CampaignFleetAPI other, FleetEncounterContext context)
boolean fleetWantsToDisengage(CampaignFleetAPI fleet, CampaignFleetAPI other)
BattleAPI createBattle(CampaignFleetAPI one, CampaignFleetAPI two)
CombatReadinessPlugin getCRPlugin()
String getString(String category, String id)