001package com.fs.starfarer.api.impl.campaign.procgen; 002 003import java.awt.Color; 004import java.util.ArrayList; 005import java.util.Collection; 006import java.util.EnumSet; 007import java.util.LinkedHashMap; 008import java.util.LinkedHashSet; 009import java.util.List; 010import java.util.Map; 011import java.util.Random; 012import java.util.Set; 013 014import org.lwjgl.util.vector.Vector2f; 015 016import com.fs.starfarer.api.Global; 017import com.fs.starfarer.api.campaign.CampaignTerrainAPI; 018import com.fs.starfarer.api.campaign.JumpPointAPI; 019import com.fs.starfarer.api.campaign.LocationAPI; 020import com.fs.starfarer.api.campaign.PlanetAPI; 021import com.fs.starfarer.api.campaign.PlanetSpecAPI; 022import com.fs.starfarer.api.campaign.SectorAPI; 023import com.fs.starfarer.api.campaign.SectorEntityToken; 024import com.fs.starfarer.api.campaign.StarSystemAPI; 025import com.fs.starfarer.api.characters.FullName.Gender; 026import com.fs.starfarer.api.impl.campaign.ids.Entities; 027import com.fs.starfarer.api.impl.campaign.ids.Factions; 028import com.fs.starfarer.api.impl.campaign.ids.Tags; 029import com.fs.starfarer.api.impl.campaign.ids.Terrain; 030import com.fs.starfarer.api.impl.campaign.procgen.Constellation.ConstellationType; 031import com.fs.starfarer.api.impl.campaign.procgen.ConstellationGen.SpringConnection; 032import com.fs.starfarer.api.impl.campaign.procgen.ConstellationGen.SpringSystem; 033import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator; 034import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.AddedEntity; 035import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.EntityLocation; 036import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.LocationType; 037import com.fs.starfarer.api.impl.campaign.terrain.BaseTiledTerrain.TileParams; 038import com.fs.starfarer.api.impl.campaign.terrain.HyperspaceTerrainPlugin; 039import com.fs.starfarer.api.impl.campaign.terrain.NebulaTerrainPlugin; 040import com.fs.starfarer.api.impl.campaign.terrain.PulsarBeamTerrainPlugin; 041import com.fs.starfarer.api.impl.campaign.terrain.StarCoronaTerrainPlugin; 042import com.fs.starfarer.api.impl.campaign.terrain.StarCoronaTerrainPlugin.CoronaParams; 043import com.fs.starfarer.api.util.Misc; 044import com.fs.starfarer.api.util.WeightedRandomPicker; 045 046 047public class StarSystemGenerator { 048 049 public static class CustomConstellationParams implements Cloneable { 050 public String name = null; 051 public String secondaryName = null; 052 public StarAge age = null; 053 public int minStars = 0; 054 public int maxStars = 0; 055 public int numStars = 0; 056 public boolean forceNebula = false; 057 public List<StarSystemType> systemTypes = new ArrayList<StarSystemType>(); 058 public List<String> starTypes = new ArrayList<String>(); 059 public Vector2f location = null; 060 061 public CustomConstellationParams(StarAge age) { 062 this.age = age; 063 } 064 065 @Override 066 public CustomConstellationParams clone() { 067 try { 068 return (CustomConstellationParams) super.clone(); 069 } catch (CloneNotSupportedException e) { 070 return null; 071 } 072 } 073 074 075 } 076 077 078 public static enum StarSystemType { 079 SINGLE, 080 BINARY_CLOSE, 081 BINARY_FAR, 082 TRINARY_2CLOSE, 083 TRINARY_1CLOSE_1FAR, 084 TRINARY_2FAR, 085 NEBULA, 086 DEEP_SPACE, 087 088 @Deprecated DEEP_SPACE_GAS_GIANT, 089 } 090 091 public static final float MIN_STAR_DIST = 2000f; 092 public static final float MAX_STAR_DIST = 2000f; 093 094 public static final float TILT_MIN = -45f; 095 public static final float TILT_MAX = 45f; 096 public static final float PITCH_MIN = -15f; 097 public static final float PITCH_MAX = 45f; 098 099 public static final float MAX_ORBIT_RADIUS = 20000; 100 public static final float FAR_MAX_ORBIT_RADIUS = 5000; 101 102 public static final float LAGRANGE_OFFSET = 60f; 103 104 public static final float BASE_INCR = 800f; 105 public static final float BASE_INCR_MOON = 200f; 106 107 public static final float STARTING_RADIUS_STAR_BASE = 750f; 108 public static final float STARTING_RADIUS_STAR_RANGE = 500f; 109 110 public static final float STARTING_RADIUS_MOON_BASE = 300f; 111 public static final float STARTING_RADIUS_MOON_RANGE = 100f; 112 113 //public static final float MOON_RADIUS_MULT = 0.75f; 114 public static final float MOON_RADIUS_MAX_FRACTION_OF_PARENT = 0.33f; 115 public static final float MOON_RADIUS_MIN_FRACTION_OF_NORMAL = 0.2f; 116 public static final float MOON_RADIUS_MAX_FRACTION_OF_NORMAL = 0.75f; 117 public static final float MIN_MOON_RADIUS = 60f; 118 //public static final float MAX_MOON_RADIUS = 100; 119 120 121 public static final String TAG_FIRST_ORBIT_ONLY = "first_orbit_only"; 122 public static final String TAG_GIANT_MOON = "around_giant_at_any_offset"; 123 public static final String TAG_LAGRANGE_ONLY = "lagrange_only"; 124 public static final String TAG_NOT_IN_NEBULA = "not_in_nebula"; 125 public static final String TAG_REQUIRES_NEBULA = "requires_nebula"; 126 127 public static final String TAG_NOT_NEBULA_UNLESS_MOON = "not_NEBULA_unless_moon"; 128 129 public static final String CAT_HAB5 = "cat_hab5"; 130 public static final String CAT_HAB4 = "cat_hab4"; 131 public static final String CAT_HAB3 = "cat_hab3"; 132 public static final String CAT_HAB2 = "cat_hab2"; 133 public static final String CAT_HAB1 = "cat_hab1"; 134 135 public static final String CAT_NOTHING = "cat_nothing"; 136 public static final String CAT_GIANT = "cat_giant"; 137 138 public static final String COL_LAGRANGE = "lagrange"; 139 public static final String COL_IN_ASTEROIDS = "in_asteroids"; 140 public static final String COL_IS_MOON = "is_moon"; 141 public static final String COL_BINARY = "binary"; 142 public static final String COL_TRINARY = "trinary"; 143 144 public static final String NEBULA_DEFAULT = "nebula"; 145 public static final String NEBULA_AMBER = "nebula_amber"; 146 public static final String NEBULA_BLUE = "nebula_blue"; 147 public static final String NEBULA_NONE = "no_nebula"; 148 149 150 public static Map<StarAge, String> nebulaTypes = new LinkedHashMap<StarAge, String>(); 151 public static Map<String, WeightedRandomPicker<String>> backgroundsByNebulaType = new LinkedHashMap<String, WeightedRandomPicker<String>>(); 152 153 154 public static List<TerrainGenPlugin> terrainPlugins = new ArrayList<TerrainGenPlugin>(); 155 public static void addTerrainGenPlugin(TerrainGenPlugin plugin) { 156 terrainPlugins.add(0, plugin); 157 } 158 public static void removeTerrainGenPlugin(TerrainGenPlugin plugin) { 159 terrainPlugins.remove(plugin); 160 } 161 public static Random random = new Random(); 162 163 static { 164 terrainPlugins.add(new RingGenPlugin()); 165 terrainPlugins.add(new AsteroidBeltGenPlugin()); 166 terrainPlugins.add(new MagFieldGenPlugin()); 167 168 terrainPlugins.add(new NebulaSmallGenPlugin()); 169 terrainPlugins.add(new AsteroidFieldGenPlugin()); 170 171 terrainPlugins.add(new AccretionDiskGenPlugin()); 172 173 nebulaTypes.put(StarAge.YOUNG, NEBULA_BLUE); 174 nebulaTypes.put(StarAge.AVERAGE, NEBULA_DEFAULT); 175 nebulaTypes.put(StarAge.OLD, NEBULA_AMBER); 176 177 nebulaTypes.put(StarAge.ANY, NEBULA_DEFAULT); 178 179 updateBackgroundPickers(); 180 } 181 182 public static void updateBackgroundPickers() 183 { 184 WeightedRandomPicker<String> picker; 185 picker = new WeightedRandomPicker<String>(random); 186 picker.add("graphics/backgrounds/background2.jpg", 10); 187 picker.add("graphics/backgrounds/background4.jpg", 10); 188 backgroundsByNebulaType.put(NEBULA_NONE, picker); 189 190 picker = new WeightedRandomPicker<String>(random); 191 picker.add("graphics/backgrounds/background5.jpg", 10); 192 backgroundsByNebulaType.put(NEBULA_BLUE, picker); 193 194 picker = new WeightedRandomPicker<String>(random); 195 picker.add("graphics/backgrounds/background6.jpg", 10); 196 backgroundsByNebulaType.put(NEBULA_AMBER, picker); 197 198 picker = new WeightedRandomPicker<String>(random); 199 picker.add("graphics/backgrounds/background1.jpg", 10); 200 picker.add("graphics/backgrounds/background2.jpg", 10); 201 backgroundsByNebulaType.put(NEBULA_DEFAULT, picker); 202 } 203 204 public static boolean DEBUG = Global.getSettings().isDevMode(); 205 206 public static TerrainGenPlugin pickTerrainGenPlugin(TerrainGenDataSpec terrainData, GenContext context) { 207 for (TerrainGenPlugin plugin : terrainPlugins) { 208 if (plugin.wantsToHandle(terrainData, context)) return plugin; 209 } 210 return null; 211 } 212 213 214 public static class GeneratedPlanet { 215 public SectorEntityToken parent; 216 public PlanetAPI planet; 217 public float orbitDays; 218 public float orbitRadius; 219 public float orbitAngle; 220 public boolean isMoon; 221 public GeneratedPlanet(SectorEntityToken parent, PlanetAPI planet, boolean isMoon, float orbitDays, float orbitRadius, float orbitAngle) { 222 this.parent = parent; 223 this.planet = planet; 224 this.isMoon = isMoon; 225 this.orbitDays = orbitDays; 226 this.orbitRadius = orbitRadius; 227 this.orbitAngle = orbitAngle; 228 } 229 } 230 231 public static enum LagrangePointType { 232// L1, 233// L2, 234// L3, 235 L4, 236 L5, 237 } 238 239 240 public static class LagrangePoint { 241 public GeneratedPlanet parent; 242 public LagrangePointType type; 243 public LagrangePoint(GeneratedPlanet parent, LagrangePointType type) { 244 this.parent = parent; 245 this.type = type; 246 } 247 } 248 249 250 public static class GenResult { 251 public float orbitalWidth; 252 public boolean onlyIncrementByWidth = false; 253 public List<SectorEntityToken> entities = new ArrayList<SectorEntityToken>(); 254 public GenContext context; 255 256 public GenResult() { 257 258 } 259 } 260 261 public static class GenContext { 262 public StarSystemGenerator gen; 263 public List<GeneratedPlanet> generatedPlanets = new ArrayList<GeneratedPlanet>(); 264 265 public Set<String> excludeCategories = new LinkedHashSet<String>(); 266 267 //public NamePick parentNamePick = null; 268 public StarSystemAPI system; 269 public SectorEntityToken center; 270 public StarGenDataSpec starData; 271 public PlanetAPI parent; 272 public int orbitIndex = -1; 273 274 public int startingOrbitIndex = 0; 275 public String age; 276 277 public float currentRadius; 278 public String parentCategory; 279 public int parentOrbitIndex; 280 public float parentRadiusOverride = -1; 281 282 public GeneratedPlanet lagrangeParent = null; 283 public LagrangePointType lagrangePointType = null; 284 285 public List<String> multipliers = new ArrayList<String>(); 286 public float maxOrbitRadius; 287 288 public Map<Object, Object> customData = new LinkedHashMap<Object, Object>(); 289 290 public GenContext(StarSystemGenerator gen, StarSystemAPI system, SectorEntityToken center, 291 StarGenDataSpec starData, PlanetAPI parent, 292 //NamePick parentNamePick, 293 int orbitIndex, 294 String age, float currentRadius, float maxOrbitRadius, String parentCategory, int parentOrbitIndex) { 295 super(); 296 //this.parentNamePick = parentNamePick; 297 this.maxOrbitRadius = maxOrbitRadius; 298 this.gen = gen; 299 this.system = system; 300 this.center = center; 301 this.starData = starData; 302 this.parent = parent; 303 this.startingOrbitIndex = orbitIndex; 304 this.orbitIndex = 0; 305 this.age = age; 306 this.currentRadius = currentRadius; 307 this.parentCategory = parentCategory; 308 this.parentOrbitIndex = parentOrbitIndex; 309 } 310 311 } 312 313 //private static long index = 0; 314 315 protected StarAge constellationAge; 316 317 protected StarSystemType systemType = StarSystemType.SINGLE; 318 protected StarAge starAge; 319 protected SectorAPI sector; 320 protected StarSystemAPI system; 321 protected LocationAPI hyper; 322 323 protected PlanetAPI star; 324 protected PlanetAPI secondary; 325 protected PlanetAPI tertiary; 326 327 protected SectorEntityToken systemCenter; 328 protected float centerRadius = 0f; 329 protected AgeGenDataSpec constellationAgeData; 330 protected AgeGenDataSpec starAgeData; 331 protected StarGenDataSpec starData; 332 protected String nebulaType; 333 protected String backgroundName; 334// protected NamePick constellationName; 335// protected NamePick primaryName; 336// protected NamePick secondaryName; 337// protected NamePick tertiaryName; 338 339 protected Map<SectorEntityToken, PlanetAPI> lagrangeParentMap = new LinkedHashMap<SectorEntityToken, PlanetAPI>(); 340 protected Map<SectorEntityToken, List<SectorEntityToken>> allNameableEntitiesAdded = new LinkedHashMap<SectorEntityToken, List<SectorEntityToken>>(); 341 protected CustomConstellationParams params; 342 343 344 public StarSystemGenerator(CustomConstellationParams params) { 345 this.params = params; 346 this.constellationAge = params.age; 347 348 if (this.constellationAge == StarAge.ANY) { 349 WeightedRandomPicker<StarAge> picker = new WeightedRandomPicker<StarAge>(random); 350 picker.add(StarAge.AVERAGE); 351 picker.add(StarAge.OLD); 352 picker.add(StarAge.YOUNG); 353 this.constellationAge = picker.pick(); 354 } 355 356 constellationAgeData = (AgeGenDataSpec) Global.getSettings().getSpec(AgeGenDataSpec.class, constellationAge.name(), true); 357 } 358 359 360 361 362 363 public void pickNebulaAndBackground() { 364 boolean hasNebula = constellationAgeData.getProbNebula() > random.nextFloat(); 365 if (params != null && params.forceNebula) hasNebula = true; 366 367// hasNebula = true; 368// hasNebula = false; 369 370 nebulaType = NEBULA_NONE; 371 if (hasNebula) { 372 nebulaType = nebulaTypes.get(constellationAge); 373 } 374 375 WeightedRandomPicker<String> bgPicker = backgroundsByNebulaType.get(nebulaType); 376 backgroundName = bgPicker.pick(); 377 } 378 379 380 381 382 public Constellation generate() { 383 384// if (true) { 385// params = new CustomConstellationParams(StarAge.OLD); 386// params.numStars = 1; 387// params.starTypes.add(StarTypes.YELLOW); 388// params.systemTypes.add(StarSystemType.SINGLE); 389// 390// this.constellationAge = params.age; 391// constellationAgeData = (AgeGenDataSpec) Global.getSettings().getSpec(AgeGenDataSpec.class, constellationAge.name(), true); 392// } 393 394 //random = new Random(12312312312L); 395 396 //DEBUG = false; 397 398 lagrangeParentMap = new LinkedHashMap<SectorEntityToken, PlanetAPI>(); 399 allNameableEntitiesAdded = new LinkedHashMap<SectorEntityToken, List<SectorEntityToken>>(); 400 401 SectorAPI sector = Global.getSector(); 402 Vector2f loc = new Vector2f(); 403 if (params != null && params.location != null) { 404 loc = new Vector2f(params.location); 405 } else { 406 loc = new Vector2f(sector.getPlayerFleet().getLocation()); 407 loc.x = (int) loc.x; 408 loc.y = (int) loc.y; 409 } 410 411 412 pickNebulaAndBackground(); 413 414 List<StarSystemAPI> systems = new ArrayList<StarSystemAPI>(); 415 int stars = (int) Math.round(getNormalRandom(1, 7)); 416 if (params != null && params.numStars > 0) { 417 stars = params.numStars; 418 } else if (params != null && params.minStars > 0 && params.maxStars > 0) { 419 stars = (int) Math.round(getNormalRandom(params.minStars, params.maxStars)); 420 } 421 422// constellationName = ProcgenUsedNames.pickName(NameGenData.TAG_CONSTELLATION, null); 423// ProcgenUsedNames.notifyUsed(constellationName.nameWithRomanSuffixIfAny); 424// Global.getSettings().greekLetterReset(); 425 426 for (int i = 0; i < stars; i++) { 427 generateSystem(new Vector2f(0, 0)); 428 if (system != null) { 429 systems.add(system); 430 } 431 } 432 433 434 SpringSystem springs = ConstellationGen.doConstellationLayout(systems, random, loc); 435 Global.getSector().getHyperspace().updateAllOrbits(); 436 437 HyperspaceTerrainPlugin plugin = (HyperspaceTerrainPlugin) Misc.getHyperspaceTerrain().getPlugin(); 438 NebulaEditor editor = new NebulaEditor(plugin); 439 440 float minRadius = plugin.getTileSize() * 2f; 441 for (StarSystemAPI curr : systems) { 442 float radius = curr.getMaxRadiusInHyperspace(); 443 editor.clearArc(curr.getLocation().x, curr.getLocation().y, 0, radius + minRadius * 0.5f, 0, 360f); 444 editor.clearArc(curr.getLocation().x, curr.getLocation().y, 0, radius + minRadius, 0, 360f, 0.25f); 445 } 446 447 for (SpringConnection conn : springs.connections) { 448 if (!conn.pull) continue; 449 float r1 = ((StarSystemAPI)conn.from.custom).getMaxRadiusInHyperspace(); 450 float r2 = ((StarSystemAPI)conn.to.custom).getMaxRadiusInHyperspace(); 451 float dist = Misc.getDistance(conn.from.loc, conn.to.loc); 452 453 float radius = Math.max(0, dist * 0.67f - r1 - r2); 454 455// float x = (conn.from.loc.x + conn.to.loc.x) * 0.5f; 456// float y = (conn.from.loc.y + conn.to.loc.y) * 0.5f; 457// editor.clearArc(x, y, 0, radius + minRadius * 0.5f, 0, 360f); 458// editor.clearArc(x, y, 0, radius + minRadius, 0, 360f, 0.25f); 459 460 Vector2f diff = Vector2f.sub(conn.to.loc, conn.from.loc, new Vector2f()); 461 float x = conn.from.loc.x + diff.x * 0.33f; 462 float y = conn.from.loc.y + diff.y * 0.33f; 463 editor.clearArc(x, y, 0, radius + minRadius * 1f, 0, 360f); 464 editor.clearArc(x, y, 0, radius + minRadius * 2f, 0, 360f, 0.25f); 465 466 x = conn.from.loc.x + diff.x * 0.67f; 467 y = conn.from.loc.y + diff.y * 0.67f; 468 editor.clearArc(x, y, 0, radius + minRadius * 1f, 0, 360f); 469 editor.clearArc(x, y, 0, radius + minRadius * 2f, 0, 360f, 0.25f); 470 } 471 472 ConstellationType type = ConstellationType.NORMAL; 473 if (!NEBULA_NONE.equals(nebulaType)) { 474 type = ConstellationType.NEBULA; 475 } 476 477 Constellation c = new Constellation(type, constellationAge); 478 //c.setType(ConstellationType.NORMAL); // for now; too many end up being called "Nebula" otherwise 479 c.getSystems().addAll(systems); 480 c.setLagrangeParentMap(lagrangeParentMap); 481 c.setAllEntitiesAdded(allNameableEntitiesAdded); 482 483 484// SalvageEntityGeneratorOld seg = new SalvageEntityGeneratorOld(c); 485// seg.addSalvageableEntities(); 486 487 488 NameAssigner namer = new NameAssigner(c); 489 namer.setSpecialNamesProbability(0.37f); 490 namer.assignNames(params.name, params.secondaryName); 491 492 for (SectorEntityToken entity : allNameableEntitiesAdded.keySet()) { 493 if (entity instanceof PlanetAPI && entity.getMarket() != null) { 494 entity.getMarket().setName(entity.getName()); 495 } 496 } 497 498 //if (systems.size() > 1) { 499 for (StarSystemAPI system : systems) { 500 system.setConstellation(c); 501 } 502 //} 503 504 return c; 505 } 506 507 508 public void generateSystem(Vector2f loc) { 509 //index++; 510 511 systemType = pickSystemType(constellationAge); 512 513// if (systemType == StarSystemType.NEBULA) { 514// System.out.println("wfwefwe1231232"); 515// } 516 517 String uuid = Misc.genUID(); 518 519// String id = "system_" + index; 520// String name = "System " + index; 521 522 String id = "system_" + uuid; 523 String name = "System " + uuid; 524 525// String base = constellationName.nameWithRomanSuffixIfAny; 526// if (constellationName.secondaryWithRomanSuffixIfAny != null) { 527// base = constellationName.secondaryWithRomanSuffixIfAny; 528// } 529// String name = Global.getSettings().getNextGreekLetter(constellationName) + " " + base; 530// String id = name.toLowerCase(); 531 532 533 //if (systemType == StarSystemType.NEBULA) name += " Nebula"; 534 535 if (!initSystem(name, loc)) { 536 cleanup(); 537 return; 538 } 539 540 star = null; 541 secondary = null; 542 tertiary = null; 543 systemCenter = null; 544 545 546 547 if (!addStars(id)) { 548 cleanup(); 549 return; 550 } 551 552// if (systemType == StarSystemType.NEBULA) { 553// if (star.getSpec().isBlackHole()) { 554// System.out.println("wefwefew"); 555// } 556// } 557 558 updateAgeAfterPickingStar(); 559 560 float binaryPad = 1500f; 561 562 float maxOrbitRadius = MAX_ORBIT_RADIUS; 563 if (systemType == StarSystemType.BINARY_FAR || 564 systemType == StarSystemType.TRINARY_1CLOSE_1FAR || 565 systemType == StarSystemType.TRINARY_2FAR) { 566 maxOrbitRadius -= FAR_MAX_ORBIT_RADIUS + binaryPad; 567 } 568 GenResult result = addPlanetsAndTerrain(MAX_ORBIT_RADIUS); 569 //addJumpPoints(result); 570 float primaryOrbitalRadius = star.getRadius(); 571 if (result != null) { 572 primaryOrbitalRadius = result.orbitalWidth * 0.5f; 573 } 574 575 // add far stars, if needed 576 float orbitAngle = random.nextFloat() * 360f; 577 float baseOrbitRadius = primaryOrbitalRadius + binaryPad; 578 float orbitDays = baseOrbitRadius / (3f + random.nextFloat() * 2f); 579 if (systemType == StarSystemType.BINARY_FAR && secondary != null) { 580 addFarStar(secondary, orbitAngle, baseOrbitRadius, orbitDays); 581 } else if (systemType == StarSystemType.TRINARY_1CLOSE_1FAR && tertiary != null) { 582 addFarStar(tertiary, orbitAngle, baseOrbitRadius, orbitDays); 583 } else if (systemType == StarSystemType.TRINARY_2FAR) { 584 addFarStar(secondary, orbitAngle, baseOrbitRadius, orbitDays); 585 addFarStar(tertiary, orbitAngle + 60f + 180f * random.nextFloat(), baseOrbitRadius, orbitDays); 586 } 587 588 589 if (systemType == StarSystemType.NEBULA) { 590 star.setSkipForJumpPointAutoGen(true); 591 } 592 593 addJumpPoints(result, false); 594 595 if (systemType == StarSystemType.NEBULA) { 596 system.removeEntity(star); 597 StarCoronaTerrainPlugin coronaPlugin = Misc.getCoronaFor(star); 598 if (coronaPlugin != null) { 599 system.removeEntity(coronaPlugin.getEntity()); 600 } 601 system.setStar(null); 602 system.initNonStarCenter(); 603 for (SectorEntityToken entity : system.getAllEntities()) { 604 if (entity.getOrbitFocus() == star || 605 entity.getOrbitFocus() == system.getCenter()) { 606 entity.setOrbit(null); 607 } 608 } 609 system.getCenter().addTag(Tags.AMBIENT_LS); 610 } 611 612 system.autogenerateHyperspaceJumpPoints(true, false); 613 614 if (systemType == StarSystemType.NEBULA) { 615 //system.addEntity(star); 616 system.setStar(star); 617 //system.removeEntity(system.getCenter()); 618 //system.setCenter(null); 619 } 620 621 addStableLocations(); 622 623 addSystemwideNebula(); 624 } 625 626 627 protected void addFarStar(PlanetAPI farStar, float orbitAngle, float baseOrbitRadius, float orbitPeriod) { 628 float min = 0; 629 float max = 2; 630 int numOrbits = (int) Math.round(getNormalRandom(min, max)); 631 GenResult resultFar = null; 632 if (numOrbits > 0) { 633 float currentRadius = farStar.getRadius() + STARTING_RADIUS_STAR_BASE + STARTING_RADIUS_STAR_RANGE * random.nextFloat(); 634 635 StarGenDataSpec farData = (StarGenDataSpec) Global.getSettings().getSpec(StarGenDataSpec.class, farStar.getSpec().getPlanetType(), false); 636 StarAge farAge = farData.getAge(); 637 if (farAge == StarAge.ANY) { 638 farAge = constellationAge; 639 } 640 641 //GenContext context = new GenContext(this, system, star, starData, 642 GenContext context = new GenContext(this, system, farStar, farData, 643 null, 0, farAge.name(), currentRadius, FAR_MAX_ORBIT_RADIUS, null, -1); 644 645 646 resultFar = addOrbitingEntities(context, numOrbits, false, true, false, true); 647 resultFar.context = context; 648 } 649 650 if (resultFar != null) { 651 baseOrbitRadius += resultFar.orbitalWidth * 0.5f; 652 } 653 654 SectorEntityToken center = star; 655 if (systemType == StarSystemType.TRINARY_1CLOSE_1FAR) { 656 center = systemCenter; 657 } 658 farStar.setCircularOrbit(center, orbitAngle, baseOrbitRadius, orbitPeriod); 659 660 if (resultFar != null) { 661 addJumpPoints(resultFar, true); 662 } 663 } 664 665 666 667 protected StarSystemType pickSystemType(StarAge constellationAge) { 668// if (true) { 669// return StarSystemType.BINARY_CLOSE; 670// } 671 672 if (params != null && !params.systemTypes.isEmpty()) { 673 return params.systemTypes.remove(0); 674 } 675 676 677 WeightedRandomPicker<StarSystemType> picker = new WeightedRandomPicker<StarSystemType>(random); 678 for (StarSystemType type : EnumSet.allOf(StarSystemType.class)) { 679 if (type == StarSystemType.DEEP_SPACE || type == StarSystemType.DEEP_SPACE_GAS_GIANT) continue; 680 681 Object test = Global.getSettings().getSpec(LocationGenDataSpec.class, type.name(), true); 682 if (test == null) continue; 683 LocationGenDataSpec data = (LocationGenDataSpec) test; 684 685 boolean nebulaStatusOk = NEBULA_NONE.equals(nebulaType) || !data.hasTag(TAG_NOT_IN_NEBULA); 686 nebulaStatusOk &= !NEBULA_NONE.equals(nebulaType) || !data.hasTag(TAG_REQUIRES_NEBULA); 687 688 if (!nebulaStatusOk) continue; 689 690 float freq = 0f; 691 switch (constellationAge) { 692 case AVERAGE: 693 freq = data.getFreqAVERAGE(); 694 break; 695 case OLD: 696 freq = data.getFreqOLD(); 697 break; 698 case YOUNG: 699 freq = data.getFreqYOUNG(); 700 break; 701 } 702 picker.add(type, freq); 703 } 704 705 return picker.pick(); 706 707 //return StarSystemType.TRINARY_1CLOSE_1FAR; 708 //return StarSystemType.TRINARY_2FAR; 709 //return StarSystemType.TRINARY_2CLOSE; 710 //return StarSystemType.BINARY_CLOSE; 711 //return StarSystemType.BINARY_FAR; 712 //return StarSystemType.NORMAL; 713 } 714 715 716 protected boolean addStars(String id) { 717 if (systemType == StarSystemType.BINARY_CLOSE || 718 systemType == StarSystemType.TRINARY_1CLOSE_1FAR || 719 systemType == StarSystemType.TRINARY_2CLOSE) { 720 system.initNonStarCenter(); 721 systemCenter = system.getCenter(); 722 } 723 724// if (systemType == StarSystemType.NEBULA) { 725// if (system.getId().equals("system 7f6")) { 726// System.out.println("wefwefew"); 727// } 728// } 729 730 PlanetSpecAPI starSpec = pickStar(constellationAge); 731 if (starSpec == null) return false; 732 733 starData = (StarGenDataSpec) Global.getSettings().getSpec(StarGenDataSpec.class, starSpec.getPlanetType(), false); 734 float radius = getRadius(starData.getMinRadius(), starData.getMaxRadius()); 735 736 float corona = radius * (starData.getCoronaMult() + starData.getCoronaVar() * (random.nextFloat() - 0.5f)); 737 if (corona < starData.getCoronaMin()) corona = starData.getCoronaMin(); 738 739 //corona += 2000f; 740 741 star = system.initStar(id, // unique id for this star 742 starSpec.getPlanetType(), // id in planets.json 743 radius, // radius (in pixels at default zoom) 744 corona, // corona radius, from star edge 745 starData.getSolarWind(), 746 (float) (starData.getMinFlare() + (starData.getMaxFlare() - starData.getMinFlare()) * random.nextFloat()), 747 starData.getCrLossMult() 748 ); 749 750 if (systemType == StarSystemType.NEBULA) { 751 star.addTag(Tags.AMBIENT_LS); 752 } 753 754 if (systemCenter == null) { 755 systemCenter = star; 756 centerRadius = star.getRadius(); 757 } 758 759 760 // create and switch aronud stars so that the primary is always the largest 761 if (systemType == StarSystemType.BINARY_CLOSE) { 762 secondary = addRandomStar(id + "_b", system.getBaseName() + " B"); 763 if (secondary == null) return false; 764 switchPrimaryAndSecondaryIfNeeded(true); 765 } else if (systemType == StarSystemType.BINARY_FAR) { 766 secondary = addRandomStar(id + "_b", system.getBaseName() + " B"); 767 if (secondary == null) return false; 768 switchPrimaryAndSecondaryIfNeeded(true); 769 770 centerRadius = star.getRadius(); 771 772 secondary.setLightColorOverrideIfStar(pickLightColorForStar(secondary)); 773 } else if (systemType == StarSystemType.TRINARY_2CLOSE || 774 systemType == StarSystemType.TRINARY_1CLOSE_1FAR || 775 systemType == StarSystemType.TRINARY_2FAR) { 776 secondary = addRandomStar(id + "_b", system.getBaseName() + " B"); 777 if (secondary == null) return false; 778 switchPrimaryAndSecondaryIfNeeded(true); 779 780 tertiary = addRandomStar(id + "_c", system.getBaseName() + " C"); 781 if (tertiary == null) return false; 782 switchPrimaryAndTertiaryIfNeeded(true); 783 784 if (systemType == StarSystemType.TRINARY_1CLOSE_1FAR) { 785 tertiary.setLightColorOverrideIfStar(pickLightColorForStar(tertiary)); 786 } else if (systemType == StarSystemType.TRINARY_2FAR) { 787 secondary.setLightColorOverrideIfStar(pickLightColorForStar(secondary)); 788 tertiary.setLightColorOverrideIfStar(pickLightColorForStar(tertiary)); 789 } 790 } 791 792 // make close stars orbit common center 793 if (systemType == StarSystemType.BINARY_CLOSE || systemType == StarSystemType.TRINARY_1CLOSE_1FAR) { 794 float dist = STARTING_RADIUS_STAR_BASE + STARTING_RADIUS_STAR_RANGE * random.nextFloat(); 795 796 float r1 = star.getRadius(); 797 float r2 = secondary.getRadius(); 798 if (star.getSpec().getPlanetType().equals("black_hole")) r1 *= 5f; 799 if (secondary.getSpec().getPlanetType().equals("black_hole")) r2 *= 5f; 800 801 float totalRadius = r1 + r2; 802 dist += totalRadius; 803 804 float orbitPrimary = dist * r2 / totalRadius; 805 float orbitSecondary = dist * r1 / totalRadius; 806 807 centerRadius = Math.max(orbitPrimary + star.getRadius(), orbitSecondary + secondary.getRadius()); 808 809 float anglePrimary = random.nextFloat() * 360f; 810 float orbitDays = dist / (30f + random.nextFloat() * 50f); 811 812 star.setCircularOrbit(system.getCenter(), anglePrimary, orbitPrimary, orbitDays); 813 secondary.setCircularOrbit(system.getCenter(), anglePrimary + 180f, orbitSecondary, orbitDays); 814 815// if (systemType == StarSystemType.TRINARY_1CLOSE_1FAR && tertiary != null) { 816// tertiary.setCircularOrbit(system.getCenter(), 817// tertiary.getCircularOrbitAngle(), 818// tertiary.getCircularOrbitRadius(), 819// tertiary.getCircularOrbitPeriod()); 820// } 821 } else if (systemType == StarSystemType.TRINARY_2CLOSE) { 822 float dist = STARTING_RADIUS_STAR_BASE + STARTING_RADIUS_STAR_RANGE * random.nextFloat(); 823 dist += star.getRadius(); 824 825 float anglePrimary = random.nextFloat() * 360f; 826 float orbitDays = dist / (20f + random.nextFloat() * 80f); 827 828 // smaller dist for primary/secondary so that their gravity wells get generated first 829 // and are closer to the center 830 star.setCircularOrbit(system.getCenter(), anglePrimary, dist - 10, orbitDays); 831 secondary.setCircularOrbit(system.getCenter(), anglePrimary + 120f, dist - 5, orbitDays); 832 tertiary.setCircularOrbit(system.getCenter(), anglePrimary + 240f, dist, orbitDays); 833 834 centerRadius = dist + star.getRadius(); 835 } else { 836 star.getLocation().set(0, 0); 837 } 838 839 840 if (star != null) { 841 starData = (StarGenDataSpec) Global.getSettings().getSpec(StarGenDataSpec.class, star.getSpec().getPlanetType(), false); 842 } 843// if (systemCenter instanceof PlanetAPI) { 844// centerRadius = star.getRadius(); 845// } 846 847 848 setDefaultLightColorBasedOnStars(); 849 850 851 if (star != null) { 852 ArrayList<SectorEntityToken> list = new ArrayList<SectorEntityToken>(); 853 list.add(star); 854 allNameableEntitiesAdded.put(star, list); 855 system.setStar(star); 856 } 857 if (secondary != null) { 858 ArrayList<SectorEntityToken> list = new ArrayList<SectorEntityToken>(); 859 list.add(secondary); 860 allNameableEntitiesAdded.put(secondary, list); 861 system.setSecondary(secondary); 862 } 863 if (tertiary != null){ 864 ArrayList<SectorEntityToken> list = new ArrayList<SectorEntityToken>(); 865 list.add(tertiary); 866 allNameableEntitiesAdded.put(tertiary, list); 867 system.setTertiary(tertiary); 868 } 869 870 setBlackHoleIfBlackHole(star); 871 setBlackHoleIfBlackHole(secondary); 872 setBlackHoleIfBlackHole(tertiary); 873 874 setPulsarIfNeutron(star); 875 setPulsarIfNeutron(secondary); 876 setPulsarIfNeutron(tertiary); 877 878 return true; 879 } 880 881 protected void setBlackHoleIfBlackHole(PlanetAPI star) { 882 if (star == null) return; 883 884 if (star.getSpec().getPlanetType().equals("black_hole")) { 885 StarCoronaTerrainPlugin coronaPlugin = Misc.getCoronaFor(star); 886 if (coronaPlugin != null) { 887 system.removeEntity(coronaPlugin.getEntity()); 888 } 889 890 StarGenDataSpec starData = (StarGenDataSpec) Global.getSettings().getSpec(StarGenDataSpec.class, star.getSpec().getPlanetType(), false); 891 float corona = star.getRadius() * (starData.getCoronaMult() + starData.getCoronaVar() * (random.nextFloat() - 0.5f)); 892 if (corona < starData.getCoronaMin()) corona = starData.getCoronaMin(); 893 894 SectorEntityToken eventHorizon = system.addTerrain(Terrain.EVENT_HORIZON, 895 new CoronaParams(star.getRadius() + corona, (star.getRadius() + corona) / 2f, 896 star, starData.getSolarWind(), 897 (float) (starData.getMinFlare() + (starData.getMaxFlare() - starData.getMinFlare()) * random.nextFloat()), 898 starData.getCrLossMult())); 899 eventHorizon.setCircularOrbit(star, 0, 0, 100); 900 } 901 } 902 903 protected void setPulsarIfNeutron(PlanetAPI star) { 904 if (star == null) return; 905 906 if (star.getSpec().getPlanetType().equals("star_neutron")) { 907 StarCoronaTerrainPlugin coronaPlugin = Misc.getCoronaFor(star); 908 if (coronaPlugin != null) { 909 system.removeEntity(coronaPlugin.getEntity()); 910 } 911 912 system.addCorona(star, 913 300, // radius 914 3, // wind 915 0, // flares 916 3); // cr loss 917 918 919 StarGenDataSpec starData = (StarGenDataSpec) Global.getSettings().getSpec(StarGenDataSpec.class, star.getSpec().getPlanetType(), false); 920 float corona = star.getRadius() * (starData.getCoronaMult() + starData.getCoronaVar() * (random.nextFloat() - 0.5f)); 921 if (corona < starData.getCoronaMin()) corona = starData.getCoronaMin(); 922 923 SectorEntityToken eventHorizon = system.addTerrain(Terrain.PULSAR_BEAM, 924 new CoronaParams(star.getRadius() + corona, (star.getRadius() + corona) / 2f, 925 star, starData.getSolarWind(), 926 (float) (starData.getMinFlare() + (starData.getMaxFlare() - starData.getMinFlare()) * random.nextFloat()), 927 starData.getCrLossMult())); 928 eventHorizon.setCircularOrbit(star, 0, 0, 100); 929 } 930 } 931 932 protected void switchPrimaryAndSecondaryIfNeeded(boolean sizeDownSmaller) { 933 if (star == null || secondary == null) return; 934 935 if (star.getRadius() < secondary.getRadius()) { 936 star = secondary; 937 secondary = system.getStar(); 938 system.setStar(star); 939 940 String temp = star.getName(); 941 star.setName(secondary.getName()); 942 secondary.setName(temp); 943 944 temp = star.getId(); 945 star.setId(secondary.getId()); 946 secondary.setId(temp); 947 948 if (sizeDownSmaller) { 949 secondary.setRadius(Math.min(secondary.getRadius(), star.getRadius() * 0.67f)); 950 } 951 952 if (secondary == systemCenter) { 953 systemCenter = star; 954 centerRadius = systemCenter.getRadius(); 955 } 956 } 957 } 958 959 protected void switchPrimaryAndTertiaryIfNeeded(boolean sizeDownSmaller) { 960 if (star == null || tertiary == null) return; 961 962 if (star.getRadius() < tertiary.getRadius()) { 963 star = tertiary; 964 tertiary = system.getStar(); 965 system.setStar(star); 966 967 String temp = star.getName(); 968 star.setName(tertiary.getName()); 969 tertiary.setName(temp); 970 971 temp = star.getId(); 972 star.setId(tertiary.getId()); 973 tertiary.setId(temp); 974 975 if (sizeDownSmaller) { 976 tertiary.setRadius(Math.min(tertiary.getRadius(), star.getRadius() * 0.67f)); 977 } 978 979 if (tertiary == systemCenter) { 980 systemCenter = star; 981 centerRadius = systemCenter.getRadius(); 982 } 983 } 984 } 985 986 987 988 protected void addStableLocations() { 989 int min = 1; 990 int max = 3; 991 992// int planets = system.getPlanets().size(); // includes stars 993// max = Math.min(max, planets/2); 994// if (min > max) min = max; 995 996 //int num = (int) Math.round(getNormalRandom(min, max)); 997 int num = random.nextInt(max + 1 - min) + min; 998 999 if (num == min && random.nextFloat() < 0.25f) { 1000 num = 0; 1001 } 1002 1003 addStableLocations(system, num); 1004 } 1005 public static void addStableLocations(StarSystemAPI system, int num) { 1006 for (int i = 0; i < num; i++) { 1007 LinkedHashMap<LocationType, Float> weights = new LinkedHashMap<LocationType, Float>(); 1008 weights.put(LocationType.STAR_ORBIT, 10f); 1009 weights.put(LocationType.OUTER_SYSTEM, 10f); 1010 weights.put(LocationType.L_POINT, 10f); 1011 weights.put(LocationType.IN_SMALL_NEBULA, 2f); 1012 WeightedRandomPicker<EntityLocation> locs = BaseThemeGenerator.getLocations(random, system, null, 100f, weights); 1013 EntityLocation loc = locs.pick(); 1014 1015 AddedEntity added = BaseThemeGenerator.addNonSalvageEntity(system, loc, Entities.STABLE_LOCATION, Factions.NEUTRAL); 1016 //if (DEBUG && added != null) System.out.println(" Added stable location"); 1017 1018 if (added != null) { 1019 BaseThemeGenerator.convertOrbitPointingDown(added.entity); 1020 } 1021 } 1022 } 1023 1024 1025 protected void addJumpPoints(GenResult result, boolean farStarMode) { 1026 1027 //float outerRadius = star.getRadius() + STARTING_RADIUS_STAR_BASE + STARTING_RADIUS_STAR_RANGE * random.nextFloat(); 1028 float outerRadius = centerRadius + STARTING_RADIUS_STAR_BASE + STARTING_RADIUS_STAR_RANGE * random.nextFloat(); 1029 if (result != null) { 1030 outerRadius = result.orbitalWidth / 2f + 500f; 1031 } 1032 1033 if (farStarMode) { 1034 //if (result.context.orbitIndex < 0) { 1035 if (result.context.orbitIndex < 0 && random.nextFloat() < 0.5f) { 1036 return; 1037 } 1038 SectorEntityToken farStar = result.context.center; 1039 String name = "Omega Jump-point"; 1040 if (result.context.center == tertiary) { 1041 name = "Omicron Jump-point"; 1042 } 1043 JumpPointAPI point = Global.getFactory().createJumpPoint(null, name); 1044 point.setStandardWormholeToHyperspaceVisual(); 1045 float orbitDays = outerRadius / (15f + random.nextFloat() * 5f); 1046 //point.setCircularOrbit(star, random.nextFloat() * 360f, outerRadius, orbitDays); 1047 point.setCircularOrbit(farStar, random.nextFloat() * 360f, outerRadius, orbitDays); 1048 system.addEntity(point); 1049 1050 return; 1051 } 1052 1053 1054 //JumpPointAPI point = Global.getFactory().createJumpPoint(null, system.getBaseName() + " Fringe"); 1055 JumpPointAPI point = Global.getFactory().createJumpPoint(null, "Fringe Jump-point"); 1056 point.setStandardWormholeToHyperspaceVisual(); 1057 float orbitDays = outerRadius / (15f + random.nextFloat() * 5f); 1058 //point.setCircularOrbit(star, random.nextFloat() * 360f, outerRadius, orbitDays); 1059 point.setCircularOrbit(systemCenter, random.nextFloat() * 360f, outerRadius, orbitDays); 1060 system.addEntity(point); 1061 1062 1063 // to make sure that "is this location clear" calculations below always work 1064 system.updateAllOrbits(); 1065 1066 1067 if (result != null) { 1068 float halfway = outerRadius * 0.5f; 1069 1070 WeightedRandomPicker<LagrangePoint> inner = new WeightedRandomPicker<LagrangePoint>(random); 1071 WeightedRandomPicker<LagrangePoint> outer = new WeightedRandomPicker<LagrangePoint>(random); 1072 1073 int total = 0; 1074 for (GeneratedPlanet planet : result.context.generatedPlanets) { 1075 if (planet.isMoon) continue; 1076 if (planet.planet.getOrbit() == null || planet.planet.getOrbit().getFocus() == null) continue; 1077 total++; 1078 1079 for (LagrangePointType type : EnumSet.of(LagrangePointType.L4, LagrangePointType.L5)) { 1080 float orbitRadius = planet.orbitRadius; 1081 float angleOffset = -LAGRANGE_OFFSET * 0.5f; 1082 if (type == LagrangePointType.L5) angleOffset = LAGRANGE_OFFSET * 0.5f; 1083 float angle = planet.orbitAngle + angleOffset; 1084 Vector2f location = Misc.getUnitVectorAtDegreeAngle(angle + angleOffset); 1085 location.scale(orbitRadius); 1086 Vector2f.add(location, planet.planet.getOrbit().getFocus().getLocation(), location); 1087 1088 boolean clear = true; 1089 for (PlanetAPI curr : system.getPlanets()) { 1090 float dist = Misc.getDistance(curr.getLocation(), location); 1091 //System.out.println(type.name() + ": " + location + ", " + "Dist: " + dist + " (to " + curr.getName() + " at " + curr.getLocation() + ")"); 1092 if (dist < 500) { 1093 clear = false; 1094 break; 1095 } 1096 } 1097 if (clear) { 1098 if (planet.orbitRadius < halfway || planet.orbitRadius < 5000f) { 1099 inner.add(new LagrangePoint(planet, type), 10f); 1100 } else { 1101 outer.add(new LagrangePoint(planet, type), 10f); 1102 } 1103 } 1104 } 1105 } 1106 1107 1108 if (outerRadius > 2000f + 5000f * random.nextFloat()) { 1109 boolean addedOne = false; 1110 if (!inner.isEmpty()) { 1111 LagrangePoint p = inner.pick(); 1112 //addJumpPoint(p, p.parent.planet.getName() + " Jump-point"); 1113 String name = "Inner System Jump-point"; 1114 if (systemType == StarSystemType.NEBULA) name = "Inner Jump-point"; 1115 addJumpPoint(p, name); 1116 addedOne = true; 1117 } 1118 1119 1120 if (!outer.isEmpty() && (random.nextFloat() < outer.getItems().size() * 0.2f || !addedOne)) { 1121 LagrangePoint p = outer.pick(); 1122 String name = "Outer System Jump-point"; 1123 if (systemType == StarSystemType.NEBULA) name = "Outer Jump-point"; 1124 addJumpPoint(p, name); 1125 //addJumpPoint(p, "Outer System Jump-point"); 1126 addedOne = true; 1127 } 1128 1129// while (!inner.isEmpty()) { 1130// LagrangePoint p = inner.pickAndRemove(); 1131// //addJumpPoint(p, p.parent.planet.getName() + " Jump-point"); 1132// addJumpPoint(p, system.getBaseName() + " Inner System Jump-point"); 1133// } 1134// while (!outer.isEmpty()) { 1135// LagrangePoint p = outer.pickAndRemove(); 1136// //addJumpPoint(p, p.parent.planet.getName() + " Jump-point"); 1137// addJumpPoint(p, system.getBaseName() + " Outer System Jump-point"); 1138// } 1139 } 1140 } 1141 1142 //system.autogenerateHyperspaceJumpPoints(true, false); 1143 } 1144 1145 protected void addJumpPoint(LagrangePoint p, String name) { 1146 float orbitRadius = p.parent.orbitRadius; 1147 float orbitDays = p.parent.orbitDays; 1148 float angleOffset = -LAGRANGE_OFFSET * 0.5f; 1149 if (p.type == LagrangePointType.L5) angleOffset = LAGRANGE_OFFSET * 0.5f; 1150 float angle = p.parent.orbitAngle + angleOffset; 1151 1152 SectorEntityToken focus = p.parent.planet.getOrbitFocus(); 1153 if (focus == null) focus = systemCenter; 1154 1155 JumpPointAPI point = Global.getFactory().createJumpPoint(null, name); 1156 point.setStandardWormholeToHyperspaceVisual(); 1157 if (!p.parent.planet.isGasGiant()) { 1158 point.setRelatedPlanet(p.parent.planet); 1159 } 1160 //point.setCircularOrbit(star, angle + angleOffset, orbitRadius, orbitDays); 1161 //point.setCircularOrbit(systemCenter, angle + angleOffset, orbitRadius, orbitDays); 1162 point.setCircularOrbit(focus, angle + angleOffset, orbitRadius, orbitDays); 1163 system.addEntity(point); 1164 } 1165 1166 public static float addOrbitingEntities(StarSystemAPI system, SectorEntityToken parentStar, StarAge age, 1167 int min, int max, float startingRadius, 1168 int nameOffset, boolean withSpecialNames) { 1169 return addOrbitingEntities(system, parentStar, age, min, max, startingRadius, nameOffset, withSpecialNames, true); 1170 } 1171 1172 public static float addOrbitingEntities(StarSystemAPI system, SectorEntityToken parentStar, StarAge age, 1173 int min, int max, float startingRadius, 1174 int nameOffset, boolean withSpecialNames, 1175 boolean allowHabitable) { 1176 CustomConstellationParams p = new CustomConstellationParams(age); 1177 p.forceNebula = true; // not sure why this is here; should avoid small nebula at lagrange points though (but is that desired?) 1178 1179 StarSystemGenerator gen = new StarSystemGenerator(p); 1180 gen.system = system; 1181 gen.starData = (StarGenDataSpec) Global.getSettings().getSpec(StarGenDataSpec.class, system.getStar().getSpec().getPlanetType(), false); 1182 gen.starAge = age; 1183 gen.constellationAge = age; 1184 gen.starAgeData = (AgeGenDataSpec) Global.getSettings().getSpec(AgeGenDataSpec.class, age.name(), true); 1185 gen.star = system.getStar(); 1186 1187 gen.pickNebulaAndBackground(); 1188 if (system.getType() != null) gen.systemType = system.getType(); 1189 1190 1191 gen.systemCenter = system.getCenter(); 1192 1193 StarGenDataSpec starData = gen.starData; 1194 PlanetGenDataSpec planetData = null; 1195 PlanetAPI parentPlanet = null; 1196 if (parentStar instanceof PlanetAPI) { 1197 PlanetAPI planet = (PlanetAPI) parentStar; 1198 if (planet.isStar()) { 1199 starData = (StarGenDataSpec) Global.getSettings().getSpec(StarGenDataSpec.class, planet.getSpec().getPlanetType(), false); 1200 } else { 1201 planetData = (PlanetGenDataSpec) Global.getSettings().getSpec(PlanetGenDataSpec.class, planet.getSpec().getPlanetType(), false); 1202 parentPlanet = planet; 1203 } 1204 } 1205 1206 int parentOrbitIndex = -1; 1207 int startingOrbitIndex = 0; 1208 1209 boolean addingAroundStar = parentPlanet == null; 1210 float r = 0; 1211 if (parentStar != null) { 1212 r = parentStar.getRadius(); 1213 } 1214 1215 float approximateExtraRadiusPerOrbit = 400f; 1216 if (addingAroundStar) { 1217 parentOrbitIndex = -1; 1218 startingOrbitIndex = (int) ((startingRadius - r - STARTING_RADIUS_STAR_BASE - STARTING_RADIUS_STAR_RANGE * 0.5f) / 1219 (BASE_INCR * 1.25f + approximateExtraRadiusPerOrbit)); 1220 1221 if (startingOrbitIndex < 0) startingOrbitIndex = 0; 1222 } else { 1223 float dist = 0f; 1224 if (parentPlanet.getOrbitFocus() != null) { 1225 dist = Misc.getDistance(parentPlanet.getLocation(), parentPlanet.getOrbitFocus().getLocation()); 1226 } 1227 parentOrbitIndex = (int) ((dist - r - STARTING_RADIUS_STAR_BASE - STARTING_RADIUS_STAR_RANGE * 0.5f) / 1228 (BASE_INCR * 1.25f + approximateExtraRadiusPerOrbit)); 1229 startingOrbitIndex = (int) ((startingRadius - STARTING_RADIUS_MOON_BASE - STARTING_RADIUS_MOON_RANGE * 0.5f) / 1230 (BASE_INCR_MOON * 1.25f)); 1231 1232 if (parentOrbitIndex < 0) parentOrbitIndex = 0; 1233 if (startingOrbitIndex < 0) startingOrbitIndex = 0; 1234 } 1235 1236 int num = (int) Math.round(getNormalRandom(min, max)); 1237 1238 GenContext context = new GenContext(gen, system, gen.systemCenter, starData, 1239 parentPlanet, startingOrbitIndex, age.name(), startingRadius, MAX_ORBIT_RADIUS, 1240 planetData != null ? planetData.getCategory() : null, parentOrbitIndex); 1241 1242 if (!allowHabitable) { 1243 context.excludeCategories.add(CAT_HAB5); 1244 context.excludeCategories.add(CAT_HAB4); 1245 context.excludeCategories.add(CAT_HAB3); 1246 context.excludeCategories.add(CAT_HAB2); 1247 } 1248 1249 GenResult result = gen.addOrbitingEntities(context, num, false, addingAroundStar, false, false); 1250 1251 1252 Constellation c = new Constellation(ConstellationType.NORMAL, age); 1253 c.getSystems().add(system); 1254 c.setLagrangeParentMap(gen.lagrangeParentMap); 1255 c.setAllEntitiesAdded(gen.allNameableEntitiesAdded); 1256 c.setLeavePickedNameUnused(true); 1257 NameAssigner namer = new NameAssigner(c); 1258 if (withSpecialNames) { 1259 namer.setSpecialNamesProbability(1f); 1260 } else { 1261 namer.setSpecialNamesProbability(0f); 1262 } 1263 namer.setRenameSystem(false); 1264 namer.setStructuralNameOffset(nameOffset); 1265 namer.assignNames(null, null); 1266 1267 for (SectorEntityToken entity : gen.allNameableEntitiesAdded.keySet()) { 1268 if (entity instanceof PlanetAPI && entity.getMarket() != null) { 1269 entity.getMarket().setName(entity.getName()); 1270 } 1271 } 1272 1273 return result.orbitalWidth * 0.5f; 1274 1275 } 1276 1277 public static void addSystemwideNebula(StarSystemAPI system, StarAge age) { 1278 CustomConstellationParams p = new CustomConstellationParams(age); 1279 p.forceNebula = true; 1280 1281 StarSystemGenerator gen = new StarSystemGenerator(p); 1282 gen.system = system; 1283 gen.starData = (StarGenDataSpec) Global.getSettings().getSpec(StarGenDataSpec.class, system.getStar().getSpec().getPlanetType(), false); 1284 gen.starAge = age; 1285 gen.constellationAge = age; 1286 gen.starAgeData = (AgeGenDataSpec) Global.getSettings().getSpec(AgeGenDataSpec.class, age.name(), true); 1287 gen.pickNebulaAndBackground(); 1288 if (system.getType() != null) gen.systemType = system.getType(); 1289 1290 gen.addSystemwideNebula(); 1291 1292 system.setAge(age); 1293 system.setHasSystemwideNebula(true); 1294 } 1295 1296 1297 protected void addSystemwideNebula() { 1298 if (nebulaType.equals(NEBULA_NONE)) return; 1299 1300 1301 int w = 128; 1302 int h = 128; 1303 1304 StringBuilder string = new StringBuilder(); 1305 for (int y = h - 1; y >= 0; y--) { 1306 for (int x = 0; x < w; x++) { 1307 string.append("x"); 1308 } 1309 } 1310 SectorEntityToken nebula = system.addTerrain(Terrain.NEBULA, new TileParams(string.toString(), 1311 w, h, 1312 "terrain", nebulaType, 4, 4, null)); 1313 nebula.getLocation().set(0, 0); 1314 1315 NebulaTerrainPlugin nebulaPlugin = (NebulaTerrainPlugin)((CampaignTerrainAPI)nebula).getPlugin(); 1316 NebulaEditor editor = new NebulaEditor(nebulaPlugin); 1317 1318 editor.regenNoise(); 1319 1320 // good medium thickness: 0.6 1321 //editor.noisePrune(0.8f); 1322 1323 // yes, star age here, despite using constellation age to determine if a nebula to all exists 1324 // basically: young star in old constellation will have lots of nebula, but of the constellation-age color 1325 editor.noisePrune(starAgeData.getNebulaDensity()); 1326 //editor.noisePrune(0.75f); 1327 //editor.noisePrune(0.1f); 1328 1329// for (float f = 0.1f; f <= 0.9f; f += 0.05f) { 1330// editor.noisePrune(f); 1331// } 1332 1333 editor.regenNoise(); 1334 1335 if (systemType != StarSystemType.NEBULA) { 1336 for (PlanetAPI planet : system.getPlanets()) { 1337 1338 if (planet.getOrbit() != null && planet.getOrbit().getFocus() != null && 1339 planet.getOrbit().getFocus().getOrbit() != null) { 1340 // this planet is orbiting something that's orbiting something 1341 // its motion will be relative to its parent moving 1342 // don't clear anything out for this planet 1343 continue; 1344 } 1345 1346 float clearThreshold = 0f; // clear everything by default 1347 float clearInnerRadius = 0f; 1348 float clearOuterRadius = 0f; 1349 Vector2f clearLoc = null; 1350 1351 1352 if (!planet.isStar() && !planet.isGasGiant()) { 1353 clearThreshold = 1f - Math.min(0f, planet.getRadius() / 300f); 1354 if (clearThreshold > 0.5f) clearThreshold = 0.5f; 1355 } 1356 1357 Vector2f loc = planet.getLocation(); 1358 if (planet.getOrbit() != null && planet.getOrbit().getFocus() != null) { 1359 Vector2f focusLoc = planet.getOrbit().getFocus().getLocation(); 1360 float dist = Misc.getDistance(planet.getOrbit().getFocus().getLocation(), loc); 1361 float width = planet.getRadius() * 4f + 100f; 1362 if (planet.isStar()) { 1363 StarCoronaTerrainPlugin corona = Misc.getCoronaFor(planet); 1364 if (corona != null) { 1365 width = corona.getParams().bandWidthInEngine * 4f; 1366 } 1367 PulsarBeamTerrainPlugin pulsar = Misc.getPulsarFor(planet); 1368 if (pulsar != null) { 1369 width = Math.max(width, pulsar.getParams().bandWidthInEngine * 0.5f); 1370 } 1371 } 1372 clearLoc = focusLoc; 1373 clearInnerRadius = dist - width / 2f; 1374 clearOuterRadius = dist + width / 2f; 1375 } else if (planet.getOrbit() == null) { 1376 float width = planet.getRadius() * 4f + 100f; 1377 if (planet.isStar()) { 1378 StarCoronaTerrainPlugin corona = Misc.getCoronaFor(planet); 1379 if (corona != null) { 1380 width = corona.getParams().bandWidthInEngine * 4f; 1381 } 1382 PulsarBeamTerrainPlugin pulsar = Misc.getPulsarFor(planet); 1383 if (pulsar != null) { 1384 width = Math.max(width, pulsar.getParams().bandWidthInEngine * 0.5f); 1385 } 1386 } 1387 clearLoc = loc; 1388 clearInnerRadius = 0f; 1389 clearOuterRadius = width; 1390 } 1391 1392 if (clearLoc != null) { 1393 float min = nebulaPlugin.getTileSize() * 2f; 1394 if (clearOuterRadius - clearInnerRadius < min) { 1395 clearOuterRadius = clearInnerRadius + min; 1396 } 1397 editor.clearArc(clearLoc.x, clearLoc.y, clearInnerRadius, clearOuterRadius, 0, 360f, clearThreshold); 1398 } 1399 } 1400 } 1401 1402 // add a spiral going from the outside towards the star 1403 float angleOffset = random.nextFloat() * 360f; 1404 editor.clearArc(0f, 0f, 30000, 31000 + 1000f * random.nextFloat(), 1405 angleOffset + 0f, angleOffset + 360f * (2f + random.nextFloat() * 2f), 0.01f, 0f); 1406 1407 // do some random arcs 1408 int numArcs = (int) (8f + 6f * random.nextFloat()); 1409 //int numArcs = 11; 1410 1411 for (int i = 0; i < numArcs; i++) { 1412 //float dist = 4000f + 10000f * random.nextFloat(); 1413 float dist = 15000f + 15000f * random.nextFloat(); 1414 float angle = random.nextFloat() * 360f; 1415 1416 Vector2f dir = Misc.getUnitVectorAtDegreeAngle(angle); 1417 dir.scale(dist - (2000f + 8000f * random.nextFloat())); 1418 1419 //float tileSize = nebulaPlugin.getTileSize(); 1420 //float width = tileSize * (2f + 4f * random.nextFloat()); 1421 float width = 800f * (1f + 2f * random.nextFloat()); 1422 1423 float clearThreshold = 0f + 0.5f * random.nextFloat(); 1424 //clearThreshold = 0f; 1425 1426 editor.clearArc(dir.x, dir.y, dist - width/2f, dist + width/2f, 0, 360f, clearThreshold); 1427 } 1428 } 1429 1430 1431 protected GenResult addPlanetsAndTerrain(float maxOrbitRadius) { 1432 boolean hasOrbits = random.nextFloat() < starData.getProbOrbits(); 1433 if (!hasOrbits) return null; 1434 1435 float min = starData.getMinOrbits() + starAgeData.getMinExtraOrbits(); 1436 float max = starData.getMaxOrbits() + starAgeData.getMaxExtraOrbits(); 1437 int numOrbits = (int) Math.round(getNormalRandom(min, max)); 1438 1439 if (numOrbits <= 0) return null; 1440 1441 1442 1443 float currentRadius = centerRadius + STARTING_RADIUS_STAR_BASE + STARTING_RADIUS_STAR_RANGE * random.nextFloat(); 1444 1445 //GenContext context = new GenContext(this, system, star, starData, 1446 GenContext context = new GenContext(this, system, systemCenter, starData, 1447 null, 0, starAge.name(), currentRadius, maxOrbitRadius, null, -1); 1448 1449 if (systemType == StarSystemType.BINARY_CLOSE || systemType == StarSystemType.TRINARY_1CLOSE_1FAR) { 1450 context.multipliers.add(COL_BINARY); 1451 } 1452 if (systemType == StarSystemType.TRINARY_2CLOSE) { 1453 context.multipliers.add(COL_TRINARY); 1454 } 1455 1456 1457 GenResult result = addOrbitingEntities(context, numOrbits, false, true, false, true); 1458 result.context = context; 1459 return result; 1460 } 1461 1462 protected GenResult addOrbitingEntities(GenContext context, int numOrbits, boolean addingMoons, boolean addMoons, boolean parentIsMoon, boolean nothingOk) { 1463 1464 if (DEBUG && context.starData != null) { 1465 if (addingMoons && context.parent != null) { 1466 System.out.println(" Adding " + numOrbits + " moon orbits around " + context.parent.getSpec().getPlanetType()); 1467 } else { 1468 System.out.println("Adding " + numOrbits + " orbits around " + context.starData.getId()); 1469 } 1470 } 1471 1472 float currentRadius = context.currentRadius; 1473 float lastIncrementExtra = 0f; 1474 1475 String extraMult = null; 1476 if (parentIsMoon) extraMult = COL_IS_MOON; 1477 1478 int extra = 0; 1479 for (int i = 0; i < numOrbits; i++) { 1480 1481 context.orbitIndex = i + context.startingOrbitIndex + extra; 1482 //CategoryGenDataSpec categoryData = pickCategory(orbitIndex, i, starAge.name(), starType, context.parentCategory, null, nothingOk); 1483 CategoryGenDataSpec categoryData = pickCategory(context, extraMult, nothingOk); 1484 nothingOk = true; // only applies to first pick, after this, we'll have *something* 1485 1486// if (!addingMoons) { 1487// categoryData = (CategoryGenDataSpec) Global.getSettings().getSpec(CategoryGenDataSpec.class, "cat_giant", true); 1488// //categoryData = (CategoryGenDataSpec) Global.getSettings().getSpec(CategoryGenDataSpec.class, "cat_terrain_rings", true); 1489// } 1490// if (orbitIndex == 0 && addMoons) { 1491// categoryData = (CategoryGenDataSpec) Global.getSettings().getSpec(CategoryGenDataSpec.class, "cat_giant", true); 1492// //categoryData = (CategoryGenDataSpec) Global.getSettings().getSpec(CategoryGenDataSpec.class, "cat_hab4", true); 1493// } 1494// if (orbitIndex == 1 && addMoons) { 1495// if (!addingMoons) { 1496// categoryData = (CategoryGenDataSpec) Global.getSettings().getSpec(CategoryGenDataSpec.class, "cat_giant", true); 1497// } 1498// } else { 1499// categoryData = (CategoryGenDataSpec) Global.getSettings().getSpec(CategoryGenDataSpec.class, "cat_terrain_rings", true); 1500// } 1501 //categoryData = (CategoryGenDataSpec) Global.getSettings().getSpec(CategoryGenDataSpec.class, "cat_terrain_rings", true); 1502 1503 GenResult result = null; 1504 float incrMult = 1f; 1505 1506 if (categoryData != null && !CAT_NOTHING.equals(categoryData.getCategory())) { 1507 //WeightedRandomPicker<EntityGenDataSpec> picker = getPickerForCategory(categoryData, orbitIndex, i, starAge.name(), starType, context.parentCategory, null); 1508 WeightedRandomPicker<EntityGenDataSpec> picker = getPickerForCategory(categoryData, context, extraMult); 1509 if (DEBUG) { 1510 picker.print(" Picking from category " + categoryData.getCategory() + 1511 ", orbit index " + (context.parent != null ? context.parentOrbitIndex : context.orbitIndex)); 1512 } 1513 EntityGenDataSpec entityData = picker.pick(); 1514 if (DEBUG) { 1515 if (entityData == null) { 1516 System.out.println(" Nothing to pick"); 1517 System.out.println(); 1518 } else { 1519 System.out.println(" Picked: " + entityData.getId()); 1520 System.out.println(); 1521 } 1522 } 1523 1524 context.currentRadius = currentRadius; 1525 //context.orbitIndex = i; 1526 1527 if (entityData instanceof PlanetGenDataSpec) { 1528 PlanetGenDataSpec planetData = (PlanetGenDataSpec) entityData; 1529 result = addPlanet(context, planetData, addingMoons, addMoons); 1530 1531 } else if (entityData instanceof TerrainGenDataSpec) { 1532 TerrainGenDataSpec terrainData = (TerrainGenDataSpec) entityData; 1533 result = addTerrain(context, terrainData); 1534 } 1535 1536 if (result != null) { 1537 //List<SectorEntityToken> combined = new ArrayList<SectorEntityToken>(result.entities); 1538 for (SectorEntityToken curr : result.entities) { 1539 if (context.lagrangeParent != null && !result.entities.isEmpty()) { 1540 lagrangeParentMap.put(curr, context.lagrangeParent.planet); 1541 } 1542 allNameableEntitiesAdded.put(curr, result.entities); 1543 } 1544 } else { 1545 incrMult = 0.5f; 1546 } 1547 } else { 1548 incrMult = 0.5f; 1549 } 1550 1551 float baseIncr = BASE_INCR; 1552 if (addingMoons) { 1553 baseIncr = BASE_INCR_MOON; 1554 } 1555 baseIncr *= incrMult; 1556 1557 float increment = baseIncr + baseIncr * 0.5f * random.nextFloat(); 1558 if (result != null) { 1559 if (result.orbitalWidth > 1000) extra++; 1560 //increment = Math.max(increment, result.orbitalWidth + baseIncr * 0.5f); 1561 //increment += result.orbitalWidth; 1562 increment = Math.max(increment + Math.min(result.orbitalWidth, 300f), 1563 result.orbitalWidth + increment * 0.5f); 1564 if (result.onlyIncrementByWidth) { 1565 increment = result.orbitalWidth; 1566 } 1567 lastIncrementExtra = Math.max(increment * 0.1f, increment - result.orbitalWidth); 1568 } else { 1569 lastIncrementExtra = increment; 1570 } 1571 currentRadius += increment; 1572 1573 if (currentRadius >= context.maxOrbitRadius) { 1574 break; 1575 } 1576 } 1577 1578 GenResult result = new GenResult(); 1579 result.onlyIncrementByWidth = false; 1580 result.orbitalWidth = (currentRadius - lastIncrementExtra) * 2f; 1581 return result; 1582 } 1583 1584 protected GenResult addTerrain(GenContext context, TerrainGenDataSpec terrainData) { 1585 TerrainGenPlugin plugin = pickTerrainGenPlugin(terrainData, context); 1586 if (plugin == null ) return null; 1587 GenResult result = plugin.generate(terrainData, context); 1588 1589 1590 return result; 1591 } 1592 1593 1594 public GenResult addPlanet(GenContext context, PlanetGenDataSpec planetData, boolean isMoon, boolean addMoons) { 1595 //float orbitRadius = (orbitIndex + 1f) * 1500 + star.getRadius(); 1596 float radius = getRadius(planetData.getMinRadius(), planetData.getMaxRadius()); 1597 if (isMoon) {// || context.lagrangeParent != null) { 1598 //radius *= MOON_RADIUS_MULT; 1599 float mult = MOON_RADIUS_MIN_FRACTION_OF_NORMAL + 1600 random.nextFloat() * (MOON_RADIUS_MAX_FRACTION_OF_NORMAL - MOON_RADIUS_MIN_FRACTION_OF_NORMAL); 1601 radius *= mult; 1602 if (radius < MIN_MOON_RADIUS) { 1603 radius = MIN_MOON_RADIUS; 1604 } 1605 float parentRadius = 100000f; 1606 if (context.parent != null || context.lagrangeParent != null) { 1607 PlanetAPI parent = context.parent; 1608 if (context.lagrangeParent != null) { 1609 parent = context.lagrangeParent.planet; 1610 } 1611 parentRadius = parent.getRadius(); 1612 } 1613 if (context.parentRadiusOverride > 0) { 1614 parentRadius = context.parentRadiusOverride; 1615 } 1616 1617 if (parentRadius > MIN_MOON_RADIUS / MOON_RADIUS_MAX_FRACTION_OF_PARENT) { 1618 float max = parentRadius * MOON_RADIUS_MAX_FRACTION_OF_PARENT; 1619 if (radius > max) { 1620 radius = max; 1621 } 1622 } 1623 } 1624 1625 float orbitRadius = context.currentRadius + radius; 1626 float orbitDays = orbitRadius / (20f + random.nextFloat() * 5f); 1627 1628 //String planetId = system.getId() + "_planet_" + context.center.getId() + "_" + context.orbitIndex; 1629 String planetId = context.center.getId() + ":planet_" + context.orbitIndex; 1630 String planetName = "Planet " + context.orbitIndex; 1631 if (context.parent != null) { 1632 planetId = system.getId() + "_moon_" + context.center.getId() + "_" + context.parent.getId() + "_" + context.orbitIndex; 1633 planetName = context.parent.getName() + " moon " + context.orbitIndex; 1634 } 1635 String planetType = planetData.getId(); 1636 SectorEntityToken parent = context.center; 1637 if (context.parent != null) parent = context.parent; 1638 1639 float angle = random.nextFloat() * 360f; 1640 1641 // if adding a moon to a largange point planet, then parentCategory == null 1642 // will fail and it'll orbit the parent rather than stay at the point 1643 if (context.parentCategory == null) { 1644 if (context.lagrangeParent != null && context.lagrangePointType != null) { 1645 orbitRadius = context.lagrangeParent.orbitRadius; 1646 orbitDays = context.lagrangeParent.orbitDays; 1647 float angleOffset = -LAGRANGE_OFFSET; 1648 if (context.lagrangePointType == LagrangePointType.L5) angleOffset = LAGRANGE_OFFSET; 1649 angle = context.lagrangeParent.orbitAngle + angleOffset; 1650 planetName += " " + context.lagrangePointType.name(); 1651 planetId += "_" + context.lagrangePointType.name(); 1652 } 1653 } 1654 1655 PlanetAPI planet = system.addPlanet(planetId, parent, planetName, planetType, angle, radius, orbitRadius, orbitDays); 1656 if (planet.isGasGiant()) { 1657 if (systemType == StarSystemType.NEBULA) { 1658 planet.setAutogenJumpPointNameInHyper(system.getBaseName() + ", " + planetName + " Gravity Well"); 1659 } 1660 } 1661 1662 float radiusWithMoons = planet.getRadius(); 1663 if (addMoons) { 1664 boolean hasOrbits = random.nextFloat() < planetData.getProbOrbits(); 1665 float min = planetData.getMinOrbits(); 1666 float max = planetData.getMaxOrbits(); 1667// double r = random.nextFloat(); 1668// r *= r; 1669// int numOrbits = (int) (min + Math.round((max - min) * r)); 1670 int numOrbits = (int) Math.round(getNormalRandom(min, max)); 1671 1672// hasOrbits = true; 1673// numOrbits = 2; 1674 1675// if (numOrbits == 3) { 1676// System.out.println("efwefwefew"); 1677// } 1678 1679 if (hasOrbits && numOrbits > 0) { 1680// if (!planet.isGasGiant()) { 1681// System.out.println("sdfwefew " + star.getId()); 1682// } 1683 float startingRadius = planet.getRadius() + STARTING_RADIUS_MOON_BASE + STARTING_RADIUS_MOON_RANGE * random.nextFloat(); 1684 GenContext moonContext = new GenContext(this, context.system, context.center, context.starData, planet, 0, starAge.name(), 1685 startingRadius, context.maxOrbitRadius, planetData.getCategory(), context.orbitIndex); 1686 moonContext.excludeCategories.addAll(context.excludeCategories); 1687 moonContext.multipliers.addAll(context.multipliers); 1688 // add moons etc 1689 GenResult moonResult = addOrbitingEntities(moonContext, numOrbits, true, false, false, false); 1690 1691 context.generatedPlanets.addAll(moonContext.generatedPlanets); 1692 1693 // move the parent planet out so that there's room for everythnig that was added 1694 radius = moonResult.orbitalWidth * 0.5f; 1695 orbitRadius = context.currentRadius + radius; 1696 orbitDays = orbitRadius / (20f + random.nextFloat() * 5f); 1697 1698 radiusWithMoons = radius; 1699 1700 planet.setOrbit(Global.getFactory().createCircularOrbit(context.center, angle, orbitRadius, orbitDays)); 1701 } 1702 } else if (isMoon) { 1703 float startingRadius = planet.getRadius() + STARTING_RADIUS_MOON_BASE + STARTING_RADIUS_MOON_RANGE * random.nextFloat(); 1704 GenContext moonContext = new GenContext(this, context.system, context.center, context.starData, planet, 0, starAge.name(), 1705 startingRadius, context.maxOrbitRadius, planetData.getCategory(), context.orbitIndex); 1706 moonContext.excludeCategories.addAll(context.excludeCategories); 1707 moonContext.multipliers.addAll(context.multipliers); 1708 GenResult moonResult = addOrbitingEntities(moonContext, 1, true, false, true, true); 1709 context.generatedPlanets.addAll(moonContext.generatedPlanets); 1710 1711 } 1712 1713 1714 Color color = getColor(planetData.getMinColor(), planetData.getMaxColor()); 1715 //System.out.println("Setting color: " + color); 1716 planet.getSpec().setPlanetColor(color); 1717 if (planet.getSpec().getAtmosphereThickness() > 0) { 1718 Color atmosphereColor = Misc.interpolateColor(planet.getSpec().getAtmosphereColor(), color, 0.25f); 1719 atmosphereColor = Misc.setAlpha(atmosphereColor, planet.getSpec().getAtmosphereColor().getAlpha()); 1720 planet.getSpec().setAtmosphereColor(atmosphereColor); 1721 1722 if (planet.getSpec().getCloudTexture() != null) { 1723 Color cloudColor = Misc.interpolateColor(planet.getSpec().getCloudColor(), color, 0.25f); 1724 cloudColor = Misc.setAlpha(cloudColor, planet.getSpec().getCloudColor().getAlpha()); 1725 planet.getSpec().setAtmosphereColor(atmosphereColor); 1726 } 1727 } 1728 1729 float tilt = planet.getSpec().getTilt(); 1730 float pitch = planet.getSpec().getPitch(); 1731 1732// "tilt" # left-right (>0 tilts to the left) 1733// "pitch" # towards-away from the viewer (>0 pitches towards) 1734 float sign = (float) Math.signum(random.nextFloat() - 0.5f); 1735 double r = random.nextFloat(); 1736 //r *= r; 1737 if (sign > 0) { 1738 tilt += r * TILT_MAX; 1739 } else { 1740 tilt += r * TILT_MIN; 1741 } 1742 1743 sign = (float) Math.signum(random.nextFloat() - 0.5f); 1744 r = random.nextFloat(); 1745 //r *= r; 1746 if (sign > 0) { 1747 pitch += r * PITCH_MAX; 1748 } else { 1749 tilt += r * PITCH_MIN; 1750 } 1751 planet.getSpec().setTilt(tilt); 1752 planet.getSpec().setPitch(pitch); 1753 1754 1755 if (context.orbitIndex == 0 && context.parent == null && context.orbitIndex < context.starData.getHabZoneStart() && 1756 orbitRadius < 2500f + context.starData.getHabZoneStart() * 200f) { 1757 //&& radiusWithMoons <= planet.getRadius() + 500f) { 1758 if (planet.getSpec().getAtmosphereThickness() > 0) { 1759 WeightedRandomPicker<String> glowPicker = new WeightedRandomPicker<String>(random); 1760 glowPicker.add("banded", 10f); 1761 glowPicker.add("aurorae", 10f); 1762 1763 String glow = glowPicker.pick(); 1764 1765 planet.getSpec().setGlowTexture(Global.getSettings().getSpriteName("hab_glows", glow)); 1766 //system.getLightColor(); 1767 if (context.center instanceof PlanetAPI) { 1768 planet.getSpec().setGlowColor(((PlanetAPI)context.center).getSpec().getCoronaColor()); 1769 } 1770 planet.getSpec().setUseReverseLightForGlow(true); 1771 planet.getSpec().setAtmosphereThickness(0.5f); 1772 planet.getSpec().setCloudRotation(planet.getSpec().getCloudRotation() * (-1f - 2f * random.nextFloat())); 1773 1774 if (planet.isGasGiant()) {// && radiusWithMoons <= planet.getRadius() + 500f) { 1775 system.addCorona(planet, Terrain.CORONA_AKA_MAINYU, 1776 300f + 200f * random.nextFloat(), // radius outside planet 1777 5f, // burn level of "wind" 1778 0f, // flare probability 1779 1f // CR loss mult while in it 1780 ); 1781 } 1782 } 1783 } 1784 1785 planet.applySpecChanges(); 1786 1787 PlanetConditionGenerator.generateConditionsForPlanet(context, planet); 1788 1789 1790 GeneratedPlanet generatedPlanetData = new GeneratedPlanet(parent, planet, isMoon, orbitDays, orbitRadius, angle); 1791 context.generatedPlanets.add(generatedPlanetData); 1792 1793 // need to add this here because planet might have been moved after adding moons 1794 //if (context.parentCategory == null && context.lagrangeParent == null && planet.isGasGiant()) { 1795 if (!isMoon && context.lagrangeParent == null) {// && planet.isGasGiant()) { 1796 addStuffAtLagrangePoints(context, generatedPlanetData); 1797 } 1798 1799 GenResult result = new GenResult(); 1800 result.orbitalWidth = radius * 2f; 1801 result.onlyIncrementByWidth = false; 1802 result.entities.add(planet); 1803 return result; 1804 } 1805 1806 protected void addStuffAtLagrangePoints(GenContext context, GeneratedPlanet planet) { 1807 float radius = planet.planet.getRadius(); 1808 float probability = radius / 500f; 1809 if (radius < 150f) probability = 0f; 1810 if (planet.planet.isGasGiant()) probability = 1f; 1811 if (random.nextFloat() > probability) { 1812 return; 1813 } 1814 1815 // still a high chance to end up w/ nothing if cat_nothing is picked 1816 1817// int orbitIndex = context.orbitIndex; 1818// String starType = context.star.getTypeId(); 1819// if (context.parentOrbitIndex >= 0) { 1820// orbitIndex = context.parentOrbitIndex; 1821// } 1822 1823 Set<LagrangePointType> points = EnumSet.of(LagrangePointType.L4, LagrangePointType.L5); 1824 for (LagrangePointType point : points) { 1825 //CategoryGenDataSpec categoryData = pickCategory(orbitIndex, 0, starAge.name(), starType, context.parentCategory, COL_LAGRANGE, true); 1826 CategoryGenDataSpec categoryData = pickCategory(context, COL_LAGRANGE, true); 1827 if (categoryData != null && !CAT_NOTHING.equals(categoryData.getCategory())) { 1828 //WeightedRandomPicker<EntityGenDataSpec> picker = getPickerForCategory(categoryData, orbitIndex, 0, starAge.name(), starType, context.parentCategory, COL_LAGRANGE); 1829 WeightedRandomPicker<EntityGenDataSpec> picker = getPickerForCategory(categoryData, context, COL_LAGRANGE); 1830 if (DEBUG) { 1831 picker.print(" Picking from category " + categoryData.getCategory() + 1832 ", orbit index " + (context.parent != null ? context.parentOrbitIndex : context.orbitIndex + ", for lagrange point")); 1833 } 1834 EntityGenDataSpec entityData = picker.pick(); 1835 if (DEBUG) { 1836 if (entityData == null) { 1837 System.out.println(" Nothing to pick"); 1838 System.out.println(); 1839 } else { 1840 System.out.println(" Picked: " + entityData.getId()); 1841 System.out.println(); 1842 } 1843 } 1844 1845 context.lagrangeParent = planet; 1846 context.lagrangePointType = point; 1847 1848 GenResult result = null; 1849 if (entityData instanceof PlanetGenDataSpec) { 1850 PlanetGenDataSpec planetData = (PlanetGenDataSpec) entityData; 1851 result = addPlanet(context, planetData, true, true); 1852 } else if (entityData instanceof TerrainGenDataSpec) { 1853 TerrainGenDataSpec terrainData = (TerrainGenDataSpec) entityData; 1854 result = addTerrain(context, terrainData); 1855 } 1856 1857 if (result != null) { 1858 for (SectorEntityToken curr : result.entities) { 1859 if (context.lagrangeParent != null && !result.entities.isEmpty()) { 1860 lagrangeParentMap.put(curr, context.lagrangeParent.planet); 1861 } 1862 allNameableEntitiesAdded.put(curr, result.entities); 1863 } 1864 } 1865 } 1866 } 1867 context.lagrangeParent = null; 1868 context.lagrangePointType = null; 1869 } 1870 1871 1872 1873 //protected CategoryGenDataSpec pickCategory(int orbitIndex, int fromParentOrbitIndex, String age, String starType, String parentCategory, String extraMult, boolean nothingOk) { 1874 public CategoryGenDataSpec pickCategory(GenContext context, String extraMult, boolean nothingOk) { 1875// int orbitIndex = context.orbitIndex; 1876// if (context.parentOrbitIndex >= 0) { 1877// orbitIndex = context.parentOrbitIndex; 1878// } 1879// int fromParentOrbitIndex = context.orbitIndex; 1880 String age = context.age; 1881 //String starType = context.star.getTypeId(); 1882 String starType = star != null ? star.getTypeId() : null; 1883 if (context.center instanceof PlanetAPI) { 1884 PlanetAPI star = (PlanetAPI) context.center; 1885 if (star.isStar()) starType = star.getTypeId(); 1886 } 1887 1888 String parentCategory = context.parentCategory; 1889 1890 WeightedRandomPicker<CategoryGenDataSpec> picker = new WeightedRandomPicker<CategoryGenDataSpec>(random); 1891 Collection<CategoryGenDataSpec> categoryDataSpecs = Global.getSettings().getAllSpecs(CategoryGenDataSpec.class); 1892 for (CategoryGenDataSpec categoryData : categoryDataSpecs) { 1893 if (context.excludeCategories.contains(categoryData.getCategory())) continue; 1894 1895 boolean catNothing = categoryData.getCategory().equals(CAT_NOTHING); 1896 if (!nothingOk && catNothing) continue; 1897// if (categoryData.getCategory().equals("cat_terrain_rings")) { 1898// System.out.println("sdfkwefewfe"); 1899// } 1900 float weight = categoryData.getFrequency(); 1901 if (age != null) weight *= categoryData.getMultiplier(age); 1902 if (starType != null) weight *= categoryData.getMultiplier(starType); 1903 if (parentCategory != null) weight *= categoryData.getMultiplier(parentCategory); 1904 for (String col : context.multipliers) { 1905 weight *= categoryData.getMultiplier(col); 1906 } 1907 if (extraMult != null) weight *= categoryData.getMultiplier(extraMult); 1908 1909 //if (weight > 0 && (catNothing || !isCategoryEmpty(categoryData, orbitIndex, fromParentOrbitIndex, age, starType, parentCategory, extraMult))) { 1910 if (weight > 0 && (catNothing || !isCategoryEmpty(categoryData, context, extraMult, nothingOk))) { 1911 picker.add(categoryData, weight); 1912 } 1913 } 1914 1915 if (DEBUG) { 1916 boolean withParent = context.parent != null; 1917 int orbitIndex = context.orbitIndex; 1918 String parentType = ""; 1919 if (withParent) { 1920 parentType = context.parent.getSpec().getPlanetType(); 1921 orbitIndex = context.parentOrbitIndex; 1922 } 1923 1924// float offset = orbitIndex; 1925// float minIndex = context.starData.getHabZoneStart() + planetData.getHabOffsetMin() + offset; 1926// float maxIndex = context.starData.getHabZoneStart() + planetData.getHabOffsetMax() + offset; 1927 //boolean inRightRange = orbitIndex >= minIndex && orbitIndex <= maxIndex; 1928 int habDiff = orbitIndex - (int) context.starData.getHabZoneStart(); 1929 if (withParent) { 1930 picker.print(" Picking category for moon of " + parentType + 1931 ", orbit from star: " + orbitIndex + " (" + habDiff + ")" + ", extra: " + extraMult); 1932 } else { 1933 picker.print(" Picking category for entity orbiting star " + starType + 1934 ", orbit from star: " + orbitIndex + " (" + habDiff + ")" + ", extra: " + extraMult); 1935 } 1936 } 1937 1938 CategoryGenDataSpec pick = picker.pick(); 1939 if (DEBUG) { 1940 System.out.println(" Picked: " + pick.getCategory()); 1941 System.out.println(); 1942 } 1943 1944 return pick; 1945 } 1946 1947 public boolean isCategoryEmpty(CategoryGenDataSpec categoryData, GenContext context, String extraMult, boolean nothingOk) { 1948 return getPickerForCategory(categoryData, context, extraMult, nothingOk).isEmpty(); 1949 } 1950 1951 protected float getHabOffset(EntityGenDataSpec data) { 1952 if (starAge == StarAge.YOUNG) { 1953 return data.getHabOffsetYOUNG(); 1954 } 1955 if (starAge == StarAge.AVERAGE) { 1956 return data.getHabOffsetAVERAGE(); 1957 } 1958 if (starAge == StarAge.OLD) { 1959 return data.getHabOffsetOLD(); 1960 } 1961 return 0f; 1962 } 1963 1964// protected WeightedRandomPicker<EntityGenDataSpec> getPickerForCategory(CategoryGenDataSpec categoryData, 1965// int orbitIndex, int fromParentOrbitIndex, String age, String starType, String parentCategory, String extraMult) { 1966 protected WeightedRandomPicker<EntityGenDataSpec> getPickerForCategory(CategoryGenDataSpec categoryData, 1967 GenContext context, String extraMult) { 1968 return getPickerForCategory(categoryData, context, extraMult, true); 1969 } 1970 protected WeightedRandomPicker<EntityGenDataSpec> getPickerForCategory(CategoryGenDataSpec categoryData, 1971 GenContext context, String extraMult, boolean nothingOk) { 1972 int orbitIndex = context.orbitIndex; 1973 if (context.parentOrbitIndex >= 0) { 1974 orbitIndex = context.parentOrbitIndex; 1975 } 1976 int fromParentOrbitIndex = context.orbitIndex; 1977 String age = context.age; 1978 //String starType = context.star.getTypeId(); 1979 String starType = star != null ? star.getTypeId() : null; 1980 if (context.center instanceof PlanetAPI) { 1981 PlanetAPI star = (PlanetAPI) context.center; 1982 if (star.isStar()) starType = star.getTypeId(); 1983 } 1984 1985 String parentCategory = context.parentCategory; 1986 1987 1988 WeightedRandomPicker<EntityGenDataSpec> picker = new WeightedRandomPicker<EntityGenDataSpec>(random); 1989 1990 Collection<PlanetGenDataSpec> planetDataSpecs = Global.getSettings().getAllSpecs(PlanetGenDataSpec.class); 1991 for (PlanetGenDataSpec planetData : planetDataSpecs) { 1992 if (!planetData.getCategory().equals(categoryData.getCategory())) continue; 1993 1994 float offset = getHabOffset(planetData); 1995 float minIndex = context.starData.getHabZoneStart() + planetData.getHabOffsetMin() + offset; 1996 float maxIndex = context.starData.getHabZoneStart() + planetData.getHabOffsetMax() + offset; 1997 boolean inRightRange = orbitIndex >= minIndex && orbitIndex <= maxIndex; 1998 boolean giantMoonException = CAT_GIANT.equals(parentCategory) && 1999 (planetData.hasTag(TAG_GIANT_MOON) && context.parent != null && context.parent.isGasGiant()); 2000 if (!inRightRange && !giantMoonException) continue; 2001 2002// if (planetData.getId().equals("rocky_unstable")) { 2003// System.out.println("dsfwefwefw"); 2004// } 2005 2006 boolean orbitIndexOk = fromParentOrbitIndex == 0 || !planetData.hasTag(TAG_FIRST_ORBIT_ONLY); 2007 if (!orbitIndexOk) continue; 2008 2009 boolean lagrangeStatusOk = COL_LAGRANGE.equals(extraMult) || !planetData.hasTag(TAG_LAGRANGE_ONLY); 2010 if (!lagrangeStatusOk) continue; 2011 2012 boolean nebulaStatusOk = NEBULA_NONE.equals(nebulaType) || !planetData.hasTag(TAG_NOT_IN_NEBULA); 2013 nebulaStatusOk &= !NEBULA_NONE.equals(nebulaType) || !planetData.hasTag(TAG_REQUIRES_NEBULA); 2014 nebulaStatusOk &= systemType != StarSystemType.NEBULA || !planetData.hasTag(TAG_NOT_NEBULA_UNLESS_MOON) || context.parent != null; 2015 if (!nebulaStatusOk) continue; 2016 2017 float weight = planetData.getFrequency(); 2018 if (age != null) weight *= planetData.getMultiplier(age); 2019 if (starType != null) weight *= planetData.getMultiplier(starType); 2020 if (parentCategory != null) weight *= planetData.getMultiplier(parentCategory); 2021 for (String col : context.multipliers) { 2022 weight *= planetData.getMultiplier(col); 2023 } 2024 if (extraMult != null) weight *= planetData.getMultiplier(extraMult); 2025 if (weight > 0) picker.add(planetData, weight); 2026 } 2027 2028 Collection<TerrainGenDataSpec> terrainDataSpecs = Global.getSettings().getAllSpecs(TerrainGenDataSpec.class); 2029 for (TerrainGenDataSpec terrainData : terrainDataSpecs) { 2030 if (!terrainData.getCategory().equals(categoryData.getCategory())) continue; 2031 2032 if (!nothingOk && terrainData.getId().equals("rings_nothing")) continue; 2033 2034 float offset = getHabOffset(terrainData); 2035 float minIndex = context.starData.getHabZoneStart() + terrainData.getHabOffsetMin() + offset; 2036 float maxIndex = context.starData.getHabZoneStart() + terrainData.getHabOffsetMax() + offset; 2037 boolean inRightRange = orbitIndex >= minIndex && orbitIndex <= maxIndex; 2038 boolean giantMoonException = CAT_GIANT.equals(parentCategory) && 2039 (terrainData.hasTag(TAG_GIANT_MOON) && context.parent != null && context.parent.isGasGiant()); 2040 if (!inRightRange && !giantMoonException) continue; 2041 2042 boolean orbitIndexOk = fromParentOrbitIndex == 0 || !terrainData.hasTag(TAG_FIRST_ORBIT_ONLY); 2043 if (!orbitIndexOk) continue; 2044 2045 boolean lagrangeStatusOk = COL_LAGRANGE.equals(extraMult) || !terrainData.hasTag(TAG_LAGRANGE_ONLY); 2046 if (!lagrangeStatusOk) continue; 2047 2048 boolean nebulaStatusOk = NEBULA_NONE.equals(nebulaType) || !terrainData.hasTag(TAG_NOT_IN_NEBULA); 2049 nebulaStatusOk &= !NEBULA_NONE.equals(nebulaType) || !terrainData.hasTag(TAG_REQUIRES_NEBULA); 2050 nebulaStatusOk &= systemType != StarSystemType.NEBULA || !terrainData.hasTag(TAG_NOT_NEBULA_UNLESS_MOON) || context.parent != null; 2051 if (!nebulaStatusOk) continue; 2052 2053 float weight = terrainData.getFrequency(); 2054 if (age != null) weight *= terrainData.getMultiplier(age); 2055 if (starType != null) weight *= terrainData.getMultiplier(starType); 2056 if (parentCategory != null) weight *= terrainData.getMultiplier(parentCategory); 2057 for (String col : context.multipliers) { 2058 weight *= terrainData.getMultiplier(col); 2059 } 2060 if (extraMult != null) weight *= terrainData.getMultiplier(extraMult); 2061 if (weight > 0) picker.add(terrainData, weight); 2062 } 2063 2064 return picker; 2065 } 2066 2067 2068 2069 protected void setDefaultLightColorBasedOnStars() { 2070 Color one = Color.white, two = null, three = null; 2071 2072 switch (systemType) { 2073 case BINARY_FAR: 2074 case TRINARY_2FAR: 2075 case SINGLE: 2076 case NEBULA: 2077 one = pickLightColorForStar(star); 2078 break; 2079 case BINARY_CLOSE: 2080 case TRINARY_1CLOSE_1FAR: 2081 one = pickLightColorForStar(star); 2082 two = pickLightColorForStar(secondary); 2083 break; 2084 case TRINARY_2CLOSE: 2085 one = pickLightColorForStar(star); 2086 two = pickLightColorForStar(secondary); 2087 three = pickLightColorForStar(tertiary); 2088 break; 2089 } 2090 2091 Color result = one; 2092 if (two != null && three == null) { 2093 result = Misc.interpolateColor(one, two, 0.5f); 2094 } else if (two != null && three != null) { 2095 result = Misc.interpolateColor(one, two, 0.5f); 2096 result = Misc.interpolateColor(result, three, 0.5f); 2097 } 2098 system.setLightColor(result); // light color in entire system, affects all entities 2099 } 2100 2101 2102 protected Color pickLightColorForStar(PlanetAPI star) { 2103 StarGenDataSpec starData = (StarGenDataSpec) Global.getSettings().getSpec(StarGenDataSpec.class, star.getSpec().getPlanetType(), false); 2104 Color min = starData.getLightColorMin(); 2105 Color max = starData.getLightColorMax(); 2106 Color lightColor = Misc.interpolateColor(min, max, random.nextFloat()); 2107 return lightColor; 2108 } 2109 2110 2111// protected void setLightColorBasedOnStar(PlanetAPI star) { 2112// StarGenDataSpec starData = (StarGenDataSpec) Global.getSettings().getSpec(StarGenDataSpec.class, star.getSpec().getPlanetType(), false); 2113// Color min = starData.getLightColorMin(); 2114// Color max = starData.getLightColorMax(); 2115// Color lightColor = Misc.interpolateColor(min, max, random.nextFloat()); 2116// system.setLightColor(lightColor); // light color in entire system, affects all entities 2117// } 2118 2119 2120 protected PlanetAPI addRandomStar(String id, String name) { 2121 PlanetSpecAPI starSpec = pickStar(constellationAge); 2122 if (starSpec == null) return null; 2123 2124 StarGenDataSpec starData = (StarGenDataSpec) Global.getSettings().getSpec(StarGenDataSpec.class, starSpec.getPlanetType(), false); 2125 float radius = getRadius(starData.getMinRadius(), starData.getMaxRadius()); 2126 2127 float corona = radius * (starData.getCoronaMult() + starData.getCoronaVar() * (random.nextFloat() - 0.5f)); 2128 if (corona < starData.getCoronaMin()) corona = starData.getCoronaMin(); 2129 2130 PlanetAPI star = system.addPlanet(id, // unique id for this star 2131 null, 2132 name, 2133 starSpec.getPlanetType(), // id in planets.json 2134 0f, // angle 2135 radius, // radius (in pixels at default zoom) 2136 10000f, // orbit radius 2137 1000f // orbit days 2138 ); 2139 2140 system.addCorona(star, corona, // corona radius, from star edge 2141 starData.getSolarWind(), 2142 (float) (starData.getMinFlare() + (starData.getMaxFlare() - starData.getMinFlare()) * random.nextFloat()), 2143 starData.getCrLossMult()); 2144 2145 return star; 2146 } 2147 2148 2149 2150 public void init(StarSystemAPI system, StarAge age) { 2151 sector = Global.getSector(); 2152 hyper = Global.getSector().getHyperspace(); 2153 this.starAge = age; 2154 this.system = system; 2155 2156 } 2157 protected boolean initSystem(String name, Vector2f loc) { 2158 sector = Global.getSector(); 2159 system = sector.createStarSystem(name); 2160 system.setProcgen(true); 2161 system.setType(systemType); 2162 system.getLocation().set(loc); 2163 hyper = Global.getSector().getHyperspace(); 2164 2165 //system.setBackgroundTextureFilename("graphics/backgrounds/background2.jpg"); 2166 system.setBackgroundTextureFilename(backgroundName); 2167 return true; 2168 } 2169 2170 protected void updateAgeAfterPickingStar() { 2171 starAge = starData.getAge(); 2172 if (starAge == StarAge.ANY) { 2173 starAge = constellationAge; 2174 } 2175 starAgeData = (AgeGenDataSpec) Global.getSettings().getSpec(AgeGenDataSpec.class, starAge.name(), true); 2176 } 2177 2178 protected void cleanup() { 2179 if (system != null) { 2180 Global.getSector().removeStarSystem(system); 2181 system = null; 2182 } 2183 } 2184 2185 public String getNebulaType() { 2186 return nebulaType; 2187 } 2188 2189 public StarAge getConstellationAge() { 2190 return constellationAge; 2191 } 2192 2193 public StarAge getStarAge() { 2194 return starAge; 2195 } 2196 2197 2198 public PlanetSpecAPI pickStar(StarAge age) { 2199 if (params != null && !params.starTypes.isEmpty()) { 2200 String id = params.starTypes.remove(0); 2201 //if (id.equals("black_hole") && systemType == StarSystemType.NEBULA) id = "nebula_center_old"; 2202 for (PlanetSpecAPI spec : Global.getSettings().getAllPlanetSpecs()) { 2203 if (spec.getPlanetType().equals(id)) { 2204 Object test = Global.getSettings().getSpec(StarGenDataSpec.class, id, true); 2205 if (test == null) continue; 2206 StarGenDataSpec data = (StarGenDataSpec) test; 2207 boolean hasTag = data.hasTag(StarSystemType.NEBULA.name()); 2208 boolean nebType = systemType == StarSystemType.NEBULA; 2209 boolean nebulaStatusOk = hasTag == nebType; 2210 if (nebulaStatusOk) { 2211 return spec; 2212 } 2213 } 2214 } 2215 // doesn't work because the actual class the spec is registered under is PlanetSpec, 2216 // not the API-exposed PlanetSpecAPI 2217 //return (PlanetSpecAPI) Global.getSettings().getSpec(PlanetSpecAPI.class, id, true); 2218 } 2219 2220 WeightedRandomPicker<PlanetSpecAPI> picker = new WeightedRandomPicker<PlanetSpecAPI>(random); 2221 for (PlanetSpecAPI spec : Global.getSettings().getAllPlanetSpecs()) { 2222 if (!spec.isStar()) continue; 2223 2224 String id = spec.getPlanetType(); 2225 Object test = Global.getSettings().getSpec(StarGenDataSpec.class, id, true); 2226 if (test == null) continue; 2227 StarGenDataSpec data = (StarGenDataSpec) test; 2228 2229 2230// boolean nebulaStatusOk = NEBULA_NONE.equals(nebulaType) || !data.hasTag(TAG_NOT_IN_NEBULA); 2231// nebulaStatusOk &= !NEBULA_NONE.equals(nebulaType) || !data.hasTag(TAG_REQUIRES_NEBULA); 2232// //nebulaStatusOk &= !NEBULA_NONE.equals(nebulaType) || !data.hasTag(StarSystemType.NEBULA.name()); 2233// //nebulaStatusOk &= systemType != StarSystemType.NEBULA || data.hasTag(StarSystemType.NEBULA.name()); 2234// nebulaStatusOk &= !data.hasTag(StarSystemType.NEBULA.name()) || systemType == StarSystemType.NEBULA; 2235 2236 boolean hasTag = data.hasTag(StarSystemType.NEBULA.name()); 2237 boolean nebType = systemType == StarSystemType.NEBULA; 2238 boolean nebulaStatusOk = hasTag == nebType; 2239 2240 if (!nebulaStatusOk) continue; 2241 2242 //if (!id.equals("empty_nebula_center")) continue; 2243 2244 float freq = 0f; 2245 switch (age) { 2246 case AVERAGE: 2247 freq = data.getFreqAVERAGE(); 2248 break; 2249 case OLD: 2250 freq = data.getFreqOLD(); 2251 break; 2252 case YOUNG: 2253 freq = data.getFreqYOUNG(); 2254 break; 2255 } 2256 //System.out.println("Adding: " + spec.getPlanetType() + ", weight: " + freq); 2257 picker.add(spec, freq); 2258 } 2259// if (systemType == StarSystemType.NEBULA) { 2260// System.out.println("wfwefwe"); 2261// } 2262 return picker.pick(); 2263 } 2264 2265 2266 public static Color getColor(Color min, Color max) { 2267 Color color = new Color((int) (min.getRed() + (max.getRed() - min.getRed()) * random.nextDouble()), 2268 (int) (min.getGreen() + (max.getGreen() - min.getGreen()) * random.nextDouble()), 2269 (int) (min.getBlue() + (max.getBlue() - min.getBlue()) * random.nextDouble()), 2270 255); 2271 2272 return color; 2273 } 2274 2275 2276 2277 public static float getNormalRandom(float min, float max) { 2278 return getNormalRandom(random, min, max); 2279 } 2280 2281 public static float getNormalRandom(Random random, float min, float max) { 2282 double r = random.nextGaussian(); 2283 r *= 0.2f; 2284 r += 0.5f; 2285 if (r < 0) r = 0; 2286 if (r > 1) r = 1; 2287 2288 // 70% chance 0.3 < r < .7 2289 // 95% chance 0.1 < r < .7 2290 // 99% chance 0 < r < 1 2291 return min + (float) r * (max - min); 2292 } 2293 2294 public static float getRadius(float min, float max) { 2295 float radius = (float) (min + (max - min) * random.nextFloat()); 2296 return radius; 2297 } 2298 2299 public static float getRandom(float min, float max) { 2300 float radius = (float) (min + (max - min) * random.nextFloat()); 2301 return radius; 2302 } 2303 public Map<SectorEntityToken, PlanetAPI> getLagrangeParentMap() { 2304 return lagrangeParentMap; 2305 } 2306 2307 public Map<SectorEntityToken, List<SectorEntityToken>> getAllEntitiesAdded() { 2308 return allNameableEntitiesAdded; 2309 } 2310 2311 public static Gender pickGender() { 2312 if (random.nextBoolean()) { 2313 return Gender.MALE; 2314 } 2315 return Gender.FEMALE; 2316 } 2317} 2318 2319 2320 2321 2322 2323 2324 2325 2326