1package com.fs.starfarer.api.impl.campaign.procgen;
4import java.util.ArrayList;
5import java.util.LinkedHashSet;
8import java.util.Random;
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;
51 protected static enum FleetQuality {
59 protected static enum OptionId {
62 ADD_UNSELECTED_OFFICERS,
72 QUALITY_2_SMODS_OMEGA,
74 QUALITY_3_SMODS_OMEGA,
82 ADD_OFFICERS_NO_SKILLS,
92 public static class FleetGenData {
93 public FactionProductionAPI prod;
94 public FleetQuality quality;
95 public boolean smodsOnAllShips =
true;
96 public boolean allowOmega =
false;
98 public boolean addOfficers =
false;
99 public boolean keepOfficerPointsFree =
false;
100 public boolean append =
false;
103 public FleetGenData() {
115 protected FleetGenData
data =
new FleetGenData();
118 protected Set<String>
ships =
new LinkedHashSet<String>();
119 protected Set<String>
fighters =
new LinkedHashSet<String>();
120 protected Set<String>
weapons =
new LinkedHashSet<String>();
123 protected Set<String>
hullmods =
new LinkedHashSet<String>();
137 visual.setVisualFade(0.25f, 0.25f);
141 dialog.setOptionOnEscape(
"Leave", OptionId.LEAVE);
155 if (optionData ==
null)
return;
157 OptionId option = (OptionId) optionData;
161 dialog.addOptionSelectedText(option);
172 case ADD_UNSELECTED_OFFICERS:
175 case OFFICERS_GO_BACK:
178 case OFFICER_LEVEL_5:
181 case OFFICER_LEVEL_6:
184 case OFFICER_LEVEL_7:
187 case QUALITY_MAX_DMODS:
188 data.quality = FleetQuality.MAX_DMODS;
191 case QUALITY_NO_DMODS:
192 data.quality = FleetQuality.NO_DMODS;
195 case QUALITY_1_SMODS:
196 data.quality = FleetQuality.ONE_SMOD;
199 case QUALITY_2_SMODS:
200 data.quality = FleetQuality.TWO_SMODS;
203 case QUALITY_2_SMODS_OMEGA:
204 data.quality = FleetQuality.TWO_SMODS;
205 data.allowOmega =
true;
208 case QUALITY_3_SMODS:
209 data.quality = FleetQuality.THREE_SMODS;
212 case QUALITY_3_SMODS_OMEGA:
213 data.quality = FleetQuality.THREE_SMODS;
214 data.allowOmega =
true;
218 data.addOfficers =
false;
222 data.addOfficers =
true;
225 case ADD_OFFICERS_NO_SKILLS:
226 data.addOfficers =
true;
227 data.keepOfficerPointsFree =
true;
257 MarketAPI nearest =
null;
258 float minDist = Float.MAX_VALUE;
260 for (MarketAPI curr :
Global.
getSector().getEconomy().getMarketsCopy()) {
261 if (curr.isHidden())
continue;
262 if (playerOnly && !curr.isPlayerOwned())
continue;
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());
280 textPanel.appendToLastParagraph(
"\n" + str);
281 System.out.println(str);
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.");
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);
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);
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);
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);
323 options.addOption(
"Do not add officers", OptionId.NO_OFFICERS);
324 options.addOption(
"Leave", OptionId.LEAVE,
null);
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);
349 dialog.showCustomProductionPicker(
new BaseCustomProductionPickerDelegateImpl() {
351 public Set<String> getAvailableFighters() {
355 public Set<String> getAvailableShipHulls() {
359 public Set<String> getAvailableWeapons() {
363 public float getCostMult() {
367 public float getMaximumValue() {
370 public boolean withQuantityLimits() {
374 public void notifyProductionSelected(FactionProductionAPI production) {
376 data.prod = production;
384 FactionProductionAPI prod =
data.prod;
388 Random random = Misc.random;
391 if (
data.quality == FleetQuality.MAX_DMODS) {
397 DefaultFleetInflaterParams p =
new DefaultFleetInflaterParams();
399 p.mode = ShipPickMode.PRIORITY_THEN_ALL;
400 p.persistent =
false;
401 p.seed = random.nextLong();
406 if (
data.quality == FleetQuality.ONE_SMOD) {
408 }
else if (
data.quality == FleetQuality.TWO_SMODS) {
410 }
else if (
data.quality == FleetQuality.THREE_SMODS) {
414 FleetInflater inflater = Misc.getInflater(
ships, p);
415 ships.setInflater(inflater);
417 for (ItemInProductionAPI pick : prod.getCurrent()) {
418 int count = pick.getQuantity();
420 if (pick.getType() == ProductionItemType.SHIP) {
422 if (variants.isEmpty()) {
423 variants.add(pick.getSpecId() +
"_Hull");
426 for (
int i = 0; i < count; i++) {
427 int index = random.nextInt(variants.size());
428 ships.getFleetData().addFleetMember(variants.get(index));
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);
435 prod.removeItem(pick.getType(), pick.getSpecId(), count);
439 List<String> addedWeapons =
new ArrayList<String>();
440 List<String> addedFighters =
new ArrayList<String>();
441 List<String> addedHullmods =
new ArrayList<String>();
443 if (
data.allowOmega) {
447 if (spec.hasTag(Tags.OMEGA)) {
454 if (!pf.knowsWeapon(
id)) {
455 addedWeapons.add(
id);
456 pf.addKnownWeapon(
id,
false);
460 if (!pf.knowsFighter(
id)) {
461 addedFighters.add(
id);
462 pf.addKnownFighter(
id,
false);
466 if (!pf.knowsHullMod(
id)) {
467 addedHullmods.add(
id);
468 pf.addKnownHullMod(
id);
472 ships.inflateIfNeeded();
474 for (String
id : addedWeapons) {
475 pf.removeKnownWeapon(
id);
477 for (String
id : addedFighters) {
478 pf.removeKnownFighter(
id);
480 for (String
id : addedHullmods) {
481 pf.removeKnownHullMod(
id);
486 if (
data.addOfficers) {
487 for (OfficerDataAPI od :
playerFleet.getFleetData().getOfficersCopy()) {
488 playerFleet.getFleetData().removeOfficer(od.getPerson());
495 for (FleetMemberAPI member :
ships.getFleetData().getMembersListCopy()) {
499 if (
data.addOfficers) {
500 int maxOfficers = Misc.getMaxOfficers(
playerFleet);
501 int add = maxOfficers -
playerFleet.getFleetData().getOfficersCopy().size();
503 FleetParamsV3 fp =
new FleetParamsV3();
505 fp.maxOfficersToAdd = add;
506 FleetFactoryV3.addCommanderAndOfficersV2(
playerFleet, fp, random);
515 int neededCrew = (int) ((
playerFleet.getFleetData().getMinCrew() + cargo.getMaxPersonnel()) / 2f
517 if (neededCrew > 0) {
518 cargo.addCrew(neededCrew);
520 cargo.addFuel(cargo.getMaxFuel() - cargo.getFuel());
521 cargo.addSupplies(cargo.getSpaceLeft() * 0.5f);
526 for (FleetMemberAPI member :
playerFleet.getFleetData().getMembersListCopy()) {
527 float max = member.getRepairTracker().getMaxCR();
528 member.getRepairTracker().setCR(max);
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;
544 if (
"shuttlepod".equals(spec.getHullId()))
continue;
545 ships.add(spec.getHullId());
550 if (spec.getAIHints().contains(AIHints.SYSTEM))
continue;
551 if (!spec.hasTag(Tags.RESTRICTED)) {
554 weapons.add(spec.getWeaponId());
558 if (!spec.hasTag(Tags.RESTRICTED)) {
570 PersonAPI p =
Global.
getSector().getPlayerFaction().createRandomPerson();
571 p.getMemoryWithoutUpdate().set(MemFlags.OFFICER_SKILL_PICKS_PER_LEVEL, 10);
572 p.getMemoryWithoutUpdate().set(MemFlags.OFFICER_MAX_LEVEL, level + 1);
574 p.getMemoryWithoutUpdate().set(MemFlags.OFFICER_MAX_ELITE_SKILLS, 4);
577 for (SkillLevelAPI sl : p.getStats().getSkillsCopy()) {
578 p.getStats().setSkillLevel(sl.getSkill().getId(), 0);
582 long xp = plugin.getXPForLevel(level + 1);
587 textPanel.addPara(
"Added level " + (level + 1) +
" officer with NO initial skill and 4 elite skills max.");
589 textPanel.addPara(
"Added level " + (level + 1) +
" officer with NO initial skill.");
static SettingsAPI getSettings()
static FactoryAPI getFactory()
static SectorAPI getSector()
Set< String > unrestrictedWeapons
void selectAppendOrReplace()
MarketAPI getNearestMarket(boolean playerOnly)
Map< String, MemoryAPI > getMemoryMap()
void addNoSkillOfficer(int level)
void init(InteractionDialogAPI dialog)
void selectOfficerLevel()
static final Color HIGHLIGHT_COLOR
void optionSelected(String text, Object optionData)
void showBlueprintPicker()
OptionId lastOptionMousedOver
void advance(float amount)
Set< String > unrestrictedFighters
CampaignFleetAPI playerFleet
void showOfficerSelector()
void backFromEngagement(EngagementResultAPI result)
void optionMousedOver(String optionText, Object optionData)
InteractionDialogAPI dialog
void selectShipsAndWeapons()
CargoAPI createCargo(boolean unlimitedStacks)
CampaignFleetAPI createEmptyFleet(String factionId, String name, boolean aiMode)
OfficerDataAPI createOfficerData(PersonAPI person)
ListMap< String > getHullIdToVariantListMap()
Object getPlugin(String id)
List< WeaponSpecAPI > getAllWeaponSpecs()
List< HullModSpecAPI > getAllHullModSpecs()
WeaponSpecAPI getWeaponSpec(String weaponId)
List< ShipHullSpecAPI > getAllShipHullSpecs()
List< FighterWingSpecAPI > getAllFighterWingSpecs()
Color getColor(String id)