Starsector API
Loading...
Searching...
No Matches
PlayerFleetGenPluginImpl.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.procgen;
2
3import java.awt.Color;
4import java.util.ArrayList;
5import java.util.LinkedHashSet;
6import java.util.List;
7import java.util.Map;
8import java.util.Random;
9import java.util.Set;
10
11import com.fs.starfarer.api.Global;
12import com.fs.starfarer.api.campaign.BaseCustomProductionPickerDelegateImpl;
13import com.fs.starfarer.api.campaign.CampaignFleetAPI;
14import com.fs.starfarer.api.campaign.CargoAPI;
15import com.fs.starfarer.api.campaign.FactionAPI;
16import com.fs.starfarer.api.campaign.FactionAPI.ShipPickMode;
17import com.fs.starfarer.api.campaign.FactionProductionAPI;
18import com.fs.starfarer.api.campaign.FactionProductionAPI.ItemInProductionAPI;
19import com.fs.starfarer.api.campaign.FactionProductionAPI.ProductionItemType;
20import com.fs.starfarer.api.campaign.FleetInflater;
21import com.fs.starfarer.api.campaign.InteractionDialogAPI;
22import com.fs.starfarer.api.campaign.InteractionDialogPlugin;
23import com.fs.starfarer.api.campaign.OptionPanelAPI;
24import com.fs.starfarer.api.campaign.TextPanelAPI;
25import com.fs.starfarer.api.campaign.VisualPanelAPI;
26import com.fs.starfarer.api.campaign.econ.MarketAPI;
27import com.fs.starfarer.api.campaign.rules.MemoryAPI;
28import com.fs.starfarer.api.characters.MutableCharacterStatsAPI.SkillLevelAPI;
29import com.fs.starfarer.api.characters.OfficerDataAPI;
30import com.fs.starfarer.api.characters.PersonAPI;
31import com.fs.starfarer.api.combat.EngagementResultAPI;
32import com.fs.starfarer.api.combat.ShipAPI.HullSize;
33import com.fs.starfarer.api.combat.ShipHullSpecAPI;
34import com.fs.starfarer.api.combat.ShipHullSpecAPI.ShipTypeHints;
35import com.fs.starfarer.api.combat.WeaponAPI.AIHints;
36import com.fs.starfarer.api.fleet.FleetMemberAPI;
37import com.fs.starfarer.api.impl.campaign.fleets.DefaultFleetInflaterParams;
38import com.fs.starfarer.api.impl.campaign.fleets.FleetFactoryV3;
39import com.fs.starfarer.api.impl.campaign.fleets.FleetParamsV3;
40import com.fs.starfarer.api.impl.campaign.ids.Factions;
41import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
42import com.fs.starfarer.api.impl.campaign.ids.Tags;
43import com.fs.starfarer.api.loading.FighterWingSpecAPI;
44import com.fs.starfarer.api.loading.HullModSpecAPI;
45import com.fs.starfarer.api.loading.WeaponSpecAPI;
46import com.fs.starfarer.api.plugins.OfficerLevelupPlugin;
47import com.fs.starfarer.api.util.Misc;
48
50
51 protected static enum FleetQuality {
52 MAX_DMODS,
53 NO_DMODS,
54 ONE_SMOD,
55 TWO_SMODS,
56 THREE_SMODS,
57 }
58
59 protected static enum OptionId {
60 INIT,
61 SELECT_SHIPS,
62 ADD_UNSELECTED_OFFICERS,
63 OFFICER_LEVEL_5,
64 OFFICER_LEVEL_6,
65 OFFICER_LEVEL_7,
66 OFFICERS_GO_BACK,
67
68 QUALITY_MAX_DMODS,
69 QUALITY_NO_DMODS,
70 QUALITY_1_SMODS,
71 QUALITY_2_SMODS,
72 QUALITY_2_SMODS_OMEGA,
73 QUALITY_3_SMODS,
74 QUALITY_3_SMODS_OMEGA,
75
76// SMODS_OFFICER_SHIPS_ONLY,
77// SMODS_ALL_SHIPS,
78// NORMAL_LEVEL_OFFICERS,
79// HIGH_LEVEL_OFFICERS,
80
81 ADD_OFFICERS,
82 ADD_OFFICERS_NO_SKILLS,
83 NO_OFFICERS,
84
85 CREATE_REPLACE,
86 CREATE_ADD,
87
88 LEAVE,
89 }
90
91
92 public static class FleetGenData {
93 public FactionProductionAPI prod;
94 public FleetQuality quality;
95 public boolean smodsOnAllShips = true;
96 public boolean allowOmega = false;
97 //public boolean eliteOfficers = false;
98 public boolean addOfficers = false;
99 public boolean keepOfficerPointsFree = false;
100 public boolean append = false;
101
102
103 public FleetGenData() {
105 prod.clear();
106 }
107 }
108
109
114
115 protected FleetGenData data = new FleetGenData();
117
118 protected Set<String> ships = new LinkedHashSet<String>();
119 protected Set<String> fighters = new LinkedHashSet<String>();
120 protected Set<String> weapons = new LinkedHashSet<String>();
121 protected Set<String> unrestrictedFighters = new LinkedHashSet<String>();
122 protected Set<String> unrestrictedWeapons = new LinkedHashSet<String>();
123 protected Set<String> hullmods = new LinkedHashSet<String>();
124
125 protected static final Color HIGHLIGHT_COLOR = Global.getSettings().getColor("buttonShortcut");
126
128 this.dialog = dialog;
129
130
134
136
137 visual.setVisualFade(0.25f, 0.25f);
138
140
141 dialog.setOptionOnEscape("Leave", OptionId.LEAVE);
142 optionSelected(null, OptionId.INIT);
143 }
144
145 public Map<String, MemoryAPI> getMemoryMap() {
146 return null;
147 }
148
150 // no combat here, so this won't get called
151 }
152
153
154 public void optionSelected(String text, Object optionData) {
155 if (optionData == null) return;
156
157 OptionId option = (OptionId) optionData;
158
159 if (text != null) {
160 //textPanel.addParagraph(text, Global.getSettings().getColor("buttonText"));
162 //textPanel.addParagraph("");
163 }
164
165 switch (option) {
166 case INIT:
168 break;
169 case SELECT_SHIPS:
171 break;
172 case ADD_UNSELECTED_OFFICERS:
174 break;
175 case OFFICERS_GO_BACK:
177 break;
178 case OFFICER_LEVEL_5:
180 break;
181 case OFFICER_LEVEL_6:
183 break;
184 case OFFICER_LEVEL_7:
186 break;
187 case QUALITY_MAX_DMODS:
188 data.quality = FleetQuality.MAX_DMODS;
190 break;
191 case QUALITY_NO_DMODS:
192 data.quality = FleetQuality.NO_DMODS;
194 break;
195 case QUALITY_1_SMODS:
196 data.quality = FleetQuality.ONE_SMOD;
198 break;
199 case QUALITY_2_SMODS:
200 data.quality = FleetQuality.TWO_SMODS;
202 break;
203 case QUALITY_2_SMODS_OMEGA:
204 data.quality = FleetQuality.TWO_SMODS;
205 data.allowOmega = true;
207 break;
208 case QUALITY_3_SMODS:
209 data.quality = FleetQuality.THREE_SMODS;
211 break;
212 case QUALITY_3_SMODS_OMEGA:
213 data.quality = FleetQuality.THREE_SMODS;
214 data.allowOmega = true;
216 break;
217 case NO_OFFICERS:
218 data.addOfficers = false;
220 break;
221 case ADD_OFFICERS:
222 data.addOfficers = true;
224 break;
225 case ADD_OFFICERS_NO_SKILLS:
226 data.addOfficers = true;
227 data.keepOfficerPointsFree = true;
229 break;
230// case NORMAL_LEVEL_OFFICERS:
231// data.eliteOfficers = false;
232// selectAppendOrReplace();
233// break;
234// case HIGH_LEVEL_OFFICERS:
235// data.eliteOfficers = true;
236// selectAppendOrReplace();
237// break;
238 case CREATE_ADD:
239 data.append = true;
240 createFleet();
241 dialog.dismiss();
242 break;
243 case CREATE_REPLACE:
244 data.append = false;
245 createFleet();
246 dialog.dismiss();
247 break;
248 case LEAVE:
249 dialog.dismiss();
250 break;
251 default:
252 break;
253 }
254 }
255
256 protected MarketAPI getNearestMarket(boolean playerOnly) {
257 MarketAPI nearest = null;
258 float minDist = Float.MAX_VALUE;
261 if (curr.isHidden()) continue;
262 if (playerOnly && !curr.isPlayerOwned()) continue;
263
264 float dist = Misc.getDistanceLY(pf, curr.getPrimaryEntity());
265 boolean nearer = dist < minDist;
266 if (dist == minDist && dist == 0 && nearest != null) {
267 float d1 = Misc.getDistance(pf, curr.getPrimaryEntity());
268 float d2 = Misc.getDistance(pf, nearest.getPrimaryEntity());
269 nearer = d1 < d2;
270 }
271 if (nearer) {
272 nearest = curr;
273 minDist = dist;
274 }
275 }
276 return nearest;
277 }
278
279 protected void print(String str) {
281 System.out.println(str);
282 }
283
284 protected void selectShipsAndWeapons() {
285 textPanel.addPara("--- QUICK PLAYER FLEET CREATOR ---");
286 textPanel.addPara("Ship variants will be randomly picked from those available for a given hull.");
287 textPanel.addPara("Selected weapons and fighters will be added to your cargo.");
288
290 options.addOption("Select ships and weapons", OptionId.SELECT_SHIPS);
291 options.addOption("Add officers with unselected skills", OptionId.ADD_UNSELECTED_OFFICERS);
292 options.addOption("Leave", OptionId.LEAVE, null);
293 }
294
295 protected void showOfficerSelector() {
296 textPanel.addPara("Select option to instantly add an officer of that level with all unspent skills. The officer "
297 + "level will be 1 higher than selected and they will not have an initial skill.");
299 options.addOption("Level 5", OptionId.OFFICER_LEVEL_5);
300 options.addOption("Level 6", OptionId.OFFICER_LEVEL_6);
301 options.addOption("Level 7", OptionId.OFFICER_LEVEL_7);
302 options.addOption("Go back", OptionId.OFFICERS_GO_BACK);
303 }
304
305 protected void selectQuality() {
306 textPanel.addPara("Select ship quality.");
308 options.addOption("Maximum number of d-mods", OptionId.QUALITY_MAX_DMODS);
309 options.addOption("No d-mods", OptionId.QUALITY_NO_DMODS);
310 options.addOption("Average of 1 s-mod", OptionId.QUALITY_1_SMODS);
311 options.addOption("Average of 2 s-mods", OptionId.QUALITY_2_SMODS);
312 options.addOption("Average of 2 s-mods; allow some Omega weapons to be mounted", OptionId.QUALITY_2_SMODS_OMEGA);
313 options.addOption("Average of 3 s-mods", OptionId.QUALITY_3_SMODS);
314 options.addOption("Average of 3 s-mods; allow some Omega weapons to be mounted", OptionId.QUALITY_3_SMODS_OMEGA);
315 options.addOption("Leave", OptionId.LEAVE, null);
316 }
317
318 protected void selectOfficerLevel() {
319 textPanel.addPara("The total number of officers and their level and elite skills will be based on your character's skills.");
321 options.addOption("Add officers (number / level / elite skills based on your character's skills)", OptionId.ADD_OFFICERS);
322 //options.addOption("Add officers, but do not spend their skill points", OptionId.ADD_OFFICERS_NO_SKILLS);
323 options.addOption("Do not add officers", OptionId.NO_OFFICERS);
324 options.addOption("Leave", OptionId.LEAVE, null);
325 }
326
327 protected void selectAppendOrReplace() {
328 textPanel.addPara("Select fleet creation mode.");
330 options.addOption("Replace current fleet with new ships", OptionId.CREATE_REPLACE);
331 options.addOption("Add new ships to current fleet", OptionId.CREATE_ADD);
332 options.addOption("Leave", OptionId.LEAVE, null);
333 }
334
335 protected OptionId lastOptionMousedOver = null;
336 public void optionMousedOver(String optionText, Object optionData) {
337
338 }
339
340 public void advance(float amount) {
341
342 }
343
344 public Object getContext() {
345 return null;
346 }
347
348 public void showBlueprintPicker() {
350 @Override
351 public Set<String> getAvailableFighters() {
352 return fighters;
353 }
354 @Override
355 public Set<String> getAvailableShipHulls() {
356 return ships;
357 }
358 @Override
359 public Set<String> getAvailableWeapons() {
360 return weapons;
361 }
362 @Override
363 public float getCostMult() {
364 return 0.001f;
365 }
366 @Override
367 public float getMaximumValue() {
368 return 1000000;
369 }
370 public boolean withQuantityLimits() {
371 return false;
372 }
373 @Override
374 public void notifyProductionSelected(FactionProductionAPI production) {
375 //convertProdToCargo(production);
376 data.prod = production;
378 }
379 });
380 }
381
382 protected void createFleet() {
383
384 FactionProductionAPI prod = data.prod;
385 CargoAPI cargo = Global.getFactory().createCargo(true);
386
387
388 Random random = Misc.random;
389
390 float quality = 2f;
391 if (data.quality == FleetQuality.MAX_DMODS) {
392 quality = -2f;
393 }
394
396 ships.setCommander(Global.getSector().getPlayerPerson());
398 p.quality = quality;
399 p.mode = ShipPickMode.PRIORITY_THEN_ALL;
400 p.persistent = false;
401 p.seed = random.nextLong();
402 p.timestamp = null;
403 p.rProb = 0f;
404 p.allWeapons = true;
405
406 if (data.quality == FleetQuality.ONE_SMOD) {
407 p.averageSMods = 1;
408 } else if (data.quality == FleetQuality.TWO_SMODS) {
409 p.averageSMods = 2;
410 } else if (data.quality == FleetQuality.THREE_SMODS) {
411 p.averageSMods = 3;
412 }
413
414 FleetInflater inflater = Misc.getInflater(ships, p);
415 ships.setInflater(inflater);
416
417 for (ItemInProductionAPI pick : prod.getCurrent()) {
418 int count = pick.getQuantity();
419
420 if (pick.getType() == ProductionItemType.SHIP) {
421 List<String> variants = Global.getSettings().getHullIdToVariantListMap().get(pick.getSpecId());
422 if (variants.isEmpty()) {
423 variants.add(pick.getSpecId() + "_Hull");
424 }
425
426 for (int i = 0; i < count; i++) {
427 int index = random.nextInt(variants.size());
428 ships.getFleetData().addFleetMember(variants.get(index));
429 }
430 } else if (pick.getType() == ProductionItemType.FIGHTER) {
431 cargo.addFighters(pick.getSpecId(), count);
432 } else if (pick.getType() == ProductionItemType.WEAPON) {
433 cargo.addWeapons(pick.getSpecId(), count);
434 }
435 prod.removeItem(pick.getType(), pick.getSpecId(), count);
436 }
437
439 List<String> addedWeapons = new ArrayList<String>();
440 List<String> addedFighters = new ArrayList<String>();
441 List<String> addedHullmods = new ArrayList<String>();
442
443 if (data.allowOmega) {
444 for (String id : weapons) {
445 if (unrestrictedWeapons.contains(id)) continue;
447 if (spec.hasTag(Tags.OMEGA)) {
448 unrestrictedWeapons.add(id);
449 }
450 }
451 }
452
453 for (String id : unrestrictedWeapons) {
454 if (!pf.knowsWeapon(id)) {
455 addedWeapons.add(id);
456 pf.addKnownWeapon(id, false);
457 }
458 }
459 for (String id : unrestrictedFighters) {
460 if (!pf.knowsFighter(id)) {
461 addedFighters.add(id);
462 pf.addKnownFighter(id, false);
463 }
464 }
465 for (String id : hullmods) {
466 if (!pf.knowsHullMod(id)) {
467 addedHullmods.add(id);
468 pf.addKnownHullMod(id);
469 }
470 }
471
472 ships.inflateIfNeeded();
473
474 for (String id : addedWeapons) {
475 pf.removeKnownWeapon(id);
476 }
477 for (String id : addedFighters) {
478 pf.removeKnownFighter(id);
479 }
480 for (String id : addedHullmods) {
481 pf.removeKnownHullMod(id);
482 }
483
484 if (!data.append && !ships.isEmpty()) {
486 if (data.addOfficers) {
488 playerFleet.getFleetData().removeOfficer(od.getPerson());
489 }
490 }
491 }
492
493 playerFleet.getCargo().addAll(cargo);
494
495 for (FleetMemberAPI member : ships.getFleetData().getMembersListCopy()) {
497 }
498
499 if (data.addOfficers) {
500 int maxOfficers = Misc.getMaxOfficers(playerFleet);
501 int add = maxOfficers - playerFleet.getFleetData().getOfficersCopy().size();
502 if (add > 0) {
503 FleetParamsV3 fp = new FleetParamsV3();
504 fp.commander = playerFleet.getCommander();
505 fp.maxOfficersToAdd = add;
507 }
508 }
509
510
512
513 cargo = playerFleet.getCargo();
514
515 int neededCrew = (int) ((playerFleet.getFleetData().getMinCrew() + cargo.getMaxPersonnel()) / 2f
516 - cargo.getCrew());
517 if (neededCrew > 0) {
518 cargo.addCrew(neededCrew);
519 }
520 cargo.addFuel(cargo.getMaxFuel() - cargo.getFuel());
521 cargo.addSupplies(cargo.getSpaceLeft() * 0.5f);
522
523
525
527 float max = member.getRepairTracker().getMaxCR();
528 member.getRepairTracker().setCR(max);
529 }
530
531
532
533 }
534
535 protected void initAvailable() {
537 //if (spec.isDefaultDHull() || spec.isDHull()) continue;
538 if (spec.isDefaultDHull()) continue;
539 if (spec.getHullSize() == HullSize.FIGHTER) continue;
540 if (!spec.hasHullName()) continue;
541 if (spec.getHints().contains(ShipTypeHints.STATION)) continue;
542// if (spec.getHints().contains(ShipTypeHints.HIDE_IN_CODEX)) continue;
543// if (spec.getHints().contains(ShipTypeHints.UNBOARDABLE)) continue;
544 if ("shuttlepod".equals(spec.getHullId())) continue;
545 ships.add(spec.getHullId());
546 }
547
549 //if (!spec.hasTag(Items.TAG_RARE_BP) && !spec.hasTag(Items.TAG_DEALER)) continue;
550 if (spec.getAIHints().contains(AIHints.SYSTEM)) continue;
551 if (!spec.hasTag(Tags.RESTRICTED)) {
552 unrestrictedWeapons.add(spec.getWeaponId());
553 }
554 weapons.add(spec.getWeaponId());
555 }
556
558 if (!spec.hasTag(Tags.RESTRICTED)) {
559 unrestrictedFighters.add(spec.getId());
560 }
561 fighters.add(spec.getId());
562 }
563
565 hullmods.add(spec.getId());
566 }
567 }
568
569 protected void addNoSkillOfficer(int level) {
573 if (level >= 7) {
575 }
576// p.getStats().setLevel(level + 1);
577 for (SkillLevelAPI sl : p.getStats().getSkillsCopy()) {
578 p.getStats().setSkillLevel(sl.getSkill().getId(), 0);
579 }
580 //p.setPersonality(Personalities.AGGRESSIVE);
582 long xp = plugin.getXPForLevel(level + 1);
584 od.addXP(xp);
586 if (level >= 7) {
587 textPanel.addPara("Added level " + (level + 1) + " officer with NO initial skill and 4 elite skills max.");
588 } else {
589 textPanel.addPara("Added level " + (level + 1) + " officer with NO initial skill.");
590 }
591 }
592}
593
594
595
596
static SettingsAPI getSettings()
Definition Global.java:57
static FactoryAPI getFactory()
Definition Global.java:41
static SectorAPI getSector()
Definition Global.java:65
static void addCommanderAndOfficersV2(CampaignFleetAPI fleet, FleetParamsV3 params, Random random)
static int getMaxOfficers(CampaignFleetAPI fleet)
Definition Misc.java:5219
static float getDistanceLY(SectorEntityToken from, SectorEntityToken to)
Definition Misc.java:602
static FleetInflater getInflater(CampaignFleetAPI fleet, Object params)
Definition Misc.java:4246
static float getDistance(SectorEntityToken from, SectorEntityToken to)
Definition Misc.java:599
CargoAPI createCargo(boolean unlimitedStacks)
CampaignFleetAPI createEmptyFleet(String factionId, String name, boolean aiMode)
OfficerDataAPI createOfficerData(PersonAPI person)
ListMap< String > getHullIdToVariantListMap()
List< WeaponSpecAPI > getAllWeaponSpecs()
List< HullModSpecAPI > getAllHullModSpecs()
WeaponSpecAPI getWeaponSpec(String weaponId)
List< ShipHullSpecAPI > getAllShipHullSpecs()
List< FighterWingSpecAPI > getAllFighterWingSpecs()
void addWeapons(String id, int count)
void addFighters(String id, int count)
boolean knowsWeapon(String weaponId)
void addKnownFighter(String wingId, boolean setTimestamp)
FactionProductionAPI getProduction()
void addKnownWeapon(String weaponId, boolean setTimestamp)
void removeKnownWeapon(String weaponId)
void removeItem(ProductionItemType type, String specId, int count)
List< OfficerDataAPI > getOfficersCopy()
void addFleetMember(FleetMemberAPI member)
List< FleetMemberAPI > getMembersListCopy()
void showCustomProductionPicker(CustomProductionPickerDelegate delegate)
void setOptionOnEscape(String text, Object optionId)
void addOption(String text, Object data)
void setVisualFade(float in, float out)
void set(String key, Object value)
MutableCharacterStatsAPI getStats()