Starsector API
Loading...
Searching...
No Matches
SectorProcGen.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.procgen;
2
3import java.util.ArrayList;
4import java.util.EnumSet;
5import java.util.List;
6import java.util.Random;
7
8import org.lwjgl.util.vector.Vector2f;
9
10import com.fs.starfarer.api.Global;
11import com.fs.starfarer.api.campaign.SectorGenProgress;
12import com.fs.starfarer.api.campaign.SectorProcGenPlugin;
13import com.fs.starfarer.api.campaign.StarSystemAPI;
14import com.fs.starfarer.api.characters.CharacterCreationData;
15import com.fs.starfarer.api.impl.campaign.ids.StarTypes;
16import com.fs.starfarer.api.impl.campaign.ids.Tags;
17import com.fs.starfarer.api.impl.campaign.procgen.StarSystemGenerator.CustomConstellationParams;
18import com.fs.starfarer.api.impl.campaign.procgen.StarSystemGenerator.StarSystemType;
19import com.fs.starfarer.api.impl.campaign.procgen.themes.SectorThemeGenerator;
20import com.fs.starfarer.api.impl.campaign.procgen.themes.ThemeGenContext;
21import com.fs.starfarer.api.impl.campaign.terrain.HyperspaceAbyssPlugin;
22import com.fs.starfarer.api.impl.campaign.terrain.HyperspaceTerrainPlugin;
23import com.fs.starfarer.api.util.Misc;
24import com.fs.starfarer.api.util.Pair;
25import com.fs.starfarer.api.util.WeightedRandomPicker;
26
27public class SectorProcGen implements SectorProcGenPlugin {
28
29 public static final float CELL_SIZE = 2000;
30 public static final int CONSTELLATION_CELLS = 10;
31
32 public void prepare(CharacterCreationData data) {
33 // do this here so that hand-crafted systems using
34 // procgen use the proper seed
35 if (data.getSeed() > 0) {
36 StarSystemGenerator.random.setSeed(data.getSeed());
37 }
39
40// List<String> names = new ArrayList<String>();
41//
42// Collection<Object> specs = Global.getSettings().getAllSpecs(NameGenData.class);
43// for (Object curr : specs) {
44// NameGenData spec = (NameGenData) curr;
45// names.add(spec.getName());
46// }
47// MarkovNames.load(names, 3);
48
50 }
51
52
53 public void generate(CharacterCreationData data, SectorGenProgress progress) {
54 float w = Global.getSettings().getFloat("sectorWidth");
55 float h = Global.getSettings().getFloat("sectorHeight");
56
57
58 boolean small = "small".equals(data.getSectorSize());
59 StarAge sectorAge = data.getSectorAge();
60 if (sectorAge == null) {
61 sectorAge = StarAge.ANY;
62 }
63
64 int cellsWide = (int) (w / CELL_SIZE);
65 int cellsHigh = (int) (h / CELL_SIZE);
66
67
68 boolean [][] cells = new boolean [cellsWide][cellsHigh];
69 int count = 100;
70
71 int vPad = CONSTELLATION_CELLS / 2;
72 int hPad = CONSTELLATION_CELLS / 2;
73 if (small) {
74 hPad = (int) (31000 / CELL_SIZE);
75 vPad = (int) (19000 / CELL_SIZE);
76 }
77
78 for (int i = 0; i < cells.length; i++) {
79 for (int j = 0; j < cells[0].length; j++) {
80 if (i <= hPad || j <= vPad || i >= cellsWide - hPad || j >= cellsHigh - vPad) {
81 cells[i][j] = true;
82 }
83 }
84 }
85
86 //System.out.println("EXISTING SYSTEMS: ");
87 for (StarSystemAPI system : Global.getSector().getStarSystems()) {
88 int [] index = getIndex(system.getLocation());
89 int x = index[0];
90 int y = index[1];
91 if (x < 0) x = 0;
92 if (y < 0) y = 0;
93 if (x > cellsWide - 1) x = cellsWide - 1;
94 if (y > cellsHigh - 1) y = cellsHigh - 1;
95
96// if (system.getName().toLowerCase().startsWith("groom")) {
97// System.out.println("ewfwefwe");
98// }
99 //System.out.println(system.getName());
100
101 blotOut(cells, x, y, 8);
102 }
103
104 // for the Orion-Perseus Abyss label/the Abyss itself
105// blotOut(cells, 0, 0, 12);
106// blotOut(cells, 6, 0, 12);
107// blotOut(cells, 12, 0, 12);
108 blotOut(cells, 0, 0, 22);
109 blotOut(cells, 16, 3, 16);
110 blotOut(cells, 5, 11, 12);
111
112 progress.render("Generating sector...", 0.1f);
113
114 List<CustomConstellationParams> custom = getCustomConstellations();
115
116 List<Constellation> constellations = new ArrayList<Constellation>();
117 for (int k = 0; k < count; k++) {
118 WeightedRandomPicker<Pair<Integer, Integer>> picker = new WeightedRandomPicker<Pair<Integer,Integer>>(StarSystemGenerator.random);
119 for (int i = 0; i < cells.length; i++) {
120 for (int j = 0; j < cells[0].length; j++) {
121 if (cells[i][j]) continue;
122
123 Pair<Integer, Integer> p = new Pair<Integer, Integer>(i, j);
124 picker.add(p);
125 }
126 }
127
128 Pair<Integer, Integer> pick = picker.pick();
129 if (pick == null) continue;
130
131 blotOut(cells, pick.one, pick.two, CONSTELLATION_CELLS);
132
133 float x = pick.one * CELL_SIZE - w / 2f;
134 float y = pick.two * CELL_SIZE - h / 2f;
135
136 CustomConstellationParams params = new CustomConstellationParams(StarAge.ANY);
137 if (!custom.isEmpty()) params = custom.remove(0);
138
139 StarAge age = sectorAge;
140 if (age == StarAge.ANY) {
141// if (x < -w/6f) {
142// age = StarAge.YOUNG;
143// } else if (x > w/6f) {
144// age = StarAge.OLD;
145// } else {
146// age = StarAge.AVERAGE;
147// }
148 WeightedRandomPicker<StarAge> agePicker = new WeightedRandomPicker<StarAge>(StarSystemGenerator.random);
149 agePicker.add(StarAge.YOUNG);
150 agePicker.add(StarAge.AVERAGE);
151 agePicker.add(StarAge.OLD);
152 age = agePicker.pick();
153 }
154
155 params.age = age;
156
157 params.location = new Vector2f(x, y);
159 constellations.add(c);
160
161 progress.render("Generating constellations...", 0.1f + 0.8f * (float)k / (float) count);
162 }
163
164
165
166 HyperspaceTerrainPlugin hyper = (HyperspaceTerrainPlugin) Misc.getHyperspaceTerrain().getPlugin();
167 NebulaEditor editor = new NebulaEditor(hyper);
168 editor.regenNoise();
169 editor.noisePrune(0.8f);
170 editor.regenNoise();
171
172
173 Random random = StarSystemGenerator.random;
174
175 // add a spiral going from the outside towards the center
176 float angleOffset = random.nextFloat() * 360f;
177 editor.clearArc(0f, 0f, w / 2f, w / 2f + 3000,
178 angleOffset + 0f, angleOffset + 360f * (2f + random.nextFloat() * 2f), 0.01f, 0.33f);
179
180 // do some random arcs
181 int numArcs = (int) (20f + 8f * random.nextFloat());
182
183 for (int i = 0; i < numArcs; i++) {
184 float dist = w/2f + w/2f * random.nextFloat();
185 float angle = random.nextFloat() * 360f;
186
187 Vector2f dir = Misc.getUnitVectorAtDegreeAngle(angle);
188 dir.scale(dist - (w/12f + w/3f * random.nextFloat()));
189
190 //float tileSize = nebulaPlugin.getTileSize();
191 //float width = tileSize * (2f + 4f * random.nextFloat());
192 float width = 800f * (1f + 2f * random.nextFloat());
193
194 float clearThreshold = 0f + 0.5f * random.nextFloat();
195 //clearThreshold = 0f;
196
197 editor.clearArc(dir.x, dir.y, dist - width/2f, dist + width/2f, 0, 360f, clearThreshold);
198 }
199
201
202 progress.render("Generating objects...", 0.9f);
203
204
205 ThemeGenContext context = new ThemeGenContext();
206 context.constellations = constellations;
207 SectorThemeGenerator.generate(context);
208
209 progress.render("Finishing generation...", 1f);
210
211 //MarkovNames.clear();
212
213 //System.out.println("Generated " + constellations.size() + " constellations");
214
215
216// List constellations = Global.getSettings().getConstellations();
217// for (int i = 0; i < constellations.size(); i++) {
218// CustomConstellationParams params = (CustomConstellationParams) constellations.get(i);
219// new StarSystemGenerator(params).generate();
220// }
221 }
222
224 float w = Global.getSettings().getFloat("sectorWidth");
225 float h = Global.getSettings().getFloat("sectorHeight");
226
227 HyperspaceTerrainPlugin hyper = (HyperspaceTerrainPlugin) Misc.getHyperspaceTerrain().getPlugin();
228 NebulaEditor editor = new NebulaEditor(hyper);
229
230 HyperspaceAbyssPlugin ac = hyper.getAbyssPlugin();
231 float ts = editor.getTileSize();
232 for (float x = -w/2f; x < w/2f; x += ts * 0.8f) {
233 for (float y = -h/2f; y < h/2f; y += ts * 0.8f) {
234 if (ac.isInAbyss(new Vector2f(x, y))) {
235 editor.setTileAt(x, y, -1, 0f, false);
236 }
237 }
238 }
239
240 for (StarSystemAPI system : Misc.getAbyssalSystems()) {
241 system.addTag(Tags.SYSTEM_ABYSSAL);
242 }
243 }
244
245
246
247
248
249 public static void blotOut(boolean [][] cells, int x, int y, int c) {
250 //int c = CONSTELLATION_CELLS;
251 for (int i = Math.max(0, x - c / 2); i <= x + c / 2 && i < cells.length; i++) {
252 for (int j = Math.max(0, y - c / 2); j <= y + c / 2 && j < cells[0].length; j++) {
253 cells[i][j] = true;
254 }
255 }
256 }
257
258 public static int [] getIndex(Vector2f loc) {
259 float w = Global.getSettings().getFloat("sectorWidth");
260 float h = Global.getSettings().getFloat("sectorHeight");
261
262 int x = (int) ((loc.x + w / 2f) / CELL_SIZE);
263 int y = (int) ((loc.y + h / 2f) / CELL_SIZE);
264
265 return new int []{x, y};
266 }
267
268
269 public static List<CustomConstellationParams> getCustomConstellations() {
270 List<CustomConstellationParams> result = new ArrayList<CustomConstellationParams>();
271
272 for (StarSystemType type : EnumSet.allOf(StarSystemType.class)) {
273 if (type == StarSystemType.DEEP_SPACE || type == StarSystemType.DEEP_SPACE_GAS_GIANT) continue;
274 CustomConstellationParams params = new CustomConstellationParams(StarAge.ANY);
275 params.systemTypes.add(type);
276 if (type == StarSystemType.NEBULA) params.forceNebula = true;
277 result.add(params);
278 }
279
280 CustomConstellationParams params = new CustomConstellationParams(StarAge.ANY);
281 params.starTypes.add(StarTypes.BLACK_HOLE);
282 result.add(params);
283
284 params = new CustomConstellationParams(StarAge.ANY);
285 params.starTypes.add(StarTypes.NEUTRON_STAR);
286 result.add(params);
287
288 return result;
289 }
290
291}
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
static SettingsAPI getSettings()
Definition Global.java:51
static SectorAPI getSector()
Definition Global.java:59
void clearArc(float x, float y, float innerRadius, float outerRadius, float startAngle, float endAngle)
void generate(CharacterCreationData data, SectorGenProgress progress)
static void blotOut(boolean[][] cells, int x, int y, int c)
static List< CustomConstellationParams > getCustomConstellations()