Starsector API
Loading...
Searching...
No Matches
ShipRecoverySpecial.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special;
2
3import java.util.ArrayList;
4import java.util.List;
5
6import org.lwjgl.input.Keyboard;
7
8import com.fs.starfarer.api.Global;
9import com.fs.starfarer.api.campaign.CampaignFleetAPI;
10import com.fs.starfarer.api.campaign.CargoAPI;
11import com.fs.starfarer.api.campaign.CargoStackAPI;
12import com.fs.starfarer.api.campaign.FactionAPI;
13import com.fs.starfarer.api.campaign.FleetMemberPickerListener;
14import com.fs.starfarer.api.campaign.InteractionDialogAPI;
15import com.fs.starfarer.api.campaign.PlanetAPI;
16import com.fs.starfarer.api.campaign.SectorEntityToken;
17import com.fs.starfarer.api.campaign.listeners.ListenerUtil;
18import com.fs.starfarer.api.combat.ShipVariantAPI;
19import com.fs.starfarer.api.fleet.FleetMemberAPI;
20import com.fs.starfarer.api.fleet.FleetMemberType;
21import com.fs.starfarer.api.impl.campaign.DModManager;
22import com.fs.starfarer.api.impl.campaign.FleetEncounterContext;
23import com.fs.starfarer.api.impl.campaign.ids.Commodities;
24import com.fs.starfarer.api.impl.campaign.ids.Entities;
25import com.fs.starfarer.api.impl.campaign.ids.Factions;
26import com.fs.starfarer.api.impl.campaign.ids.FleetTypes;
27import com.fs.starfarer.api.impl.campaign.ids.Stats;
28import com.fs.starfarer.api.impl.campaign.ids.Tags;
29import com.fs.starfarer.api.impl.campaign.rulecmd.AddRemoveCommodity;
30import com.fs.starfarer.api.impl.campaign.rulecmd.FireAll;
31import com.fs.starfarer.api.impl.campaign.rulecmd.FireBest;
32import com.fs.starfarer.api.impl.campaign.rulecmd.ShowDefaultVisual;
33import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.SalvageSpecialInteraction.SalvageSpecialData;
34import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.SalvageSpecialInteraction.SalvageSpecialDialogPlugin;
35import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.SalvageSpecialInteraction.SalvageSpecialPlugin;
36import com.fs.starfarer.api.loading.HullModSpecAPI;
37import com.fs.starfarer.api.util.Misc;
38import com.fs.starfarer.api.util.WeightedRandomPicker;
39
41
42 public static final String RECOVER = "recover";
43 public static final String NOT_NOW = "not_now";
44 public static final String RECOVERY_FINISHED = "finished";
45 public static final String ABORT_CONTINUE = "abort_continue";
46
47
48 public static enum ShipCondition {
49 PRISTINE,
50 GOOD,
51 AVERAGE,
52 BATTERED,
53 WRECKED,
54 }
55
56 public static class PerShipData implements Cloneable {
57 public ShipCondition condition = ShipCondition.AVERAGE;
58 public String variantId = null;
59 public ShipVariantAPI variant = null;
60 public String shipName = null;
61 public String fleetMemberId = null;
62 public boolean addDmods = true;
63 public boolean pruneWeapons = true;
64 public Boolean nameAlwaysKnown = null;
65 public float sModProb = 0f;
66 public PerShipData(String variantId, ShipCondition condition) {
67 this(variantId, condition, 0f);
68 }
69 public PerShipData(String variantId, ShipCondition condition, float sModProb) {
70 this(variantId, condition, Factions.INDEPENDENT, sModProb);
71 }
72 public PerShipData(ShipVariantAPI variant, ShipCondition condition, String shipName, String factionIdForShipName, float sModProb) {
73 this.variant = variant;
74 this.condition = condition;
75
76 if (shipName != null) {
77 this.shipName = shipName;
78 } else {
79 FactionAPI faction = Global.getSector().getFaction(factionIdForShipName);
80 this.shipName = faction.pickRandomShipName();
81 }
82
83 this.sModProb = sModProb;
84 }
85
86 public PerShipData(String variantId, ShipCondition condition, String factionIdForShipName, float sModProb) {
87 this.variantId = variantId;
88 this.condition = condition;
89
90 FactionAPI faction = Global.getSector().getFaction(factionIdForShipName);
91 this.shipName = faction.pickRandomShipName();
92
93 this.sModProb = sModProb;
94 }
95
96 public ShipVariantAPI getVariant() {
97 ShipVariantAPI result = variant;
98 if (result == null && variantId != null) {
99 result = Global.getSettings().getVariant(variantId);
100 }
101 return result;
102 }
103
104 @Override
105 public PerShipData clone() {
106 try { return (PerShipData) super.clone(); } catch (CloneNotSupportedException e) { return null; }
107 }
108
109 }
110
111 public static class ShipRecoverySpecialData implements SalvageSpecialData {
112 public List<PerShipData> ships = new ArrayList<PerShipData>();
113 public String desc = null;
114 public Boolean storyPointRecovery = null;
115 public Boolean notNowOptionExits = null;
116 public Boolean noDescriptionText = null;
117
118 public ShipRecoverySpecialData(String desc) {
119 this.desc = desc;
120 }
121
122 public void addShip(PerShipData ship) {
123 ships.add(ship);
124 }
125 public void addShip(String variantId, ShipCondition condition, float sModProb) {
126 ships.add(new PerShipData(variantId, condition, sModProb));
127 }
128 public void addShip(String variantId, ShipCondition condition, String factionIdForShipName, float sModProb) {
129 ships.add(new PerShipData(variantId, condition, factionIdForShipName, sModProb));
130 }
131
132 public SalvageSpecialPlugin createSpecialPlugin() {
133 return new ShipRecoverySpecial();
134 }
135 }
136
137 protected ShipRecoverySpecialData data;
138
139 public static ShipRecoverySpecialData getSpecialData(SectorEntityToken entity, String desc, boolean create, boolean replace) {
140 Object o = Misc.getSalvageSpecial(entity);
141 ShipRecoverySpecialData data = null;
142 if (o instanceof ShipRecoverySpecialData) {
143 data = (ShipRecoverySpecialData) o;
144 }
145
146 if (data == null && !create) return null;
147 if (o != null && data == null && !replace) return null;
148
149 if (data == null) {
150 data = new ShipRecoverySpecialData(desc);
151 Misc.setSalvageSpecial(entity, data);
152 }
153
154 return data;
155 }
156
158 }
159
160
161 @Override
162 public void init(InteractionDialogAPI dialog, Object specialData) {
163 super.init(dialog, specialData);
164
165 data = (ShipRecoverySpecialData) specialData;
166
167// int max = Global.getSettings().getMaxShipsInFleet() - Global.getSector().getPlayerFleet().getFleetData().getMembersListCopy().size();
168// while (data.ships.size() > max && !data.ships.isEmpty()) {
169// data.ships.remove(0);
170// }
171
172 if (data.ships.isEmpty()) {
173 initNothing();
174 } else {
175 init();
176 }
177 }
178
179 protected List<FleetMemberAPI> members = new ArrayList<FleetMemberAPI>();
180 protected List<FleetMemberAPI> recovered = new ArrayList<FleetMemberAPI>();
181 protected void init() {
182 members.clear();
183
184 for (PerShipData curr : data.ships) {
185 addMember(curr);
186 }
187
188 if (members.isEmpty()) {
189 initNothing();
190 return;
191 }
192
193 CampaignFleetAPI recoverable = Global.getFactory().createEmptyFleet(Factions.NEUTRAL, FleetTypes.PATROL_SMALL, true);
194 for (FleetMemberAPI member : members) {
195 recoverable.getFleetData().addFleetMember(member);
196 }
197
198 if (recoverable.getFleetData().getMembersListCopy().size() == 1) {
199 visual.showFleetMemberInfo(recoverable.getFleetData().getMembersListCopy().get(0), true);
200 } else {
201 visual.showFleetInfo("Your fleet", playerFleet, "Recoverable ships", recoverable, null, true);
202 }
203
205
206 if (isStoryPointRecovery()) {
208 } else {
209 options.clearOptions();
210 options.addOption("Consider ship recovery", RECOVER);
211
212 if (data.notNowOptionExits != null && data.notNowOptionExits) {
213 options.addOption("Leave", NOT_NOW);
214 options.setShortcut(NOT_NOW, Keyboard.KEY_ESCAPE, false, false, false, true);
215 } else {
216 options.addOption("Not now", NOT_NOW);
217 }
218 }
219 }
220
221
222 protected void addStoryOptions() {
223 options.clearOptions();
224 options.addOption("Take a look at the chief engineer's report and make a decision", RECOVER);
225 options.addOption("\"I'll need to consider my options.\"", NOT_NOW);
226 dialog.setOptionColor(RECOVER, Misc.getStoryOptionColor());
227 }
228
229 protected boolean isStoryPointRecovery() {
230 return data != null && data.storyPointRecovery != null && data.storyPointRecovery;
231 }
232
233
234 protected void addInitialText() {
235
236 if (data.noDescriptionText != null && data.noDescriptionText) {
237 return;
238 }
239
240 boolean debris = Entities.DEBRIS_FIELD_SHARED.equals(entity.getCustomEntityType());
241 boolean wreck = Entities.WRECK.equals(entity.getCustomEntityType());
242 wreck |= entity.hasTag(Tags.WRECK);
243 //boolean dock = Entities.WRECK.equals(entity.getCustomEntityType());
244
245 boolean withDesc = !debris && !wreck;
246
247 if (isStoryPointRecovery()) {
248 addText("Some time later, you hear back from your chief engineer, " +
249 "who mumbles about being a miracle worker to someone offscreen before " +
250 "noticing you've picked up the call.");
251 if (members.size() == 1) {
252 addText("\"Commander, looks like we might be able to pull this off, though I'll say you're not going to " +
253 "find what I'm going to do in any manual. And it wouldn't pass any inspection, but then again " +
254 "we're not in the Hegemony fleet. It'll fly, though.");
255 } else {
256 addText("\"Commander, looks like we might be able to pull this off, though I'll say you're not going to " +
257 "find what I'm going to do in any manual. And it wouldn't pass any inspection, but then again " +
258 "we're not in the Hegemony fleet. These ships can be made to fly again, though.");
259 }
260 return;
261 }
262
263//
264//
265//
266
267 String ships = "several ships";
268 String they = "they";
269 if (members.size() == 1) {
270 ships = "a ship";
271 they = "it";
272 }
273
274 if (wreck) {
275 if (data.storyPointRecovery != null && data.storyPointRecovery) {
276 addText("A crack engineering team sent to the wreck reports successfully preparing it " +
277 "for recovery.");
278 } else {
279 if (!FireBest.fire(null, dialog, memoryMap, "ShipRecoveryCustomText")) {
280 addText("Salvage crews boarding the wreck discover that many essential systems " +
281 "are undamaged and the ship could be restored to basic functionality.");
282
283 ExtraSalvage es = BaseSalvageSpecial.getExtraSalvage(entity);
284 if (es != null && !es.cargo.isEmpty()) {
285 addText("There are also indications that it has some sort of cargo on board.");
286 }
287 }
288 }
289 } else if (debris) {
290 addText("Close-range scans of the debris field reveal " + ships +
291 " that could be restored to basic functionality.");
292 } else if (withDesc) {
293 String desc = data.desc;
294 if (desc == null) desc = "floating near";
295 //desc = "docked with";
296
297 if (entity instanceof PlanetAPI) {
298 addText("Salvage crews report " + ships + " " + desc + ". " +
299 "Closer inspection reveals " + they + " could be restored to basic functionality.");
300 } else {
301 addText("Salvage crews report " + ships + " " + desc + " the $shortName. " +
302 "Closer inspection reveals " + they + " could be restored to basic functionality.");
303 }
304 }
305
306 if (members.size() == 1) {
307 if (members.size() > 0 && Misc.getCurrSpecialMods(members.get(0).getVariant()) > 0) {
308 text.addPara("The crew chief also reports that the hull has undergone %s, which appear to have " +
309 "survived its present state.",
310 Misc.getStoryOptionColor(), "special modifications");
311 }
312// if (wreck) {
313// addText("");
314// } else {
315 addText("If not recovered, the ship will be scuttled, " +
316 "and any fitted weapons and fighter LPCs will be retrieved.");
317// }
318 } else {
319 addText("Any ships that aren't recovered will be scuttled, " +
320 "and any fitted weapons and fighter LPCs will be retrieved.");
321 }
322 }
323
324 protected FleetMemberAPI first = null;
325 protected void addMember(PerShipData shipData) {
326 if (shipData.variant == null && shipData.variantId == null) {
327 return;
328 }
329
330 FleetMemberAPI member = null;
331 if (shipData.variantId != null) {
332 member = Global.getFactory().createFleetMember(FleetMemberType.SHIP, shipData.variantId);
333 } else {
334 member = Global.getFactory().createFleetMember(FleetMemberType.SHIP, shipData.variant);
335 }
336
337 //if (member.getHullSpec().getHints().contains(ShipTypeHints.UNBOARDABLE)) {
338 if (Misc.isUnboardable(member)) {
339 return;
340 }
341
342 members.add(member);
343
344 if (first == null) first = member;
345
346 member.setOwner(1);
347 if (shipData.fleetMemberId != null) {
348 member.setId(shipData.fleetMemberId);
349 }
350
351 if (isNameKnown(shipData.condition) || (shipData.nameAlwaysKnown != null && shipData.nameAlwaysKnown)) {
352 member.setShipName(shipData.shipName);
353 } else {
354 member.setShipName("<name unknown>");
355 }
356
357 prepareMember(member, shipData);
358 }
359
360 public static boolean isNameKnown(ShipCondition condition) {
361 return condition == ShipCondition.PRISTINE || condition == ShipCondition.GOOD;
362 }
363
364 public void prepareMember(FleetMemberAPI member, PerShipData shipData) {
365
366 int hits = getHitsForCondition(member, shipData.condition);
367 int dmods = getDmodsForCondition(shipData.condition);
368
369 int reduction = (int) playerFleet.getStats().getDynamic().getValue(Stats.SHIP_DMOD_REDUCTION, 0);
370 reduction = random.nextInt(reduction + 1);
371 dmods -= reduction;
372
373
374 member.getStatus().setRandom(random);
375
376 for (int i = 0; i < hits; i++) {
377 member.getStatus().applyDamage(1000000f);
378 }
379
380 member.getStatus().setHullFraction(getHullForCondition(shipData.condition));
381 member.getRepairTracker().setCR(0f);
382
383
384 ShipVariantAPI variant = member.getVariant();
385 variant = variant.clone();
386 variant.setOriginalVariant(null);
387
388 int dModsAlready = DModManager.getNumDMods(variant);
389 dmods = Math.max(0, dmods - dModsAlready);
390
391 if (dmods > 0 && shipData.addDmods) {
392 DModManager.setDHull(variant);
393 }
394 member.setVariant(variant, false, true);
395
396 if (dmods > 0 && shipData.addDmods) {
397 DModManager.addDMods(member, true, dmods, random);
398 }
399
400 if (shipData.sModProb > 0 && random.nextFloat() < shipData.sModProb) {
401 int num = 1;
402 float r = random.nextFloat();
403 if (r > 0.85f) {
404 num = 3;
405 } else if (r > 0.5f) {
406 num = 2;
407 }
408
409 WeightedRandomPicker<String> picker = new WeightedRandomPicker<String>(random);
410 for (String id : variant.getHullMods()) {
411 HullModSpecAPI spec = Global.getSettings().getHullModSpec(id);
412 if (spec.isHidden()) continue;
413 if (spec.isHiddenEverywhere()) continue;
414 if (spec.hasTag(Tags.HULLMOD_DMOD)) continue;
415 if (spec.hasTag(Tags.HULLMOD_NO_BUILD_IN)) continue;
416 if (variant.getPermaMods().contains(spec.getId())) continue;
417 picker.add(id, spec.getCapitalCost());
418 }
419 for (int i = 0; i < num && !picker.isEmpty(); i++) {
420 String id = picker.pickAndRemove();
421 variant.addPermaMod(id, true);
422 //variant.getPermaMods().add(id);
423 }
424 }
425
426
427 if (shipData.pruneWeapons) {
428 float retain = getFighterWeaponRetainProb(shipData.condition);
429 FleetEncounterContext.prepareShipForRecovery(member, false, false, false, retain, retain, random);
430 member.getVariant().autoGenerateWeaponGroups();
431 }
432 }
433
434
435 protected float getHullForCondition(ShipCondition condition) {
436 switch (condition) {
437 case PRISTINE: return 1f;
438 case GOOD: return 0.6f + random.nextFloat() * 0.2f;
439 case AVERAGE: return 0.4f + random.nextFloat() * 0.2f;
440 case BATTERED: return 0.2f + random.nextFloat() * 0.2f;
441 case WRECKED: return random.nextFloat() * 0.1f;
442 }
443 return 1;
444 }
445
446
447 protected int getDmodsForCondition(ShipCondition condition) {
448 if (condition == ShipCondition.PRISTINE) return 0;
449
450 switch (condition) {
451 case GOOD: return 1;
452 case AVERAGE: return 1 + random.nextInt(2);
453 case BATTERED: return 2 + random.nextInt(2);
454 case WRECKED: return 3 + random.nextInt(2);
455 }
456 return 1;
457 }
458
459 protected float getFighterWeaponRetainProb(ShipCondition condition) {
460 switch (condition) {
461 case PRISTINE: return 1f;
462 case GOOD: return 0.67f;
463 case AVERAGE: return 0.5f;
464 case BATTERED: return 0.33f;
465 case WRECKED: return 0.2f;
466 }
467 return 0f;
468 }
469
470 protected int getHitsForCondition(FleetMemberAPI member, ShipCondition condition) {
471 if (condition == ShipCondition.PRISTINE) return 0;
472 if (condition == ShipCondition.WRECKED) return 20;
473
474 switch (member.getHullSpec().getHullSize()) {
475 case CAPITAL_SHIP:
476 switch (condition) {
477 case GOOD: return 2 + random.nextInt(2);
478 case AVERAGE: return 4 + random.nextInt(3);
479 case BATTERED: return 7 + random.nextInt(6);
480 }
481 break;
482 case CRUISER:
483 switch (condition) {
484 case GOOD: return 1 + random.nextInt(2);
485 case AVERAGE: return 2 + random.nextInt(3);
486 case BATTERED: return 4 + random.nextInt(4);
487 }
488 break;
489 case DESTROYER:
490 switch (condition) {
491 case GOOD: return 1 + random.nextInt(2);
492 case AVERAGE: return 2 + random.nextInt(2);
493 case BATTERED: return 3 + random.nextInt(3);
494 }
495 break;
496 case FRIGATE:
497 switch (condition) {
498 case GOOD: return 1;
499 case AVERAGE: return 2;
500 case BATTERED: return 3;
501 }
502 break;
503 }
504 return 1;
505 }
506
507
508// public void doRecovery() {
509// for (FleetMemberAPI member : new ArrayList<FleetMemberAPI>(members)) {
510// int index = members.indexOf(member);
511// if (index >= 0) {
512// PerShipData shipData = data.ships.get(index);
513// data.ships.remove(index);
514// members.remove(index);
515//
516//
517// member.setShipName(shipData.shipName);
518//
519// float minHull = playerFleet.getStats().getDynamic().getValue(Stats.RECOVERED_HULL_MIN, 0f);
520// float maxHull = playerFleet.getStats().getDynamic().getValue(Stats.RECOVERED_HULL_MAX, 0f);
521// float minCR = playerFleet.getStats().getDynamic().getValue(Stats.RECOVERED_CR_MIN, 0f);
522// float maxCR = playerFleet.getStats().getDynamic().getValue(Stats.RECOVERED_CR_MAX, 0f);
523//
524// float hull = (float) Math.random() * (maxHull - minHull) + minHull;
525// hull = Math.max(hull, member.getStatus().getHullFraction());
526// member.getStatus().setHullFraction(hull);
527//
528// float cr = (float) Math.random() * (maxCR - minCR) + minCR;
529// member.getRepairTracker().setCR(cr);
530//
531// playerFleet.getFleetData().addFleetMember(member);
532// }
533// }
534// optionSelected(null, RECOVERY_FINISHED);
535// }
536
537 @Override
538 public void optionSelected(String optionText, Object optionData) {
539 if (RECOVER.equals(optionData)) {
540
541 if (isStoryPointRecovery()) {
543 } else {
544 options.clearOptions();
545 options.addOption("Consider ship recovery", RECOVER);
546 if (data.notNowOptionExits != null && data.notNowOptionExits) {
547 options.addOption("Leave", NOT_NOW);
548 options.setShortcut(NOT_NOW, Keyboard.KEY_ESCAPE, false, false, false, true);
549 } else {
550 options.addOption("Not now", NOT_NOW);
551 }
552 }
553
554 List<FleetMemberAPI> pool = members;
555 List<FleetMemberAPI> storyPool = new ArrayList<FleetMemberAPI>();
556 if (isStoryPointRecovery()) {
557 pool = storyPool;
558 storyPool = members;
559 }
560
561 dialog.showFleetMemberRecoveryDialog("Select ships to recover", pool, storyPool,
562 new FleetMemberPickerListener() {
563 public void pickedFleetMembers(List<FleetMemberAPI> selected) {
564 if (selected.isEmpty()) return;
565
566 new ShowDefaultVisual().execute(null, dialog, Misc.tokenize(""), memoryMap);
567
568 for (FleetMemberAPI member : selected) {
569 int index = members.indexOf(member);
570 if (index >= 0) {
571 PerShipData shipData = data.ships.get(index);
572 data.ships.remove(index);
573 members.remove(index);
574
575
576 member.setShipName(shipData.shipName);
577 if (shipData.fleetMemberId != null) {
578 member.setId(shipData.fleetMemberId);
579 }
580
581 float minHull = playerFleet.getStats().getDynamic().getValue(Stats.RECOVERED_HULL_MIN, 0f);
582 float maxHull = playerFleet.getStats().getDynamic().getValue(Stats.RECOVERED_HULL_MAX, 0f);
583 float minCR = playerFleet.getStats().getDynamic().getValue(Stats.RECOVERED_CR_MIN, 0f);
584 float maxCR = playerFleet.getStats().getDynamic().getValue(Stats.RECOVERED_CR_MAX, 0f);
585
586 float hull = (float) Math.random() * (maxHull - minHull) + minHull;
587 hull = Math.max(hull, member.getStatus().getHullFraction());
588 member.getStatus().setHullFraction(hull);
589
590 float cr = (float) Math.random() * (maxCR - minCR) + minCR;
591 member.getRepairTracker().setCR(cr);
592
593 playerFleet.getFleetData().addFleetMember(member);
594 recovered.add(member);
595 }
596 }
597
598// setExtraSalvageFromUnrecoveredShips();
599// setDone(true);
600// setShowAgain(!data.ships.isEmpty());
601 if (dialog.getPlugin() instanceof SalvageSpecialDialogPlugin) {
602 SalvageSpecialDialogPlugin plugin = (SalvageSpecialDialogPlugin) dialog.getPlugin();
603 plugin.optionSelected(null, RECOVERY_FINISHED);
604 } else {
605 // bad state, exit dialog
606 // apparently possible? maybe mods involved
607 // http://fractalsoftworks.com/forum/index.php?topic=12492.0
608 dialog.dismiss();
609 }
610 }
611 public void cancelledFleetMemberPicking() {
612 }
613 });
614
615 } else if (NOT_NOW.equals(optionData)) {
616 if (data.notNowOptionExits != null && data.notNowOptionExits) {
617// setDone(true);
618// setShowAgain(true);
619// setEndWithContinue(false);
620 dialog.dismiss();
621 } else {
622 if (isStoryPointRecovery()) {
623 //Misc.setSalvageSpecial(entity, null);
624 Misc.setSalvageSpecial(entity, Misc.getPrevSalvageSpecial(entity));
625 }
626
627 new ShowDefaultVisual().execute(null, dialog, Misc.tokenize(""), memoryMap);
628
629 // only get extra salvage when it's not story-point recovery
630 // since unless the story point is spent and the ship is recovered
631 // it's not in a "recoverable" state an should grant no bonus stuff when salvaged
632 if (!isStoryPointRecovery()) {
634 }
635 setDone(true);
636 setEndWithContinue(false);
637 setShowAgain(true);
638 }
639 } else if (RECOVERY_FINISHED.equals(optionData)) {
640 new ShowDefaultVisual().execute(null, dialog, Misc.tokenize(""), memoryMap);
641
642 boolean wreck = Entities.WRECK.equals(entity.getCustomEntityType());
643 wreck |= entity.hasTag(Tags.WRECK);
644
645 if (wreck) {
646 //ExtraSalvage es = BaseSalvageSpecial.getExtraSalvage(entity);
647 //if (es != null && !es.cargo.isEmpty()) {
649 if (extra != null && !extra.isEmpty()) {
650 addText("Your crews find some securely stowed cargo during the recovery operation.");
651
652 extra.sort();
653 playerFleet.getCargo().addAll(extra);
654
655
656 for (CargoStackAPI stack : extra.getStacksCopy()) {
658 }
660
661 ListenerUtil.reportSpecialCargoGainedFromRecoveredDerelict(extra, dialog);
662 //addText("The recovery operation is finished without any further surprises.");
663 }
664
665 addText("The " + first.getShipName() + " is now part of your fleet.");
666
668 options.clearOptions();
669 options.addOption("Leave", ABORT_CONTINUE);
670 options.setShortcut(ABORT_CONTINUE, Keyboard.KEY_ESCAPE, false, false, false, true);
671
672 ListenerUtil.reportShipsRecovered(recovered, dialog);
673
674 for (FleetMemberAPI member : recovered) {
675 dialog.getInteractionTarget().getMemoryWithoutUpdate().set("$srs_memberId", member.getId(), 0);
676 dialog.getInteractionTarget().getMemoryWithoutUpdate().set("$srs_hullId", member.getHullId(), 0);
677 dialog.getInteractionTarget().getMemoryWithoutUpdate().set("$srs_baseHullId", member.getHullSpec().getBaseHullId(), 0);
678 FireAll.fire(null, dialog, memoryMap, "PostShipRecoverySpecial");
679 }
680
681 } else {
683 setEndWithContinue(false);
684 setDone(true);
685 setShowAgain(!data.ships.isEmpty());
686
687// setExtraSalvageFromUnrecoveredShips();
688// setDone(true);
689// setEndWithContinue(false);
690// setShowAgain(true);
691 }
692 } else if (ABORT_CONTINUE.equals(optionData)) {
693 setDone(true);
694 setEndWithContinue(false);
695 }
696 }
697
699 if (members.isEmpty()) return;
700
701 CargoAPI extra = Global.getFactory().createCargo(true);
702 for (FleetMemberAPI member : members) {
703 addStuffFromMember(extra, member);
704 }
705 addTempExtraSalvage(extra);
706 }
707
708 protected void addStuffFromMember(CargoAPI cargo, FleetMemberAPI member) {
709 cargo.addCommodity(Commodities.SUPPLIES, member.getRepairTracker().getSuppliesFromScuttling());
710 cargo.addCommodity(Commodities.FUEL, member.getRepairTracker().getFuelFromScuttling());
711 cargo.addCommodity(Commodities.HEAVY_MACHINERY, member.getRepairTracker().getHeavyMachineryFromScuttling());
712
713 ShipVariantAPI variant = member.getVariant();
714 for (String slotId : variant.getNonBuiltInWeaponSlots()) {
715 cargo.addWeapons(variant.getWeaponId(slotId), 1);
716 }
717
718 int index = 0;
719 for (String wingId : variant.getWings()) {
720 if (wingId != null && !wingId.isEmpty() && !variant.getHullSpec().isBuiltInWing(index)) {
721 cargo.addFighters(wingId, 1);
722 }
723 index++;
724 }
725 }
726
727
728}
729
730
731
732
733
static SettingsAPI getSettings()
Definition Global.java:51
static FactoryAPI getFactory()
Definition Global.java:35
static SectorAPI getSector()
Definition Global.java:59
static void addDMods(FleetMemberData data, boolean own, CampaignFleetAPI recoverer, Random random)
static boolean setDHull(ShipVariantAPI variant)
static int getNumDMods(ShipVariantAPI variant)
static void prepareShipForRecovery(FleetMemberAPI member, boolean retainAllHullmods, boolean retainKnownHullmods, boolean clearSMods, float weaponRetainProb, float wingRetainProb, Random salvageRandom)
static void addStackGainText(CargoStackAPI stack, TextPanelAPI text)
static boolean fire(String ruleId, InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap, String params)
Definition FireAll.java:55
static boolean fire(String ruleId, InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap, String params)
Definition FireBest.java:56
boolean execute(String ruleId, InteractionDialogAPI dialog, List< Token > params, Map< String, MemoryAPI > memoryMap)
static CargoAPI getCombinedExtraSalvage(Map< String, MemoryAPI > memoryMap)
void setShouldAbortSalvageAndRemoveEntity(boolean shouldAbortSalvageAndRemoveEntity)
static ShipRecoverySpecialData getSpecialData(SectorEntityToken entity, String desc, boolean create, boolean replace)
CargoAPI createCargo(boolean unlimitedStacks)
CampaignFleetAPI createEmptyFleet(String factionId, String name, boolean aiMode)
FleetMemberAPI createFleetMember(FleetMemberType type, String variantOrWingId)
HullModSpecAPI getHullModSpec(String modId)