001package com.fs.starfarer.api.impl.campaign.fleets; 002 003import java.util.ArrayList; 004import java.util.LinkedHashMap; 005import java.util.LinkedHashSet; 006import java.util.List; 007import java.util.Map; 008import java.util.Random; 009import java.util.Set; 010 011import com.fs.starfarer.api.Global; 012import com.fs.starfarer.api.campaign.CampaignFleetAPI; 013import com.fs.starfarer.api.campaign.CargoAPI; 014import com.fs.starfarer.api.campaign.FactionAPI; 015import com.fs.starfarer.api.campaign.FleetInflater; 016import com.fs.starfarer.api.campaign.econ.MarketAPI; 017import com.fs.starfarer.api.campaign.econ.SubmarketAPI; 018import com.fs.starfarer.api.characters.MutableCharacterStatsAPI; 019import com.fs.starfarer.api.combat.MutableShipStatsAPI; 020import com.fs.starfarer.api.combat.ShipAPI; 021import com.fs.starfarer.api.combat.ShipVariantAPI; 022import com.fs.starfarer.api.combat.WeaponAPI; 023import com.fs.starfarer.api.combat.WeaponAPI.WeaponSize; 024import com.fs.starfarer.api.fleet.FleetMemberAPI; 025import com.fs.starfarer.api.impl.campaign.DModManager; 026import com.fs.starfarer.api.impl.campaign.ids.MemFlags; 027import com.fs.starfarer.api.impl.campaign.ids.Tags; 028import com.fs.starfarer.api.loading.FighterWingSpecAPI; 029import com.fs.starfarer.api.loading.VariantSource; 030import com.fs.starfarer.api.loading.WeaponSlotAPI; 031import com.fs.starfarer.api.loading.WeaponSpecAPI; 032import com.fs.starfarer.api.plugins.AutofitPlugin.AutofitPluginDelegate; 033import com.fs.starfarer.api.plugins.AutofitPlugin.AvailableFighter; 034import com.fs.starfarer.api.plugins.AutofitPlugin.AvailableWeapon; 035import com.fs.starfarer.api.plugins.impl.CoreAutofitPlugin; 036import com.fs.starfarer.api.util.ListMap; 037import com.fs.starfarer.api.util.Misc; 038import com.fs.starfarer.api.util.WeightedRandomPicker; 039 040public class DefaultFleetInflater implements FleetInflater, AutofitPluginDelegate { 041 042 public static float GOAL_VARIANT_PROBABILITY = 0.5f; 043 044 045 public static class SortedWeapons { 046 protected Map<Integer, WeaponsForTier> tierMap = new LinkedHashMap<Integer, WeaponsForTier>(); 047 048 public WeaponsForTier getWeapons(int tier) { 049 WeaponsForTier data = tierMap.get(tier); 050 if (data == null) { 051 data = new WeaponsForTier(); 052 tierMap.put(tier, data); 053 } 054 return data; 055 } 056 } 057 058 public static class WeaponsForTier { 059// protected Map<String, List<AvailableWeapon>> catMap = new LinkedHashMap<String, List<AvailableWeapon>>(); 060// 061// public List<AvailableWeapon> getWeapons(String cat) { 062// List<AvailableWeapon> list = catMap.get(cat); 063// if (list == null) { 064// list = new ArrayList<AvailableWeapon>(); 065// catMap.put(cat, list); 066// } 067// return list; 068// } 069 protected Map<String, WeaponsForSize> catMap = new LinkedHashMap<String, WeaponsForSize>(); 070 071 public WeaponsForSize getWeapons(String cat) { 072 WeaponsForSize size = catMap.get(cat); 073 if (size == null) { 074 size = new WeaponsForSize(); 075 catMap.put(cat, size); 076 } 077 return size; 078 } 079 } 080 081 public static class WeaponsForSize { 082 protected Map<WeaponSize, List<AvailableWeapon>> sizeMap = new LinkedHashMap<WeaponAPI.WeaponSize, List<AvailableWeapon>>(); 083 public List<AvailableWeapon> getWeapons(WeaponSize size) { 084 List<AvailableWeapon> list = sizeMap.get(size); 085 if (list == null) { 086 list = new ArrayList<AvailableWeapon>(); 087 sizeMap.put(size, list); 088 } 089 return list; 090 } 091 } 092 093 public static class AvailableFighterImpl implements AvailableFighter { 094 protected FighterWingSpecAPI spec; 095 protected int quantity = 0; 096 097 public AvailableFighterImpl(FighterWingSpecAPI spec, int quantity) { 098 this.spec = spec; 099 this.quantity = quantity; 100 } 101 102 public AvailableFighterImpl(String wingId, int quantity) { 103 spec = Global.getSettings().getFighterWingSpec(wingId); 104 this.quantity = quantity; 105 } 106 107 public String getId() { 108 return spec.getId(); 109 } 110 public float getPrice() { 111 return 0; 112 } 113 public int getQuantity() { 114 return quantity; 115 } 116 public CargoAPI getSource() { 117 return null; 118 } 119 public SubmarketAPI getSubmarket() { 120 return null; 121 } 122 public FighterWingSpecAPI getWingSpec() { 123 return spec; 124 } 125 public void setQuantity(int quantity) { 126 this.quantity = quantity; 127 } 128 } 129 130 public static class AvailableWeaponImpl implements AvailableWeapon { 131 protected WeaponSpecAPI spec; 132 protected int quantity = 0; 133 public AvailableWeaponImpl(WeaponSpecAPI spec, int quantity) { 134 this.spec = spec; 135 this.quantity = quantity; 136 } 137 138 public String getId() { 139 return spec.getWeaponId(); 140 } 141 public float getPrice() { 142 return 0; 143 } 144 public int getQuantity() { 145 return quantity; 146 } 147 public CargoAPI getSource() { 148 return null; 149 } 150 public SubmarketAPI getSubmarket() { 151 return null; 152 } 153 public WeaponSpecAPI getSpec() { 154 return spec; 155 } 156 public void setQuantity(int quantity) { 157 this.quantity = quantity; 158 } 159 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; 164 165 cachedOPCost = spec.getOrdnancePointCost(stats, shipStats); 166 savedCostStats = shipStats; 167 return cachedOPCost; 168 } 169 } 170 171// protected float quality = 1f; 172// protected Long seed = null; 173// protected Long timestamp = null; 174// protected Boolean persistent = null; 175// protected ShipPickMode mode = null; 176 177 protected DefaultFleetInflaterParams p; 178 179 protected transient FleetMemberAPI currMember = null; 180 protected transient ShipVariantAPI currVariant = null; 181 protected transient List<AvailableFighter> fighters; 182 protected transient List<AvailableWeapon> weapons; 183 protected transient List<String> hullmods; 184 protected transient CampaignFleetAPI fleet; 185 protected transient FactionAPI faction; 186 187 188 public DefaultFleetInflater(DefaultFleetInflaterParams p) { 189 //this(p.quality, p.seed, p.persistent, p.mode, p.timestamp); 190 this.p = p; 191 } 192// public DefaultFleetInflater(float quality, Long seed, Boolean persistent, ShipPickMode mode, Long timestamp) { 193// this.quality = quality; 194// this.seed = seed; 195// this.persistent = persistent; 196// this.mode = mode; 197// this.timestamp = timestamp; 198// } 199 200 201 public static float getTierProbability(int tier, float quality) { 202 //if (true) return 1f; 203 204// if (tier == 1) return 0.5f + quality; 205// if (tier == 2) return 0.25f + quality * 0.5f; 206// if (tier == 3) return 0.125f + quality * 0.25f; 207 208 //if (tier != 0) return 0f; 209 210// if (tier == 1) return Math.min(0.9f, 0.5f + quality); 211// if (tier == 2) return Math.min(0.9f, 0.25f + quality * 0.5f); 212// if (tier == 3) return Math.min(0.9f, 0.125f + quality * 0.25f); 213 214 // since whether to upgrade or not is now randomized, higher probability of 215 // better tier weapons being available (as they may still not end up being used) 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); 219 220 return 1f; 221 } 222 223 224 public void inflate(CampaignFleetAPI fleet) { 225 Random random = new Random(); 226 //p.seed = null; 227 if (p.seed != null) random = new Random(p.seed); 228 229 //p.quality = 2f; 230 231 //random = new Random(); 232 233 234 Random dmodRandom = new Random(); 235 if (p.seed != null) dmodRandom = Misc.getRandom(p.seed, 5); 236 237 CoreAutofitPlugin auto = new CoreAutofitPlugin(fleet.getCommander()); 238 auto.setRandom(random); 239 240 boolean upgrade = random.nextFloat() < Math.min(0.1f + p.quality * 0.5f, 0.5f); 241 auto.setChecked(CoreAutofitPlugin.UPGRADE, upgrade); 242 243 //auto.setChecked(CoreAutofitPlugin.RANDOMIZE, true); 244 //auto.getOptions().get(4).checked = true; // upgrade 245 246 this.fleet = fleet; 247 this.faction = fleet.getFaction(); 248 if (p.factionId != null) { 249 this.faction = Global.getSector().getFaction(p.factionId); 250 } 251 252 //this.faction = Global.getSector().getFaction(Factions.HEGEMONY); 253 254 hullmods = new ArrayList<String>(faction.getKnownHullMods()); 255 256// fighters = new ArrayList<AvailableFighter>(); 257// for (String wingId : faction.getKnownFighters()) { 258// fighters.add(new AvailableFighterImpl(wingId, 1000)); 259// } 260 261 SortedWeapons nonPriorityWeapons = new SortedWeapons(); 262 SortedWeapons priorityWeapons = new SortedWeapons(); 263 264 265 Set<String> weaponCategories = new LinkedHashSet<String>(); 266 for (String weaponId : faction.getKnownWeapons()) { 267 if (!faction.isWeaponKnownAt(weaponId, p.timestamp)) continue; 268 269 WeaponSpecAPI spec = Global.getSettings().getWeaponSpec(weaponId); 270 //if (mode == ShipPickMode.IMPORTED && !spec.hasTag(Items.TAG_BASE_BP)) continue; 271 272 if (spec == null) { 273 throw new RuntimeException("Weapon with spec id [" + weaponId + "] not found"); 274 } 275 276 int tier = spec.getTier(); 277 String cat = spec.getAutofitCategory(); 278 279 if (isPriority(spec)) { 280 List<AvailableWeapon> list = priorityWeapons.getWeapons(tier).getWeapons(cat).getWeapons(spec.getSize()); 281 list.add(new AvailableWeaponImpl(spec, 1000)); 282 } else { 283 List<AvailableWeapon> list = nonPriorityWeapons.getWeapons(tier).getWeapons(cat).getWeapons(spec.getSize()); 284 list.add(new AvailableWeaponImpl(spec, 1000)); 285 } 286 weaponCategories.add(cat); 287 } 288 289 ListMap<AvailableFighter> nonPriorityFighters = new ListMap<AvailableFighter>(); 290 ListMap<AvailableFighter> priorityFighters = new ListMap<AvailableFighter>(); 291 Set<String> fighterCategories = new LinkedHashSet<String>(); 292 for (String wingId : faction.getKnownFighters()) { 293 if (!faction.isFighterKnownAt(wingId, p.timestamp)) continue; 294 295 FighterWingSpecAPI spec = Global.getSettings().getFighterWingSpec(wingId); 296 if (spec == null) { 297 throw new RuntimeException("Fighter wing with spec id [" + wingId + "] not found"); 298 } 299 300 //if (mode == ShipPickMode.IMPORTED && !spec.hasTag(Items.TAG_BASE_BP)) continue; 301 //int tier = spec.getTier(); 302 String cat = spec.getAutofitCategory(); 303// if (cat == null) { 304// System.out.println("wfewfwe"); 305// } 306 if (isPriority(spec)) { 307 priorityFighters.add(cat, new AvailableFighterImpl(spec, 1000)); 308 } else { 309 nonPriorityFighters.add(cat, new AvailableFighterImpl(spec, 1000)); 310 } 311 fighterCategories.add(cat); 312 } 313 314 315 //float averageDmods = (1f - quality) / Global.getSettings().getFloat("qualityPerDMod"); 316 float averageDmods = getAverageDmodsForQuality(p.quality); 317 318 //System.out.println("Quality: " + quality + ", Average: " + averageDmods); 319 320 boolean forceAutofit = fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_FORCE_AUTOFIT_ON_NO_AUTOFIT_SHIPS); 321 int memberIndex = 0; 322 for (FleetMemberAPI member : fleet.getFleetData().getMembersListCopy()) { 323 324 if (!forceAutofit && member.getHullSpec().hasTag(Tags.TAG_NO_AUTOFIT)) { 325 continue; 326 } 327 if (!forceAutofit && member.getVariant() != null && member.getVariant().hasTag(Tags.TAG_NO_AUTOFIT)) { 328 continue; 329 } 330 331 if (!faction.isPlayerFaction()) { 332 if (!forceAutofit && member.getHullSpec().hasTag(Tags.TAG_NO_AUTOFIT_UNLESS_PLAYER)) { 333 continue; 334 } 335 if (!forceAutofit && member.getVariant() != null && member.getVariant().hasTag(Tags.TAG_NO_AUTOFIT_UNLESS_PLAYER)) { 336 continue; 337 } 338 } 339 340 // need this so that when reinflating a fleet that lost members, the members reinflate consistently 341 if (p.seed != null) { 342 int extra = member.getShipName().hashCode(); 343 random = new Random(p.seed * extra); 344 auto.setRandom(random); 345 dmodRandom = Misc.getRandom(p.seed * extra, 5); 346 } 347 348 List<WeaponSize> sizes = new ArrayList<WeaponAPI.WeaponSize>(); 349 sizes.add(WeaponSize.SMALL); 350 sizes.add(WeaponSize.MEDIUM); 351 sizes.add(WeaponSize.LARGE); 352 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++) { 358 float p = getTierProbability(tier, this.p.quality); 359 if (this.p.allWeapons != null && this.p.allWeapons) { 360 p = 1f; 361 } 362 363 List<AvailableWeapon> priority = priorityWeapons.getWeapons(tier).getWeapons(cat).getWeapons(size); 364 List<AvailableWeapon> nonPriority = nonPriorityWeapons.getWeapons(tier).getWeapons(cat).getWeapons(size); 365 366 if (!foundSome) { 367 p = 1f; 368 } 369 370 boolean tierAvailable = random.nextFloat() < p; 371 if (!tierAvailable && foundSome) continue; 372 //if (random.nextFloat() >= p) continue; 373 374 int num = 2; 375 switch (size) { 376 case LARGE: num = 2; break; 377 case MEDIUM: num = 2; break; 378 case SMALL: num = 2; break; 379 } 380// if (!tierAvailable) { 381// num = 1; 382// } 383 384 if (this.p.allWeapons != null && this.p.allWeapons) { 385 num = 500; 386 } 387 388 Set<Integer> picks = makePicks(num, priority.size(), random); 389 for (Integer index : picks) { 390 AvailableWeapon w = priority.get(index); 391 weapons.add(w); 392 foundSome = true; 393 } 394 395 num -= picks.size(); 396 if (num > 0) { 397 picks = makePicks(num, nonPriority.size(), random); 398 for (Integer index : picks) { 399 AvailableWeapon w = nonPriority.get(index); 400 weapons.add(w); 401 foundSome = true; 402 } 403 } 404 } 405 } 406 } 407 408 fighters = new ArrayList<AvailableFighter>(); 409 for (String cat : fighterCategories) { 410 List<AvailableFighter> priority = priorityFighters.get(cat); 411 412 boolean madePriorityPicks = false; 413 if (priority != null) { 414 int num = random.nextInt(2) + 1; 415 if (this.p.allWeapons != null && this.p.allWeapons) { 416 num = 100; 417 } 418 419 Set<Integer> picks = makePicks(num, priority.size(), random); 420 for (Integer index : picks) { 421 AvailableFighter f = priority.get(index); 422 fighters.add(f); 423 madePriorityPicks = true; 424 } 425 } 426 427 if (!madePriorityPicks) { 428 int num = random.nextInt(2) + 1; 429 if (this.p.allWeapons != null && this.p.allWeapons) { 430 num = 100; 431 } 432 433 List<AvailableFighter> nonPriority = nonPriorityFighters.get(cat); 434 Set<Integer> picks = makePicks(num, nonPriority.size(), random); 435 for (Integer index : picks) { 436 AvailableFighter f = nonPriority.get(index); 437 fighters.add(f); 438 } 439 } 440 } 441 442// if (member.getHullId().equals("grendel")) { 443// System.out.println("efwefwef"); 444// } 445 ShipVariantAPI target = member.getVariant(); 446 if (target.getOriginalVariant() != null) { 447 // needed if inflating the same fleet repeatedly to pick up weapon availability changes etc 448 target = Global.getSettings().getVariant(target.getOriginalVariant()); 449 } 450 451 if (faction.isPlayerFaction()) { 452 if (random.nextFloat() < GOAL_VARIANT_PROBABILITY) { 453 List<ShipVariantAPI> targets = Global.getSector().getAutofitVariants().getTargetVariants(member.getHullId()); 454 WeightedRandomPicker<ShipVariantAPI> alts = new WeightedRandomPicker<ShipVariantAPI>(random); 455 for (ShipVariantAPI curr : targets) { 456 if (curr.getHullSpec().getHullId().equals(target.getHullSpec().getHullId())) { 457 alts.add(curr); 458 } 459 } 460 if (!alts.isEmpty()) { 461 target = alts.pick(); 462 } 463 } 464 } 465 466 467 currVariant = Global.getSettings().createEmptyVariant(fleet.getId() + "_" + memberIndex, target.getHullSpec()); 468 currMember = member; 469 470 if (target.isStockVariant()) { 471 currVariant.setOriginalVariant(target.getHullVariantId()); 472 } 473 474 float rProb = faction.getDoctrine().getAutofitRandomizeProbability(); 475 if (p.rProb != null) rProb = p.rProb; 476 boolean randomize = random.nextFloat() < rProb; 477 if (member.isStation()) randomize = false; 478 auto.setChecked(CoreAutofitPlugin.RANDOMIZE, randomize); 479 480 memberIndex++; 481 482 int maxSmods = 0; 483 if (p.averageSMods != null && !member.isCivilian()) { 484 maxSmods = getMaxSMods(currVariant, p.averageSMods, dmodRandom) - currVariant.getSMods().size(); 485 } 486 auto.doFit(currVariant, target, maxSmods, this); 487 currVariant.setSource(VariantSource.REFIT); 488 member.setVariant(currVariant, false, false); 489 490 //int dmods = (int) Math.round(averageDmods + dmodRandom.nextFloat() * 2f - 1f); 491// int dmods = (int) Math.round(averageDmods + dmodRandom.nextFloat() * 3f - 2f); 492// if (dmods > 5) dmods = 5; 493// int dmodsAlready = DModManager.getNumDMods(currVariant); 494// dmods -= dmodsAlready; 495// if (dmods > 0) { 496// DModManager.setDHull(currVariant); 497// DModManager.addDMods(member, true, dmods, dmodRandom); 498// } 499 500 if (!currMember.isStation()) { 501 int addDmods = getNumDModsToAdd(currVariant, averageDmods, dmodRandom); 502 if (addDmods > 0) { 503 DModManager.setDHull(currVariant); 504 DModManager.addDMods(member, true, addDmods, dmodRandom); 505 } 506 } 507 } 508 509 510 fleet.getFleetData().setSyncNeeded(); 511 fleet.getFleetData().syncIfNeeded(); 512 513 // handled in the method that calls inflate() 514 //ListenerUtil.reportFleetInflated(fleet, this); 515 } 516 517 public static int getNumDModsToAdd(ShipVariantAPI variant, float averageDMods, Random random) { 518 int dmods = (int) Math.round(averageDMods + random.nextDouble() * 3f - 2f); 519 if (dmods > 5) dmods = 5; 520 int dmodsAlready = DModManager.getNumDMods(variant); 521 dmods -= dmodsAlready; 522 523 return Math.max(0, dmods); 524 } 525 526 public static int getMaxSMods(ShipVariantAPI variant, int averageSMods, Random random) { 527 float f = random.nextFloat(); 528 int sMods = averageSMods; 529 if (f < 0.25f) { 530 sMods = averageSMods - 1; 531 } else if (f < 0.5f) { 532 sMods = averageSMods + 1; 533 } 534 if (sMods > 3) sMods = 3; 535 if (sMods < 0) sMods = 0; 536 return sMods; 537 } 538 539 public static float getAverageDmodsForQuality(float quality) { 540 float averageDmods = (1f - quality) / Global.getSettings().getFloat("qualityPerDMod"); 541 return averageDmods; 542 } 543 544 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; 549 550 if (num == max) { 551 for (int i = 0; i < max; i++) { 552 result.add(i); 553 } 554 return result; 555 } 556 557 while (result.size() < num) { 558 int add = random.nextInt(max); 559 result.add(add); 560 } 561 562 return result; 563 } 564 565 566 public boolean removeAfterInflating() { 567 return p.persistent == null || !p.persistent; 568 } 569 570 public void setRemoveAfterInflating(boolean removeAfterInflating) { 571 p.persistent = !removeAfterInflating; 572 if (!p.persistent) p.persistent = null; 573 } 574 575 public void clearFighterSlot(int index, ShipVariantAPI variant) { 576 variant.setWingId(index, null); 577 for (AvailableFighter curr : fighters) { 578 if (curr.getId().equals(curr.getId())) { 579 curr.setQuantity(curr.getQuantity() + 1); 580 break; 581 } 582 } 583 } 584 585 public void clearWeaponSlot(WeaponSlotAPI slot, ShipVariantAPI variant) { 586 variant.clearSlot(slot.getId()); 587 for (AvailableWeapon curr : weapons) { 588 if (curr.getId().equals(curr.getId())) { 589 curr.setQuantity(curr.getQuantity() + 1); 590 break; 591 } 592 } 593 } 594 595 public void fitFighterInSlot(int index, AvailableFighter fighter, ShipVariantAPI variant) { 596 fighter.setQuantity(fighter.getQuantity() - 1); 597 variant.setWingId(index, fighter.getId()); 598 } 599 600 public void fitWeaponInSlot(WeaponSlotAPI slot, AvailableWeapon weapon, ShipVariantAPI variant) { 601 weapon.setQuantity(weapon.getQuantity() - 1); 602 variant.addWeapon(slot.getId(), weapon.getId()); 603 } 604 605 public List<AvailableFighter> getAvailableFighters() { 606 return fighters; 607 } 608 609 public List<AvailableWeapon> getAvailableWeapons() { 610 return weapons; 611 } 612 613 public List<String> getAvailableHullmods() { 614 return hullmods; 615 } 616 617 public ShipAPI getShip() { 618 return null; 619 } 620 621 622// public void syncUIWithVariant() { 623// syncUIWithVariant(null); 624// } 625 public void syncUIWithVariant(ShipVariantAPI variant) { 626 627 } 628 629 public boolean isPriority(WeaponSpecAPI weapon) { 630 return faction.isWeaponPriority(weapon.getWeaponId()); 631 } 632 633 public boolean isPriority(FighterWingSpecAPI wing) { 634 return faction.isFighterPriority(wing.getId()); 635 } 636 637 public FleetMemberAPI getMember() { 638 return currMember; 639 } 640 641 642 public static void main(String[] args) { 643 644 Random random = new Random(); 645 646 647 float total = 0f; 648 float num = 1000f; 649 int []counts = new int[10]; 650 for (int i = 0; i < num; i++) { 651 int dmods = 1; 652 total += dmods; 653 counts[dmods]++; 654 } 655 656 System.out.println("Average dmods: " + total / num); 657 for (int i = 0; i <= 5; i++) { 658 System.out.println(i + ":" + counts[i]); 659 } 660 } 661 public FactionAPI getFaction() { 662 return faction; 663 } 664 public Long getSeed() { 665 return p.seed; 666 } 667 public void setSeed(Long seed) { 668 this.p.seed = seed; 669 } 670 public Boolean getPersistent() { 671 return p.persistent; 672 } 673 public void setPersistent(Boolean persistent) { 674 this.p.persistent = persistent; 675 } 676 public float getQuality() { 677 return p.quality; 678 } 679 public int getAverageNumSMods() { 680 return p.averageSMods == null ? 0 : p.averageSMods; 681 } 682 public void setQuality(float quality) { 683 this.p.quality = quality; 684 } 685 public Long getTimestamp() { 686 return p.timestamp; 687 } 688 public void setTimestamp(Long timestamp) { 689 this.p.timestamp = timestamp; 690 } 691 public Object getParams() { 692 return p; 693 } 694 695 696 public boolean canAddRemoveHullmodInPlayerCampaignRefit(String modId) { 697 return true; 698 } 699 700 public boolean isPlayerCampaignRefit() { 701 return false; 702 } 703 704 705 public boolean isAllowSlightRandomization() { 706 return true; 707 } 708 709 710 @Override 711 public MarketAPI getMarket() { 712 return null; 713 } 714 715 @Override 716 public FleetMemberAPI getFleetMember() { 717 return null; 718 } 719}