001package com.fs.starfarer.api.impl.campaign.procgen.themes; 002 003import java.util.ArrayList; 004import java.util.Collections; 005import java.util.Comparator; 006import java.util.HashSet; 007import java.util.LinkedHashMap; 008import java.util.List; 009import java.util.Random; 010import java.util.Set; 011 012import org.lwjgl.util.vector.Vector2f; 013 014import com.fs.starfarer.api.Global; 015import com.fs.starfarer.api.campaign.LocationAPI; 016import com.fs.starfarer.api.campaign.PlanetAPI; 017import com.fs.starfarer.api.campaign.SectorEntityToken; 018import com.fs.starfarer.api.campaign.StarSystemAPI; 019import com.fs.starfarer.api.campaign.econ.MarketAPI.SurveyLevel; 020import com.fs.starfarer.api.campaign.econ.MarketConditionAPI; 021import com.fs.starfarer.api.impl.campaign.ids.Commodities; 022import com.fs.starfarer.api.impl.campaign.ids.Conditions; 023import com.fs.starfarer.api.impl.campaign.ids.Entities; 024import com.fs.starfarer.api.impl.campaign.ids.Factions; 025import com.fs.starfarer.api.impl.campaign.ids.MemFlags; 026import com.fs.starfarer.api.impl.campaign.ids.Tags; 027import com.fs.starfarer.api.impl.campaign.intel.events.ht.HTPoints; 028import com.fs.starfarer.api.impl.campaign.procgen.Constellation; 029import com.fs.starfarer.api.impl.campaign.procgen.StarSystemGenerator; 030import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.DomainSurveyDerelictSpecial.DomainSurveyDerelictSpecialData; 031import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.DomainSurveyDerelictSpecial.SpecialType; 032import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.SurveyDataSpecial.SurveyDataSpecialData; 033import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.SurveyDataSpecial.SurveyDataSpecialType; 034import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.TopographicDataSpecial.TopographicDataSpecialData; 035import com.fs.starfarer.api.plugins.SurveyPlugin; 036import com.fs.starfarer.api.util.Misc; 037import com.fs.starfarer.api.util.WeightedRandomPicker; 038 039 040public class DerelictThemeGenerator extends BaseThemeGenerator { 041 042 public static final float BASE_LINK_FRACTION = 0.25f; 043 public static final float SALVAGE_SPECIAL_FRACTION = 0.5f; 044 public static final float TOPOGRAPHIC_DATA_FRACTION = 0.2f; 045 046 public static final int BRANCHES_PER_MOTHERSHIP_MIN = 3; 047 public static final int BRANCHES_PER_MOTHERSHIP_MAX = 4; 048 049 public static final int BRANCHES_PER_SHIP_MIN = 2; 050 public static final int BRANCHES_PER_SHIP_MAX = 3; 051 052 053 public static class SystemGenData { 054 public int numMotherships; 055 public int numSurveyShips; 056 public int numProbes; 057 } 058 059 060 public String getThemeId() { 061 return Themes.DERELICTS; 062 } 063 064 @Override 065 public void generateForSector(ThemeGenContext context, float allowedUnusedFraction) { 066 067 float total = (float) (context.constellations.size() - context.majorThemes.size()) * allowedUnusedFraction; 068 if (total <= 0) return; 069 070 float avg1 = (BRANCHES_PER_MOTHERSHIP_MIN + BRANCHES_PER_MOTHERSHIP_MAX) / 2f; 071 float avg2 = (BRANCHES_PER_SHIP_MIN + BRANCHES_PER_SHIP_MAX) / 2f; 072 float perChain = 1 + avg1 + (avg1 * avg2); 073 074 float num = total / perChain; 075 if (num < 1) num = 1; 076 if (num > 3) num = 3; 077 078 if (num > 1 && num < 2) { 079 num = 2; 080 } else { 081 num = Math.round(num); 082 } 083 084 List<AddedEntity> mothershipsSoFar = new ArrayList<AddedEntity>(); 085 086 for (int i = 0; i < num; i++) { 087 addMothershipChain(context, mothershipsSoFar); 088 } 089 090 091 092 WeightedRandomPicker<StarSystemAPI> cryoSystems = new WeightedRandomPicker<StarSystemAPI>(StarSystemGenerator.random); 093 WeightedRandomPicker<StarSystemAPI> backup = new WeightedRandomPicker<StarSystemAPI>(StarSystemGenerator.random); 094 OUTER: for (StarSystemAPI system : Global.getSector().getStarSystems()) { 095 float w = 0f; 096 if (system.hasTag(Tags.THEME_DERELICT_PROBES)) { 097 w = 10f; 098 } else if (system.hasTag(Tags.THEME_DERELICT_SURVEY_SHIP)) { 099 w = 10f; 100 } else if (system.hasTag(Tags.THEME_DERELICT_MOTHERSHIP)) { 101 w = 10f; 102 } else if (system.hasTag(Tags.THEME_DERELICT)) { 103 w = 10f; 104 } else { 105 continue; 106 } 107 108 int numPlanets = 0; 109 boolean hasHab = false; 110 for (PlanetAPI planet : system.getPlanets()) { 111 if (planet.isStar()) continue; 112 if (planet.getSpec().isPulsar()) continue OUTER; 113 hasHab |= planet.getMarket() != null && planet.getMarket().hasCondition(Conditions.HABITABLE); 114 numPlanets++; 115 } 116 117 WeightedRandomPicker<StarSystemAPI> use = cryoSystems; 118 if (!hasHab || numPlanets < 3) { 119 use = backup; 120 } 121 122 if (hasHab) w += 5; 123 w += numPlanets; 124 125 if (use == backup) { 126 w *= 0.0001f; 127 } 128 use.add(system, w); 129 } 130 131 int numCryo = 2; 132 if (cryoSystems.isEmpty() || cryoSystems.getItems().size() < numCryo + 1) { 133 cryoSystems.addAll(backup); 134 } 135 136 int added = 0; 137 WeightedRandomPicker<String> cryosleeperNames = new WeightedRandomPicker<String>(random); 138 cryosleeperNames.add("Calypso"); 139 cryosleeperNames.add("Tantalus"); 140 while (added < numCryo && !cryoSystems.isEmpty()) { 141 StarSystemAPI pick = cryoSystems.pickAndRemove(); 142 String name = cryosleeperNames.pickAndRemove(); 143 AddedEntity cryo = addCryosleeper(pick, name); 144 if (cryo != null) { 145 added++; 146 } 147 } 148 } 149 150 protected void addMothershipChain(ThemeGenContext context, List<AddedEntity> mothershipsSoFar) { 151 152 List<AddedEntity> all = new ArrayList<AddedEntity>(); 153 154 155 Vector2f center = new Vector2f(); 156 for (AddedEntity e : mothershipsSoFar) { 157 Vector2f.add(center, e.entity.getLocationInHyperspace(), center); 158 } 159 center.scale(1f / (float)(mothershipsSoFar.size() + 1f)); 160 161 List<Constellation> constellations = getSortedAvailableConstellations(context, false, center, null); 162 WeightedRandomPicker<Constellation> picker = new WeightedRandomPicker<Constellation>(StarSystemGenerator.random); 163 for (int i = 0; i < constellations.size() / 3; i++) { 164 picker.add(constellations.get(i)); 165 } 166 167 Constellation main = picker.pick(); 168 if (main == null) return; 169 170 if (DEBUG) { 171 System.out.println("Picked for mothership chain start: [" + main.getNameWithType() + "] (" + (int)main.getLocation().x + ", " + (int)main.getLocation().y + ")"); 172 } 173 174 constellations.remove(main); 175 context.majorThemes.put(main, Themes.DERELICTS); 176 177 178 StarSystemAPI mainSystem = main.getSystemWithMostPlanets(); 179 if (mainSystem == null) return; 180 181 //mainSystem.addTag(Tags.THEME_DERELICT); 182 for (StarSystemAPI system : main.getSystems()) { 183 system.addTag(Tags.THEME_DERELICT); 184 } 185 186// if (mainSystem.getName().toLowerCase().contains("valac")) { 187// System.out.println("HERE13123123123"); 188// } 189 190 AddedEntity mothership = addMothership(mainSystem); 191 if (mothership == null) return; 192 193 all.add(mothership); 194 195 if (DEBUG) { 196 System.out.println(" Added mothership to [" + mainSystem.getNameWithLowercaseType() + "]"); 197 } 198 199 //if (true) return; 200 201 // probes in mothership system 202 //int probesNearMothership = (int) Math.round(StarSystemGenerator.getRandom(2, 4)); 203 int probesNearMothership = getNumProbesForSystem(mothership.entity.getContainingLocation()); 204 List<AddedEntity> added = addToSystem(mainSystem, Entities.DERELICT_SURVEY_PROBE, probesNearMothership); 205 all.addAll(added); 206 207 208 linkFractionToParent(mothership, added, 209 BASE_LINK_FRACTION, 210 SpecialType.LOCATION_MOTHERSHIP); 211 212 // survey ships in mothership constellation 213 int surveyShipsNearMothership = (int) Math.round(StarSystemGenerator.getRandom(0, 3)); 214 if (surveyShipsNearMothership > main.getSystems().size()) surveyShipsNearMothership = main.getSystems().size(); 215 if (DEBUG) { 216 System.out.println(String.format("Adding %d survey ships near mothership", surveyShipsNearMothership)); 217 } 218 List<AddedEntity> addedShips = addToConstellation(main, Entities.DERELICT_SURVEY_SHIP, surveyShipsNearMothership, false); 219 all.addAll(addedShips); 220 221 // probes in each system with survey ship 222 for (AddedEntity e : addedShips) { 223 int probesNearSurveyShip = (int) Math.round(StarSystemGenerator.getRandom(1, 3)); 224 //int probesNearSurveyShip = getNumProbesForSystem(e.entity.getContainingLocation()); 225 added = addProbes((StarSystemAPI) e.entity.getContainingLocation(), probesNearSurveyShip); 226 all.addAll(added); 227 228 linkFractionToParent(e, added, 229 BASE_LINK_FRACTION, 230 SpecialType.LOCATION_SURVEY_SHIP); 231 } 232 233 linkFractionToParent(mothership, addedShips, 234 BASE_LINK_FRACTION, 235 SpecialType.LOCATION_MOTHERSHIP); 236 237 //if (true) return; 238 239 constellations = getSortedAvailableConstellations(context, false, mothership.entity.getLocationInHyperspace(), null); 240 picker = new WeightedRandomPicker<Constellation>(StarSystemGenerator.random); 241 for (int i = constellations.size() - 7; i < constellations.size(); i++) { 242 if (i < 0) continue; 243 picker.add(constellations.get(i)); 244 } 245 246 int numSurveyShipsInNearConstellations = (int) Math.round(StarSystemGenerator.getRandom(BRANCHES_PER_MOTHERSHIP_MIN, BRANCHES_PER_MOTHERSHIP_MAX)); 247 if (DEBUG) { 248 System.out.println(String.format("Adding up to %d survey ships", numSurveyShipsInNearConstellations)); 249 } 250 List<Constellation> constellationsForSurveyShips = new ArrayList<Constellation>(); 251 for (int i = 0; i < numSurveyShipsInNearConstellations && !picker.isEmpty(); i++) { 252 constellationsForSurveyShips.add(picker.pickAndRemove()); 253 } 254 List<AddedEntity> outerShips = new ArrayList<AddedEntity>(); 255 256 257 for (Constellation c : constellationsForSurveyShips) { 258 context.majorThemes.put(c, Themes.DERELICTS); 259 260 if (DEBUG) { 261 System.out.println(" Picked for survey ship: [" + c.getNameWithType() + "]"); 262 } 263 264 addedShips = addToConstellation(c, Entities.DERELICT_SURVEY_SHIP, 1, true); 265 if (addedShips.isEmpty()) continue; 266 267 all.addAll(addedShips); 268 269 AddedEntity ship = addedShips.get(0); 270 outerShips.addAll(addedShips); 271 272 //int probesNearSurveyShip = (int) Math.round(StarSystemGenerator.getRandom(1, 3)); 273 int probesNearSurveyShip = getNumProbesForSystem(ship.entity.getContainingLocation()); 274 added = addProbes((StarSystemAPI) ship.entity.getContainingLocation(), probesNearSurveyShip); 275 all.addAll(added); 276 277 linkFractionToParent(ship, added, 278 BASE_LINK_FRACTION, 279 SpecialType.LOCATION_SURVEY_SHIP); 280 281 int probesInSameConstellation = (int) Math.round(StarSystemGenerator.getRandom(2, 5)); 282 int max = c.getSystems().size() + 2; 283 if (probesInSameConstellation > max) probesInSameConstellation = max; 284 285 added = addToConstellation(c, Entities.DERELICT_SURVEY_PROBE, probesInSameConstellation, false); 286 all.addAll(added); 287 288 linkFractionToParent(ship, added, 289 BASE_LINK_FRACTION, 290 SpecialType.LOCATION_SURVEY_SHIP); 291 292 293 294 List<Constellation> c2 = getSortedAvailableConstellations(context, false, c.getLocation(), constellationsForSurveyShips); 295 WeightedRandomPicker<Constellation> p2 = new WeightedRandomPicker<Constellation>(StarSystemGenerator.random); 296 //for (int i = 0; i < constellations.size() / 3 && i < 7; i++) { 297 for (int i = c2.size() - 3; i < c2.size(); i++) { 298 if (i < 0) continue; 299 p2.add(constellations.get(i)); 300 } 301 302 int probeSystemsNearShip = (int) Math.round(StarSystemGenerator.getRandom(BRANCHES_PER_SHIP_MIN, BRANCHES_PER_SHIP_MAX)); 303 int k = 0; 304 if (DEBUG) { 305 System.out.println(String.format("Adding probes to %d constellations near survey ship", probeSystemsNearShip)); 306 } 307 List<AddedEntity> probes3 = new ArrayList<AddedEntity>(); 308 while (k < probeSystemsNearShip && !p2.isEmpty()) { 309 Constellation pick = p2.pickAndRemove(); 310 k++; 311 context.majorThemes.put(pick, Themes.NO_THEME); 312 int probesInConstellation = (int) Math.round(StarSystemGenerator.getRandom(1, 3)); 313 probes3.addAll(addToConstellation(pick, Entities.DERELICT_SURVEY_PROBE, probesInConstellation, false)); 314 } 315 316 all.addAll(probes3); 317 linkFractionToParent(ship, probes3, 318 BASE_LINK_FRACTION, 319 SpecialType.LOCATION_MOTHERSHIP); 320 } 321 322 linkFractionToParent(mothership, outerShips, 323 BASE_LINK_FRACTION, 324 SpecialType.LOCATION_MOTHERSHIP); 325 326 327 328 assignRandomSpecials(all); 329 } 330 331 public static Set<String> interestingConditions = new HashSet<String>(); 332 public static Set<String> interestingConditionsWithoutHabitable = new HashSet<String>(); 333 public static Set<String> interestingConditionsWithRuins = new HashSet<String>(); 334 static { 335 //interestingConditions.add(Conditions.VOLATILES_ABUNDANT); 336 interestingConditions.add(Conditions.VOLATILES_PLENTIFUL); 337 //interestingConditions.add(Conditions.ORE_RICH); 338 interestingConditions.add(Conditions.RARE_ORE_RICH); 339 interestingConditions.add(Conditions.RARE_ORE_ULTRARICH); 340 interestingConditions.add(Conditions.ORE_ULTRARICH); 341 interestingConditions.add(Conditions.FARMLAND_BOUNTIFUL); 342 interestingConditions.add(Conditions.FARMLAND_ADEQUATE); 343 //interestingConditions.add(Conditions.ORGANICS_ABUNDANT); 344 interestingConditions.add(Conditions.ORGANICS_PLENTIFUL); 345 interestingConditions.add(Conditions.HABITABLE); 346 347 interestingConditionsWithoutHabitable.addAll(interestingConditions); 348 interestingConditionsWithoutHabitable.remove(Conditions.HABITABLE); 349 350 interestingConditionsWithRuins.addAll(interestingConditions); 351 interestingConditionsWithRuins.add(Conditions.RUINS_VAST); 352 interestingConditionsWithRuins.add(Conditions.RUINS_EXTENSIVE); 353 } 354 355 356 357 protected void assignRandomSpecials(List<AddedEntity> entities) { 358 Set<PlanetAPI> usedPlanets = new HashSet<PlanetAPI>(); 359 Set<StarSystemAPI> usedSystems = new HashSet<StarSystemAPI>(); 360 361 for (AddedEntity e : entities) { 362 if (hasSpecial(e.entity)) continue; 363 364 SurveyDataSpecialType type = null; 365 366 if (StarSystemGenerator.random.nextFloat() < TOPOGRAPHIC_DATA_FRACTION) { 367 int min = 0; 368 int max = 0; 369 if (Entities.DERELICT_SURVEY_PROBE.equals(e.entityType)) { 370 min = HTPoints.LOW_MIN; 371 max = HTPoints.LOW_MAX; 372 } else if (Entities.DERELICT_SURVEY_SHIP.equals(e.entityType)) { 373 min = HTPoints.MEDIUM_MIN; 374 max = HTPoints.MEDIUM_MAX; 375 } else if (Entities.DERELICT_MOTHERSHIP.equals(e.entityType)) { 376 min = HTPoints.HIGH_MIN; 377 max = HTPoints.HIGH_MAX; 378 } 379 int points = min + StarSystemGenerator.random.nextInt(max - min + 1); 380 if (points > 0) { 381 TopographicDataSpecialData data = new TopographicDataSpecialData(points); 382 Misc.setSalvageSpecial(e.entity, data); 383 continue; 384 } 385 } 386 if (StarSystemGenerator.random.nextFloat() < SALVAGE_SPECIAL_FRACTION) { 387 float pNothing = 0.1f; 388 if (Entities.DERELICT_SURVEY_PROBE.equals(e.entityType)) { 389 pNothing = 0.5f; 390 } else if (Entities.DERELICT_SURVEY_SHIP.equals(e.entityType)) { 391 pNothing = 0.25f; 392 } else if (Entities.DERELICT_MOTHERSHIP.equals(e.entityType)) { 393 pNothing = 0f; 394 } 395 396 float r = StarSystemGenerator.random.nextFloat(); 397 if (r >= pNothing) { 398 type = SurveyDataSpecialType.PLANET_SURVEY_DATA; 399 } 400 } 401 402 //type = SpecialType.PLANET_SURVEY_DATA; 403 404 if (type == SurveyDataSpecialType.PLANET_SURVEY_DATA) { 405 PlanetAPI planet = findInterestingPlanet(e.entity.getConstellation().getSystems(), usedPlanets); 406 if (planet != null) { 407 SurveyDataSpecialData data = new SurveyDataSpecialData(SurveyDataSpecialType.PLANET_SURVEY_DATA); 408 data.entityId = planet.getId(); 409 data.includeRuins = false; 410 Misc.setSalvageSpecial(e.entity, data); 411 usedPlanets.add(planet); 412 413// DomainSurveyDerelictSpecialData special = new DomainSurveyDerelictSpecialData(type); 414// special.entityId = planet.getId(); 415// usedPlanets.add(planet); 416// e.entity.getMemoryWithoutUpdate().set(MemFlags.SALVAGE_SPECIAL_DATA, special); 417 } 418 } 419 } 420 } 421 422 423 public static StarSystemAPI findNearbySystem(SectorEntityToken from, Set<StarSystemAPI> exclude) { 424 return findNearbySystem(from, exclude, null, 10000f); 425 } 426 427 public static StarSystemAPI findNearbySystem(SectorEntityToken from, Set<StarSystemAPI> exclude, Random random, float maxRange) { 428 if (random == null) random = StarSystemGenerator.random; 429 430 WeightedRandomPicker<StarSystemAPI> picker = new WeightedRandomPicker<StarSystemAPI>(random); 431 432 for (StarSystemAPI system : Global.getSector().getStarSystems()) { 433 if (exclude != null && exclude.contains(system)) continue; 434 435 float dist = Misc.getDistance(from.getLocationInHyperspace(), system.getLocation()); 436 if (dist > maxRange) continue; 437 if (systemIsEmpty(system)) continue; 438 439 picker.add(system); 440 } 441 442 return picker.pick(); 443 } 444 445 446 public static String getInterestingCondition(PlanetAPI planet, boolean includeRuins) { 447 if (planet == null) return null; 448 449 Set<String> conditions = interestingConditions; 450 if (includeRuins) conditions = interestingConditionsWithRuins; 451 452 for (MarketConditionAPI mc : planet.getMarket().getConditions()) { 453 if (conditions.contains(mc.getId())) { 454 return mc.getId(); 455 } 456 } 457 return null; 458 } 459 460 public static PlanetAPI findInterestingPlanet(List<StarSystemAPI> systems, Set<PlanetAPI> exclude) { 461 return findInterestingPlanet(systems, exclude, true, false, null); 462 } 463 public static PlanetAPI findInterestingPlanet(List<StarSystemAPI> systems, Set<PlanetAPI> exclude, boolean includeKnown, boolean includeRuins, Random random) { 464 if (random == null) random = StarSystemGenerator.random; 465 466 WeightedRandomPicker<PlanetAPI> planets = new WeightedRandomPicker<PlanetAPI>(random); 467 468 Set<String> conditions = interestingConditions; 469 if (includeRuins) conditions = interestingConditionsWithRuins; 470 471 SurveyPlugin plugin = (SurveyPlugin) Global.getSettings().getNewPluginInstance("surveyPlugin"); 472 473 for (StarSystemAPI system : systems) { 474 if (system.hasTag(Tags.THEME_HIDDEN)) continue; 475 476 for (PlanetAPI planet : system.getPlanets()) { 477 if (planet.isStar()) continue; 478 if (exclude != null && exclude.contains(planet)) continue; 479 if (planet.getMarket() == null || !planet.getMarket().isPlanetConditionMarketOnly()) continue; 480 if (!includeKnown && planet.getMarket() != null && planet.getMarket().getSurveyLevel() == SurveyLevel.FULL) { 481 continue; 482 } 483 //if (planet.getMarket().getSurveyLevel() == SurveyLevel.FULL) continue; 484 485 String type = plugin.getSurveyDataType(planet); 486 boolean classIV = Commodities.SURVEY_DATA_4.equals(type); 487 boolean classV = Commodities.SURVEY_DATA_5.equals(type); 488 489 if (!(classIV || classV || planet.getMarket().getHazardValue() <= 1f)) continue; 490 491 float w = 1f; 492 for (MarketConditionAPI mc : planet.getMarket().getConditions()) { 493 if (conditions.contains(mc.getId())) { 494 w += 1f; 495 } 496 } 497 if (classIV) w *= 0.5f; 498 if (classV) w *= 4f; 499 planets.add(planet, w); 500 } 501 } 502 return planets.pick(); 503 } 504 505 506 protected int getNumProbesForSystem(LocationAPI system) { 507 int base = 1; 508 int planets = system.getPlanets().size(); 509 510 if (planets <= 3) { 511 } else if (planets <= 5) { 512 base += 1; 513 } else if (planets <= 8) { 514 base += 2; 515 } else { 516 base += 3; 517 } 518 519 base += StarSystemGenerator.random.nextInt(2); 520 521 return base; 522 } 523 protected void linkFractionToParent(AddedEntity parent, List<AddedEntity> children, float p, SpecialType type) { 524 525 WeightedRandomPicker<AddedEntity> picker = new WeightedRandomPicker<AddedEntity>(StarSystemGenerator.random); 526 for (AddedEntity c : children) { 527 if (!hasSpecial(c.entity)) { 528 picker.add(c); 529 } 530 } 531 532 int extraLinks = (int) Math.max(1, Math.round(children.size() * p * (1f + StarSystemGenerator.random.nextFloat() * 0.5f))); 533 for (int i = 0; i < extraLinks && !picker.isEmpty(); i++) { 534 AddedEntity e = picker.pickAndRemove(); 535 linkToParent(e.entity, parent.entity, type); 536 } 537 } 538 539// protected AddedEntity getClosest(AddedEntity from, List<AddedEntity> choices) { 540// float min = Float.MAX_VALUE; 541// AddedEntity result = null; 542// for (AddedEntity e : choices) { 543// 544// } 545// 546// return result; 547// } 548 549 protected void linkToParent(SectorEntityToken from, SectorEntityToken parent, SpecialType type) { 550 if (hasSpecial(from)) return; 551 552 DomainSurveyDerelictSpecialData special = new DomainSurveyDerelictSpecialData(type); 553 special.entityId = parent.getId(); 554 from.getMemoryWithoutUpdate().set(MemFlags.SALVAGE_SPECIAL_DATA, special); 555 } 556 557 protected void linkToMothership(SectorEntityToken from, SectorEntityToken mothership) { 558 if (hasSpecial(from)) return; 559 560 DomainSurveyDerelictSpecialData special = new DomainSurveyDerelictSpecialData(SpecialType.LOCATION_MOTHERSHIP); 561 special.entityId = mothership.getId(); 562 from.getMemoryWithoutUpdate().set(MemFlags.SALVAGE_SPECIAL_DATA, special); 563 } 564 565 public static boolean hasSpecial(SectorEntityToken entity) { 566 return entity.getMemoryWithoutUpdate().contains(MemFlags.SALVAGE_SPECIAL_DATA); 567 } 568 569 protected List<AddedEntity> addToConstellation(Constellation c, String type, int num, boolean biggestFirst) { 570 List<AddedEntity> result = new ArrayList<AddedEntity>(); 571 572 WeightedRandomPicker<StarSystemAPI> picker = new WeightedRandomPicker<StarSystemAPI>(StarSystemGenerator.random); 573 picker.addAll(c.getSystems()); 574 575 boolean first = true; 576 for (int i = 0; i < num; i++) { 577 StarSystemAPI system = picker.pick(); 578 if (biggestFirst && first) system = c.getSystemWithMostPlanets(); 579 first = false; 580 581 if (system == null) continue; 582 583 result.addAll(addToSystem(system, type, 1)); 584 } 585 586 return result; 587 } 588 589 protected List<AddedEntity> addToSystem(StarSystemAPI system, String type, int num) { 590 List<AddedEntity> result = new ArrayList<AddedEntity>(); 591 if (system == null) return result; 592 593 for (int i = 0; i < num; i++) { 594 AddedEntity e = null; 595 if (Entities.DERELICT_MOTHERSHIP.equals(type)) { 596 e = addMothership(system); 597 } else if (Entities.DERELICT_SURVEY_SHIP.equals(type)) { 598 e = addSurveyShip(system); 599 } else if (Entities.DERELICT_SURVEY_PROBE.equals(type)) { 600 result.addAll(addProbes(system, 1)); 601 } 602 if (e != null) { 603 result.add(e); 604 } 605 } 606 return result; 607 } 608 609 610 611 protected AddedEntity addMothership(StarSystemAPI system) { 612 LinkedHashMap<LocationType, Float> weights = new LinkedHashMap<LocationType, Float>(); 613 weights.put(LocationType.PLANET_ORBIT, 10f); 614 weights.put(LocationType.JUMP_ORBIT, 1f); 615 weights.put(LocationType.NEAR_STAR, 1f); 616 weights.put(LocationType.OUTER_SYSTEM, 5f); 617 weights.put(LocationType.IN_ASTEROID_BELT, 10f); 618 weights.put(LocationType.IN_RING, 10f); 619 weights.put(LocationType.IN_ASTEROID_FIELD, 10f); 620 weights.put(LocationType.STAR_ORBIT, 1f); 621 weights.put(LocationType.IN_SMALL_NEBULA, 1f); 622 weights.put(LocationType.L_POINT, 1f); 623 WeightedRandomPicker<EntityLocation> locs = getLocations(random, system, 100f, weights); 624 625// if (system.getName().toLowerCase().contains("valac")) { 626// for (int i = 0; i < 10; i++) { 627// //Random random = new Random(32895278947689263L); 628// StarSystemGenerator.random = new Random(32895278947689263L); 629// random = StarSystemGenerator.random; 630// locs = getLocations(random, system, 100f, weights); 631// EntityLocation loc = locs.pickAndRemove(); 632// System.out.println("Location: " + loc.toString()); 633// } 634// } 635 636 AddedEntity entity = addEntity(random, system, locs, Entities.DERELICT_MOTHERSHIP, Factions.DERELICT); 637 if (entity != null) { 638 system.addTag(Tags.THEME_INTERESTING); 639 system.addTag(Tags.THEME_DERELICT); 640 system.addTag(Tags.THEME_DERELICT_MOTHERSHIP); 641 } 642 643 if (DEBUG) { 644 if (entity != null) { 645 System.out.println(String.format(" Added mothership to %s", system.getNameWithLowercaseType())); 646 } else { 647 System.out.println(String.format(" Failed to add mothership to %s", system.getNameWithLowercaseType())); 648 } 649 } 650 return entity; 651 } 652 653 654 protected AddedEntity addCryosleeper(StarSystemAPI system, String name) { 655 LinkedHashMap<LocationType, Float> weights = new LinkedHashMap<LocationType, Float>(); 656 weights.put(LocationType.PLANET_ORBIT, 10f); 657 weights.put(LocationType.JUMP_ORBIT, 1f); 658 weights.put(LocationType.NEAR_STAR, 1f); 659 weights.put(LocationType.OUTER_SYSTEM, 5f); 660 weights.put(LocationType.IN_ASTEROID_BELT, 5f); 661 weights.put(LocationType.IN_RING, 5f); 662 weights.put(LocationType.IN_ASTEROID_FIELD, 5f); 663 weights.put(LocationType.STAR_ORBIT, 5f); 664 weights.put(LocationType.IN_SMALL_NEBULA, 5f); 665 weights.put(LocationType.L_POINT, 10f); 666 WeightedRandomPicker<EntityLocation> locs = getLocations(random, system, 100f, weights); 667 668 669 AddedEntity entity = addEntity(random, system, locs, Entities.DERELICT_CRYOSLEEPER, Factions.DERELICT); 670 if (entity != null) { 671 system.addTag(Tags.THEME_INTERESTING); 672 system.addTag(Tags.THEME_DERELICT); 673 system.addTag(Tags.THEME_DERELICT_CRYOSLEEPER); 674 675 if (name != null) { 676 entity.entity.setName(entity.entity.getName() + " \"" + name + "\""); 677 //entity.entity.setName("Cryosleeper" + "\"" + name + "\""); 678 } 679 } 680 681 if (DEBUG) { 682 if (entity != null) { 683 System.out.println(String.format(" Added cryosleeper to %s", system.getNameWithLowercaseType())); 684 } else { 685 System.out.println(String.format(" Failed to add cryosleeper to %s", system.getNameWithLowercaseType())); 686 } 687 } 688 return entity; 689 } 690 691 protected AddedEntity addSurveyShip(StarSystemAPI system) { 692 LinkedHashMap<LocationType, Float> weights = new LinkedHashMap<LocationType, Float>(); 693 weights.put(LocationType.PLANET_ORBIT, 10f); 694 weights.put(LocationType.JUMP_ORBIT, 1f); 695 weights.put(LocationType.NEAR_STAR, 1f); 696 weights.put(LocationType.OUTER_SYSTEM, 5f); 697 weights.put(LocationType.IN_ASTEROID_BELT, 10f); 698 weights.put(LocationType.IN_RING, 10f); 699 weights.put(LocationType.IN_ASTEROID_FIELD, 10f); 700 weights.put(LocationType.STAR_ORBIT, 1f); 701 weights.put(LocationType.IN_SMALL_NEBULA, 1f); 702 weights.put(LocationType.L_POINT, 1f); 703 WeightedRandomPicker<EntityLocation> locs = getLocations(random, system, 100f, weights); 704 705 AddedEntity entity = addEntity(random, system, locs, Entities.DERELICT_SURVEY_SHIP, Factions.DERELICT); 706 707 if (entity != null) { 708 system.addTag(Tags.THEME_INTERESTING); 709 system.addTag(Tags.THEME_DERELICT); 710 system.addTag(Tags.THEME_DERELICT_SURVEY_SHIP); 711 } 712 713 if (DEBUG) { 714 if (entity != null) { 715 System.out.println(String.format(" Added survey ship to %s", system.getNameWithLowercaseType())); 716 } else { 717 System.out.println(String.format(" Failed to add survey ship to %s", system.getNameWithLowercaseType())); 718 } 719 } 720 return entity; 721 } 722 723 protected List<AddedEntity> addProbes(StarSystemAPI system, int num) { 724 LinkedHashMap<LocationType, Float> weights = new LinkedHashMap<LocationType, Float>(); 725 weights.put(LocationType.PLANET_ORBIT, 20f); 726 weights.put(LocationType.JUMP_ORBIT, 10f); 727 weights.put(LocationType.NEAR_STAR, 10f); 728 weights.put(LocationType.OUTER_SYSTEM, 5f); 729 weights.put(LocationType.IN_ASTEROID_BELT, 5f); 730 weights.put(LocationType.IN_RING, 5f); 731 weights.put(LocationType.IN_ASTEROID_FIELD, 5f); 732 weights.put(LocationType.STAR_ORBIT, 1f); 733 weights.put(LocationType.IN_SMALL_NEBULA, 1f); 734 weights.put(LocationType.L_POINT, 1f); 735 WeightedRandomPicker<EntityLocation> locs = getLocations(random, system, 100f, weights); 736 737 List<AddedEntity> result = new ArrayList<AddedEntity>(); 738 for (int i = 0; i < num; i++) { 739 AddedEntity probe = addEntity(random, system, locs, Entities.DERELICT_SURVEY_PROBE, Factions.DERELICT); 740 if (probe != null) { 741 result.add(probe); 742 743 system.addTag(Tags.THEME_INTERESTING_MINOR); 744 system.addTag(Tags.THEME_DERELICT); 745 system.addTag(Tags.THEME_DERELICT_PROBES); 746 } 747 748 if (DEBUG) { 749 if (probe != null) { 750 System.out.println(String.format(" Added probe to %s", system.getNameWithLowercaseType())); 751 } else { 752 System.out.println(String.format(" Failed to add probe to %s", system.getNameWithLowercaseType())); 753 } 754 } 755 } 756 return result; 757 } 758 759 760 /** 761 * Sorted by *descending* distance from sortFrom. 762 * @param context 763 * @param sortFrom 764 * @return 765 */ 766 protected List<Constellation> getSortedAvailableConstellations(ThemeGenContext context, boolean emptyOk, final Vector2f sortFrom, List<Constellation> exclude) { 767 List<Constellation> constellations = new ArrayList<Constellation>(); 768 for (Constellation c : context.constellations) { 769 if (context.majorThemes.containsKey(c)) continue; 770 if (!emptyOk && constellationIsEmpty(c)) continue; 771 772 constellations.add(c); 773 } 774 775 if (exclude != null) { 776 constellations.removeAll(exclude); 777 } 778 779 Collections.sort(constellations, new Comparator<Constellation>() { 780 public int compare(Constellation o1, Constellation o2) { 781 float d1 = Misc.getDistance(o1.getLocation(), sortFrom); 782 float d2 = Misc.getDistance(o2.getLocation(), sortFrom); 783 return (int) Math.signum(d2 - d1); 784 } 785 }); 786 return constellations; 787 } 788 789 790 public static boolean constellationIsEmpty(Constellation c) { 791 for (StarSystemAPI s : c.getSystems()) { 792 if (!systemIsEmpty(s)) return false; 793 } 794 return true; 795 } 796 public static boolean systemIsEmpty(StarSystemAPI system) { 797 for (PlanetAPI p : system.getPlanets()) { 798 if (!p.isStar()) return false; 799 } 800 //system.getTerrainCopy().isEmpty() 801 return true; 802 } 803 804 805 806 807 808 809 810 811 812// public List<AddedEntity> generateForSystem(StarSystemAPI system, SystemGenData data) { 813// if (data == null) return new ArrayList<AddedEntity>(); 814// 815// LinkedHashMap<LocationType, Float> weights = new LinkedHashMap<LocationType, Float>(); 816// weights.put(LocationType.PLANET_ORBIT, 1f); 817// weights.put(LocationType.JUMP_ORBIT, 1f); 818// weights.put(LocationType.NEAR_STAR, 1f); 819// weights.put(LocationType.OUTER_SYSTEM, 1f); 820// weights.put(LocationType.IN_ASTEROID_BELT, 1f); 821// weights.put(LocationType.IN_RING, 1f); 822// weights.put(LocationType.IN_ASTEROID_FIELD, 1f); 823// weights.put(LocationType.STAR_ORBIT, 1f); 824// weights.put(LocationType.IN_SMALL_NEBULA, 1f); 825// weights.put(LocationType.L_POINT, 1f); 826// WeightedRandomPicker<EntityLocation> locs = getLocations(random, system, 100f, weights); 827// 828// List<AddedEntity> result = new ArrayList<AddedEntity>(); 829// for (int i = 0; i < data.numProbes; i++) { 830// AddedEntity e = addEntity(system, locs, Entities.DERELICT_SURVEY_PROBE, Factions.DERELICT); 831// if (e != null) result.add(e); 832// } 833// 834// for (int i = 0; i < data.numSurveyShips; i++) { 835// AddedEntity e = addEntity(system, locs, Entities.DERELICT_SURVEY_SHIP, Factions.DERELICT); 836// if (e != null) result.add(e); 837// } 838// 839// for (int i = 0; i < data.numMotherships; i++) { 840// AddedEntity e = addEntity(system, locs, Entities.DERELICT_MOTHERSHIP, Factions.DERELICT); 841// if (e != null) result.add(e); 842// } 843// 844// 845// return result; 846// 847// } 848 849 850 851 @Override 852 public int getOrder() { 853 return 1000; 854 } 855 856 857 858 859 860} 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876