1package com.fs.starfarer.api.impl.campaign.fleets;
3import java.util.ArrayList;
4import java.util.LinkedHashMap;
5import java.util.LinkedHashSet;
8import java.util.Random;
11import com.fs.starfarer.api.Global;
12import com.fs.starfarer.api.campaign.CampaignFleetAPI;
13import com.fs.starfarer.api.campaign.CargoAPI;
14import com.fs.starfarer.api.campaign.FactionAPI;
15import com.fs.starfarer.api.campaign.FleetInflater;
16import com.fs.starfarer.api.campaign.econ.MarketAPI;
17import com.fs.starfarer.api.campaign.econ.SubmarketAPI;
18import com.fs.starfarer.api.characters.MutableCharacterStatsAPI;
19import com.fs.starfarer.api.combat.MutableShipStatsAPI;
20import com.fs.starfarer.api.combat.ShipAPI;
21import com.fs.starfarer.api.combat.ShipVariantAPI;
22import com.fs.starfarer.api.combat.WeaponAPI;
23import com.fs.starfarer.api.combat.WeaponAPI.WeaponSize;
24import com.fs.starfarer.api.fleet.FleetMemberAPI;
25import com.fs.starfarer.api.impl.campaign.DModManager;
26import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
27import com.fs.starfarer.api.impl.campaign.ids.Tags;
28import com.fs.starfarer.api.loading.FighterWingSpecAPI;
29import com.fs.starfarer.api.loading.VariantSource;
30import com.fs.starfarer.api.loading.WeaponSlotAPI;
31import com.fs.starfarer.api.loading.WeaponSpecAPI;
32import com.fs.starfarer.api.plugins.AutofitPlugin.AutofitPluginDelegate;
33import com.fs.starfarer.api.plugins.AutofitPlugin.AvailableFighter;
34import com.fs.starfarer.api.plugins.AutofitPlugin.AvailableWeapon;
35import com.fs.starfarer.api.plugins.impl.CoreAutofitPlugin;
36import com.fs.starfarer.api.util.ListMap;
37import com.fs.starfarer.api.util.Misc;
38import com.fs.starfarer.api.util.WeightedRandomPicker;
45 public static class SortedWeapons {
46 protected Map<Integer, WeaponsForTier> tierMap =
new LinkedHashMap<Integer, WeaponsForTier>();
48 public WeaponsForTier getWeapons(
int tier) {
49 WeaponsForTier data = tierMap.get(tier);
51 data =
new WeaponsForTier();
52 tierMap.put(tier, data);
58 public static class WeaponsForTier {
69 protected Map<String, WeaponsForSize> catMap =
new LinkedHashMap<String, WeaponsForSize>();
71 public WeaponsForSize getWeapons(String cat) {
72 WeaponsForSize size = catMap.get(cat);
74 size =
new WeaponsForSize();
75 catMap.put(cat, size);
81 public static class WeaponsForSize {
82 protected Map<WeaponSize, List<AvailableWeapon>> sizeMap =
new LinkedHashMap<
WeaponAPI.
WeaponSize, List<AvailableWeapon>>();
83 public List<AvailableWeapon> getWeapons(WeaponSize size) {
84 List<AvailableWeapon> list = sizeMap.get(size);
86 list =
new ArrayList<AvailableWeapon>();
87 sizeMap.put(size, list);
93 public static class AvailableFighterImpl
implements AvailableFighter {
94 protected FighterWingSpecAPI spec;
95 protected int quantity = 0;
97 public AvailableFighterImpl(FighterWingSpecAPI spec,
int quantity) {
99 this.quantity = quantity;
102 public AvailableFighterImpl(String wingId,
int quantity) {
103 spec = Global.getSettings().getFighterWingSpec(wingId);
104 this.quantity = quantity;
107 public String getId() {
110 public float getPrice() {
113 public int getQuantity() {
116 public CargoAPI getSource() {
119 public SubmarketAPI getSubmarket() {
122 public FighterWingSpecAPI getWingSpec() {
125 public void setQuantity(
int quantity) {
126 this.quantity = quantity;
130 public static class AvailableWeaponImpl
implements AvailableWeapon {
131 protected WeaponSpecAPI spec;
132 protected int quantity = 0;
133 public AvailableWeaponImpl(WeaponSpecAPI spec,
int quantity) {
135 this.quantity = quantity;
138 public String getId() {
139 return spec.getWeaponId();
141 public float getPrice() {
144 public int getQuantity() {
147 public CargoAPI getSource() {
150 public SubmarketAPI getSubmarket() {
153 public WeaponSpecAPI getSpec() {
156 public void setQuantity(
int quantity) {
157 this.quantity = quantity;
160 protected MutableShipStatsAPI savedCostStats =
null;
161 protected float cachedOPCost = -1;
162 public float getOPCost(MutableCharacterStatsAPI stats, MutableShipStatsAPI shipStats) {
163 if (savedCostStats == shipStats && cachedOPCost >= 0)
return cachedOPCost;
165 cachedOPCost = spec.getOrdnancePointCost(stats, shipStats);
166 savedCostStats = shipStats;
181 protected transient List<AvailableFighter>
fighters;
182 protected transient List<AvailableWeapon>
weapons;
216 if (tier == 1)
return Math.min(0.9f, 0.75f + quality);
217 if (tier == 2)
return Math.min(0.9f, 0.5f + quality * 0.5f);
218 if (tier == 3)
return Math.min(0.9f, 0.25f + quality * 0.25f);
225 Random random =
new Random();
227 if (
p.
seed !=
null) random =
new Random(
p.
seed);
234 Random dmodRandom =
new Random();
240 boolean upgrade = random.nextFloat() < Math.min(0.1f +
p.
quality * 0.5f, 0.5f);
261 SortedWeapons nonPriorityWeapons =
new SortedWeapons();
262 SortedWeapons priorityWeapons =
new SortedWeapons();
265 Set<String> weaponCategories =
new LinkedHashSet<String>();
273 throw new RuntimeException(
"Weapon with spec id [" + weaponId +
"] not found");
280 List<AvailableWeapon> list = priorityWeapons.getWeapons(tier).getWeapons(cat).getWeapons(spec.
getSize());
281 list.add(
new AvailableWeaponImpl(spec, 1000));
283 List<AvailableWeapon> list = nonPriorityWeapons.getWeapons(tier).getWeapons(cat).getWeapons(spec.
getSize());
284 list.add(
new AvailableWeaponImpl(spec, 1000));
286 weaponCategories.add(cat);
291 Set<String> fighterCategories =
new LinkedHashSet<String>();
297 throw new RuntimeException(
"Fighter wing with spec id [" + wingId +
"] not found");
307 priorityFighters.
add(cat,
new AvailableFighterImpl(spec, 1000));
309 nonPriorityFighters.
add(cat,
new AvailableFighterImpl(spec, 1000));
311 fighterCategories.add(cat);
327 if (!forceAutofit && member.getVariant() !=
null && member.getVariant().hasTag(
Tags.
TAG_NO_AUTOFIT)) {
341 if (
p.
seed !=
null) {
342 int extra = member.getShipName().hashCode();
343 random =
new Random(
p.
seed * extra);
349 sizes.add(WeaponSize.SMALL);
350 sizes.add(WeaponSize.MEDIUM);
351 sizes.add(WeaponSize.LARGE);
353 weapons =
new ArrayList<AvailableWeapon>();
354 for (String cat : weaponCategories) {
355 for (WeaponSize size : sizes) {
356 boolean foundSome =
false;
357 for (
int tier = 0; tier < 4; tier++) {
359 if (this.p.allWeapons !=
null &&
this.p.allWeapons) {
363 List<AvailableWeapon> priority = priorityWeapons.getWeapons(tier).getWeapons(cat).getWeapons(size);
364 List<AvailableWeapon> nonPriority = nonPriorityWeapons.getWeapons(tier).getWeapons(cat).getWeapons(size);
370 boolean tierAvailable = random.nextFloat() <
p;
371 if (!tierAvailable && foundSome)
continue;
376 case LARGE: num = 2;
break;
377 case MEDIUM: num = 2;
break;
378 case SMALL: num = 2;
break;
384 if (this.p.allWeapons !=
null &&
this.p.allWeapons) {
388 Set<Integer> picks =
makePicks(num, priority.size(), random);
389 for (Integer index : picks) {
397 picks =
makePicks(num, nonPriority.size(), random);
398 for (Integer index : picks) {
408 fighters =
new ArrayList<AvailableFighter>();
409 for (String cat : fighterCategories) {
410 List<AvailableFighter> priority = priorityFighters.
get(cat);
412 boolean madePriorityPicks =
false;
413 if (priority !=
null) {
414 int num = random.nextInt(2) + 1;
415 if (this.p.
allWeapons !=
null &&
this.p.allWeapons) {
419 Set<Integer> picks =
makePicks(num, priority.size(), random);
420 for (Integer index : picks) {
423 madePriorityPicks =
true;
427 if (!madePriorityPicks) {
428 int num = random.nextInt(2) + 1;
429 if (this.p.
allWeapons !=
null &&
this.p.allWeapons) {
433 List<AvailableFighter> nonPriority = nonPriorityFighters.
get(cat);
434 Set<Integer> picks =
makePicks(num, nonPriority.size(), random);
435 for (Integer index : picks) {
461 target = alts.
pick();
476 boolean randomize = random.nextFloat() < rProb;
477 if (member.isStation()) randomize =
false;
518 int dmods = (int) Math.round(averageDMods + random.nextDouble() * 3f - 2f);
519 if (dmods > 5) dmods = 5;
521 dmods -= dmodsAlready;
523 return Math.max(0, dmods);
527 float f = random.nextFloat();
528 int sMods = averageSMods;
530 sMods = averageSMods - 1;
531 }
else if (f < 0.5f) {
532 sMods = averageSMods + 1;
534 if (sMods > 3) sMods = 3;
535 if (sMods < 0) sMods = 0;
545 public static Set<Integer>
makePicks(
int num,
int max, Random random) {
546 if (num > max) num = max;
547 Set<Integer> result =
new LinkedHashSet<Integer>();
548 if (num == 0)
return result;
551 for (
int i = 0; i < max; i++) {
557 while (result.size() < num) {
558 int add = random.nextInt(max);
578 if (curr.getId().equals(curr.getId())) {
579 curr.setQuantity(curr.getQuantity() + 1);
588 if (curr.getId().equals(curr.getId())) {
589 curr.setQuantity(curr.getQuantity() + 1);
642 public static void main(String[] args) {
644 Random random =
new Random();
649 int []counts =
new int[10];
650 for (
int i = 0; i < num; i++) {
656 System.out.println(
"Average dmods: " + total / num);
657 for (
int i = 0; i <= 5; i++) {
658 System.out.println(i +
":" + counts[i]);
674 this.p.persistent = persistent;
683 this.p.quality = quality;
689 this.p.timestamp = timestamp;
static SettingsAPI getSettings()
static SectorAPI getSector()
static void addDMods(FleetMemberData data, boolean own, CampaignFleetAPI recoverer, Random random)
static boolean setDHull(ShipVariantAPI variant)
static int getNumDMods(ShipVariantAPI variant)
static float getAverageDmodsForQuality(float quality)
boolean removeAfterInflating()
void setPersistent(Boolean persistent)
static float GOAL_VARIANT_PROBABILITY
boolean isPriority(FighterWingSpecAPI wing)
transient List< AvailableWeapon > weapons
transient FactionAPI faction
DefaultFleetInflaterParams p
FleetMemberAPI getFleetMember()
transient FleetMemberAPI currMember
static int getNumDModsToAdd(ShipVariantAPI variant, float averageDMods, Random random)
DefaultFleetInflater(DefaultFleetInflaterParams p)
List< String > getAvailableHullmods()
boolean isPlayerCampaignRefit()
static float getTierProbability(int tier, float quality)
void clearWeaponSlot(WeaponSlotAPI slot, ShipVariantAPI variant)
transient CampaignFleetAPI fleet
boolean canAddRemoveHullmodInPlayerCampaignRefit(String modId)
transient List< String > hullmods
static int getMaxSMods(ShipVariantAPI variant, int averageSMods, Random random)
void fitFighterInSlot(int index, AvailableFighter fighter, ShipVariantAPI variant)
void clearFighterSlot(int index, ShipVariantAPI variant)
void inflate(CampaignFleetAPI fleet)
FleetMemberAPI getMember()
void syncUIWithVariant(ShipVariantAPI variant)
transient ShipVariantAPI currVariant
static Set< Integer > makePicks(int num, int max, Random random)
void setTimestamp(Long timestamp)
boolean isAllowSlightRandomization()
void fitWeaponInSlot(WeaponSlotAPI slot, AvailableWeapon weapon, ShipVariantAPI variant)
static void main(String[] args)
transient List< AvailableFighter > fighters
boolean isPriority(WeaponSpecAPI weapon)
void setRemoveAfterInflating(boolean removeAfterInflating)
List< AvailableWeapon > getAvailableWeapons()
List< AvailableFighter > getAvailableFighters()
void setQuality(float quality)
static final String MEMORY_KEY_FORCE_AUTOFIT_ON_NO_AUTOFIT_SHIPS
void setRandom(Random random)
void doFit(ShipVariantAPI current, ShipVariantAPI target, int maxSMods, AutofitPluginDelegate delegate)
void setChecked(String id, boolean checked)
List< V > get(Object key)
void add(String key, V value)
static Random getRandom(long seed, int level)
ShipVariantAPI getVariant(String variantId)
ShipVariantAPI createEmptyVariant(String hullVariantId, ShipHullSpecAPI hullSpec)
float getFloat(String key)
FighterWingSpecAPI getFighterWingSpec(String wingId)
WeaponSpecAPI getWeaponSpec(String weaponId)
List< ShipVariantAPI > getTargetVariants(String hullId)
FleetDataAPI getFleetData()
boolean isWeaponKnownAt(String weaponId, Long timestamp)
Set< String > getKnownFighters()
Set< String > getKnownWeapons()
boolean isWeaponPriority(String weaponId)
boolean isFighterKnownAt(String wing, Long timestamp)
Set< String > getKnownHullMods()
FactionDoctrineAPI getDoctrine()
boolean isPlayerFaction()
boolean isFighterPriority(String wingId)
float getAutofitRandomizeProbability()
List< FleetMemberAPI > getMembersListCopy()
FactionAPI getFaction(String factionId)
AutofitVariantsAPI getAutofitVariants()
MemoryAPI getMemoryWithoutUpdate()
boolean getBoolean(String key)
LinkedHashSet< String > getSMods()
String getOriginalVariant()
void addWeapon(String slotId, String weaponId)
void clearSlot(String slotId)
String getHullVariantId()
void setWingId(int index, String wingId)
void setOriginalVariant(String targetVariant)
ShipHullSpecAPI getHullSpec()
void setSource(VariantSource source)
String getAutofitCategory()
String getAutofitCategory()
void setQuantity(int quantity)
void setQuantity(int quantity)