Starsector API
Loading...
Searching...
No Matches
RuinsThemeGenerator.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.Collections;
5import java.util.Comparator;
6import java.util.List;
7
8import org.lwjgl.util.vector.Vector2f;
9
10import com.fs.starfarer.api.campaign.PlanetAPI;
11import com.fs.starfarer.api.campaign.StarSystemAPI;
12import com.fs.starfarer.api.impl.campaign.ids.Entities;
13import com.fs.starfarer.api.impl.campaign.ids.Tags;
14import com.fs.starfarer.api.impl.campaign.procgen.Constellation;
15import com.fs.starfarer.api.impl.campaign.procgen.NameAssigner;
16import com.fs.starfarer.api.impl.campaign.procgen.StarSystemGenerator;
17import com.fs.starfarer.api.impl.campaign.procgen.themes.SalvageSpecialAssigner.SpecialCreationContext;
18import com.fs.starfarer.api.util.Misc;
19import com.fs.starfarer.api.util.WeightedRandomPicker;
20
21
23
24 public static final int MIN_CONSTELLATIONS_WITH_RUINS = 15;
25 public static final int MAX_CONSTELLATIONS_WITH_RUINS = 25;
26
27 public static float CONSTELLATION_SKIP_PROB = 0f;
28
29
30 public String getThemeId() {
31 return Themes.RUINS;
32 }
33
34
35 @Override
36 public void generateForSector(ThemeGenContext context, float allowedUnusedFraction) {
37
38 float total = (float) (context.constellations.size() - context.majorThemes.size()) * allowedUnusedFraction;
39 if (total <= 0) return;
40
42 if (num > total) num = (int) total;
43
44
45 List<Constellation> constellations = getSortedAvailableConstellations(context, false, new Vector2f(), null);
46 Collections.reverse(constellations);
47
48 float skipProb = CONSTELLATION_SKIP_PROB;
49 if (total < num / (1f - skipProb)) {
50 skipProb = 1f - (num / total);
51 }
52 skipProb = 0f;
53
54 List<StarSystemData> ruinSystems = new ArrayList<StarSystemData>();
55
56 if (DEBUG) System.out.println("\n\n\n");
57 if (DEBUG) System.out.println("Generating systems with ruins");
58
59 int count = 0;
60
61 int numUsed = 0;
62 for (int i = 0; i < num && i < constellations.size(); i++) {
63 Constellation c = constellations.get(i);
64 if (random.nextFloat() < skipProb) {
65 if (DEBUG) System.out.println("Skipping constellation " + c.getName());
66 continue;
67 }
68
69
70// if (c.getName().toLowerCase().contains("shero")) {
71// System.out.println("wefwefwef");
72// }
73
74 List<StarSystemData> systems = new ArrayList<StarSystemData>();
75 for (StarSystemAPI system : c.getSystems()) {
76 StarSystemData data = computeSystemData(system);
77 systems.add(data);
78 }
79
80 List<StarSystemData> mainCandidates = getSortedSystemsSuitedToBePopulated(systems);
81
82 int numMain = 1 + random.nextInt(3);
83 if (numMain > mainCandidates.size()) numMain = mainCandidates.size();
84 if (numMain <= 0) {
85 if (DEBUG) System.out.println("Skipping constellation " + c.getName() + ", no suitable main candidates");
86 continue;
87 }
88
89 context.majorThemes.put(c, Themes.RUINS);
90 numUsed++;
91
92 if (DEBUG) System.out.println("Generating " + numMain + " main systems in " + c.getName());
93 for (int j = 0; j < numMain; j++) {
94 StarSystemData data = mainCandidates.get(j);
95 populateMain(data);
96
97 data.system.addTag(Tags.THEME_INTERESTING);
98 data.system.addTag(Tags.THEME_RUINS);
99 data.system.addTag(Tags.THEME_RUINS_MAIN);
100 ruinSystems.add(data);
101
102 RuinsFleetRouteManager fleets = new RuinsFleetRouteManager(data.system);
103 data.system.addScript(fleets);
104
105 if (!NameAssigner.isNameSpecial(data.system)) {
106 NameAssigner.assignSpecialNames(data.system);
107 }
108 }
109
110 for (StarSystemData data : systems) {
111 int index = mainCandidates.indexOf(data);
112 if (index >= 0 && index < numMain) continue;
113
114 populateNonMain(data);
115
116 data.system.addTag(Tags.THEME_INTERESTING);
117 data.system.addTag(Tags.THEME_RUINS);
118 data.system.addTag(Tags.THEME_RUINS_SECONDARY);
119 ruinSystems.add(data);
120 }
121
122// if (count == 1) {
123// System.out.println("RANDOM INDEX " + count + ": " + random.nextLong());
124// }
125 count++;
126 }
127
128 SpecialCreationContext specialContext = new SpecialCreationContext();
129 specialContext.themeId = getThemeId();
130 SalvageSpecialAssigner.assignSpecials(ruinSystems, specialContext);
131
132 if (DEBUG) System.out.println("Finished generating systems with ruins\n\n\n\n\n");
133
134 }
135
136
137
138 public void populateNonMain(StarSystemData data) {
139 if (DEBUG) System.out.println(" Generating secondary ruins in " + data.system.getName());
140 boolean special = data.isBlackHole() || data.isNebula() || data.isPulsar();
141 if (special) {
142 addResearchStations(data, 0.75f, 1, 1, createStringPicker(Entities.STATION_RESEARCH, 10f));
143 }
144
145 if (random.nextFloat() < 0.5f) return;
146
147 if (!data.resourceRich.isEmpty()) {
148 addMiningStations(data, 0.5f, 1, 1, createStringPicker(Entities.STATION_MINING, 10f));
149 }
150
151 if (!special && !data.habitable.isEmpty()) {
152 // ruins on planet, or orbital station
153 addHabCenters(data, 0.25f, 1, 1, createStringPicker(Entities.ORBITAL_HABITAT, 10f));
154 }
155
156 WeightedRandomPicker<String> factions = SalvageSpecialAssigner.getNearbyFactions(random, data.system.getCenter(),
157 15f, 10f, 10f);
158
159 addShipGraveyard(data, 0.05f, 1, 1, factions);
160
161 addDebrisFields(data, 0.25f, 1, 2);
162
163 addDerelictShips(data, 0.5f, 0, 3, factions);
164
165 addCaches(data, 0.25f, 0, 2, createStringPicker(
166 Entities.WEAPONS_CACHE, 4f,
167 Entities.WEAPONS_CACHE_SMALL, 10f,
168 Entities.WEAPONS_CACHE_HIGH, 4f,
169 Entities.WEAPONS_CACHE_SMALL_HIGH, 10f,
170 Entities.WEAPONS_CACHE_LOW, 4f,
171 Entities.WEAPONS_CACHE_SMALL_LOW, 10f,
172 Entities.SUPPLY_CACHE, 4f,
173 Entities.SUPPLY_CACHE_SMALL, 10f,
174 Entities.EQUIPMENT_CACHE, 4f,
175 Entities.EQUIPMENT_CACHE_SMALL, 10f
176 ));
177
178 }
179
180
181 public void populateMain(StarSystemData data) {
182
183 if (DEBUG) System.out.println(" Generating ruins in " + data.system.getName());
184
185 StarSystemAPI system = data.system;
186
187 int maxHabCenters = 1 + random.nextInt(3);
188
189 HabitationLevel level = HabitationLevel.LOW;
190 if (maxHabCenters == 2) level = HabitationLevel.MEDIUM;
191 if (maxHabCenters >= 3) level = HabitationLevel.HIGH;
192
193 addHabCenters(data, 1, maxHabCenters, maxHabCenters, createStringPicker(Entities.ORBITAL_HABITAT, 10f));
194
195 // add various stations, orbiting entities, etc
196 float probGate = 1f;
197 float probRelay = 1f;
198 float probMining = 0.5f;
199 float probResearch = 0.25f;
200
201 switch (level) {
202 case HIGH:
203 probGate = 0.5f;
204 probRelay = 1f;
205 break;
206 case MEDIUM:
207 probGate = 0.3f;
208 probRelay = 0.75f;
209 break;
210 case LOW:
211 probGate = 0.2f;
212 probRelay = 0.5f;
213 break;
214 }
215
216// MN-6186477243757813340
217// float test = Misc.getDistance(data.system.getLocation(), new Vector2f(48500, -22000));
218// if (test < 1000) {
219// System.out.println("HERE: " + random.nextLong());
220// }
221// if (data.system.getName().toLowerCase().contains("cadmus")) {
222// System.out.println("wefwefwefew");
223// }
224 //addCommRelay(data, probRelay);
225
226 addObjectives(data, probRelay);
227
228
229 WeightedRandomPicker<String> factions = SalvageSpecialAssigner.getNearbyFactions(random, system.getCenter(),
230 15f, 5f, 5f);
231 addInactiveGate(data, probGate, 0.75f, 0.75f, factions);
232
233 addShipGraveyard(data, 0.25f, 1, 1, factions);
234
235 addMiningStations(data, probMining, 1, 1, createStringPicker(Entities.STATION_MINING, 10f));
236
237 addResearchStations(data, probResearch, 1, 1, createStringPicker(Entities.STATION_RESEARCH, 10f));
238
239
240 //addDebrisFields(data, 0.75f, 1, 5, Factions.REMNANTS, 0.2f, 1, 3);
241 addDebrisFields(data, 0.75f, 1, 5);
242
243 addDerelictShips(data, 0.75f, 0, 7, factions);
244
245
246 WeightedRandomPicker<String> caches = createStringPicker(
247 Entities.SUPPLY_CACHE, 10f,
248 Entities.SUPPLY_CACHE_SMALL, 10f,
249 Entities.EQUIPMENT_CACHE, 10f,
250 Entities.EQUIPMENT_CACHE_SMALL, 10f
251 );
252
253
254 float r = random.nextFloat();
255 if (r < 0.33f) {
256 caches.add(Entities.WEAPONS_CACHE, 10f);
257 caches.add(Entities.WEAPONS_CACHE_SMALL, 10f);
258 } else if (r < 0.67f) {
259 caches.add(Entities.WEAPONS_CACHE_LOW, 10f);
260 caches.add(Entities.WEAPONS_CACHE_SMALL_LOW, 10f);
261 } else {
262 caches.add(Entities.WEAPONS_CACHE_HIGH, 10f);
263 caches.add(Entities.WEAPONS_CACHE_SMALL_HIGH, 10f);
264 }
265
266 addCaches(data, 0.75f, 0, 3, caches);
267
268 }
269
270
271
272 public List<StarSystemData> getSortedSystemsSuitedToBePopulated(List<StarSystemData> systems) {
273 List<StarSystemData> result = new ArrayList<StarSystemData>();
274
275 for (StarSystemData data : systems) {
276 if (data.isBlackHole() || data.isNebula() || data.isPulsar()) continue;
277
278 if (data.planets.size() >= 4 || data.habitable.size() >= 1) {
279 result.add(data);
280 }
281 }
282
283 Collections.sort(systems, new Comparator<StarSystemData>() {
284 public int compare(StarSystemData o1, StarSystemData o2) {
285 float s1 = getMainCenterScore(o1);
286 float s2 = getMainCenterScore(o2);
287 return (int) Math.signum(s2 - s1);
288 }
289 });
290
291 return result;
292 }
293
294 public float getMainCenterScore(StarSystemData data) {
295 float total = 0f;
296 total += data.planets.size() * 1f;
297 total += data.habitable.size() * 2f;
298 total += data.resourceRich.size() * 0.25f;
299 return total;
300 }
301
302
303
310 protected List<Constellation> getSortedAvailableConstellations(ThemeGenContext context, boolean emptyOk, final Vector2f sortFrom, List<Constellation> exclude) {
311 List<Constellation> constellations = new ArrayList<Constellation>();
312 for (Constellation c : context.constellations) {
313 if (context.majorThemes.containsKey(c)) continue;
314 if (!emptyOk && constellationIsEmpty(c)) continue;
315
316 constellations.add(c);
317 }
318
319 if (exclude != null) {
320 constellations.removeAll(exclude);
321 }
322
323 Collections.sort(constellations, new Comparator<Constellation>() {
324 public int compare(Constellation o1, Constellation o2) {
325 float d1 = Misc.getDistance(o1.getLocation(), sortFrom);
326 float d2 = Misc.getDistance(o2.getLocation(), sortFrom);
327 return (int) Math.signum(d2 - d1);
328 }
329 });
330 return constellations;
331 }
332
333
334 public static boolean constellationIsEmpty(Constellation c) {
335 for (StarSystemAPI s : c.getSystems()) {
336 if (!systemIsEmpty(s)) return false;
337 }
338 return true;
339 }
340 public static boolean systemIsEmpty(StarSystemAPI system) {
341 for (PlanetAPI p : system.getPlanets()) {
342 if (!p.isStar()) return false;
343 }
344 return true;
345 }
346
347
348
349
350 @Override
351 public int getOrder() {
352 return 2000;
353 }
354
355
356
357
358}
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
static boolean isNameSpecial(StarSystemAPI system)
void addShipGraveyard(StarSystemData data, float chanceToAddAny, int min, int max, WeightedRandomPicker< String > factions)
void addResearchStations(StarSystemData data, float chanceToAddAny, int min, int max, WeightedRandomPicker< String > stationTypes)
List< AddedEntity > addObjectives(StarSystemData data, float prob)
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)
AddedEntity addInactiveGate(StarSystemData data, float prob, float probDebris, float probShips, WeightedRandomPicker< String > factions)
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)
void addMiningStations(StarSystemData data, float chanceToAddAny, int min, int max, WeightedRandomPicker< String > stationTypes)
void generateForSector(ThemeGenContext context, float allowedUnusedFraction)
List< StarSystemData > getSortedSystemsSuitedToBePopulated(List< StarSystemData > systems)
List< Constellation > getSortedAvailableConstellations(ThemeGenContext context, boolean emptyOk, final Vector2f sortFrom, List< Constellation > exclude)
static WeightedRandomPicker< String > getNearbyFactions(Random random, SectorEntityToken entity)