1package com.fs.starfarer.api.impl.campaign.procgen.themes;
3import java.util.ArrayList;
4import java.util.Collections;
5import java.util.Comparator;
6import java.util.EnumSet;
7import java.util.HashSet;
8import java.util.LinkedHashMap;
9import java.util.LinkedHashSet;
11import java.util.Random;
14import org.lwjgl.util.vector.Vector2f;
16import com.fs.starfarer.api.Global;
17import com.fs.starfarer.api.campaign.CampaignTerrainAPI;
18import com.fs.starfarer.api.campaign.CampaignTerrainPlugin;
19import com.fs.starfarer.api.campaign.CargoAPI;
20import com.fs.starfarer.api.campaign.CircularOrbitWithSpinAPI;
21import com.fs.starfarer.api.campaign.CustomCampaignEntityAPI;
22import com.fs.starfarer.api.campaign.LocationAPI;
23import com.fs.starfarer.api.campaign.OrbitAPI;
24import com.fs.starfarer.api.campaign.PlanetAPI;
25import com.fs.starfarer.api.campaign.SectorEntityToken;
26import com.fs.starfarer.api.campaign.StarSystemAPI;
27import com.fs.starfarer.api.campaign.econ.MarketAPI;
28import com.fs.starfarer.api.campaign.rules.MemoryAPI;
29import com.fs.starfarer.api.impl.campaign.DerelictShipEntityPlugin;
30import com.fs.starfarer.api.impl.campaign.DerelictShipEntityPlugin.DerelictShipData;
31import com.fs.starfarer.api.impl.campaign.ids.Conditions;
32import com.fs.starfarer.api.impl.campaign.ids.Entities;
33import com.fs.starfarer.api.impl.campaign.ids.Factions;
34import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
35import com.fs.starfarer.api.impl.campaign.ids.Tags;
36import com.fs.starfarer.api.impl.campaign.procgen.Constellation;
37import com.fs.starfarer.api.impl.campaign.procgen.ObjectiveGenDataSpec;
38import com.fs.starfarer.api.impl.campaign.procgen.SalvageEntityGenDataSpec;
39import com.fs.starfarer.api.impl.campaign.procgen.SalvageEntityGenDataSpec.DropData;
40import com.fs.starfarer.api.impl.campaign.procgen.StarSystemGenerator;
41import com.fs.starfarer.api.impl.campaign.procgen.StarSystemGenerator.LagrangePointType;
42import com.fs.starfarer.api.impl.campaign.procgen.StarSystemGenerator.StarSystemType;
43import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.SalvageEntity;
44import com.fs.starfarer.api.impl.campaign.terrain.AsteroidBeltTerrainPlugin;
45import com.fs.starfarer.api.impl.campaign.terrain.AsteroidFieldTerrainPlugin;
46import com.fs.starfarer.api.impl.campaign.terrain.BaseRingTerrain;
47import com.fs.starfarer.api.impl.campaign.terrain.BaseTiledTerrain;
48import com.fs.starfarer.api.impl.campaign.terrain.DebrisFieldTerrainPlugin;
49import com.fs.starfarer.api.impl.campaign.terrain.DebrisFieldTerrainPlugin.DebrisFieldParams;
50import com.fs.starfarer.api.impl.campaign.terrain.DebrisFieldTerrainPlugin.DebrisFieldSource;
51import com.fs.starfarer.api.impl.campaign.terrain.MagneticFieldTerrainPlugin;
52import com.fs.starfarer.api.impl.campaign.terrain.NebulaTerrainPlugin;
53import com.fs.starfarer.api.impl.campaign.terrain.PulsarBeamTerrainPlugin;
54import com.fs.starfarer.api.impl.campaign.terrain.RadioChatterTerrainPlugin;
55import com.fs.starfarer.api.impl.campaign.terrain.RingSystemTerrainPlugin;
56import com.fs.starfarer.api.impl.campaign.terrain.StarCoronaTerrainPlugin;
57import com.fs.starfarer.api.util.Misc;
58import com.fs.starfarer.api.util.WeightedRandomPicker;
62 public static enum HabitationLevel {
68 public static class StarSystemData {
70 public List<PlanetAPI> stars =
new ArrayList<PlanetAPI>();
71 public List<PlanetAPI> planets =
new ArrayList<PlanetAPI>();
72 public List<PlanetAPI> habitable =
new ArrayList<PlanetAPI>();
73 public List<PlanetAPI> gasGiants =
new ArrayList<PlanetAPI>();
74 public List<PlanetAPI> resourceRich =
new ArrayList<PlanetAPI>();
76 public Set<SectorEntityToken> alreadyUsed =
new LinkedHashSet<SectorEntityToken>();
78 public Set<AddedEntity> generated =
new LinkedHashSet<AddedEntity>();
80 public boolean isBlackHole() {
84 public boolean isPulsar() {
89 public boolean isNebula() {
94 public String toString() {
95 return String.format(system.
getName() +
" %d %d %d %d %d", stars.size(), planets.size(), habitable.size(),
107 public static class AddedEntity {
109 public EntityLocation location;
110 public String entityType;
111 public AddedEntity(
SectorEntityToken entity, EntityLocation location, String entityType) {
112 this.entity = entity;
113 this.location = location;
114 this.entityType = entityType;
119 public static enum LocationType {
135 public static class EntityLocation {
136 public LocationType type;
137 public Vector2f location =
null;
142 public String toString() {
143 return String.format(
"Type: %s, orbitPeriod: %s", type.name(), orbit ==
null ?
"null" :
"" + orbit.
getOrbitalPeriod());
166 if (
random.nextFloat() >= chanceToAddAny)
return;
167 int num = min +
random.nextInt(max - min + 1);
169 for (
int i = 0; i < num; i++) {
170 LinkedHashMap<LocationType, Float> weights =
new LinkedHashMap<LocationType, Float>();
178 weights.put(LocationType.STAR_ORBIT, 5f);
180 EntityLocation loc = locs.
pick();
197 int numShips =
random.nextInt(9) + 3;
199 if (
DEBUG) System.out.println(
" Adding ship graveyard (" + numShips +
" ships)");
202 for (
int i = 0; i < numShips + 5; i++) {
203 bands.
add(
new Float(140 + i * 20), (i + 1) * (i + 1));
211 for (
int i = 0; i < numShips; i++) {
215 if (hulls !=
null && !hulls.
isEmpty()) {
218 if (params !=
null) {
223 float orbitDays = radius / (5f +
random.nextFloat() * 10f);
225 if (
DEBUG) System.out.println(
" Added ship: " +
228 AddedEntity added =
new AddedEntity(entity,
null,
Entities.
WRECK);
229 data.generated.add(added);
235 if (
random.nextFloat() >= chanceToAddAny)
return;
239 int num = min +
random.nextInt(max - min + 1);
240 for (
int i = 0; i < num; i++) {
248 if (
random.nextFloat() >= chanceToAddAny)
return;
250 int num = min +
random.nextInt(max - min + 1);
251 if (
DEBUG) System.out.println(
" Adding " + num +
" mining stations");
252 for (
int i = 0; i < num; i++) {
253 List<PlanetAPI> miningCandidates =
new ArrayList<PlanetAPI>();
254 miningCandidates.addAll(data.gasGiants);
255 miningCandidates.addAll(data.resourceRich);
257 LinkedHashMap<LocationType, Float> weights =
new LinkedHashMap<LocationType, Float>();
258 weights.put(LocationType.IN_ASTEROID_BELT, 10f);
259 weights.put(LocationType.IN_ASTEROID_FIELD, 10f);
260 weights.put(LocationType.IN_RING, 10f);
261 weights.put(LocationType.IN_SMALL_NEBULA, 10f);
263 EntityLocation loc = locs.
pick();
265 String type = stationTypes.
pick();
266 if (loc !=
null || !miningCandidates.isEmpty()) {
267 if ((
random.nextFloat() > 0.5f && loc !=
null) || miningCandidates.isEmpty()) {
270 PlanetAPI planet = miningCandidates.get(
random.nextInt(miningCandidates.size()));
273 data.alreadyUsed.add(planet);
284 if (
random.nextFloat() >= chanceToAddAny)
return;
287 for (
PlanetAPI planet : data.habitable) {
290 if (h < 0.1f) h = 0.1f;
292 habPlanets.
add(planet, w);
297 if (data.habitable.contains(planet))
continue;
298 otherPlanets.
add(planet);
301 int num = min +
random.nextInt(max - min + 1);
302 if (
DEBUG) System.out.println(
" Adding up to " + num +
" hab centers on planets/in orbit");
303 for (
int i = 0; i < num; i++) {
318 data.alreadyUsed.add(planet);
319 }
else if (option == 1) {
322 data.alreadyUsed.add(planet);
323 }
else if (option == 2) {
324 String type = stationTypes.
pick();
333 if (
random.nextFloat() >= chanceToAddAny)
return;
335 int num = min +
random.nextInt(max - min + 1);
336 if (
DEBUG) System.out.println(
" Adding " + num +
" research stations");
337 for (
int i = 0; i < num; i++) {
338 String type = stationTypes.
pick();
340 List<PlanetAPI> researchCandidates =
new ArrayList<PlanetAPI>();
341 researchCandidates.addAll(data.gasGiants);
343 LinkedHashMap<LocationType, Float> weights =
new LinkedHashMap<LocationType, Float>();
344 weights.put(LocationType.IN_SMALL_NEBULA, 5f);
345 weights.put(LocationType.GAS_GIANT_ORBIT, 10f);
346 weights.put(LocationType.NEAR_STAR, 5f);
348 EntityLocation loc = locs.
pick();
355 data.alreadyUsed.add(planet);
364 if (planet ==
null)
return;
370 if (
DEBUG) System.out.println(
" Added " + ruins +
" to " + market.
getName());
373 if (
DEBUG) System.out.println(
" Added decivilized to " + market.
getName());
379 float chance = 0.25f;
392 return random.nextFloat() < chance;
397 List<AddedEntity> result =
new ArrayList<AddedEntity>();
399 Set<String> used =
new HashSet<String>();
404 if (
random.nextFloat() >= prob * mult)
continue;
414 if (pick ==
null)
break;
423 if (loc.getOrbit() !=
null) {
424 built.
setOrbit(loc.getOrbit().makeCopy());
426 built.
setLocation(loc.getLocation().x, loc.getLocation().y);
429 AddedEntity e =
new AddedEntity(built,
null, pick.
getId());
443 if (
random.nextFloat() >= prob)
return null;
445 LinkedHashMap<LocationType, Float> weights =
new LinkedHashMap<LocationType, Float>();
446 weights.put(LocationType.STAR_ORBIT, 10f);
447 weights.put(LocationType.OUTER_SYSTEM, 10f);
449 EntityLocation loc = locs.
pick();
452 if (
DEBUG && added !=
null) System.out.println(
" Added comm relay");
464 if (
random.nextFloat() >= prob)
return null;
472 LinkedHashMap<LocationType, Float> weights =
new LinkedHashMap<LocationType, Float>();
473 weights.put(LocationType.STAR_ORBIT, 10f);
474 weights.put(LocationType.OUTER_SYSTEM, 10f);
476 EntityLocation loc = locs.
pick();
484 if (
random.nextFloat() < probDebris) {
485 if (
DEBUG && added !=
null) System.out.println(
" Added debris field around gate");
487 if (
random.nextFloat() < probShips) {
488 if (
DEBUG && added !=
null) System.out.println(
" Added ship graveyard around gate");
503 float add1 = 0, add2 = 0;
508 }
else if (hazard <= 1.25f) {
518 return picker.
pick();
522 public AddedEntity
addStation(EntityLocation loc, StarSystemData data, String customEntityId, String factionId) {
523 if (loc ==
null)
return null;
525 AddedEntity station =
addEntity(
random, data.system, loc, customEntityId, factionId);
526 if (station !=
null) {
527 data.generated.add(station);
530 if (
DEBUG) System.out.println(
" Added " + customEntityId);
533 data.alreadyUsed.add(planet);
537 if (planet.
isStar() && !nearStar) {
553 if (
random.nextFloat() >= chanceToAddAny)
return;
555 int num = min +
random.nextInt(max - min + 1);
556 if (
DEBUG) System.out.println(
" Adding " + num +
" resource caches");
557 for (
int i = 0; i < num; i++) {
559 String type = cacheTypes.
pick();
562 data.generated.add(added);
565 if (
DEBUG && added !=
null) System.out.println(
" Added resource cache: " + type);
569 public void addDebrisFields(StarSystemData data,
float chanceToAddAny,
int min,
int max) {
572 public void addDebrisFields(StarSystemData data,
float chanceToAddAny,
int min,
int max, String defFaction,
float defProb,
int minStr,
int maxStr) {
573 if (
random.nextFloat() >= chanceToAddAny)
return;
575 int numDebrisFields = min +
random.nextInt(max - min + 1);
576 if (
DEBUG) System.out.println(
" Adding up to " + numDebrisFields +
" debris fields");
577 for (
int i = 0; i < numDebrisFields; i++) {
580 float radius = 150f +
random.nextFloat() * 300f;
582 if (loc ==
null)
continue;
584 DebrisFieldParams params =
new DebrisFieldParams(
590 if (defFaction !=
null) {
591 params.defFaction = defFaction;
592 params.defenderProb = defProb;
593 params.minStr = minStr;
594 params.maxStr = maxStr;
597 params.source = DebrisFieldSource.GEN;
602 data.generated.add(added);
604 if (
DEBUG) System.out.println(
" Added debris field");
609 DebrisFieldParams params =
new DebrisFieldParams(
615 params.source = DebrisFieldSource.GEN;
618 if (
DEBUG) System.out.println(
" Added debris field");
620 EntityLocation loc =
new EntityLocation();
621 loc.type = LocationType.OUTER_SYSTEM;
623 data.generated.add(added);
636 for (
int i = 0; i < params.length; i += 2) {
637 String item = (String) params[i];
639 if (params[i+1] instanceof Float) {
640 weight = (Float) params[i+1];
641 }
else if (params[i+1] instanceof Integer) {
642 weight = (Integer) params[i+1];
644 picker.
add(item, weight);
651 if (loc ==
null)
return;
657 String faction = factions.
pick();
659 if (params !=
null) {
664 if (
DEBUG) System.out.println(
" Added ship: " +
667 AddedEntity added =
new AddedEntity(entity,
null,
Entities.
WRECK);
668 data.generated.add(added);
673 public AddedEntity
addDerelictShip(StarSystemData data, EntityLocation loc, String variantId) {
674 if (loc ==
null)
return null;
677 if (params !=
null) {
682 if (
DEBUG) System.out.println(
" Added ship: " +
685 AddedEntity added =
new AddedEntity(entity,
null,
Entities.
WRECK);
686 data.generated.add(added);
696 LinkedHashMap<LocationType, Float> weights =
new LinkedHashMap<LocationType, Float>();
697 weights.put(LocationType.PLANET_ORBIT, 10f);
698 if (allowStarOrbit) {
699 weights.put(LocationType.STAR_ORBIT, 10f);
701 weights.put(LocationType.GAS_GIANT_ORBIT, 5f);
711 LinkedHashMap<LocationType, Float> weights =
new LinkedHashMap<LocationType, Float>();
712 weights.put(LocationType.IN_ASTEROID_BELT, 5f);
713 weights.put(LocationType.IN_ASTEROID_FIELD, 5f);
714 weights.put(LocationType.IN_RING, 5f);
715 weights.put(LocationType.IN_SMALL_NEBULA, 5f);
716 weights.put(LocationType.L_POINT, 5f);
717 weights.put(LocationType.GAS_GIANT_ORBIT, 5f);
718 weights.put(LocationType.JUMP_ORBIT, 5f);
719 weights.put(LocationType.NEAR_STAR, 5f);
720 weights.put(LocationType.OUTER_SYSTEM, 5f);
730 LinkedHashMap<LocationType, Float> weights =
new LinkedHashMap<LocationType, Float>();
731 weights.put(LocationType.PLANET_ORBIT, 10f);
732 weights.put(LocationType.STAR_ORBIT, 10f);
733 weights.put(LocationType.IN_ASTEROID_BELT, 5f);
734 weights.put(LocationType.IN_ASTEROID_FIELD, 5f);
735 weights.put(LocationType.IN_RING, 5f);
736 weights.put(LocationType.IN_SMALL_NEBULA, 5f);
737 weights.put(LocationType.L_POINT, 5f);
738 weights.put(LocationType.GAS_GIANT_ORBIT, 5f);
739 weights.put(LocationType.JUMP_ORBIT, 5f);
740 weights.put(LocationType.NEAR_STAR, 5f);
741 weights.put(LocationType.OUTER_SYSTEM, 5f);
748 LinkedHashMap<LocationType, Float> weights =
new LinkedHashMap<LocationType, Float>();
749 weights.put(LocationType.IN_ASTEROID_BELT, 5f);
750 weights.put(LocationType.IN_ASTEROID_FIELD, 5f);
751 weights.put(LocationType.IN_RING, 5f);
752 weights.put(LocationType.IN_SMALL_NEBULA, 5f);
753 weights.put(LocationType.L_POINT, 5f);
754 weights.put(LocationType.GAS_GIANT_ORBIT, 5f);
755 weights.put(LocationType.NEAR_STAR, 5f);
756 weights.put(LocationType.OUTER_SYSTEM, 5f);
766 LinkedHashMap<LocationType, Float> weights =
new LinkedHashMap<LocationType, Float>();
767 weights.put(LocationType.IN_ASTEROID_BELT, 5f);
768 weights.put(LocationType.IN_ASTEROID_FIELD, 5f);
769 weights.put(LocationType.IN_RING, 5f);
770 weights.put(LocationType.IN_SMALL_NEBULA, 5f);
771 weights.put(LocationType.L_POINT, 5f);
772 weights.put(LocationType.GAS_GIANT_ORBIT, 5f);
773 weights.put(LocationType.OUTER_SYSTEM, 5f);
786 float minGap, LinkedHashMap<LocationType, Float> weights) {
790 float minGap, LinkedHashMap<LocationType, Float> weights) {
803 if (outer < 3000) outer = 3000;
804 if (outer > 25000) outer = 25000;
806 StarSystemType systemType = system.
getType();
808 for (LocationType type : weights.keySet()) {
809 float weight = weights.get(type);
810 List<EntityLocation> locs =
new ArrayList<EntityLocation>();
815 if (planet.isGasGiant())
continue;
816 if (planet.isStar())
continue;
817 if (exclude !=
null && exclude.contains(planet))
continue;
820 List<OrbitGap> gaps =
findGaps(planet, 100f, 100f + ow + minGap, minGap);
822 if (loc !=
null) locs.add(loc);
827 if (planet.isStar())
continue;
828 if (planet.isMoon())
continue;
829 if (planet.getRadius() < 100)
continue;
830 if (planet.getOrbit() ==
null || planet.getOrbit().getFocus() ==
null)
continue;
831 if (planet.getCircularOrbitRadius() <= 0)
continue;
832 for (LagrangePointType lpt : EnumSet.of(LagrangePointType.L4, LagrangePointType.L5)) {
833 float orbitRadius = planet.getCircularOrbitRadius();
834 float angleOffset = -StarSystemGenerator.LAGRANGE_OFFSET * 0.5f;
835 if (lpt == LagrangePointType.L5) angleOffset = StarSystemGenerator.LAGRANGE_OFFSET * 0.5f;
836 float angle = planet.getCircularOrbitAngle() + angleOffset;
838 location.scale(orbitRadius);
839 Vector2f.add(location, planet.getOrbit().getFocus().getLocation(), location);
843 EntityLocation loc =
new EntityLocation();
845 float orbitDays = planet.getCircularOrbitPeriod();
849 angle, orbitRadius, orbitDays,
random.nextFloat() * 10f + 1f);
855 case GAS_GIANT_ORBIT:
857 if (planet.isStar())
continue;
858 if (!planet.isGasGiant())
continue;
859 if (exclude !=
null && exclude.contains(planet))
continue;
862 List<OrbitGap> gaps =
findGaps(planet, 100f, 100f + ow + minGap, minGap);
864 if (loc !=
null) locs.add(loc);
870 if (exclude !=
null && exclude.contains(point))
continue;
871 List<OrbitGap> gaps =
findGaps(point, 200f, 200f + point.getRadius() + minGap, minGap);
873 if (loc !=
null) locs.add(loc);
877 if (systemType != StarSystemType.NEBULA) {
881 List<OrbitGap> gaps =
findGaps(system.
getStar(), 200f, 200f + r + minGap, minGap);
883 if (loc !=
null) locs.add(loc);
889 if (loc !=
null) locs.add(loc);
895 if (loc !=
null) locs.add(loc);
901 if (exclude !=
null && exclude.contains(terrain))
continue;
906 float start = ring.params.middleRadius - ring.params.bandWidthInEngine / 2f;
907 List<OrbitGap> gaps =
findGaps(terrain,
908 start - 100f, start + ring.
params.bandWidthInEngine + 100f, minGap);
910 if (loc !=
null) locs.add(loc);
914 case IN_SMALL_NEBULA:
916 if (exclude !=
null && exclude.contains(terrain))
continue;
920 float tilesHigh = nebula.
getTiles()[0].length;
921 float tilesWide = nebula.
getTiles().length;
923 float w = ts * tilesWide;
924 float h = ts * tilesHigh;
926 float r = (float) Math.sqrt(w * w + h * h);
927 if (terrain.getOrbit() ==
null) {
929 EntityLocation loc =
new EntityLocation();
931 loc.location = point;
935 float min = Math.min(100f, r * 0.25f);
937 EntityLocation loc =
new EntityLocation();
939 float orbitRadius = min + (max - min) * (0.75f *
random.nextFloat());
940 float orbitDays = orbitRadius / (20f +
random.nextFloat() * 5f);
942 random.nextFloat() * 360f, orbitRadius, orbitDays,
random.nextFloat() * 10f + 1f);
949 case IN_ASTEROID_BELT:
951 if (exclude !=
null && exclude.contains(terrain))
continue;
955 if (ring.
params !=
null) {
956 float start = ring.params.middleRadius - ring.params.bandWidthInEngine / 2f;
957 List<OrbitGap> gaps =
findGaps(terrain,
958 start - 100f, start + ring.
params.bandWidthInEngine + 100f, minGap);
960 if (loc !=
null) locs.add(loc);
967 case IN_ASTEROID_FIELD:
969 if (exclude !=
null && exclude.contains(terrain))
continue;
974 float min = Math.min(100f, ring.
params.bandWidthInEngine * 0.25f);
975 float max = ring.
params.bandWidthInEngine;
976 EntityLocation loc =
new EntityLocation();
978 float orbitRadius = min + (max - min) * (0.75f *
random.nextFloat());
979 float orbitDays = orbitRadius / (20f +
random.nextFloat() * 5f);
983 random.nextFloat() * 360f, orbitRadius, orbitDays,
random.nextFloat() * 10f + 1f);
1002 EntityLocation loc =
new EntityLocation();
1014 orbitRadius, orbitDays,
random.nextFloat() * 10f + 1f);
1016 }
else if (near !=
null) {
1017 EntityLocation loc =
new EntityLocation();
1019 float orbitRadius = outer + 500f + 500f *
random.nextFloat();
1020 float orbitDays = orbitRadius / (20f +
random.nextFloat() * 5f);
1022 random.nextFloat() * 360f, orbitRadius, orbitDays,
random.nextFloat() * 10f + 1f);
1033 List<SectorEntityToken> secondary =
new ArrayList<SectorEntityToken>();
1038 case TRINARY_1CLOSE_1FAR:
1048 List<OrbitGap> gaps =
findGaps(main, inner, outer + minGap, minGap);
1050 for (OrbitGap gap : gaps) {
1051 loc = createLocationAtGap(
random, main, gap, type);
1052 if (loc !=
null) locs.add(loc);
1058 if (ow < 3000) ow = 3000;
1060 List<OrbitGap> gaps =
findGaps(star, r, ow + r + minGap, minGap);
1062 for (OrbitGap gap : gaps) {
1063 loc = createLocationAtGap(
random, star, gap, type);
1064 if (loc !=
null) locs.add(loc);
1072 if (system.
getType() == StarSystemType.NEBULA) {
1073 for (EntityLocation loc : locs) {
1074 if (loc.orbit !=
null && loc.orbit.getFocus() == system.
getCenter()) {
1075 loc.location = loc.orbit.computeCurrentLocation();
1081 if (!locs.isEmpty()) {
1082 float weightPer = weight / (float) locs.size();
1083 for (EntityLocation loc : locs) {
1084 result.
add(loc, weightPer);
1096 List<OrbitGap> gaps =
findGaps(center, 100f, 100f + ow + minGap, minGap);
1103 if (gaps.isEmpty())
return null;
1107 OrbitGap gap = picker.
pick();
1108 return createLocationAtGap(
random, center, gap, type);
1111 private static EntityLocation createLocationAtGap(Random
random,
SectorEntityToken center, OrbitGap gap, LocationType type) {
1114 EntityLocation loc =
new EntityLocation();
1116 float orbitRadius = gap.start + (gap.end - gap.start) * (0.25f + 0.5f *
random.nextFloat());
1117 float orbitDays = orbitRadius / (20f +
random.nextFloat() * 5f);
1121 random.nextFloat() * 360f, orbitRadius, orbitDays,
random.nextFloat() * 10f + 1f);
1128 public static class OrbitGap {
1133 public static class OrbitItem {
1135 public float orbitRadius;
1136 public float orbitalWidth;
1140 List<OrbitGap> gaps =
new ArrayList<OrbitGap>();
1143 if (loc ==
null)
return gaps;
1145 List<OrbitItem> items =
new ArrayList<OrbitItem>();
1147 if (planet.getOrbitFocus() != center)
continue;
1149 OrbitItem item =
new OrbitItem();
1151 item.orbitRadius = planet.getCircularOrbitRadius();
1152 if (item.orbitRadius > maxDist)
continue;
1159 if (terrain.getOrbitFocus() != center)
continue;
1169 OrbitItem item =
new OrbitItem();
1170 item.item = terrain;
1171 item.orbitRadius = ring.
params.middleRadius;
1172 if (item.orbitRadius > maxDist)
continue;
1174 item.orbitalWidth = ring.
params.bandWidthInEngine;
1181 if (custom.getOrbitFocus() != center)
continue;
1183 OrbitItem item =
new OrbitItem();
1185 item.orbitRadius = custom.getCircularOrbitRadius();
1186 if (item.orbitRadius > maxDist)
continue;
1188 item.orbitalWidth = custom.getRadius() * 2f;
1195 if (point.getOrbitFocus() != center)
continue;
1197 OrbitItem item =
new OrbitItem();
1199 item.orbitRadius = point.getCircularOrbitRadius();
1200 if (item.orbitRadius > maxDist)
continue;
1202 item.orbitalWidth = point.getRadius() * 2f;
1206 Collections.sort(items,
new Comparator<OrbitItem>() {
1207 public int compare(OrbitItem o1, OrbitItem o2) {
1208 return (
int)Math.signum(o1.orbitRadius - o2.orbitRadius);
1212 float prev = center.
getRadius() + minPad;
1213 for (OrbitItem item : items) {
1214 float next = item.orbitRadius - item.orbitalWidth / 2f;
1215 if (next - prev >= minGap) {
1216 OrbitGap gap =
new OrbitGap();
1221 prev = Math.max(prev, item.orbitRadius + item.orbitalWidth / 2f);
1224 if (maxDist - prev >= minGap) {
1225 OrbitGap gap =
new OrbitGap();
1244 if (system.
getStar() ==
null)
return 0;
1247 case TRINARY_1CLOSE_1FAR:
1250 case TRINARY_2CLOSE:
1266 float threshold = max * 0.75f;
1270 if (r > threshold) {
1299 r += point.getRadius();
1300 if (r > threshold) {
1305 return picker.
pick();
1315 if (r > max) max = r;
1323 float r = ring.params.middleRadius + ring.params.bandWidthInEngine * 0.5f;
1325 if (r > max) max = r;
1332 if (r > max) max = r;
1347 r += point.getRadius();
1348 if (r > max) max = r;
1360 if (dist < range + planet.getRadius())
return false;
1366 if (dist < range + custom.getRadius()) {
1379 float r = ring.params.middleRadius + ring.params.bandWidthInEngine * 0.5f;
1381 if (dist < range + r)
return false;
1390 if (loc ==
null)
return center.
getRadius();
1394 if (planet.getOrbitFocus() != center)
continue;
1396 if (r > max) max = r;
1400 if (terrain.getOrbitFocus() != center)
continue;
1408 float r = ring.params.middleRadius + ring.params.bandWidthInEngine * 0.5f;
1409 if (r > max) max = r;
1415 if (custom.getOrbitFocus() != center)
continue;
1416 float r = custom.getCircularOrbitRadius() + custom.getRadius();
1417 if (r > max) max = r;
1431 if (loc.orbit !=
null) {
1438 AddedEntity data =
new AddedEntity(entity, loc, type);
1456 if (loc.orbit !=
null) {
1463 AddedEntity data =
new AddedEntity(entity, loc, type);
1471 if (loc.orbit !=
null) {
1478 AddedEntity data =
new AddedEntity(entity, loc, type);
1504 case ALWAYS_VISIBLE:
1512 case NOT_DISCOVERABLE:
1518 long seed =
random.nextLong();
1532 List<DropData> dropValue =
new ArrayList<DropData>(entity.
getDropValue());
1533 List<DropData> dropRandom =
new ArrayList<DropData>(entity.
getDropRandom());
1548 StarSystemData data =
new StarSystemData();
1549 data.system = system;
1552 if (planet.isStar()) {
1553 data.stars.add(planet);
1555 data.planets.add(planet);
1558 if (planet.isGasGiant()) {
1559 data.gasGiants.add(planet);
1562 if (planet.getMarket() !=
null && planet.getMarket().isPlanetConditionMarketOnly()) {
1565 data.habitable.add(planet);
1570 data.resourceRich.add(planet);
1582 if (market ==
null)
return;
1593 if (focus !=
null) {
1606 if (focus !=
null) {
1617 if (focus !=
null) {
1642 List<Constellation> constellations =
new ArrayList<Constellation>();
1647 constellations.add(c);
1650 if (exclude !=
null) {
1651 constellations.removeAll(exclude);
1654 Collections.sort(constellations,
new Comparator<Constellation>() {
1658 return (
int) Math.signum(d2 - d1);
1661 return constellations;
1672 if (!p.isStar())
return false;
static SettingsAPI getSettings()
static FactoryAPI getFactory()
void modifyFlat(String source, float value)
static float getDefaultSModProb()
static DerelictShipData createRandom(String factionId, DerelictType type, Random random)
static DerelictShipData createVariant(String variantId, Random random, float sModProb)
static DerelictShipData createHull(String hullId, Random random, float sModProb)
static final String RUINS_WIDESPREAD
static final String RUINS_SCATTERED
static final String RUINS_EXTENSIVE
static final String RUINS_VAST
static final String DECIVILIZED
static final String HABITABLE
static final String INACTIVE_GATE
static final String WRECK
static final String COMM_RELAY
static final String DEBRIS_FIELD_SHARED
static final String NEUTRAL
static final String OBJECTIVE_NON_FUNCTIONAL
static final String SALVAGE_SEED
List< StarSystemAPI > getSystems()
float getDetectionRange()
DiscoverabilityType getType()
float getRadiusOverride()
List< DropData > getDropValue()
List< DropData > getDropRandom()
static EntityLocation pickHiddenLocationNotNearStar(Random random, StarSystemAPI system, float gap, Set< SectorEntityToken > exclude)
static AddedEntity addEntityAutoDetermineType(Random random, LocationAPI system, EntityLocation loc, String type, String faction)
List< Constellation > getSortedAvailableConstellations(ThemeGenContext context, boolean emptyOk, final Vector2f sortFrom, List< Constellation > exclude)
static SectorEntityToken addSalvageEntity(Random random, LocationAPI location, String id, String faction)
void addShipGraveyard(StarSystemData data, float chanceToAddAny, int min, int max, WeightedRandomPicker< String > factions)
void addRuins(PlanetAPI planet)
static StarSystemData computeSystemData(StarSystemAPI system)
static SectorEntityToken addSalvageEntity(LocationAPI location, String id, String faction, Object pluginParams)
static SectorEntityToken pickOuterEntityToSpawnNear(Random random, StarSystemAPI system)
AddedEntity addDerelictShip(StarSystemData data, EntityLocation loc, String variantId)
static AddedEntity setEntityLocation(SectorEntityToken entity, EntityLocation loc, String type)
static void convertOrbitNoSpin(SectorEntityToken entity)
void addDerelictShip(StarSystemData data, EntityLocation loc, WeightedRandomPicker< String > factions)
static AddedEntity addEntity(Random random, StarSystemAPI system, WeightedRandomPicker< EntityLocation > locs, String type, String faction)
void setRandom(Random random)
static EntityLocation pickHiddenLocation(Random random, StarSystemAPI system, float gap, Set< SectorEntityToken > exclude)
static EntityLocation pickCommonLocation(Random random, StarSystemAPI system, float gap, boolean allowStarOrbit, Set< SectorEntityToken > exclude)
static WeightedRandomPicker< EntityLocation > getLocations(Random random, StarSystemAPI system, float minGap, LinkedHashMap< LocationType, Float > weights)
static float getOuterRadius(StarSystemAPI system)
void addResearchStations(StarSystemData data, float chanceToAddAny, int min, int max, WeightedRandomPicker< String > stationTypes)
static float getOrbitalRadius(SectorEntityToken center)
boolean shouldHaveDecivilized(PlanetAPI planet, String ruins)
static boolean isAreaEmpty(LocationAPI loc, Vector2f coords)
List< AddedEntity > addObjectives(StarSystemData data, float prob)
static EntityLocation pickAnyLocation(Random random, StarSystemAPI system, float gap, Set< SectorEntityToken > exclude)
static EntityLocation pickUncommonLocation(Random random, StarSystemAPI system, float gap, Set< SectorEntityToken > exclude)
static List< OrbitGap > findGaps(SectorEntityToken center, float minPad, float maxDist, float minGap)
abstract String getThemeId()
void addCaches(StarSystemData data, float chanceToAddAny, int min, int max, WeightedRandomPicker< String > cacheTypes)
static float getInnerRadius(StarSystemAPI system)
static EntityLocation createLocationAtRandomGap(Random random, SectorEntityToken center, float minGap)
abstract void generateForSector(ThemeGenContext context, float allowedSectorFraction)
void addDerelictShips(StarSystemData data, float chanceToAddAny, int min, int max, WeightedRandomPicker< String > factions)
static void clearRuins(MarketAPI market)
static SectorEntityToken addSalvageEntity(Random random, LocationAPI location, String id, String faction, Object pluginParams)
static SectorEntityToken addSalvageEntity(LocationAPI location, String id, String faction)
AddedEntity addCommRelay(StarSystemData data, float prob)
static AddedEntity addEntity(Random random, LocationAPI system, EntityLocation loc, String type, String faction)
static WeightedRandomPicker< EntityLocation > getLocations(Random random, StarSystemAPI system, Set< SectorEntityToken > exclude, float minGap, LinkedHashMap< LocationType, Float > weights)
static void convertOrbitWithSpin(SectorEntityToken entity, float spin)
AddedEntity addInactiveGate(StarSystemData data, float prob, float probDebris, float probShips, WeightedRandomPicker< String > factions)
static void convertOrbitNoSpin(SectorEntityToken entity, float facing)
WeightedRandomPicker< String > createStringPicker(Object ... params)
void addHabCenters(StarSystemData data, float chanceToAddAny, int min, int max, WeightedRandomPicker< String > stationTypes)
void addDebrisFields(StarSystemData data, float chanceToAddAny, int min, int max)
AddedEntity addDebrisField(StarSystemData data, SectorEntityToken focus, float radius)
static ObjectiveGenDataSpec getObjectiveSpec(String id)
void addDebrisFields(StarSystemData data, float chanceToAddAny, int min, int max, String defFaction, float defProb, int minStr, int maxStr)
static AddedEntity addNonSalvageEntity(LocationAPI system, EntityLocation loc, String type, String faction)
static boolean constellationIsEmpty(Constellation c)
String pickRuinsType(PlanetAPI planet)
static CargoAPI genCargoFromDrop(SectorEntityToken entity)
static WeightedRandomPicker< String > createStringPicker(Random random, Object ... params)
void addShipGraveyard(StarSystemData data, SectorEntityToken focus, WeightedRandomPicker< String > factions, WeightedRandomPicker< String > hulls)
static void convertOrbitPointingDown(SectorEntityToken entity)
static boolean systemIsEmpty(StarSystemAPI system)
AddedEntity addStation(EntityLocation loc, StarSystemData data, String customEntityId, String factionId)
void addShipGraveyard(StarSystemData data, SectorEntityToken focus, WeightedRandomPicker< String > factions)
void addMiningStations(StarSystemData data, float chanceToAddAny, int min, int max, WeightedRandomPicker< String > stationTypes)
static float ORBITAL_HABITAT_PROB
static float NOT_HABITABLE_PLANET_PROB
static Set< String > interestingConditionsWithoutHabitable
static SalvageEntityGenDataSpec getSalvageSpec(String id)
static boolean hasSalvageSpec(String id)
List< Constellation > constellations
Map< Constellation, String > majorThemes
static CargoAPI generateSalvage(Random random, float valueMult, float overallMult, float fuelMult, List< DropData > dropValue, List< DropData > dropRandom)
AsteroidBeltParams params
AsteroidFieldParams params
static Vector2f getUnitVectorAtDegreeAngle(float degrees)
static SectorEntityToken addDebrisField(LocationAPI loc, DebrisFieldParams params, Random random)
static Random getRandom(long seed, int level)
static float getDistance(SectorEntityToken from, SectorEntityToken to)
static Vector2f getPointWithinRadius(Vector2f from, float r)
void addAll(Collection< T > items)
OrbitAPI createCircularOrbitWithSpin(SectorEntityToken focus, float angle, float orbitRadius, float orbitDays, float spin)
< T > Collection< T > getAllSpecs(Class< T > c)
Object getSpec(Class c, String id, boolean nullOnNotFound)
void setRadius(float radius)
List getEntities(Class implementedClassOrInterface)
List< SectorEntityToken > getJumpPoints()
List< SectorEntityToken > getEntitiesWithTag(String tag)
List< PlanetAPI > getPlanets()
List< CampaignTerrainAPI > getTerrainCopy()
void addEntity(SectorEntityToken entity)
SectorEntityToken createToken(float x, float y)
CustomCampaignEntityAPI addCustomEntity(String id, String name, String type, String factionId)
void removeEntity(SectorEntityToken entity)
String getNameWithLowercaseTypeShort()
void setEntity(SectorEntityToken entity)
SectorEntityToken getFocus()
LocationAPI getContainingLocation()
StatBonus getDetectedRangeMod()
CustomCampaignEntityPlugin getCustomPlugin()
void setCircularOrbitPointingDown(SectorEntityToken focus, float angle, float orbitRadius, float orbitDays)
String getCustomEntityType()
List< DropData > getDropRandom()
void setCircularOrbit(SectorEntityToken focus, float angle, float orbitRadius, float orbitDays)
float getCircularOrbitAngle()
void setSensorProfile(Float sensorProfile)
void setDiscoverable(Boolean discoverable)
void setLocation(float x, float y)
void setFacing(float facing)
void setOrbit(OrbitAPI orbit)
SectorEntityToken getOrbitFocus()
float getCircularOrbitRadius()
void setCircularOrbitWithSpin(SectorEntityToken focus, float angle, float orbitRadius, float orbitDays, float minSpin, float maxSpin)
MemoryAPI getMemoryWithoutUpdate()
List< DropData > getDropValue()
float getCircularOrbitPeriod()
SectorEntityToken getCenter()
String addCondition(String id)
boolean hasCondition(String id)
void removeCondition(String id)
void set(String key, Object value)