1package com.fs.starfarer.api.impl.campaign.fleets;
3import java.util.ArrayList;
4import java.util.Collections;
5import java.util.Comparator;
6import java.util.HashMap;
7import java.util.HashSet;
8import java.util.Iterator;
9import java.util.LinkedHashSet;
12import java.util.Random;
15import org.apache.log4j.Logger;
17import com.fs.starfarer.api.Global;
18import com.fs.starfarer.api.campaign.CampaignFleetAPI;
19import com.fs.starfarer.api.campaign.FactionAPI;
20import com.fs.starfarer.api.campaign.FactionAPI.ShipPickMode;
21import com.fs.starfarer.api.campaign.FactionAPI.ShipPickParams;
22import com.fs.starfarer.api.campaign.FactionDoctrineAPI;
23import com.fs.starfarer.api.campaign.FleetInflater;
24import com.fs.starfarer.api.campaign.SectorEntityToken;
25import com.fs.starfarer.api.campaign.econ.CommodityOnMarketAPI;
26import com.fs.starfarer.api.campaign.econ.MarketAPI;
27import com.fs.starfarer.api.characters.MutableCharacterStatsAPI;
28import com.fs.starfarer.api.characters.PersonAPI;
29import com.fs.starfarer.api.characters.SkillSpecAPI;
30import com.fs.starfarer.api.combat.ShieldAPI.ShieldType;
31import com.fs.starfarer.api.combat.ShipAPI.HullSize;
32import com.fs.starfarer.api.combat.ShipHullSpecAPI.ShipTypeHints;
33import com.fs.starfarer.api.combat.WeaponAPI.WeaponType;
34import com.fs.starfarer.api.fleet.FleetMemberAPI;
35import com.fs.starfarer.api.fleet.FleetMemberType;
36import com.fs.starfarer.api.fleet.ShipRolePick;
37import com.fs.starfarer.api.impl.campaign.events.OfficerManagerEvent;
38import com.fs.starfarer.api.impl.campaign.events.OfficerManagerEvent.SkillPickPreference;
39import com.fs.starfarer.api.impl.campaign.fleets.GenerateFleetOfficersPlugin.GenerateFleetOfficersPickData;
40import com.fs.starfarer.api.impl.campaign.ids.Commodities;
41import com.fs.starfarer.api.impl.campaign.ids.Factions;
42import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
43import com.fs.starfarer.api.impl.campaign.ids.Personalities;
44import com.fs.starfarer.api.impl.campaign.ids.Ranks;
45import com.fs.starfarer.api.impl.campaign.ids.ShipRoles;
46import com.fs.starfarer.api.impl.campaign.ids.Skills;
47import com.fs.starfarer.api.impl.campaign.ids.Stats;
48import com.fs.starfarer.api.impl.campaign.terrain.HyperspaceTerrainPlugin;
49import com.fs.starfarer.api.loading.AbilitySpecAPI;
50import com.fs.starfarer.api.loading.WeaponSlotAPI;
51import com.fs.starfarer.api.plugins.CreateFleetPlugin;
52import com.fs.starfarer.api.plugins.OfficerLevelupPlugin;
53import com.fs.starfarer.api.util.Misc;
54import com.fs.starfarer.api.util.WeightedRandomPicker;
103 return (stability - 5f) * 0.05f;
106 return 1f + (stability - 5f) * 0.05f;
111 if (marketSize < 3) marketSize = 3;
133 switch ((
int)marketSize) {
135 case 4:
return 0.75f;
137 case 6:
return 1.25f;
139 case 8:
return 1.75f;
141 case 10:
return 2.5f;
144 return marketSize / 6f;
149 return 1f + (float) (doctrineNumShips - 1f) * (max - 1f) / 4f;
155 if (plugin !=
null) {
162 boolean fakeMarket =
false;
164 if (market ==
null) {
185 boolean sourceWasNull = params.source ==
null;
186 params.source = market;
236 float numShipsMult = 1f;
241 float quality = params.quality + params.
qualityMod;
249 Random random =
new Random();
254 float combatPts = params.combatPts * numShipsMult;
260 float freighterPts = params.freighterPts * numShipsMult;
261 float tankerPts = params.tankerPts * numShipsMult;
262 float transportPts = params.transportPts * numShipsMult;
263 float linerPts = params.linerPts * numShipsMult;
264 float utilityPts = params.utilityPts * numShipsMult;
268 if (combatPts < 10 && combatPts > 0) {
269 combatPts = Math.max(combatPts, 5 + random.nextInt(6));
272 float dW = (float) doctrine.
getWarships() + random.nextInt(3) - 2;
273 float dC = (float) doctrine.
getCarriers() + random.nextInt(3) - 2;
274 float dP = (float) doctrine.
getPhaseShips() + random.nextInt(3) - 2;
284 float r1 = random.nextFloat();
285 float r2 = random.nextFloat();
286 float min = Math.min(r1, r2);
287 float max = Math.max(r1, r2);
291 float v2 = max - min;
324 params.banPhaseShipsEtc = banPhaseShipsEtc;
337 float extra = 7 - (dC + dP + dW);
338 if (extra < 0) extra = 0f;
348 float doctrineTotal = dW + dC + dP;
352 combatPts = (int) combatPts;
353 int warships = (int) (combatPts * dW / doctrineTotal);
354 int carriers = (int) (combatPts * dC / doctrineTotal);
355 int phase = (int) (combatPts * dP / doctrineTotal);
357 warships += (combatPts - warships - carriers - phase);
360 for (String variantId : params.
addShips) {
364 if (warships < 0) warships = 0;
371 freighterPts -= added * 0.5f;
372 warships -= added * 0.5f;
374 float combatFreighters = (int) Math.min(freighterPts * 1.5f, warships * 1.5f);
376 freighterPts -= added * 0.5f;
377 warships -= added * 0.5f;
397 float targetFP =
getFP(fleet);
410 pruneFleet(maxShips, size, fleet, targetFP, random);
412 float currFP =
getFP(fleet);
446 if (curr.isFlagship())
continue;
463 params.source =
null;
472 p.seed = random.nextLong();
491 member.getRepairTracker().setCR(member.getRepairTracker().getMaxCR());
514 List<FleetMemberAPI> combat =
new ArrayList<FleetMemberAPI>();
516 List<FleetMemberAPI> tanker =
new ArrayList<FleetMemberAPI>();
517 List<FleetMemberAPI> freighter =
new ArrayList<FleetMemberAPI>();
518 List<FleetMemberAPI> liner =
new ArrayList<FleetMemberAPI>();
519 List<FleetMemberAPI> other =
new ArrayList<FleetMemberAPI>();
522 if (member.isCivilian()) {
523 civFP += member.getFleetPointCost();
526 if (member.getHullSpec().getHints().contains(ShipTypeHints.FREIGHTER)) {
527 freighter.add(member);
528 }
else if (member.getHullSpec().getHints().contains(ShipTypeHints.TANKER)) {
530 }
else if (member.getHullSpec().getHints().contains(ShipTypeHints.TRANSPORT) ||
531 member.getHullSpec().getHints().contains(ShipTypeHints.LINER)) {
538 combatFP += member.getFleetPointCost();
542 if (civFP < 1) civFP = 1;
543 if (combatFP < 1) combatFP = 1;
545 int keepCombat = (int) ((
float)maxShips * combatFP / (civFP + combatFP));
546 int keepCiv = maxShips - keepCombat;
547 if (civFP > 10 && keepCiv < 2) {
549 if (!freighter.isEmpty()) keepCiv++;
550 if (!tanker.isEmpty()) keepCiv++;
551 if (!liner.isEmpty()) keepCiv++;
552 if (!other.isEmpty()) keepCiv++;
554 keepCiv = maxShips - keepCiv;
558 float f = 0, t = 0, l = 0, o = 0;
559 float total = freighter.size() + tanker.size() + liner.size() + other.size();
560 if (total < 1) total = 1;
562 f = (float) freighter.size() / total;
563 t = (float) tanker.size() / total;
564 l = (float) liner.size() / total;
565 o = (float) other.size() / total;
572 if (f > 0) f = Math.round(f);
573 if (t > 0) t = Math.round(t);
574 if (l > 0) l = Math.round(l);
575 if (o > 0) o = Math.round(o);
577 if (freighter.size() > 0 && f < 1) f = 1;
578 if (tanker.size() > 0 && t < 1) t = 1;
579 if (liner.size() > 0 && l < 1) l = 1;
580 if (other.size() > 0 && o < 1) o = 1;
582 int extra = (int) ((f + t + l + o) - keepCiv);
584 if (extra > 0 && o >= 2) {
588 if (extra > 0 && l >= 2) {
592 if (extra > 0 && t >= 2) {
596 if (extra > 0 && f >= 2) {
602 LinkedHashSet<FleetMemberAPI> keep =
new LinkedHashSet<FleetMemberAPI>();
604 Comparator<FleetMemberAPI> c =
new Comparator<FleetMemberAPI>() {
609 Collections.sort(combat, c);
610 Collections.sort(freighter, c);
611 Collections.sort(tanker, c);
612 Collections.sort(liner, c);
613 Collections.sort(other, c);
615 int [] ratio =
new int [] { 4, 2, 1, 1 };
629 addAll(ratio, combat, keep, keepCombat, random);
632 addAll(ratio, freighter, keep, (
int)f, random);
633 addAll(ratio, tanker, keep, (
int)t, random);
634 addAll(ratio, liner, keep, (
int)l, random);
635 addAll(ratio, other, keep, (
int)o, random);
638 if (!keep.contains(member)) {
643 float currFP =
getFP(fleet);
644 if (currFP > targetFP) {
649 for (
int i = 0; i < copy.size()/2; i+=2) {
653 copy.set(copy.size() - 1 - i, f1);
676 float fpGoal = currFP - targetFP;
679 if (curr.isCivilian())
continue;
683 float fpCurr = curr.getFleetPointCost();
684 float fpReplace = replace.getFleetPointCost();
685 if (fpCurr > fpReplace) {
686 float fpDiff = fpCurr - fpReplace;
687 if (fpDone + fpDiff <= fpGoal) {
692 if (fpDiff < bestDiff) {
705 if (fpDone >= fpGoal) {
714 public static void addAll(
int [] ratio, List<FleetMemberAPI> from, LinkedHashSet<FleetMemberAPI> to,
int num, Random random) {
717 while (added < num && !from.isEmpty()) {
718 to.add(from.remove(0));
725 for (
int i = 0; i < num; i++) {
727 OUTER:
while (!picker.
isEmpty()) {
730 if (member.getHullSpec().getHullSize() == size) {
743 while (added < num && !from.isEmpty()) {
744 to.add(from.remove(0));
752 for (
int i = 0; i < ratio[0]; i++) {
753 picker.
add(HullSize.CAPITAL_SHIP);
755 for (
int i = 0; i < ratio[1]; i++) {
756 picker.
add(HullSize.CRUISER);
758 for (
int i = 0; i < ratio[2]; i++) {
759 picker.
add(HullSize.DESTROYER);
761 for (
int i = 0; i < ratio[3]; i++) {
762 picker.
add(HullSize.FRIGATE);
775 fp += member.getFleetPointCost();
782 List<FleetMemberAPI>
remove =
new ArrayList<FleetMemberAPI>();
795 Collections.reverse(copy);
797 Iterator<FleetMemberAPI> iter;
799 iter = copy.iterator();
800 while (iter.hasNext()) {
808 iter = copy.iterator();
809 while (iter.hasNext()) {
817 iter = copy.iterator();
818 while (iter.hasNext()) {
826 iter = copy.iterator();
827 while (iter.hasNext()) {
835 iter = copy.iterator();
836 while (iter.hasNext()) {
844 iter = copy.iterator();
845 while (iter.hasNext()) {
853 iter = copy.iterator();
854 while (iter.hasNext()) {
862 iter = copy.iterator();
863 while (iter.hasNext()) {
888 GenerateFleetOfficersPickData pickData =
new GenerateFleetOfficersPickData(fleet, params);
890 if (genPlugin !=
null) {
902 if (members.isEmpty())
return;
904 float combatPoints = 0f;
905 float combatShips = 0f;
907 if (member.isCivilian() && !putOfficersOnCivShips)
continue;
908 if (member.isFighterWing())
continue;
909 combatPoints += member.getFleetPointCost();
912 if (combatPoints < 1f) combatPoints = 1f;
913 if (combatShips < 1f) combatShips = 1f;
915 boolean debug =
true;
927 if (officerQualityMult > 1f) officerQualityMult = 1f;
935 float combatShipsPerOfficer = baseCombatShipsPerOfficer * (1f - officerQualityMult * 0.5f);
938 float fleetSizeOfficerQualityMult = combatShips / (baseShipsForMaxOfficerLevel * (1f - officerQualityMult * 0.5f));
939 if (fleetSizeOfficerQualityMult > 1) fleetSizeOfficerQualityMult = 1;
944 int numOfficers = (int) Math.min(maxOfficers, combatShips / combatShipsPerOfficer);
949 if (debug) System.out.println(
"numOfficers: " + numOfficers);
955 if (numOfficers > maxOfficers) numOfficers = maxOfficers;
965 int maxOfficerLevel = (int)Math.round(((
float)doctrine.
getOfficerQuality() / 2f) +
966 (fleetSizeOfficerQualityMult * 1f) * (
float) baseMaxOfficerLevel);
967 if (maxOfficerLevel < 1) maxOfficerLevel = 1;
969 if (maxOfficerLevel < 1) maxOfficerLevel = 1;
971 if (debug) System.out.println(
"maxOfficers: " + maxOfficers);
972 if (debug) System.out.println(
"maxOfficerLevel: " + maxOfficerLevel);
980 if (member.isFighterWing())
continue;
981 if (member.isFlagship())
continue;
982 if (member.isCivilian() && !putOfficersOnCivShips)
continue;
983 if (!member.getCaptain().isDefault())
continue;
984 int size = member.getHullSpec().getHullSize().ordinal();
985 if (size > maxSize) {
991 if (member.isFighterWing())
continue;
992 if (member.isFlagship())
continue;
993 if (member.isCivilian() && !putOfficersOnCivShips)
continue;
994 if (!member.getCaptain().isDefault())
continue;
996 float weight = (float) member.getFleetPointCost();
997 int size = member.getHullSpec().getHullSize().ordinal();
998 if (size >= maxSize) {
999 flagshipPicker.
add(member, weight);
1002 picker.
add(member, weight);
1006 picker.
add(members.get(0), 1f);
1008 if (flagshipPicker.
isEmpty()) {
1009 flagshipPicker.
add(members.get(0), 1f);
1014 if (!simFleet) picker.
remove(flagship);
1015 int commanderLevel = maxOfficerLevel;
1016 int commanderLevelLimit = maxCommanderLevel;
1025 if (commanderLevel > commanderLevelLimit) commanderLevel = commanderLevelLimit;
1029 if (commander ==
null) {
1048 int officerLevelLimit = plugin.
getMaxLevel(
null) + commanderOfficerLevelBonus;
1055 System.out.println(
"Created level " + commander.
getStats().
getLevel() +
" commander");
1056 System.out.println(
"Max officer level bonus: " + commanderOfficerLevelBonus +
" (due to commander skill)");
1057 System.out.println(
"Adding up to " + numOfficers +
" officers");
1061 for (
int i = 0; i < numOfficers; i++) {
1063 if (member ==
null) {
1067 int level = maxOfficerLevel - random.nextInt(3);
1071 if (level < 1) level = 1;
1075 if (level > officerLevelLimit) level = officerLevelLimit;
1091 System.out.println(
"Added level " + person.
getStats().
getLevel() +
" officer");
1102 System.out.println(
"Added " + added +
" officers total");
1109 float ballistic = 0f;
1115 switch (slot.getSlotSize()) {
1116 case LARGE: w = 4f;
break;
1117 case MEDIUM: w = 2f;
break;
1118 case SMALL: w = 1f;
break;
1120 WeaponType type = slot.getWeaponType();
1121 if (type == WeaponType.BALLISTIC || type == WeaponType.HYBRID) {
1124 }
else if (type == WeaponType.ENERGY) {
1127 }
else if (type == WeaponType.MISSILE || type == WeaponType.SYNERGY || type == WeaponType.COMPOSITE) {
1133 if (total <= 0f) total = 1f;
1135 boolean e = energy >= total * 0.33f;
1136 boolean b = ballistic >= total * 0.33f;
1138 if (ballistic * 1.5f >= energy) {
1144 boolean m = missile >= total * 0.17f;
1151 String n1 = e ?
"YES_ENERGY" :
"NO_ENERGY";
1152 String n2 = b ?
"YES_BALLISTIC" :
"NO_BALLISTIC";
1153 String n3 = m ?
"YES_MISSILE" :
"NO_MISSILE";
1154 String n4 = d ?
"YES_DEFENSE" :
"NO_DEFENSE";
1155 SkillPickPreference pref = SkillPickPreference.valueOf(n1 +
"_" + n2 +
"_" + n3 +
"_" + n4);
1164 if (random ==
null) random =
new Random();
1173 if (level >= forTwo) {
1175 }
else if (level >= forOne) {
1179 if (numSkills <= 0)
return;
1188 Iterator<String> iter = skills.iterator();
1189 while (iter.hasNext()) {
1190 String
id = iter.next();
1198 if (skills.isEmpty())
return;
1201 Collections.shuffle(skills, random);
1206 boolean debug =
true;
1208 if (debug) System.out.println(
"Generating commander skills, person level " + stats.
getLevel() +
", skills: " + numSkills);
1210 for (String skillId : skills) {
1211 if (debug) System.out.println(
"Selected skill: [" + skillId +
"]");
1214 if (picks >= numSkills) {
1218 if (debug) System.out.println(
"Done generating commander skills\n");
1229 case CAPITAL_SHIP: weight += 8;
break;
1230 case CRUISER: weight += 4;
break;
1231 case DESTROYER: weight += 2;
break;
1232 case FRIGATE: weight += 1;
break;
1233 case FIGHTER: weight += 1;
break;
1235 if (nonCombat) weight *= 0.1f;
1249 float distToClosest = Float.MAX_VALUE;
1251 float distToClosestMatchingSize = Float.MAX_VALUE;
1261 if (market.getPrimaryEntity() ==
null)
continue;
1265 if (hostileToIndependent)
continue;
1267 if (!market.getFactionId().equals(params.
factionId))
continue;
1270 float currDist =
Misc.
getDistance(market.getPrimaryEntity().getLocationInHyperspace(),
1272 if (currDist < distToClosest) {
1273 distToClosest = currDist;
1277 if (market.getSize() >= size && currDist < distToClosestMatchingSize) {
1278 distToClosestMatchingSize = currDist;
1279 closestMatchingSize = market;
1283 if (closestMatchingSize !=
null) {
1284 return closestMatchingSize;
1287 if (closest !=
null) {
1300 if (fp <= 20)
return 1;
1301 if (fp <= 50)
return 3;
1302 if (fp <= 100)
return 5;
1303 if (fp <= 150)
return 7;
1311 private static List<String> startingAbilities =
null;
1318 if (market !=
null && !market.
getId().equals(
"fake")) {
1322 if (startingAbilities ==
null) {
1323 startingAbilities =
new ArrayList<String>();
1327 startingAbilities.add(
id);
1332 for (String
id : startingAbilities) {
1339 public static class FPRemaining {
1342 public FPRemaining(
int fp) {
1345 public FPRemaining() {
1421 boolean addedSomething =
false;
1422 for (
int i = 0; i < count; i++) {
1423 if (rem.fp <= 0)
break;
1424 float added =
addToFleet(role, market, random, fleet, rem.fp, params);
1427 addedSomething =
true;
1430 return addedSomething;
1479 public static enum SizeFilterMode {
1489 SizeFilterMode sizeFilterMode,
1490 String roleSmall, String roleMedium, String roleLarge) {
1491 if (fp <= 0)
return 0f;
1494 if (params.
mode == ShipPickMode.PRIORITY_THEN_ALL) {
1499 if (numPriority > 0) {
1500 params.mode = ShipPickMode.PRIORITY_ONLY;
1501 added =
addFleetPoints(fleet, random, fp, params, sizeFilterMode,
1502 roleSmall, roleMedium, roleLarge);
1503 params.mode = ShipPickMode.PRIORITY_THEN_ALL;
1505 params.mode = ShipPickMode.ALL;
1506 added =
addFleetPoints(fleet, random, fp, params, sizeFilterMode,
1507 roleSmall, roleMedium, roleLarge);
1508 params.mode = ShipPickMode.PRIORITY_THEN_ALL;
1518 added =
addFleetPoints(fleet, random, fp, params, sizeFilterMode,
1519 roleSmall, roleMedium, roleLarge);
1577 SizeFilterMode sizeFilterMode,
1587 boolean addedSomething =
true;
1588 FPRemaining rem =
new FPRemaining();
1591 while (addedSomething && rem.fp > 0) {
1603 if (sizeFilterMode == SizeFilterMode.SMALL_IS_FRIGATE) {
1606 }
else if (sizeFilterMode == SizeFilterMode.SMALL_IS_DESTROYER) {
1614 int smallPre = small / 2;
1617 int mediumPre = medium / 2;
1618 medium -= mediumPre;
1620 addedSomething =
false;
1622 addedSomething |=
addShips(roles[0], smallPre, params.
source, random, fleet, rem, params);
1624 addedSomething |=
addShips(roles[1], mediumPre, params.
source, random, fleet, rem, params);
1625 addedSomething |=
addShips(roles[0], small, params.
source, random, fleet, rem, params);
1627 addedSomething |=
addShips(roles[2], large, params.
source, random, fleet, rem, params);
1628 addedSomething |=
addShips(roles[1], medium, params.
source, random, fleet, rem, params);
1639 float warshipFP,
float carrierFP,
float phaseFP,
FleetParamsV3 params) {
1673 smallPicker.
add(smallRole, warshipFP);
1689 Set<String> usePriorityOnly =
new HashSet<String>();
1691 if (params.
mode == ShipPickMode.PRIORITY_THEN_ALL) {
1708 if (params.
mode == ShipPickMode.PRIORITY_THEN_ALL) {
1714 Map<String, FPRemaining> remaining =
new HashMap<String, FPRemaining>();
1715 FPRemaining remWarship =
new FPRemaining((
int)warshipFP);
1716 FPRemaining remCarrier =
new FPRemaining((
int)carrierFP);
1717 FPRemaining remPhase =
new FPRemaining((
int)phaseFP);
1736 mediumPicker.
clear();
1739 largePicker.
clear();
1742 capitalPicker.
clear();
1746 smallPicker.
clear();
1749 mediumPicker.
clear();
1752 largePicker.
clear();
1760 while (numFails < 2) {
1772 if (size < 5 && capital > 1) {
1784 int smallPre = small / 2;
1787 int mediumPre = medium / 2;
1788 medium -= mediumPre;
1790 boolean addedSomething =
false;
1793 addedSomething |=
addShips(smallPicker, usePriorityOnly, remaining,
null, smallPre, fleet, random, params);
1795 addedSomething |=
addShips(mediumPicker, usePriorityOnly, remaining,
null, mediumPre, fleet, random, params);
1797 addedSomething |=
addShips(smallPicker, usePriorityOnly, remaining,
null, small, fleet, random, params);
1799 addedSomething |=
addShips(largePicker, usePriorityOnly, remaining,
null, large, fleet, random, params);
1801 addedSomething |=
addShips(mediumPicker, usePriorityOnly, remaining,
null, medium, fleet, random, params);
1805 if (!priorityCapitalPicker.
isEmpty()) {
1806 params.mode = ShipPickMode.PRIORITY_ONLY;
1807 params.blockFallback =
true;
1808 FPRemaining combined =
new FPRemaining(remWarship.fp + remCarrier.fp + remPhase.fp);
1809 boolean addedCapital =
addShips(priorityCapitalPicker, usePriorityOnly, remaining, combined, capital, fleet, random, params);
1810 addedSomething |= addedCapital;
1814 params.mode = ShipPickMode.PRIORITY_THEN_ALL;
1815 params.blockFallback =
null;
1818 addedSomething |=
addShips(capitalPicker, usePriorityOnly, remaining,
null, capital, fleet, random, params);
1822 if (!addedSomething) {
1825 if (numFails == 2) {
1826 boolean goAgain =
false;
1827 if (remPhase.fp > 0) {
1828 remWarship.fp += remPhase.fp;
1832 if (remCarrier.fp > 0) {
1833 remWarship.fp += remCarrier.fp;
1840 smallPicker.
add(smallRole, 1);
1854 if (numPriority > 0) {
1861 protected static void redistributeFP(FPRemaining one, FPRemaining two, FPRemaining three,
int newTotal) {
1862 float total = one.fp + two.fp + three.fp;
1863 if (total <= 0)
return;
1865 int f1 = (int) Math.round((
float)one.fp / total * newTotal);
1866 int f2 = (int) Math.round((
float)two.fp / total * newTotal);
1867 int f3 = (int) Math.round((
float)three.fp / total * newTotal);
1869 f1 += newTotal - f1 - f2 - f3;
1878 if (rolePicker.
isEmpty())
return false;
1880 boolean addedSomething =
false;
1881 for (
int i = 0; i < count; i++) {
1882 String role = rolePicker.
pick();
1883 if (role ==
null)
break;
1884 FPRemaining rem = remaining.get(role);
1885 FPRemaining remForProperRole = rem;
1886 if (remOverride !=
null) rem = remOverride;
1887 if (usePriorityOnly.contains(role)) {
1888 params.mode = ShipPickMode.PRIORITY_ONLY;
1890 int fpPrePick = rem.fp;
1892 boolean added =
addShips(role, 1, params.
source, random, fleet, rem, params);
1894 if (added && remOverride !=
null) {
1895 int fpSpent = fpPrePick - rem.fp;
1896 int maxToTakeFromProperRole = Math.min(remForProperRole.fp, fpSpent);
1897 remForProperRole.fp -= maxToTakeFromProperRole;
1900 if (usePriorityOnly.contains(role)) {
1901 params.mode = ShipPickMode.PRIORITY_THEN_ALL;
1910 addedSomething |= added;
1912 return addedSomething;
1921 float f = available / demand;
1925 if (mult < 0) mult = 0;
1926 if (mult > 1) mult = 1;
1938 boolean damageRemainingShips, Random random) {
1945 if (member.isCivilian()) w *= 0.25f;
1947 picker.
add(member, w);
1950 List<FleetMemberAPI>
remove =
new ArrayList<FleetMemberAPI>();
1951 float removedFP = 0f;
1954 while (removedFP < fpToRemove &&
remove.size() < members.size() - 1 && !picker.
isEmpty()) {
1965 if (damageRemainingShips) {
1966 int numStrikes = (int) Math.round(picker.
getItems().size() * damage);
1968 for (
int i = 0; i < numStrikes; i++) {
1970 if (member ==
null)
return;
1972 if (random.nextFloat() > damage)
continue;
1977 if (suppliesPerDep <= 0 || crPerDep <= 0)
return;
1978 float suppliesPer100CR = suppliesPerDep * 1f / Math.max(0.01f, crPerDep);
1980 float strikeSupplies = suppliesPer100CR * damage * (0.25f + 0.75f * random.nextFloat());
1981 float strikeDamage = strikeSupplies / suppliesPer100CR * (0.75f + (float) Math.random() * 0.5f);
1987 if (strikeDamage > 0) {
1989 float crDamage = Math.min(currCR, strikeDamage);
1994 int numHits = (int) (strikeDamage / 0.1f);
1995 if (numHits < 1) numHits = 1;
1996 for (
int j = 0; j < numHits; j++) {
static SettingsAPI getSettings()
static FactoryAPI getFactory()
static Logger getLogger(Class c)
static SectorAPI getSector()
void modifyFlat(String source, float value)
void modifyFlat(String source, float value)
float computeEffective(float baseValue)
AvailableOfficer createOfficer(boolean isMerc, MarketAPI market, Random random)
static float BASE_QUALITY_WHEN_NO_MARKET
static void pruneFleet(int maxShips, int doctrineSize, CampaignFleetAPI fleet, float targetFP, Random random)
static float addFreighterFleetPoints(CampaignFleetAPI fleet, Random random, float fp, FleetParamsV3 params)
static float addCarrierFleetPoints(CampaignFleetAPI fleet, Random random, float fp, FleetParamsV3 params)
static void addCommanderSkills(PersonAPI commander, CampaignFleetAPI fleet, Random random)
static float addToFleet(String role, MarketAPI market, Random random, CampaignFleetAPI fleet, int maxFP, FleetParamsV3 params)
static void addCommanderAndOfficersV2(CampaignFleetAPI fleet, FleetParamsV3 params, Random random)
static List< FleetMemberAPI > getRemoveOrder(CampaignFleetAPI fleet)
static float addUtilityFleetPoints(CampaignFleetAPI fleet, Random random, float fp, FleetParamsV3 params)
static float MIN_NUM_SHIPS_DEFICIT_MULT
static int getFP(CampaignFleetAPI fleet)
static float addTankerFleetPoints(CampaignFleetAPI fleet, Random random, float fp, FleetParamsV3 params)
static void addCombatFleetPoints(CampaignFleetAPI fleet, Random random, float warshipFP, float carrierFP, float phaseFP, FleetParamsV3 params)
static void redistributeFP(FPRemaining one, FPRemaining two, FPRemaining three, int newTotal)
static void addCommanderAndOfficers(CampaignFleetAPI fleet, FleetParamsV3 params, Random random)
static int[][] BASE_COUNTS_WITH_4
static void addCommanderAndOfficersV2(CampaignFleetAPI fleet, FleetParamsV3 params, Random random, boolean simFleet, boolean putOfficersOnCivShips)
static float getShipDeficitFleetSizeMult(MarketAPI market)
static int[][] MAX_EXTRA_WITH_3
static float getNumShipsMultForMarketSize(float marketSize)
static float getShipQualityModForStability(float stability)
static int[][] MAX_EXTRA_WITH_4
static float getDoctrineNumShipsMult(int doctrineNumShips)
static SkillPickPreference getSkillPrefForShip(FleetMemberAPI member)
static float getNumShipsMultForStability(float stability)
static int FLEET_POINTS_THRESHOLD_FOR_ANNOYING_SHIPS
static int getAdjustedDoctrineSize(int size, CampaignFleetAPI fleetSoFar)
static void addToPriorityOnlySet(CampaignFleetAPI fleet, Set< String > set, String small, String medium, String large)
static CampaignFleetAPI createFleet(FleetParamsV3 params)
static float addPhaseFleetPoints(CampaignFleetAPI fleet, Random random, float fp, FleetParamsV3 params)
static CampaignFleetAPI createEmptyFleet(String factionId, String fleetType, MarketAPI market)
static void applyDamageToFleet(CampaignFleetAPI fleet, float damage, boolean damageRemainingShips, Random random)
static float addLinerFleetPoints(CampaignFleetAPI fleet, Random random, float fp, FleetParamsV3 params)
static void addAll(int[] ratio, List< FleetMemberAPI > from, LinkedHashSet< FleetMemberAPI > to, int num, Random random)
static int[][] BASE_COUNTS_WITH_3
static float addFleetPoints(CampaignFleetAPI fleet, Random random, float fp, FleetParamsV3 params, SizeFilterMode sizeFilterMode, String ... roles)
static float addToFleet(ShipRolePick pick, CampaignFleetAPI fleet, Random random)
static boolean addShips(WeightedRandomPicker< String > rolePicker, Set< String > usePriorityOnly, Map< String, FPRemaining > remaining, FPRemaining remOverride, int count, CampaignFleetAPI fleet, Random random, FleetParamsV3 params)
static float addTransportFleetPoints(CampaignFleetAPI fleet, Random random, float fp, FleetParamsV3 params)
static float getMemberWeight(FleetMemberAPI member)
static float addPriorityOnlyThenAll(CampaignFleetAPI fleet, Random random, float fp, FleetParamsV3 params, SizeFilterMode sizeFilterMode, String roleSmall, String roleMedium, String roleLarge)
static WeightedRandomPicker< HullSize > makePicker(int[] ratio, Random random)
static int getMinPreferredMarketSize(FleetParamsV3 params)
static MarketAPI pickMarket(FleetParamsV3 params)
static String KEY_SPAWN_FP_MULT
static float addCombatFreighterFleetPoints(CampaignFleetAPI fleet, Random random, float fp, FleetParamsV3 params)
static void addCommanderSkills(PersonAPI commander, CampaignFleetAPI fleet, FleetParamsV3 params, Random random)
static boolean addShips(String role, int count, MarketAPI market, Random random, CampaignFleetAPI fleet, FPRemaining rem, FleetParamsV3 params)
transient Boolean blockFallback
ShipPickMode modeOverride
void updateQualityAndProducerFromSourceMarket()
Boolean noCommanderSkills
FactionAPI factionOverride
Boolean forceAllowPhaseShipsEtc
FactionDoctrineAPI doctrineOverride
transient boolean banPhaseShipsEtc
Boolean doNotAddShipsBeforePruning
Boolean ignoreMarketFleetSizeMult
transient ShipPickMode mode
Boolean onlyApplyFleetSizeToCombatShips
Boolean treatCombatFreighterSettingAsFraction
Boolean onlyRetainFlagship
ShipVariantAPI flagshipVariant
static final String SHIPS
static final String SCAVENGERS
static final String CUSTOM_SPAWNS_AS_INDEPENDENT
static final String INDEPENDENT
static final String MEMORY_KEY_SOURCE_MARKET
static final String MEMORY_KEY_FLEET_TYPE
static final String TIMID
static final String CAUTIOUS
static String SPACE_COMMANDER
static String POST_FLEET_COMMANDER
static final String UTILITY
static final String TANKER_LARGE
static final String COMBAT_CAPITAL
static final String COMBAT_LARGE
static final String PERSONNEL_LARGE
static final String TANKER_SMALL
static final String PHASE_MEDIUM
static final String LINER_SMALL
static final String COMBAT_SMALL
static final String CARRIER_LARGE
static final String COMBAT_FREIGHTER_MEDIUM
static final String FREIGHTER_MEDIUM
static final String COMBAT_MEDIUM
static final String PHASE_LARGE
static final String COMBAT_FREIGHTER_SMALL
static final String PERSONNEL_MEDIUM
static final String PHASE_CAPITAL
static final String COMBAT_FREIGHTER_LARGE
static final String FREIGHTER_LARGE
static final String TANKER_MEDIUM
static final String CARRIER_SMALL
static final String LINER_MEDIUM
static final String FREIGHTER_SMALL
static final String COMBAT_SMALL_FOR_SMALL_FLEET
static final String PHASE_SMALL
static final String CARRIER_MEDIUM
static final String LINER_LARGE
static final String PERSONNEL_SMALL
static final String TAG_PLAYER_ONLY
static final String COMBAT_FLEET_SIZE_MULT
static final String FLEET_QUALITY_MOD
static final String OFFICER_MAX_LEVEL_MOD
static float STORM_MAX_STRIKE_DAMAGE
static FleetInflater getInflater(CampaignFleetAPI fleet, Object params)
static float getDistance(SectorEntityToken from, SectorEntityToken to)
static long getSalvageSeed(SectorEntityToken entity)
static void setSpawnFPMult(CampaignFleetAPI fleet, float mult)
static ShipPickMode getShipPickMode(MarketAPI market)
void setWeight(int index, float weight)
MarketAPI createMarket(String id, String name, int size)
CampaignFleetAPI createEmptyFleet(String factionId, String name, boolean aiMode)
FleetMemberAPI createFleetMember(FleetMemberType type, String variantOrWingId)
AbilitySpecAPI getAbilitySpec(String abilityId)
ShipVariantAPI getVariant(String variantId)
SkillSpecAPI getSkillSpec(String skillId)
Object getPlugin(String id)
List< String > getSortedAbilityIds()
float getFloat(String key)
void profilerBegin(String id)
void setName(String name)
void setCommander(PersonAPI commander)
FleetMemberAPI getFlagship()
FleetDataAPI getFleetData()
void setInflater(FleetInflater inflater)
boolean getCustomBoolean(String key)
String getFleetTypeName(String type)
int getNumAvailableForRole(String roleId, ShipPickMode mode)
FactionDoctrineAPI getDoctrine()
float getVariantWeightForRole(String roleId, ShipPickMode mode)
boolean isPlayerFaction()
float getCombatFreighterProbability()
float getCommanderSkillsShuffleProbability()
float getAutofitRandomizeProbability()
boolean isStrictComposition()
List< String > getCommanderSkills()
void addOfficer(PersonAPI person)
String pickShipName(FleetMemberAPI member, Random random)
void setOnlySyncMemberLists(boolean onlySyncMemberLists)
void setFlagship(FleetMemberAPI flagship)
void addFleetMember(FleetMemberAPI member)
void removeFleetMember(FleetMemberAPI member)
List< FleetMemberAPI > getMembersListCopy()
< T > T pickPlugin(Class< T > c, Object params)
SectorEntityToken createToken(float x, float y)
GenericPluginManagerAPI getGenericPlugins()
FactionAPI getFaction(String factionId)
LocationAPI getHyperspace()
MemoryAPI getMemoryWithoutUpdate()
void addAbility(String id)
List< MarketAPI > getMarketsCopy()
List< ShipRolePick > pickShipsForRole(String role, ShipPickParams params, Random random, ShipFilter filter)
void setFactionId(String factionId)
CommodityOnMarketAPI getCommodityData(String commodityId)
void setPrimaryEntity(SectorEntityToken primaryEntity)
void setCachedFaction(FactionAPI faction)
MutableMarketStatsAPI getStats()
MutableStatWithTempMods getStability()
void set(String key, Object value)
DynamicStatsAPI getDynamic()
MutableStat getOfficerNumber()
void setSkillLevel(String id, float level)
void refreshCharacterStatsEffects()
void setSkipRefresh(boolean skipRefresh)
void setRankId(String rank)
MutableCharacterStatsAPI getStats()
void setPersonality(String personality)
PersonalityAPI getPersonalityAPI()
void setPostId(String postId)
boolean hasTag(String tag)
StatBonus getArmorBonus()
MutableStat getSuppliesToRecover()
List< WeaponSlotAPI > getAllWeaponSlotsCopy()
ShieldType getShieldType()
ShipAPI.HullSize getHullSize()
ShipVariantAPI getVariant()
void setCaptain(PersonAPI commander)
void setShipName(String name)
FleetMemberStatusAPI getStatus()
RepairTrackerAPI getRepairTracker()
ShipHullSpecAPI getHullSpec()
void setVariant(ShipVariantAPI variant, boolean withRefit, boolean withStatsUpdate)
MutableShipStatsAPI getStats()
void applyDamage(float hitStrength)
void setHullFraction(float fraction)
DynamicStatsAPI getDynamic()
void addCommanderAndOfficers(CampaignFleetAPI fleet, FleetParamsV3 params, Random random)
CampaignFleetAPI createFleet(FleetParamsV3 params)
int getMaxLevel(PersonAPI person)
StatBonus getMod(String id)