Starsector API
Loading...
Searching...
No Matches
MiscellaneousThemeGenerator.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.procgen.themes;
2
3import java.util.ArrayList;
4import java.util.Arrays;
5import java.util.Collections;
6import java.util.Comparator;
7import java.util.HashSet;
8import java.util.List;
9import java.util.Set;
10
11import org.lwjgl.util.vector.Vector2f;
12
13import com.fs.starfarer.api.EveryFrameScript;
14import com.fs.starfarer.api.Global;
15import com.fs.starfarer.api.campaign.CampaignFleetAPI;
16import com.fs.starfarer.api.campaign.CargoAPI;
17import com.fs.starfarer.api.campaign.CustomEntitySpecAPI;
18import com.fs.starfarer.api.campaign.JumpPointAPI;
19import com.fs.starfarer.api.campaign.PlanetAPI;
20import com.fs.starfarer.api.campaign.SectorEntityToken;
21import com.fs.starfarer.api.campaign.StarSystemAPI;
22import com.fs.starfarer.api.fleet.FleetMemberAPI;
23import com.fs.starfarer.api.impl.campaign.CoronalTapParticleScript;
24import com.fs.starfarer.api.impl.campaign.DerelictShipEntityPlugin;
25import com.fs.starfarer.api.impl.campaign.DerelictShipEntityPlugin.DerelictShipData;
26import com.fs.starfarer.api.impl.campaign.econ.impl.PlanetaryShield;
27import com.fs.starfarer.api.impl.campaign.fleets.DefaultFleetInflater;
28import com.fs.starfarer.api.impl.campaign.fleets.DefaultFleetInflaterParams;
29import com.fs.starfarer.api.impl.campaign.ids.Commodities;
30import com.fs.starfarer.api.impl.campaign.ids.Conditions;
31import com.fs.starfarer.api.impl.campaign.ids.Entities;
32import com.fs.starfarer.api.impl.campaign.ids.Factions;
33import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
34import com.fs.starfarer.api.impl.campaign.ids.Planets;
35import com.fs.starfarer.api.impl.campaign.ids.StarTypes;
36import com.fs.starfarer.api.impl.campaign.ids.Submarkets;
37import com.fs.starfarer.api.impl.campaign.ids.Tags;
38import com.fs.starfarer.api.impl.campaign.ids.Terrain;
39import com.fs.starfarer.api.impl.campaign.procgen.Constellation;
40import com.fs.starfarer.api.impl.campaign.procgen.DefenderDataOverride;
41import com.fs.starfarer.api.impl.campaign.procgen.NameGenData;
42import com.fs.starfarer.api.impl.campaign.procgen.PlanetConditionGenerator;
43import com.fs.starfarer.api.impl.campaign.procgen.PlanetGenDataSpec;
44import com.fs.starfarer.api.impl.campaign.procgen.ProcgenUsedNames;
45import com.fs.starfarer.api.impl.campaign.procgen.ProcgenUsedNames.NamePick;
46import com.fs.starfarer.api.impl.campaign.procgen.StarSystemGenerator;
47import com.fs.starfarer.api.impl.campaign.procgen.StarSystemGenerator.StarSystemType;
48import com.fs.starfarer.api.impl.campaign.procgen.themes.SalvageSpecialAssigner.ShipRecoverySpecialCreator;
49import com.fs.starfarer.api.impl.campaign.procgen.themes.SalvageSpecialAssigner.SpecialCreationContext;
50import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.ShipRecoverySpecial.PerShipData;
51import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.ShipRecoverySpecial.ShipCondition;
52import com.fs.starfarer.api.impl.campaign.terrain.AsteroidFieldTerrainPlugin.AsteroidFieldParams;
53import com.fs.starfarer.api.util.Misc;
54import com.fs.starfarer.api.util.WeightedRandomPicker;
55
56
58
59 public static String PK_SYSTEM_KEY = "$core_pkSystem";
60 public static String PK_PLANET_KEY = "$core_pkPlanet";
61 public static String PK_CACHE_KEY = "$core_pkCache";
62 public static String PK_NEXUS_KEY = "$core_pkNexus";
63
64 public static String PLANETARY_SHIELD_PLANET_KEY = "$core_planetaryShieldPlanet";
65 public static String PLANETARY_SHIELD_PLANET = "$psi_planet";
66
67 public static String LOCR_BLOCK_FIRST_SURVEY = "$locr_blockFirstSurvey";
68 public static String LOCR_LUDDIC_PLANET_KEY = "$locr_luddicPlanet";
69 public static String LOCR_LUDDIC_TRANSPORT_KEY = "$locr_luddicTransport";
70 public static String LOCR_LUDDIC = "$locr_luddic";
71 public static String LOCR_MINERS_PLANET_KEY = "$locr_minersPlanet";
72 public static String LOCR_MINERS = "$locr_miners";
73 //public static String LOCR_UTOPIA_PLANET_KEY = "$locr_utopiaPlanet";
74 //public static String LOCR_UTOPIA = "$locr_utopia";
75 public static String LOCR_PIRATE_PLANET_KEY = "$locr_piratePlanet";
76 public static String LOCR_PIRATE = "$locr_pirate";
77
78 public static float PROB_TO_ADD_SOMETHING = 0.5f;
79
80 public static int MIN_GATES = Global.getSettings().getInt("minNonCoreGatesInSector");
81 public static int MAX_GATES = Global.getSettings().getInt("maxNonCoreGatesInSector");
82 public static int MIN_GATES_TO_ADD = Global.getSettings().getInt("minGatesToAddOnSecondPass");
83
84
85 public String getThemeId() {
86 return Themes.MISC;
87 }
88
89 @Override
90 public float getWeight() {
91 return 0f;
92 }
93
94 @Override
95 public int getOrder() {
96 return 1000000;
97 }
98
99 @Override
100 public void generateForSector(ThemeGenContext context, float allowedUnusedFraction) {
101
102 if (DEBUG) System.out.println("\n\n\n");
103 if (DEBUG) System.out.println("Generating misc derelicts etc in all systems");
104 //getSortedAvailableConstellations(context, true, new Vector2f(), null).size()
105 List<StarSystemData> all = new ArrayList<StarSystemData>();
106
107 /* this adds misc stuff to systems that are:
108 1) Not tagged with some other theme
109 2) But does add misc stuff to derelict-tagged systems
110 So, basicallly it covers:
111 derelict theme + whatever few constellations didn't get anything from any theme
112 */
113 for (Constellation c : context.constellations) {
114 String theme = context.majorThemes.get(c);
115
116 List<StarSystemData> systems = new ArrayList<StarSystemData>();
117 for (StarSystemAPI system : c.getSystems()) {
118 StarSystemData data = computeSystemData(system);
119 systems.add(data);
120 }
121
122 for (StarSystemData data : systems) {
123 //if (data.system.getName().toLowerCase().contains("alpha mok morred")) {
124// if (data.system.getName().toLowerCase().contains("vasuki")) {
125// System.out.println("efwefwef");
126// }
127 boolean derelict = data.system.hasTag(Tags.THEME_DERELICT);
128 if (!derelict && theme != null && !data.system.getTags().isEmpty()) continue;
129// if (!derelict && theme != null && !theme.equals(Themes.DERELICTS) &&
130// !theme.equals(Themes.NO_THEME)) continue;
131
132 if (random.nextFloat() > PROB_TO_ADD_SOMETHING || (derelict && theme != null)) {
133 data.system.addTag(Tags.THEME_MISC_SKIP);
134 continue;
135 }
136
137 populateNonMain(data);
138 all.add(data);
139 data.system.addTag(Tags.THEME_MISC);
140 data.system.addTag(Tags.THEME_INTERESTING_MINOR);
141 }
142 }
143
144
145 SpecialCreationContext specialContext = new SpecialCreationContext();
146 specialContext.themeId = getThemeId();
147 SalvageSpecialAssigner.assignSpecials(all, specialContext);
148
149 if (DEBUG) System.out.println("Finished generating misc derelicts\n\n\n\n\n");
150
151
152 addDerelicts(context, "legion_xiv_Elite", 2, 3, 1, 2, Tags.THEME_REMNANT);
153 addDerelicts(context, "phantom_Elite", 1, 2, 0, 1, Tags.THEME_REMNANT, Tags.THEME_RUINS, Tags.THEME_DERELICT, Tags.THEME_UNSAFE);
154 addDerelicts(context, "revenant_Elite", 1, 2, 0, 1, Tags.THEME_REMNANT, Tags.THEME_RUINS, Tags.THEME_DERELICT, Tags.THEME_UNSAFE);
155
156
157 addRedPlanet(context);
158 addPKSystem(context);
160
161 addCoronalTaps(context);
162
163 addExtraGates(context);
164
165 addLOCRPiratePlanet(context);
166 addLOCRLuddicPlanet(context);
167 //addLOCRUtopiaPlanet(context);
168 addLOCRMinersPlanet(context);
169 }
170
171 protected void addRedPlanet(ThemeGenContext context) {
172 if (DEBUG) System.out.println("Looking for planetary shield planet");
173
174 PlanetAPI bestHab = null;
175 PlanetAPI bestNonHab = null;
176// OrbitGap gapHab = null;
177// OrbitGap gapNonHab = null;
178 float habDist = 0;
179 float nonHabDist = 0;
180
181 // looking for a habitable planet furthest from the Sector's center, with a bit of
182 // a random factor
183 int systemsChecked = 0;
184 for (Constellation c : context.constellations) {
185 for (StarSystemAPI system : c.getSystems()) {
186 if (system.hasTag(Tags.THEME_SPECIAL)) continue;
187
188 if (!system.hasTag(Tags.THEME_MISC_SKIP) &&
189 !system.hasTag(Tags.THEME_MISC)) {
190 continue;
191 }
192 //[theme_derelict, theme_derelict_probes, theme_misc_skip, theme_derelict_survey_ship]
193 if (system.hasTag(Tags.THEME_DERELICT)) {
194 continue;
195 }
196
197 systemsChecked++;
198
199 for (PlanetAPI curr : system.getPlanets()) {
200 if (curr.isStar()) continue;
201 if (curr.isMoon()) continue;
202 if (!curr.getMarket().isPlanetConditionMarketOnly()) continue;
203
204 if (curr.hasTag(Tags.NOT_RANDOM_MISSION_TARGET)) continue;
205
206 float dist = system.getLocation().length() + random.nextFloat() * 6000;
207 if (curr.getMarket().hasCondition(Conditions.HABITABLE)) {
208 if (dist > habDist) {
209// List<OrbitGap> gaps = findGaps(curr, 50f, 500f, 100f);
210// if (!gaps.isEmpty()) {
211 habDist = dist;
212 bestHab = curr;
213// gapHab = gaps.get(0);
214// }
215 }
216 } else {
217 if (dist > nonHabDist) {
218// List<OrbitGap> gaps = findGaps(curr, 50f, 500f, 100f);
219// if (!gaps.isEmpty()) {
220 nonHabDist = dist;
221 bestNonHab = curr;
222// gapNonHab = gaps.get(0);
223// }
224 }
225 }
226 }
227 }
228 }
229
230 PlanetAPI planet = bestHab;
231 //OrbitGap gap = gapHab;
232 if (planet == null) {
233 planet = bestNonHab;
234 //gap = gapNonHab;
235 }
236
237 if (planet != null) {
238 if (DEBUG) System.out.println("Adding Planetary Shield to [" + planet.getName() + "] in [" + planet.getContainingLocation().getNameWithLowercaseType() + "]");
239 PlanetaryShield.applyVisuals(planet);
240 Global.getSector().getMemoryWithoutUpdate().set(PLANETARY_SHIELD_PLANET_KEY, planet);
241 planet.getMemoryWithoutUpdate().set(PLANETARY_SHIELD_PLANET, true);
242
243 long seed = StarSystemGenerator.random.nextLong();
244 planet.getMemoryWithoutUpdate().set(MemFlags.SALVAGE_SEED, seed);
245 planet.getMemoryWithoutUpdate().set(MemFlags.SALVAGE_SPEC_ID_OVERRIDE, "red_planet");
246 planet.addTag(Tags.NOT_RANDOM_MISSION_TARGET);
247 //planet.addTag(Tags.SALVAGEABLE);
248
249// SectorEntityToken beacon = Misc.addWarningBeacon(planet, gap, Tags.BEACON_HIGH);
250// beacon.getMemoryWithoutUpdate().set(PLANETARY_SHIELD_BEACON, true);
251// beacon.getMemoryWithoutUpdate().set(MemFlags.SALVAGE_SEED, seed);
252
253 } else {
254 if (DEBUG) System.out.println("Failed to find a planet in remnant systems");
255 }
256 if (DEBUG) System.out.println("Finished adding Planetary Shield planet\n\n\n\n\n");
257 }
258
259 protected void addDerelicts(ThemeGenContext context, String variant,
260 int minNonSalvageable, int maxNonSalvageable,
261 int minSalvageable, int maxSalvageable,
262 String ... allowedThemes) {
263 if (Global.getSettings().getVariant(variant) != null) {
264 if (DEBUG) System.out.println("Adding " + variant + " to star systems");
265
266 Set<String> tags = new HashSet<String>(Arrays.asList(allowedThemes));
267
268 int numSalvageable = minSalvageable + random.nextInt(maxSalvageable - minSalvageable + 1);
269 int numNonSalvageable = minNonSalvageable + random.nextInt(maxNonSalvageable - minNonSalvageable + 1);
270
271 List<Constellation> list = new ArrayList<Constellation>(context.constellations);
272 Collections.shuffle(list, random);
273
274 List<StarSystemData> systems = new ArrayList<StarSystemData>();
275 for (Constellation c : list) {
276 for (StarSystemAPI system : c.getSystems()) {
277 StarSystemData data = computeSystemData(system);
278 systems.add(data);
279 }
280 }
281
282 Collections.shuffle(systems, random);
283 for (StarSystemData data : systems) {
284 boolean matches = false;
285 for (String tag : data.system.getTags()) {
286 if (tags.contains(tag)) {
287 matches = true;
288 break;
289 }
290 }
291 if (!matches) continue;
292
293 EntityLocation loc = pickAnyLocation(random, data.system, 70f, null);
294 AddedEntity ae = addDerelictShip(data, loc, variant);
295 if (ae != null) {
296 if (numSalvageable > 0) {
297 numSalvageable--;
298 ShipRecoverySpecialCreator creator = new ShipRecoverySpecialCreator(random, 0, 0, false, null, null);
299 Object specialData = creator.createSpecial(ae.entity, new SpecialCreationContext());
300 if (specialData != null) {
301 Misc.setSalvageSpecial(ae.entity, specialData);
302 }
303 } else {
304 numNonSalvageable--;
305 SalvageSpecialAssigner.assignSpecials(ae.entity, true);
306 }
307 if (DEBUG) System.out.println(" Added " + variant + " to " + data.system + "\n");
308 }
309 if (numSalvageable + numNonSalvageable <= 0) break;
310 }
311 //if (numSalvageable + numNonSalvageable <= 0) break;
312
313 if (DEBUG) System.out.println("Finished adding " + variant + " to star systems\n\n\n\n\n");
314 }
315 }
316
317
319
320 int num = 2 + random.nextInt(3);
321
322 //System.out.println("RANDOM CHECK: " + random.nextLong());
323
324 if (DEBUG) System.out.println("Adding up to " + num + " solar shades and mirrors");
325 List<Constellation> list = new ArrayList<Constellation>(context.constellations);
326 WeightedRandomPicker<PlanetAPI> picker = new WeightedRandomPicker<PlanetAPI>(random);
327 for (Constellation c : list) {
328 for (StarSystemAPI system : c.getSystems()) {
329 if (system.hasTag(Tags.THEME_CORE)) continue;
330 if (system.isNebula()) continue;
331
332 for (PlanetAPI planet : system.getPlanets()) {
333 if (planet.isStar()) continue;
334
335 SectorEntityToken focus = planet.getOrbitFocus();
336 if (!(focus instanceof PlanetAPI)) continue;
337 if (!((PlanetAPI) focus).isNormalStar()) continue;
338
339
341 Global.getSettings().getSpec(PlanetGenDataSpec.class, planet.getSpec().getPlanetType(), true);
342 if (spec == null) continue;
343
344 String cat = spec.getCategory();
345 if (cat == null) continue;
346
347 float weight = 0f;
348 if (Planets.CAT_HAB1.equals(cat)) {
349 weight = 1f;
350 } else if (Planets.CAT_HAB2.equals(cat)) {
351 weight = 1f;
352 } else if (Planets.CAT_HAB3.equals(cat)) {
353 weight = 1f;
354 }
355
356 if (weight <= 0) continue;
357
358 weight = 0;
359
360 if (planet.hasCondition(Conditions.HOT)) {
361 weight += 5f;
362 }
363 if (planet.hasCondition(Conditions.POOR_LIGHT)) {
364 weight += 5f;
365 }
366 if (planet.hasCondition(Conditions.WATER_SURFACE)) {
367 weight += 5f;
368 }
369 if (Misc.hasFarmland(planet.getMarket())) {
370 weight += 10f;
371 }
372
373 if (weight <= 0) continue;
374
375 // +250 beyond normal radius
376 boolean enoughRoom = true;
377 for (PlanetAPI other : system.getPlanets()) {
378 if (other.getOrbitFocus() == planet) {
379 if (other.getCircularOrbitRadius() < planet.getRadius() + other.getRadius() + 320) {
380 enoughRoom = false;
381 break;
382 }
383 }
384 }
385 if (!enoughRoom) continue;
386
387
388 picker.add(planet, weight);
389 }
390 }
391 }
392
393 if (DEBUG) System.out.println("Found " + picker.getItems().size() + " candidates");
394 for (int i = 0; i < num && !picker.isEmpty(); i++) {
395 PlanetAPI planet = picker.pickAndRemove();
396 if (DEBUG) System.out.println("Adding solar shades and mirrors to [" + planet.getName() + "] in [" +
397 planet.getStarSystem() + " located at " + planet.getLocationInHyperspace());
398
399 planet.getMarket().addCondition(Conditions.SOLAR_ARRAY);
400
401 StarSystemAPI system = planet.getStarSystem();
402 PlanetAPI star = (PlanetAPI) planet.getOrbitFocus();
403
404 boolean shade = planet.hasCondition(Conditions.HOT) ||
405 planet.getTypeId().equals(Planets.DESERT) ||
406 planet.getTypeId().equals(Planets.DESERT1) ||
407 planet.getTypeId().equals(Planets.ARID) ||
408 star.getTypeId().equals(StarTypes.BLUE_GIANT) ||
409 star.getTypeId().equals(StarTypes.BLUE_SUPERGIANT);
410 boolean mirror = planet.hasCondition(Conditions.POOR_LIGHT) ||
411 planet.getTypeId().equals(Planets.PLANET_TERRAN_ECCENTRIC) ||
412// star.getTypeId().equals(StarTypes.RED_SUPERGIANT) ||
413// star.getTypeId().equals(StarTypes.RED_GIANT) ||
414 star.getTypeId().equals(StarTypes.RED_DWARF) ||
415 star.getTypeId().equals(StarTypes.BROWN_DWARF);
416
417 boolean forceFew = false;
418 if (!shade && !mirror) {
419 mirror = true;
420 shade = true;
421 forceFew = true;
422 }
423
424 String faction = Factions.NEUTRAL;
425 float period = planet.getCircularOrbitPeriod();
426 float angle = planet.getCircularOrbitAngle();
427 float radius = 270f + planet.getRadius();
428 //String name = planet.getName();
429
430 float xp = 300f;
431 float profile = 2000f;
432
433 if (mirror) {
434 boolean manyMirrors = random.nextBoolean();
435
436 SectorEntityToken mirror2 = system.addCustomEntity(null, "Stellar Mirror Beta", Entities.STELLAR_MIRROR, faction);
437 SectorEntityToken mirror3 = system.addCustomEntity(null, "Stellar Mirror Gamma", Entities.STELLAR_MIRROR, faction);
438 SectorEntityToken mirror4 = system.addCustomEntity(null, "Stellar Mirror Delta", Entities.STELLAR_MIRROR, faction);
439 mirror2.setCircularOrbitPointingDown(planet, angle - 30, radius, period);
440 mirror3.setCircularOrbitPointingDown(planet, angle + 0, radius, period);
441 mirror4.setCircularOrbitPointingDown(planet, angle + 30, radius, period);
442 makeDiscoverable(mirror2, xp, profile);
443 makeDiscoverable(mirror3, xp, profile);
444 makeDiscoverable(mirror4, xp, profile);
445
446 if (manyMirrors && !forceFew) {
447 SectorEntityToken mirror1 = system.addCustomEntity(null, "Stellar Mirror Alpha", Entities.STELLAR_MIRROR, faction);
448 SectorEntityToken mirror5 = system.addCustomEntity(null, "Stellar Mirror Epsilon", Entities.STELLAR_MIRROR, faction);
449 mirror1.setCircularOrbitPointingDown(planet, angle - 60, radius, period);
450 mirror5.setCircularOrbitPointingDown(planet, angle + 60, radius, period);
451 makeDiscoverable(mirror1, xp, profile);
452 makeDiscoverable(mirror5, xp, profile);
453 }
454 }
455
456 if (shade) {
457 boolean manyShades = random.nextBoolean();
458 SectorEntityToken shade2 = system.addCustomEntity(null, "Stellar Shade Psi", Entities.STELLAR_SHADE, faction);
459 shade2.setCircularOrbitPointingDown(planet, angle + 180 + 0, radius + 25, period);
460 makeDiscoverable(shade2, xp, profile);
461
462 if (manyShades && !forceFew) {
463 SectorEntityToken shade1 = system.addCustomEntity(null, "Stellar Shade Omega", Entities.STELLAR_SHADE, faction);
464 SectorEntityToken shade3 = system.addCustomEntity(null, "Stellar Shade Chi", Entities.STELLAR_SHADE, faction);
465 shade1.setCircularOrbitPointingDown(planet, angle + 180 - 26, radius - 10, period);
466 shade3.setCircularOrbitPointingDown(planet, angle + 180 + 26, radius - 10, period);
467 makeDiscoverable(shade1, xp, profile);
468 makeDiscoverable(shade3, xp, profile);
469 }
470 }
471
472 }
473
474 if (DEBUG) System.out.println("Done adding solar shades and mirrors");
475 }
476
477 public static void makeDiscoverable(SectorEntityToken entity, float xp, float sensorProfile) {
478 entity.setDiscoverable(true);
479 entity.setDiscoveryXP(xp);
480 entity.setSensorProfile(sensorProfile);
481 }
482
483
484 public void populateNonMain(StarSystemData data) {
485 if (DEBUG) System.out.println(" Generating misc derelicts in system " + data.system.getName());
486 boolean special = data.isBlackHole() || data.isNebula() || data.isPulsar();
487 if (special) {
488 addResearchStations(data, 0.25f, 1, 1, createStringPicker(Entities.STATION_RESEARCH, 10f));
489 }
490
491 if (random.nextFloat() < 0.5f) return;
492
493 WeightedRandomPicker<String> factions = SalvageSpecialAssigner.getNearbyFactions(random, data.system.getCenter(),
494 15f, 10f, 10f);
495
496 addShipGraveyard(data, 0.05f, 1, 1, factions);
497
498 addDebrisFields(data, 0.25f, 1, 2);
499
500 addDerelictShips(data, 0.5f, 0, 3, factions);
501
502 addCaches(data, 0.25f, 0, 2, createStringPicker(
503 Entities.WEAPONS_CACHE, 4f,
504 Entities.WEAPONS_CACHE_SMALL, 10f,
505 Entities.WEAPONS_CACHE_HIGH, 4f,
506 Entities.WEAPONS_CACHE_SMALL_HIGH, 10f,
507 Entities.WEAPONS_CACHE_LOW, 4f,
508 Entities.WEAPONS_CACHE_SMALL_LOW, 10f,
509 Entities.SUPPLY_CACHE, 4f,
510 Entities.SUPPLY_CACHE_SMALL, 10f,
511 Entities.EQUIPMENT_CACHE, 4f,
512 Entities.EQUIPMENT_CACHE_SMALL, 10f
513 ));
514
515 }
516
517
518 protected void addExtraGates(ThemeGenContext context) {
519// List<SectorEntityToken> gates = new ArrayList<SectorEntityToken>();
520// List<StarSystemAPI> systems = new ArrayList<StarSystemAPI>();
521// List<Constellation> list = new ArrayList<Constellation>(context.constellations);
522// for (Constellation c : list) {
523// for (StarSystemAPI system : c.getSystems()) {
524// gates.addAll(system.getEntitiesWithTag(Tags.GATE));
525// systems.add(system);
526// }
527// }
528
529 List<StarSystemAPI> systems = new ArrayList<StarSystemAPI>(Global.getSector().getStarSystems());
530 List<SectorEntityToken> gates = new ArrayList<SectorEntityToken>();
531
532 for (StarSystemAPI system : new ArrayList<StarSystemAPI>(systems)) {
533 //if (system.hasTag(Tags.THEME_CORE)) continue; // this isn't set yet
534 boolean galatia = system.getBaseName().toLowerCase().equals("galatia");
535 if (system.getTags().isEmpty() || galatia) {
536 systems.remove(system);
537 continue;
538 }
539 gates.addAll(system.getEntitiesWithTag(Tags.GATE));
540 }
541
542
543 int addGates = MIN_GATES + random.nextInt(MAX_GATES - MIN_GATES + 1) - gates.size();
544 if (addGates < MIN_GATES_TO_ADD) addGates = MIN_GATES_TO_ADD;
545 if (addGates <= 0) {
546 if (DEBUG) System.out.println(" Already have " + gates.size() + " gates, not adding any");
547 return;
548 }
549
550 List<StarSystemData> all = new ArrayList<BaseThemeGenerator.StarSystemData>();
551
552 if (DEBUG) System.out.println("");
553 if (DEBUG) System.out.println("");
554 if (DEBUG) System.out.println("");
555 if (DEBUG) System.out.println(" Adding " + addGates + " extra gates, for a total of " + (addGates + gates.size()));
556
557 for (int i = 0; i < addGates; i++) {
558 float maxDist = 0;
559 StarSystemAPI farthest = null;
560 for (StarSystemAPI system : systems) {
561 if (system.getPlanets().size() < 3) continue; // skip empty systems
562
563 float minDist = Float.MAX_VALUE;
564 for (SectorEntityToken gate : gates) {
565 float dist = Misc.getDistanceLY(gate, system.getCenter());
566 if (dist < minDist) minDist = dist;
567 }
568 if (minDist > maxDist) {
569 maxDist = minDist;
570 farthest = system;
571 }
572 }
573 if (farthest != null) {
574 StarSystemData data = new StarSystemData();
575 data.system = farthest;
576 WeightedRandomPicker<String> factions = SalvageSpecialAssigner.getNearbyFactions(random, farthest.getCenter(),
577 15f, 5f, 5f);
578 AddedEntity gate = addInactiveGate(data, 1f, 0.5f, 0.5f, factions);
579 if (gate != null && gate.entity != null) gates.add(gate.entity);
580 }
581 }
582 if (DEBUG) System.out.println(" Done adding extra gates");
583 if (DEBUG) System.out.println("");
584 if (DEBUG) System.out.println("");
585 if (DEBUG) System.out.println("");
586
587 SpecialCreationContext specialContext = new SpecialCreationContext();
588 specialContext.themeId = getThemeId();
589 SalvageSpecialAssigner.assignSpecials(all, specialContext);
590
591
592
593 }
594
595
596 protected void addCoronalTaps(ThemeGenContext context) {
597 if (DEBUG) System.out.println("Adding coronal taps...");
598
599 List<Constellation> list = new ArrayList<Constellation>(context.constellations);
600
601 WeightedRandomPicker<StarSystemAPI> tapSystems = new WeightedRandomPicker<StarSystemAPI>(StarSystemGenerator.random);
602 WeightedRandomPicker<StarSystemAPI> backup = new WeightedRandomPicker<StarSystemAPI>(StarSystemGenerator.random);
603 for (Constellation c : list) {
604 for (StarSystemAPI system : c.getSystems()) {
605 if (system.hasTag(Tags.THEME_SPECIAL)) continue;
606
607 float w = 0f;
608 if (system.hasTag(Tags.THEME_REMNANT)) {
609 w = 10f;
610 } else if (system.hasTag(Tags.THEME_DERELICT)) {
611 w = 10f;
612 } else if (system.hasTag(Tags.THEME_RUINS)) {
613 w = 10f;
614 } else if (system.hasTag(Tags.THEME_MISC)) {
615 w = 5f;
616 }
617
618 if (w <= 0) continue;
619
620 if (system.getType() == StarSystemType.TRINARY_2CLOSE) {
621 w *= 5f;
622 }
623
624 boolean hasBlueStar = false;
625 boolean hasNormalStar = false;
626 for (PlanetAPI planet : system.getPlanets()) {
627 if (!planet.isNormalStar()) continue;
628 if (planet.getTypeId().equals(StarTypes.BLUE_GIANT) ||
629 planet.getTypeId().equals(StarTypes.BLUE_SUPERGIANT)) {
630 hasBlueStar = true;
631 }
632 hasNormalStar = true;
633 }
634
635 if (!hasNormalStar) continue;
636
637 WeightedRandomPicker<StarSystemAPI> use = tapSystems;
638 if (!hasBlueStar) {
639 use = backup;
640 }
641 use.add(system, w);
642 }
643 }
644
645
646 if (tapSystems.isEmpty()) {
647 tapSystems.addAll(backup);
648 }
649
650 int numTaps = 2 + random.nextInt(2);
651 numTaps = 2;
652 int added = 0;
653 while (added < numTaps && !tapSystems.isEmpty()) {
654 StarSystemAPI pick = tapSystems.pickAndRemove();
655 AddedEntity tap = addCoronalTap(pick);
656 if (tap != null) {
657 added++;
658 }
659 }
660
661 if (DEBUG) System.out.println("Done adding coronal taps\n\n\n");
662 }
663
664 public static class MakeCoronalTapFaceNearestStar implements EveryFrameScript {
665 protected SectorEntityToken tap;
666 public MakeCoronalTapFaceNearestStar(SectorEntityToken tap) {
667 this.tap = tap;
668 }
669 public void advance(float amount) {
670 if (!tap.isInCurrentLocation()) return;
671
672 float minDist = Float.MAX_VALUE;
673 PlanetAPI closest = null;
674 for (PlanetAPI star : tap.getContainingLocation().getPlanets()) {
675 if (!star.isStar()) continue;
676 float dist = Misc.getDistance(tap.getLocation(), star.getLocation());
677 if (dist < minDist) {
678 minDist = dist;
679 closest = star;
680 }
681 }
682 if (closest != null) {
683 tap.setFacing(Misc.getAngleInDegrees(tap.getLocation(), closest.getLocation()) + 180f);
684 }
685 }
686 public boolean isDone() {
687 return false;
688 }
689 public boolean runWhilePaused() {
690 return false;
691 }
692 }
693
694 protected AddedEntity addCoronalTap(StarSystemAPI system) {
695
696 if (DEBUG) System.out.println("Adding coronal tap to [" + system.getNameWithLowercaseType() + ", " + system.getLocation());
697
698 String factionId = Factions.NEUTRAL;
699
700 AddedEntity entity = null;
701 if (system.getType() == StarSystemType.TRINARY_2CLOSE) {
702 EntityLocation loc = new EntityLocation();
703 loc.location = new Vector2f();
704 entity = addEntity(random, system, loc, Entities.CORONAL_TAP, factionId);
705 if (entity != null) {
706 system.addScript(new MakeCoronalTapFaceNearestStar(entity.entity));
707 }
708 } else {
709 WeightedRandomPicker<PlanetAPI> picker = new WeightedRandomPicker<PlanetAPI>();
710 WeightedRandomPicker<PlanetAPI> fallback = new WeightedRandomPicker<PlanetAPI>();
711 for (PlanetAPI planet : system.getPlanets()) {
712 if (!planet.isNormalStar()) continue;
713 if (planet.getTypeId().equals(StarTypes.BLUE_GIANT) ||
714 planet.getTypeId().equals(StarTypes.BLUE_SUPERGIANT)) {
715 picker.add(planet);
716 } else {
717 fallback.add(planet);
718 }
719 }
720 if (picker.isEmpty()) {
721 picker.addAll(fallback);
722 }
723
724 PlanetAPI star = picker.pick();
725 if (star != null) {
726 CustomEntitySpecAPI spec = Global.getSettings().getCustomEntitySpec(Entities.CORONAL_TAP);
727 EntityLocation loc = new EntityLocation();
728 float orbitRadius = star.getRadius() + spec.getDefaultRadius() + 100f;
729 float orbitDays = orbitRadius / 20f;
730 loc.orbit = Global.getFactory().createCircularOrbitPointingDown(star, random.nextFloat() * 360f, orbitRadius, orbitDays);
731 entity = addEntity(random, system, loc, Entities.CORONAL_TAP, factionId);
732 }
733 }
734
735
736 if (entity != null) {
737 system.addScript(new CoronalTapParticleScript(entity.entity));
738// system.addCorona(entity.entity, Terrain.CORONA_JET,
739// 500f, // radius outside planet
740// 15f, // burn level of "wind"
741// 0f, // flare probability
742// 1f // CR loss mult while in it
743// );
744
745// system.addTag(Tags.THEME_DERELICT);
746 system.addTag(Tags.HAS_CORONAL_TAP);
747 }
748
749 if (DEBUG) {
750 if (entity != null) {
751 System.out.println(String.format(" Added coronal tap to %s", system.getNameWithLowercaseType()));
752 } else {
753 System.out.println(String.format(" Failed to add coronal tap to %s", system.getNameWithLowercaseType()));
754 }
755 }
756 return entity;
757 }
758
759
760 protected void addPKSystem(ThemeGenContext context) {
761 if (DEBUG) System.out.println("Looking for system to hide PK in");
762
763 List<StarSystemAPI> preferred = new ArrayList<StarSystemAPI>();
764 List<StarSystemAPI> other = new ArrayList<StarSystemAPI>();
765
766 for (Constellation c : context.constellations) {
767 for (StarSystemAPI system : c.getSystems()) {
768 if (system.hasTag(Tags.THEME_SPECIAL)) continue;
769
770 if (system.isNebula()) continue;
771 if (system.hasPulsar()) continue;
772 if (system.hasBlackHole()) continue;
773
774 boolean misc = system.hasTag(Tags.THEME_MISC_SKIP) || system.hasTag(Tags.THEME_MISC);
775 if (system.hasTag(Tags.THEME_DERELICT)) misc = false;
776
777 boolean nonLargeDerelict = system.hasTag(Tags.THEME_DERELICT) &&
778 !system.hasTag(Tags.THEME_DERELICT_MOTHERSHIP) &&
779 !system.hasTag(Tags.THEME_DERELICT_CRYOSLEEPER) &&
780 !system.hasTag(Tags.THEME_DERELICT_SURVEY_SHIP);
781
782 boolean secondaryRuins = system.hasTag(Tags.THEME_RUINS_SECONDARY);
783 boolean remnantNoFleets = system.hasTag(Tags.THEME_REMNANT_NO_FLEETS);
784 boolean unsafe = system.hasTag(Tags.THEME_UNSAFE);
785
786 if (unsafe || !(misc || nonLargeDerelict || secondaryRuins || remnantNoFleets)) {
787 continue;
788 }
789
790 int count = 0;
791 for (PlanetAPI curr : system.getPlanets()) {
792 if (curr.isStar()) continue;
793 if (curr.isMoon()) continue;
794 if (curr.isGasGiant()) continue;
795 if (!curr.getMarket().isPlanetConditionMarketOnly()) continue;
796 if (curr.getCircularOrbitRadius() < 6000) continue;
797 if (curr.hasTag(Tags.NOT_RANDOM_MISSION_TARGET)) continue;
798 count++;
799 }
800
801 if (count > 0) {
802 preferred.add(system);
803 } else {
804 other.add(system);
805 }
806 }
807 }
808
809 Comparator<StarSystemAPI> comp = new Comparator<StarSystemAPI>() {
810 public int compare(StarSystemAPI o1, StarSystemAPI o2) {
811 return (int) Math.signum(o2.getLocation().length() - o1.getLocation().length());
812 }
813 };
814
815 List<StarSystemAPI> sorted = new ArrayList<StarSystemAPI>();
816 if (!preferred.isEmpty()) {
817 sorted.addAll(preferred);
818 } else {
819 sorted.addAll(other);
820 }
821 if (sorted.isEmpty()) {
822 if (DEBUG) System.out.println("FAILED TO FIND SUITABLE SYSTEM FOR PK");
823 return;
824 }
825 Collections.sort(sorted, comp);
826
827
828 // pick from some of the matching systems furthest from core
829 WeightedRandomPicker<StarSystemAPI> picker = new WeightedRandomPicker<StarSystemAPI>(random);
830 for (int i = 0; i < 20 && i < sorted.size(); i++) {
831 //sorted.get(i).addTag(Tags.PK_SYSTEM);
832 picker.add(sorted.get(i), 1f);
833 }
834
835 StarSystemAPI system = picker.pick();
836
837 if (DEBUG) System.out.println("Adding PK to [" + system.getName() + "] at [" + system.getLocation() + "]");
838 setUpPKSystem(system);
839
840
841 if (DEBUG) System.out.println("Finished adding PK system\n\n\n\n\n");
842 }
843
844 protected void setUpPKSystem(StarSystemAPI system) {
845 system.addTag(Tags.THEME_SPECIAL);
846 system.addTag(Tags.PK_SYSTEM);
847
848 Global.getSector().getPersistentData().put(PK_SYSTEM_KEY, system);
849 Global.getSector().getMemoryWithoutUpdate().set(PK_SYSTEM_KEY, system.getId());
850
851 // - pick a planet at 6k range or higher to make into a tundra world
852 // - turn any planets with a lower hazard rating into barren and reassign their conditions
853
854 PlanetAPI tundra = null;
855 for (PlanetAPI curr : system.getPlanets()) {
856 if (curr.isStar()) continue;
857 //if (curr.isMoon()) continue;
858 if (curr.isGasGiant()) continue;
859 if (curr.getMarket() == null) continue;
860 if (!curr.getMarket().isPlanetConditionMarketOnly()) continue;
861 if (curr.getCircularOrbitRadius() < 6000) continue;
862
863 tundra = curr;
864 break;
865 }
866
867 //pick = null;
868
869 // if there's no planet in a suitable range, create one
870 // could end up with a tundra world really far out if the system is full of stuff
871 // but has no planets, but it's unlikely
872 if (tundra == null) {
873 List<OrbitGap> gaps = BaseThemeGenerator.findGaps(system.getCenter(), 6000, 20000, 800);
874 float orbitRadius = 7000;
875 if (!gaps.isEmpty()) {
876 orbitRadius = (gaps.get(0).start + gaps.get(0).end) * 0.5f;
877 }
878 float orbitDays = orbitRadius / (20f + random.nextFloat() * 5f);
879 float radius = 100f + random.nextFloat() * 50f;
880 float angle = random.nextFloat() * 360f;
881 String type = Planets.BARREN;
882 NamePick namePick = ProcgenUsedNames.pickName(NameGenData.TAG_PLANET, null, null);
883 String name = namePick.nameWithRomanSuffixIfAny;
884 tundra = system.addPlanet(Misc.genUID(), system.getStar(), name, type, angle, radius, orbitRadius, orbitDays);
885
886 if (tundra == null) {
887 if (DEBUG) System.out.println("FAILED TO CREATE PLANET IN PK SYSTEM");
888 return;
889 }
890 }
891
892 tundra.setName("Sentinel");
893 tundra.addTag(Tags.NOT_RANDOM_MISSION_TARGET);
894 tundra.getMemoryWithoutUpdate().set(PK_PLANET_KEY, true);
895 Global.getSector().getPersistentData().put(PK_PLANET_KEY, tundra);
896
897 if (DEBUG) System.out.println("Setting planet [" + tundra.getName() + "] to tundra");
898 tundra.changeType(Planets.TUNDRA, random);
899 tundra.getMarket().getConditions().clear();
900 PlanetConditionGenerator.generateConditionsForPlanet(null, tundra, system.getAge());
901 tundra.getMarket().removeCondition(Conditions.DECIVILIZED);
902 tundra.getMarket().removeCondition(Conditions.DECIVILIZED_SUBPOP);
903 tundra.getMarket().removeCondition(Conditions.RUINS_EXTENSIVE);
904 tundra.getMarket().removeCondition(Conditions.RUINS_SCATTERED);
905 tundra.getMarket().removeCondition(Conditions.RUINS_VAST);
906 tundra.getMarket().removeCondition(Conditions.RUINS_WIDESPREAD);
907 tundra.getMarket().removeCondition(Conditions.INIMICAL_BIOSPHERE);
908
909 tundra.getMarket().removeCondition(Conditions.FARMLAND_POOR);
910 tundra.getMarket().removeCondition(Conditions.FARMLAND_ADEQUATE);
911 tundra.getMarket().removeCondition(Conditions.FARMLAND_RICH);
912 tundra.getMarket().removeCondition(Conditions.FARMLAND_BOUNTIFUL);
913 tundra.getMarket().addCondition(Conditions.FARMLAND_POOR);
914
915
916 // make sure the tundra world is the best habitable world in-system so there's no questions
917 // as to why it was chosen by the survivors
918 float pickHazard = tundra.getMarket().getHazardValue();
919
920 for (PlanetAPI curr : system.getPlanets()) {
921 if (curr.isStar()) continue;
922 if (curr.isGasGiant()) continue;
923 if (curr.getMarket() == null) continue;
924 if (!curr.getMarket().isPlanetConditionMarketOnly()) continue;
925 if (curr == tundra) continue;
926
927 float h = curr.getMarket().getHazardValue();
928 if (curr.hasCondition(Conditions.HABITABLE) && h <= pickHazard) {
929 curr.changeType(Planets.BARREN_VENUSLIKE, random);
930 curr.getMarket().getConditions().clear();
931 PlanetConditionGenerator.generateConditionsForPlanet(null, curr, system.getAge());
932 }
933 }
934
935 for (SectorEntityToken curr : system.getEntitiesWithTag(Tags.STABLE_LOCATION)) {
936 system.removeEntity(curr);
937 }
938 for (SectorEntityToken curr : system.getEntitiesWithTag(Tags.OBJECTIVE)) {
939 system.removeEntity(curr);
940 }
941
942
943 List<OrbitGap> gaps = BaseThemeGenerator.findGaps(system.getCenter(), 2000, 20000, 800);
944 float orbitRadius = 7000;
945 if (!gaps.isEmpty()) {
946 orbitRadius = (gaps.get(0).start + gaps.get(0).end) * 0.5f;
947 }
948 float radius = 500f + 200f * random.nextFloat();
949 float area = radius * radius * 3.14f;
950 int count = (int) (area / 80000f);
951 count *= 2;
952 if (count < 10) count = 10;
953 if (count > 100) count = 100;
954 float angle = random.nextFloat() * 360f;
955 float orbitDays = orbitRadius / (20f + random.nextFloat() * 5f);
956
957 SectorEntityToken field = system.addTerrain(Terrain.ASTEROID_FIELD,
958 new AsteroidFieldParams(
959 radius, // min radius
960 radius + 100f, // max radius
961 count, // min asteroid count
962 count, // max asteroid count
963 4f, // min asteroid radius
964 16f, // max asteroid radius
965 null)); // null for default name
966
967 field.setCircularOrbit(system.getCenter(), angle, orbitRadius, orbitDays);
968
969 SectorEntityToken cache = BaseThemeGenerator.addSalvageEntity(system, Entities.HIDDEN_CACHE, Factions.NEUTRAL);
970 cache.getMemoryWithoutUpdate().set(PK_CACHE_KEY, true);
971 cache.addTag(Tags.NOT_RANDOM_MISSION_TARGET);
972 //cache.getLocation().set(10000, 10000);
973 cache.setCircularOrbit(field, 0, 0, 100f);
974 Misc.setDefenderOverride(cache, new DefenderDataOverride(Factions.HEGEMONY, 1f, 20, 20, 1));
975
976 // Misc.addDefeatTrigger(fleet, trigger);
977
978 // add a ship graveyard around the cache - Luddic Path ships, presumably from another
979 // Path operative that got farther along but never reported back
980 StarSystemData data = new StarSystemData();
981 WeightedRandomPicker<String> derelictShipFactions = new WeightedRandomPicker<String>(random);
982 derelictShipFactions.add(Factions.LUDDIC_PATH);
983 WeightedRandomPicker<String> hulls = new WeightedRandomPicker<String>(random);
984 hulls.add("prometheus2", 1f);
985 hulls.add("colossus2", 1f);
986 hulls.add("colossus2", 1f);
987 hulls.add("colossus2", 1f);
988 hulls.add("eradicator", 1f);
989 hulls.add("enforcer", 1f);
990 hulls.add("sunder", 1f);
991 hulls.add("venture_pather", 1f);
992 hulls.add("manticore_luddic_path", 1f);
993 hulls.add("cerberus_luddic_path", 1f);
994 hulls.add("hound_luddic_path", 1f);
995 hulls.add("buffalo2", 1f);
996 addShipGraveyard(data, field, derelictShipFactions, hulls);
997 for (AddedEntity ae : data.generated) {
998 SalvageSpecialAssigner.assignSpecials(ae.entity, true);
999 }
1000
1001 // add some remnant derelicts around a fringe jump-point
1002 // where the fight was
1003 float max = 0f;
1004 JumpPointAPI fringePoint = null;
1005 List<JumpPointAPI> points = system.getEntities(JumpPointAPI.class);
1006 for (JumpPointAPI curr : points) {
1007 float dist = curr.getCircularOrbitRadius();
1008 if (dist > max) {
1009 max = dist;
1010 fringePoint = curr;
1011 }
1012 }
1013
1014 if (fringePoint != null) {
1015 data = new StarSystemData();
1016 WeightedRandomPicker<String> remnantShipFactions = new WeightedRandomPicker<String>(random);
1017 remnantShipFactions.add(Factions.REMNANTS);
1018 hulls = new WeightedRandomPicker<String>(random);
1019 hulls.add("radiant", 0.25f);
1020 hulls.add("nova", 0.5f);
1021 hulls.add("brilliant", 1f);
1022 hulls.add("apex", 1f);
1023 hulls.add("scintilla", 1f);
1024 hulls.add("scintilla", 1f);
1025 hulls.add("fulgent", 1f);
1026 hulls.add("fulgent", 1f);
1027 hulls.add("glimmer", 1f);
1028 hulls.add("glimmer", 1f);
1029 hulls.add("lumen", 1f);
1030 hulls.add("lumen", 1f);
1031 addShipGraveyard(data, fringePoint, remnantShipFactions, hulls);
1032 addDebrisField(data, fringePoint, 400f);
1033
1034 for (AddedEntity ae : data.generated) {
1035 SalvageSpecialAssigner.assignSpecials(ae.entity, true);
1036 if (ae.entity.getCustomPlugin() instanceof DerelictShipEntityPlugin) {
1037 DerelictShipEntityPlugin plugin = (DerelictShipEntityPlugin) ae.entity.getCustomPlugin();
1038 plugin.getData().ship.condition = ShipCondition.WRECKED;
1039 }
1040 }
1041 }
1042
1043 // Improvised dockyard where presumably the ship conversion took place
1044 SectorEntityToken dockyard = system.addCustomEntity("pk_dockyard",
1045 "Sentinel Gantries", Entities.ORBITAL_DOCKYARD, "neutral");
1046
1047 dockyard.setCircularOrbitPointingDown(tundra, 45, 300, 30);
1048 dockyard.setCustomDescriptionId("pk_orbital_dockyard");
1049 dockyard.getMemoryWithoutUpdate().set("$pkDockyard", true);
1050
1051 //neutralStation.setInteractionImage("illustrations", "abandoned_station2");
1052 Misc.setAbandonedStationMarket("pk_dockyard", dockyard);
1053
1054
1055 // add some unused stuff to the dockyard
1056 CargoAPI cargo = dockyard.getMarket().getSubmarket(Submarkets.SUBMARKET_STORAGE).getCargo();
1057 cargo.initMothballedShips(Factions.HEGEMONY);
1058
1059 CampaignFleetAPI temp = Global.getFactory().createEmptyFleet(Factions.HEGEMONY, null, true);
1060 temp.getFleetData().addFleetMember("enforcer_XIV_Elite");
1061 temp.getFleetData().addFleetMember("enforcer_XIV_Elite");
1062 temp.getFleetData().addFleetMember("eagle_xiv_Elite");
1063 temp.getFleetData().addFleetMember("dominator_XIV_Elite");
1064 DefaultFleetInflaterParams p = new DefaultFleetInflaterParams();
1065 p.quality = -1;
1066 temp.setInflater(new DefaultFleetInflater(p));
1067 temp.inflateIfNeeded();
1068 temp.setInflater(null);
1069
1070 int index = 0;
1071 for (FleetMemberAPI member : temp.getFleetData().getMembersListCopy()) {
1072 for (String slotId : member.getVariant().getFittedWeaponSlots()) {
1073 String weaponId = member.getVariant().getWeaponId(slotId);
1074 if (random.nextFloat() < 0.5f) {
1075 member.getVariant().clearSlot(slotId);
1076 }
1077 if (random.nextFloat() < 0.25f) {
1078 cargo.addWeapons(weaponId, 1);
1079 }
1080 }
1081 if (index == 0 || index == 2) {
1082 cargo.getMothballedShips().addFleetMember(member);
1083 }
1084 index++;
1085 }
1086 cargo.addCommodity(Commodities.METALS, 50f + random.nextInt(51));
1087
1088 List<CampaignFleetAPI> stations = getRemnantStations(true, false);
1089 float minDist = Float.MAX_VALUE;
1090 CampaignFleetAPI nexus = null;
1091 for (CampaignFleetAPI curr : stations) {
1092 float dist = Misc.getDistanceLY(tundra, curr);
1093 if (dist < minDist) {
1094 minDist = dist;
1095 nexus = curr;
1096 }
1097 }
1098 if (nexus != null) {
1099 if (DEBUG) System.out.println("Found Remnant nexus in [" + nexus.getContainingLocation().getName() + "]");
1100 nexus.getMemoryWithoutUpdate().set(PK_NEXUS_KEY, true);
1101 Global.getSector().getPersistentData().put(PK_NEXUS_KEY, nexus);
1102 Global.getSector().getMemoryWithoutUpdate().set(PK_NEXUS_KEY, nexus.getContainingLocation().getId());
1103
1104 Misc.addDefeatTrigger(nexus, "PKNexusDefeated");
1105 }
1106 }
1107
1108 protected void addLOCRLuddicPlanet(ThemeGenContext context) {
1109 if (DEBUG) System.out.println("Looking for LOCR_LUDDIC planet");
1110
1111 WeightedRandomPicker<PlanetAPI> picker = new WeightedRandomPicker<PlanetAPI>(random);
1112 WeightedRandomPicker<PlanetAPI> picker_fallback = new WeightedRandomPicker<PlanetAPI>(random);
1113
1114 // looking for a habitable planet in the fringe WITH good farming
1115 for (Constellation c : context.constellations) {
1116 for (StarSystemAPI system : c.getSystems()) {
1117
1118 if (system.hasTag(Tags.THEME_SPECIAL)) continue;
1119 if (system.isNebula()) continue;
1120 if (system.hasPulsar()) continue;
1121 if (system.hasBlackHole()) continue;
1122 if (!system.hasTag(Tags.THEME_MISC_SKIP) && !system.hasTag(Tags.THEME_MISC)) continue;
1123 if (system.hasTag(Tags.THEME_DERELICT)) continue;
1124
1125 for (PlanetAPI curr : system.getPlanets()) {
1126 if (curr.isStar()) continue;
1127 if (!curr.getMarket().isPlanetConditionMarketOnly()) continue;
1128
1129 if (curr.hasTag(Tags.NOT_RANDOM_MISSION_TARGET)) continue;
1130 if (curr.getMarket().hasCondition(Conditions.WATER_SURFACE)) continue; // Ludd gets seasick, I guess.
1131 if (curr.isGasGiant()) continue; // I mean, let's just be sure, right?
1132 if (curr.getMarket().hasCondition(Conditions.DECIVILIZED_SUBPOP)) continue;
1133
1134 // must have good farmland! Or at least OK farmland.
1135 if (curr.getMarket().hasCondition("farmland_rich") || curr.getMarket().hasCondition("farmland_bountiful"))
1136 {
1137 picker.add(curr);
1138 }
1139 else if ( curr.getMarket().hasCondition("farmland_adequate"))
1140 {
1141 picker_fallback.add(curr);
1142 }
1143 }
1144 }
1145 }
1146
1147 PlanetAPI planet = picker.pick();
1148 if (planet == null)
1149 {
1150 planet = picker_fallback.pick();
1151 }
1152
1153 if (planet != null) {
1154
1155 // add the ship they came in on
1156
1157 DerelictShipData params = new DerelictShipData(new PerShipData("nebula_Standard", ShipCondition.BATTERED, 0f), false);
1158 params.ship.shipName = "CGR Light of Exultation";
1159 params.ship.nameAlwaysKnown = true;
1160 //params.ship.fleetMemberId = id;
1161
1162 SectorEntityToken ship = BaseThemeGenerator.addSalvageEntity(planet.getStarSystem(), Entities.WRECK, Factions.NEUTRAL, params);
1163 ship.setDiscoverable(true);
1164 float orbitDays = 200f / (10f + (float) Math.random() * 5f);
1165 ship.setCircularOrbit(planet, (float) Math.random() * 360f, planet.getRadius() + 100f, orbitDays);
1166 ShipRecoverySpecialCreator creator = new ShipRecoverySpecialCreator(null, 0, 0, false, null, null);
1167 Misc.setSalvageSpecial(ship, creator.createSpecial(ship, null));
1168
1169 Global.getSector().getMemoryWithoutUpdate().set(LOCR_LUDDIC_TRANSPORT_KEY, ship);
1170 //ship.getMemoryWithoutUpdate().set(LOCR_LUDDIC, true);
1171
1172
1173 if (DEBUG) System.out.println("Adding LOCR_LUDDIC flag to [" + planet.getName() + "] in [" + planet.getContainingLocation().getNameWithLowercaseType() + "]");
1174 Global.getSector().getMemoryWithoutUpdate().set(LOCR_LUDDIC_PLANET_KEY, planet);
1175 planet.getMemoryWithoutUpdate().set(LOCR_LUDDIC, true);
1176 planet.getMemoryWithoutUpdate().set(LOCR_BLOCK_FIRST_SURVEY, true);
1177
1178 long seed = StarSystemGenerator.random.nextLong();
1179 planet.addTag(Tags.NOT_RANDOM_MISSION_TARGET);
1180
1181 } else {
1182 if (DEBUG) System.out.println("Failed to find a LOCR_LUDDIC planet, may Ludd forgive you.");
1183 }
1184 if (DEBUG) System.out.println("Finished adding LOCR_LUDDIC planet\n\n\n");
1185 }
1186
1187/* Maybe later. -dgb
1188 protected void addLOCRUtopiaPlanet(ThemeGenContext context) {
1189 if (DEBUG) System.out.println("Looking for LOCR_UTOPIA planet");
1190
1191 WeightedRandomPicker<PlanetAPI> picker = new WeightedRandomPicker<PlanetAPI>(random);
1192
1193 // looking for a habitable planet in the fringe
1194 for (Constellation c : context.constellations) {
1195 for (StarSystemAPI system : c.getSystems()) {
1196
1197 if (system.hasTag(Tags.THEME_SPECIAL)) continue;
1198 if (system.isNebula()) continue;
1199 if (system.hasPulsar()) continue;
1200 if (system.hasBlackHole()) continue;
1201 if (!system.hasTag(Tags.THEME_MISC_SKIP) && !system.hasTag(Tags.THEME_MISC)) continue;
1202 if (system.hasTag(Tags.THEME_DERELICT)) continue;
1203
1204 for (PlanetAPI curr : system.getPlanets()) {
1205 if (curr.isStar()) continue;
1206 if (!curr.getMarket().isPlanetConditionMarketOnly()) continue;
1207 if (curr.hasTag(Tags.NOT_RANDOM_MISSION_TARGET)) continue;
1208 if (curr.getMarket().hasCondition(Conditions.DECIVILIZED_SUBPOP)) continue; // no competition, please.
1209 if (curr.getMarket().hasCondition(Conditions.WATER_SURFACE)) continue; // I'd have to write around this.
1210 if (!curr.getMarket().hasCondition(Conditions.HABITABLE)) continue;
1211
1212 picker.add(curr);
1213 }
1214 }
1215 }
1216
1217 PlanetAPI planet = picker.pick();
1218
1219 if (planet != null) {
1220 if (DEBUG) System.out.println("Adding LOCR_UTOPIA flag to [" + planet.getName() + "] in [" + planet.getContainingLocation().getNameWithLowercaseType() + "]");
1221 Global.getSector().getMemoryWithoutUpdate().set(LOCR_UTOPIA_PLANET_KEY, planet);
1222 planet.getMemoryWithoutUpdate().set(LOCR_UTOPIA, true);
1223 planet.getMemoryWithoutUpdate().set(LOCR_BLOCK_FIRST_SURVEY, true);
1224
1225 long seed = StarSystemGenerator.random.nextLong();
1226 planet.addTag(Tags.NOT_RANDOM_MISSION_TARGET);
1227
1228 } else {
1229 if (DEBUG) System.out.println("Failed to find a planet for LOCR_UTOPIA; the dream is dead :( ");
1230 }
1231 if (DEBUG) System.out.println("Finished adding LOCR_UTOPIA planet\n\n\n");
1232 }
1233*/
1234
1235 protected void addLOCRMinersPlanet(ThemeGenContext context) {
1236 if (DEBUG) System.out.println("Looking for LOCR_MINERS planet");
1237
1238 WeightedRandomPicker<PlanetAPI> picker = new WeightedRandomPicker<PlanetAPI>(random);
1239
1240 // looking for a non-habitable planet or moon with good mining in the fringe
1241 for (Constellation c : context.constellations) {
1242 for (StarSystemAPI system : c.getSystems()) {
1243
1244 if (system.hasTag(Tags.THEME_SPECIAL)) continue;
1245 if (system.hasPulsar()) continue;
1246 if (!system.hasTag(Tags.THEME_MISC_SKIP) && !system.hasTag(Tags.THEME_MISC)) continue;
1247 if (system.hasTag(Tags.THEME_DERELICT)) continue;
1248
1249 for (PlanetAPI curr : system.getPlanets()) {
1250 if (curr.isStar()) continue;
1251 if (!curr.getMarket().isPlanetConditionMarketOnly()) continue;
1252 if (curr.hasTag(Tags.NOT_RANDOM_MISSION_TARGET)) continue;
1253 if (curr.getMarket().hasCondition(Conditions.HABITABLE)) continue;
1254 if (curr.getMarket().hasCondition(Conditions.EXTREME_TECTONIC_ACTIVITY)) continue; // It has to be a GOOD planet.
1255 if (curr.getMarket().hasCondition(Conditions.DECIVILIZED_SUBPOP)) continue;
1256 if (curr.getMarket().hasCondition(Conditions.WATER_SURFACE)) continue; // don't want to write around this.
1257 if (curr.isGasGiant()) continue;
1258 if (!( curr.getMarket().hasCondition(Conditions.VOLATILES_PLENTIFUL) ||
1259 curr.getMarket().hasCondition(Conditions.ORGANICS_PLENTIFUL) ||
1260 curr.getMarket().hasCondition(Conditions.RARE_ORE_ULTRARICH) ) ) continue;
1261 // curr.getMarket().hasCondition(Conditions.ORE_ULTRARICH) ) ) continue;
1262
1263 picker.add(curr);
1264 }
1265 }
1266 }
1267
1268 PlanetAPI planet = picker.pick();
1269
1270 if (planet != null) {
1271 if (DEBUG) System.out.println("Adding LOCR_MINERS flag to [" + planet.getName() + "] in [" + planet.getContainingLocation().getNameWithLowercaseType() + "]");
1272 Global.getSector().getMemoryWithoutUpdate().set(LOCR_MINERS_PLANET_KEY, planet);
1273 planet.getMemoryWithoutUpdate().set(LOCR_MINERS, true);
1274 planet.getMemoryWithoutUpdate().set(LOCR_BLOCK_FIRST_SURVEY, true);
1275
1276 long seed = StarSystemGenerator.random.nextLong();
1277 planet.addTag(Tags.NOT_RANDOM_MISSION_TARGET);
1278
1279 } else {
1280 if (DEBUG) System.out.println("Failed to find a planet for LOCR_MINERS.");
1281 }
1282 if (DEBUG) System.out.println("Finished adding LOCR_MINERS planet\n\n\n\n\n");
1283 }
1284
1285 protected void addLOCRPiratePlanet(ThemeGenContext context) {
1286 if (DEBUG) System.out.println("Looking for LOCR_PIRATE planet");
1287
1288 WeightedRandomPicker<PlanetAPI> picker = new WeightedRandomPicker<PlanetAPI>(random);
1289
1290 // looking for an obscure non-habitable planet or moon
1291 for (Constellation c : context.constellations) {
1292 for (StarSystemAPI system : c.getSystems()) {
1293
1294 if (system.hasTag(Tags.THEME_SPECIAL)) continue;
1295 if (system.hasPulsar()) continue;
1296 if (!system.hasTag(Tags.THEME_MISC_SKIP) && !system.hasTag(Tags.THEME_MISC)) continue;
1297 if (system.hasTag(Tags.THEME_DERELICT)) continue;
1298
1299 for (PlanetAPI curr : system.getPlanets()) {
1300 if (curr.isStar()) continue;
1301 if (!curr.getMarket().isPlanetConditionMarketOnly()) continue;
1302 if (curr.hasTag(Tags.NOT_RANDOM_MISSION_TARGET)) continue;
1303 if (curr.getMarket().hasCondition(Conditions.DECIVILIZED_SUBPOP)) continue; // no competition, please.
1304 if (curr.getMarket().hasCondition(Conditions.HABITABLE)) continue; // should be a POS
1305 if (curr.isGasGiant()) continue;
1306
1307 picker.add(curr);
1308 }
1309 }
1310 }
1311
1312 PlanetAPI planet = picker.pick();
1313
1314 if (planet != null) {
1315 if (DEBUG) System.out.println("Adding LOCR_PIRATE flag to [" + planet.getName() + "] in [" + planet.getContainingLocation().getNameWithLowercaseType() + "]");
1316 Global.getSector().getMemoryWithoutUpdate().set(LOCR_PIRATE_PLANET_KEY, planet);
1317 planet.getMemoryWithoutUpdate().set(LOCR_PIRATE, true);
1318 planet.getMemoryWithoutUpdate().set(LOCR_BLOCK_FIRST_SURVEY, true);
1319
1320 long seed = StarSystemGenerator.random.nextLong();
1321 planet.addTag(Tags.NOT_RANDOM_MISSION_TARGET);
1322
1323 } else {
1324 if (DEBUG) System.out.println("Failed to find a planet for LOCR_PIRATE; the dream is dead :( ");
1325 }
1326 if (DEBUG) System.out.println("Finished adding LOCR_PIRATE planet\n\n\n");
1327 }
1328
1329
1330 public static List<CampaignFleetAPI> getRemnantStations(boolean includeDamaged, boolean onlyDamaged) {
1331 List<CampaignFleetAPI> stations = new ArrayList<CampaignFleetAPI>();
1332 for (StarSystemAPI system : Global.getSector().getStarSystems()) {
1333 if (!system.hasTag(Tags.THEME_REMNANT_MAIN)) continue;
1334 if (system.hasTag(Tags.THEME_REMNANT_DESTROYED)) continue;
1335
1336 for (CampaignFleetAPI fleet : system.getFleets()) {
1337 if (!fleet.isStationMode()) continue;
1338 if (!Factions.REMNANTS.equals(fleet.getFaction().getId())) continue;
1339
1340 boolean damaged = fleet.getMemoryWithoutUpdate().getBoolean("$damagedStation");
1341 if (damaged && !includeDamaged) continue;
1342 if (!damaged && onlyDamaged) continue;
1343
1344 stations.add(fleet);
1345 }
1346 }
1347 return stations;
1348 }
1349}
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
static SettingsAPI getSettings()
Definition Global.java:51
static FactoryAPI getFactory()
Definition Global.java:35
static SectorAPI getSector()
Definition Global.java:59
static void generateConditionsForPlanet(GenContext context, PlanetAPI planet)
static NamePick pickName(String tag, String parent, LagrangePointType lagrangePoint)
void addShipGraveyard(StarSystemData data, float chanceToAddAny, int min, int max, WeightedRandomPicker< String > factions)
void addDerelictShip(StarSystemData data, EntityLocation loc, WeightedRandomPicker< String > factions)
static AddedEntity addEntity(Random random, StarSystemAPI system, WeightedRandomPicker< EntityLocation > locs, String type, String faction)
void addResearchStations(StarSystemData data, float chanceToAddAny, int min, int max, WeightedRandomPicker< String > stationTypes)
static EntityLocation pickAnyLocation(Random random, StarSystemAPI system, float gap, Set< SectorEntityToken > exclude)
static List< OrbitGap > findGaps(SectorEntityToken center, float minPad, float maxDist, float minGap)
void addCaches(StarSystemData data, float chanceToAddAny, int min, int max, WeightedRandomPicker< String > cacheTypes)
void addDerelictShips(StarSystemData data, float chanceToAddAny, int min, int max, WeightedRandomPicker< String > factions)
static SectorEntityToken addSalvageEntity(LocationAPI location, String id, String faction)
AddedEntity addInactiveGate(StarSystemData data, float prob, float probDebris, float probShips, WeightedRandomPicker< String > factions)
WeightedRandomPicker< String > createStringPicker(Object ... params)
void addDebrisFields(StarSystemData data, float chanceToAddAny, int min, int max)
AddedEntity addDebrisField(StarSystemData data, SectorEntityToken focus, float radius)
static void makeDiscoverable(SectorEntityToken entity, float xp, float sensorProfile)
void addDerelicts(ThemeGenContext context, String variant, int minNonSalvageable, int maxNonSalvageable, int minSalvageable, int maxSalvageable, String ... allowedThemes)
static List< CampaignFleetAPI > getRemnantStations(boolean includeDamaged, boolean onlyDamaged)
static WeightedRandomPicker< String > getNearbyFactions(Random random, SectorEntityToken entity)
CampaignFleetAPI createEmptyFleet(String factionId, String name, boolean aiMode)
OrbitAPI createCircularOrbitPointingDown(SectorEntityToken focus, float angle, float orbitRadius, float orbitDays)
ShipVariantAPI getVariant(String variantId)
Object getSpec(Class c, String id, boolean nullOnNotFound)
CustomEntitySpecAPI getCustomEntitySpec(String id)