001package com.fs.starfarer.api.impl.campaign.procgen; 002 003import java.util.ArrayList; 004import java.util.Collections; 005import java.util.Comparator; 006import java.util.List; 007 008import org.lwjgl.util.vector.Vector2f; 009 010import com.fs.starfarer.api.Global; 011import com.fs.starfarer.api.campaign.CampaignTerrainAPI; 012import com.fs.starfarer.api.campaign.CampaignTerrainPlugin; 013import com.fs.starfarer.api.campaign.JumpPointAPI; 014import com.fs.starfarer.api.campaign.PlanetAPI; 015import com.fs.starfarer.api.campaign.SectorEntityToken; 016import com.fs.starfarer.api.campaign.StarSystemAPI; 017import com.fs.starfarer.api.campaign.JumpPointAPI.JumpDestination; 018import com.fs.starfarer.api.impl.campaign.procgen.Constellation.ConstellationType; 019import com.fs.starfarer.api.impl.campaign.procgen.ProcgenUsedNames.NamePick; 020import com.fs.starfarer.api.impl.campaign.procgen.StarSystemGenerator.LagrangePointType; 021import com.fs.starfarer.api.impl.campaign.procgen.StarSystemGenerator.StarSystemType; 022import com.fs.starfarer.api.impl.campaign.terrain.AsteroidBeltTerrainPlugin; 023import com.fs.starfarer.api.impl.campaign.terrain.AsteroidFieldTerrainPlugin; 024import com.fs.starfarer.api.impl.campaign.terrain.MagneticFieldTerrainPlugin; 025import com.fs.starfarer.api.impl.campaign.terrain.NebulaTerrainPlugin; 026import com.fs.starfarer.api.impl.campaign.terrain.RingSystemTerrainPlugin; 027import com.fs.starfarer.api.util.Misc; 028 029public class NameAssigner { 030 031 public static class NamingTreeNode { 032 public NamingTreeNode parent; 033 public LagrangePointType lagrangePointType = null; 034 public NamePick name; 035 public SectorEntityToken entity; 036 public List<NamingTreeNode> children = new ArrayList<NamingTreeNode>(); 037 public StarSystemAPI system; 038 public NamingTreeNode(StarSystemAPI system) { 039 this.system = system; 040 } 041 042 public boolean isPrimaryStar() { 043 return entity == system.getStar(); 044 } 045 public boolean isSecondaryStar() { 046 return entity == system.getSecondary(); 047 } 048 public boolean isTertiaryStar() { 049 return entity == system.getTertiary(); 050 } 051 public boolean isMoon() { 052 return !isTerrain() && parent != null && 053 parent.entity instanceof PlanetAPI && 054 !((PlanetAPI)parent.entity).isStar(); 055 } 056 public boolean isTerrain() { 057 return entity instanceof CampaignTerrainAPI; 058 } 059 } 060 061 private Constellation constellation; 062 private NamePick constellationName; 063 private NamingTreeNode root; 064 065 private float specialNamesProbability = 0.5f; 066 private boolean renameSystem = true; 067 private int structuralNameOffset = 0; 068 069 public NameAssigner(Constellation constellation) { 070 this.constellation = constellation; 071 } 072 073 public void setSpecialNamesProbability(float specialNamesProbability) { 074 this.specialNamesProbability = specialNamesProbability; 075 } 076 077 public void setRenameSystem(boolean renameStar) { 078 this.renameSystem = renameStar; 079 } 080 081 public void setStructuralNameOffset(int structuralNameOffset) { 082 this.structuralNameOffset = structuralNameOffset; 083 } 084 085 public void assignNames(String name, String secondary) { 086 if (constellation.getSystems().isEmpty()) return; 087 088 if (name == null) { 089 constellationName = ProcgenUsedNames.pickName(NameGenData.TAG_CONSTELLATION, null, null); 090 } else { 091 NameGenData data = (NameGenData) Global.getSettings().getSpec(NameGenData.class, name, true); 092 if (data == null) { 093 data = new NameGenData(name, null); 094 } else { 095 ProcgenUsedNames.notifyUsed(name); 096 } 097 constellationName = new NamePick(data, name, secondary); 098 } 099 if (!constellationName.spec.isReusable() && !constellation.isLeavePickedNameUnused()) { 100 ProcgenUsedNames.notifyUsed(constellationName.nameWithRomanSuffixIfAny); 101 } 102 Global.getSettings().greekLetterReset(); 103 104 constellation.setNamePick(constellationName); 105 106 Collections.sort(constellation.getSystems(), new Comparator<StarSystemAPI>() { 107 public int compare(StarSystemAPI o1, StarSystemAPI o2) { 108 if (o1.getStar() == null || o2.getStar() != null) return 1; 109 if (o1.getStar() != null || o2.getStar() == null) return -1; 110 return (int) Math.signum(o1.getStar().getRadius() - o2.getStar().getRadius()); 111 } 112 }); 113 114 115 for (StarSystemAPI system : constellation.getSystems()) { 116 String base = constellationName.nameWithRomanSuffixIfAny; 117 if (constellationName.secondaryWithRomanSuffixIfAny != null) { 118 base = constellationName.secondaryWithRomanSuffixIfAny; 119 } 120 String n = Global.getSettings().getNextGreekLetter(constellationName) + " " + base; 121 122 computeNamingTree(system); 123 assignStructuralNames(system, n); 124 if (StarSystemGenerator.random.nextFloat() < specialNamesProbability || (constellation.systems.size() <= 1 && specialNamesProbability > 0)) { 125 assignSpecialNames(root); 126 } 127 128 updateJumpPointDestinationNames(system); 129 } 130// String tag = NameGenData.TAG_PLANET; 131// if (isMoon) tag = NameGenData.TAG_MOON; 132// NamePick namePick = ProcgenUsedNames.pickName(tag, null); 133 } 134 135 136 public void assignSpecialNames(NamingTreeNode curr) { 137 String tag = null; 138 CampaignTerrainPlugin plugin = null; 139 if (curr.entity != null) { 140 if (curr.isTerrain()) { 141 CampaignTerrainAPI terrain = (CampaignTerrainAPI) curr.entity; 142 plugin = terrain.getPlugin(); 143 if (plugin instanceof AsteroidFieldTerrainPlugin) { 144 tag = NameGenData.TAG_ASTEROID_FIELD; 145 } else if (plugin instanceof AsteroidBeltTerrainPlugin) { 146 tag = NameGenData.TAG_ASTEROID_BELT; 147 } else if (plugin instanceof RingSystemTerrainPlugin) { 148 RingSystemTerrainPlugin ringPlugin = (RingSystemTerrainPlugin) plugin; 149 if (ringPlugin.getNameForTooltip() != null && ringPlugin.getNameForTooltip().contains("Accretion")) { 150 tag = NameGenData.TAG_ACCRETION; 151 } 152 } else if (plugin instanceof NebulaTerrainPlugin) { 153 tag = NameGenData.TAG_NEBULA; 154 } else if (plugin instanceof MagneticFieldTerrainPlugin) { 155 tag = NameGenData.TAG_MAGNETIC_FIELD; 156 } 157 } else if (curr.isMoon()) { 158 tag = NameGenData.TAG_MOON; 159 } else if (curr.isPrimaryStar() || curr.isSecondaryStar() || curr.isTertiaryStar()) { 160 tag = NameGenData.TAG_STAR; 161 } else if (curr.entity instanceof PlanetAPI) { 162 tag = NameGenData.TAG_PLANET; 163 } 164 } 165 166 if (tag != null) { 167 String parent = null; 168 if (curr.parent != null && curr.parent.name != null) { 169 parent = curr.parent.name.spec.getName(); 170 } 171 if (curr == root) { 172 parent = constellationName.spec.getName(); 173 } 174 175 176 boolean noRename = curr.system.getStar() == curr.entity && !renameSystem; 177 NamePick pick = ProcgenUsedNames.pickName(tag, parent, curr.lagrangePointType); 178 if (!pick.spec.isReusable() && !noRename) { 179 ProcgenUsedNames.notifyUsed(pick.nameWithRomanSuffixIfAny); 180 } 181 182 if (pick != null) { 183 if (noRename) { 184 String name = curr.system.getBaseName(); 185 NameGenData data = (NameGenData) Global.getSettings().getSpec(NameGenData.class, name, true); 186 if (data == null) { 187 data = new NameGenData(name, null); 188 } else { 189 ProcgenUsedNames.notifyUsed(name); 190 } 191 curr.name = new NamePick(data, name, null); 192 } else { 193 curr.name = pick; 194 String name = pick.nameWithRomanSuffixIfAny; 195 List<SectorEntityToken> all = constellation.allEntitiesAdded.get(curr.entity); 196 for (SectorEntityToken entity : all) { 197 // if (tag != null && tag.equals(NameGenData.TAG_RING) && pick.spec.isReusable()) { 198 // if (entity instanceof CampaignTerrainAPI) { 199 // ((CampaignTerrainAPI) entity).getPlugin().setTerrainName(name); 200 // } 201 // } 202 entity.setName(name); 203 if (entity.getMarket() != null) entity.getMarket().setName(name); 204 updateJumpPointNameFor(entity); 205 if (entity instanceof CampaignTerrainAPI) { 206 ((CampaignTerrainAPI) entity).getPlugin().setTerrainName(name); 207 } 208 } 209 if (curr.system.getStar() == curr.entity) { 210 curr.system.setBaseName(name); 211 } 212 } 213 } 214 } 215 216 for (NamingTreeNode node : curr.children) { 217 assignSpecialNames(node); 218 } 219 220 } 221 222 223 public void assignStructuralNames(StarSystemAPI system, String name) { 224// if (system.getSecondary() != null) { 225// System.out.println("wefwefe"); 226// } 227 if (renameSystem) { 228 system.setBaseName(name); 229 if (system.getStar() != null) { 230 system.getStar().setName(name); 231 updateJumpPointNameFor(system.getStar()); 232 } 233 } else { 234 name = system.getBaseName(); 235 } 236 237 int i = structuralNameOffset; 238 for (NamingTreeNode node : root.children) { 239// if (node.entity instanceof PlanetAPI && ((PlanetAPI)node.entity).isStar()) { 240// System.out.println("wefwefwefwe"); 241// } 242 assignSNamesHelper(node, name, i); 243 244 if (node.entity instanceof PlanetAPI) { 245 PlanetAPI planet = (PlanetAPI) node.entity; 246 if (!planet.isStar()) { 247 i++; 248 } 249 } 250 } 251 } 252 253 public void assignSNamesHelper(NamingTreeNode curr, String parentName, int index) { 254 if (parentName == null) return; 255 256 String name = parentName; 257 258 if (curr.entity != null) { 259 CampaignTerrainAPI terrain = null; 260 CampaignTerrainPlugin plugin = null; 261 if (curr.entity instanceof CampaignTerrainAPI) { 262 terrain = (CampaignTerrainAPI) curr.entity; 263 plugin = terrain.getPlugin(); 264 } 265 boolean rename = true; 266 if (curr.isSecondaryStar()) { 267 name += " B"; 268 } else if (curr.isTertiaryStar()) { 269 name += " C"; 270 } else { 271 String [] moonPostfixes = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N"}; 272 if (curr.isTerrain()) { 273 if (curr.lagrangePointType != null) { 274 name += " " + curr.lagrangePointType.name(); 275 if (plugin instanceof AsteroidFieldTerrainPlugin) { 276 name += " Asteroid Field"; 277 } else if (plugin instanceof NebulaTerrainPlugin) { 278 name += " Nebula"; 279 } 280 } else { 281 rename = false; 282 } 283 } else if (curr.isMoon()) { 284 if (curr.lagrangePointType != null) { 285 name += "-" + curr.lagrangePointType.name(); 286 } else { 287 name += "-" + moonPostfixes[index]; 288 } 289 } else { 290 name += " " + Global.getSettings().getRoman(index + 1); 291 } 292 } 293 294 if (rename) { 295// curr.entity.setName(name); 296// if (plugin != null) { 297// plugin.setTerrainName(name); 298// } 299 List<SectorEntityToken> all = constellation.allEntitiesAdded.get(curr.entity); 300 for (SectorEntityToken entity : all) { 301 entity.setName(name); 302 if (entity.getMarket() != null) entity.getMarket().setName(name); 303 updateJumpPointNameFor(entity); 304 if (entity instanceof CampaignTerrainAPI) { 305 ((CampaignTerrainAPI) entity).getPlugin().setTerrainName(name); 306 } 307 } 308 } 309 } 310 311 int i = 0; 312 for (NamingTreeNode node : curr.children) { 313 assignSNamesHelper(node, name, i); 314 315 if (node.entity instanceof PlanetAPI) { 316 PlanetAPI planet = (PlanetAPI) node.entity; 317 if (!planet.isStar()) { 318 i++; 319 } 320 } 321 } 322 } 323 324 public void updateJumpPointNameFor(SectorEntityToken entity) { 325 if (!(entity instanceof PlanetAPI)) return; 326 if (!(entity.getContainingLocation() instanceof StarSystemAPI)) return; 327 328 StarSystemAPI system = (StarSystemAPI) entity.getContainingLocation(); 329 330 for (JumpPointAPI point : system.getAutogeneratedJumpPointsInHyper()) { 331 if (point.getDestinationVisualEntity() == entity) { 332 PlanetAPI planet = (PlanetAPI) entity; 333 String name = null; 334 if (planet.isGasGiant()) { 335 name = planet.getName() + " Gravity Well"; 336 } else if (planet.isStar()) { 337 name = planet.getName() + ", " + planet.getSpec().getName(); 338 } 339 if (name != null) { 340 point.setName(name); 341 } 342 343// for (JumpDestination dest : point.getDestinations()) { 344// dest.setLabelInInteractionDialog(system.getBaseName()); 345// } 346 347 break; 348 } 349 } 350 } 351 352 public void updateJumpPointDestinationNames(StarSystemAPI system) { 353 for (JumpPointAPI point : system.getAutogeneratedJumpPointsInHyper()) { 354 for (JumpDestination dest : point.getDestinations()) { 355 //dest.setLabelInInteractionDialog(system.getBaseName()); 356// String name = "the " + system.getName(); 357// name = name.replaceAll("Star System", "star system"); 358// name = name.replaceAll("Nebula", "nebula"); 359 String name = "the " + system.getNameWithLowercaseType(); 360 dest.setLabelInInteractionDialog(name); 361 } 362 } 363 } 364 365 366 367 368 public void computeNamingTree(StarSystemAPI system) { 369 root = new NamingTreeNode(system); 370 if (system.getStar() != null && system.getType() != StarSystemType.NEBULA) { 371 root.entity = system.getStar(); 372 } 373 374 for (PlanetAPI planet : system.getPlanets()) { 375 if (!planet.isStar()) continue; 376 if (planet == system.getStar()) continue; 377 if (!constellation.allEntitiesAdded.containsKey(planet)) continue; 378 379 NamingTreeNode node = new NamingTreeNode(system); 380 node.entity = planet; 381 node.parent = root; 382 root.children.add(node); 383 } 384 385 addChildren(system, root); 386 for (NamingTreeNode node : root.children) { 387 addChildren(system, node); 388 } 389 } 390 391 public void addChildren(StarSystemAPI system, NamingTreeNode curr) { 392 OUTER: for (PlanetAPI planet : system.getPlanets()) { 393 if (planet.isStar()) continue; 394 if (planet == curr.entity) continue; 395 if (!constellation.allEntitiesAdded.containsKey(planet)) continue; 396 for (NamingTreeNode n : curr.children) { 397 if (n.entity == planet) continue OUTER; 398 } 399 400 PlanetAPI lagrangeParent = constellation.lagrangeParentMap.get(planet); 401 boolean mainStarAndOrbitingSystemCenter = curr.entity == curr.system.getStar() && 402 planet.getOrbitFocus() == curr.system.getCenter() && 403 lagrangeParent == null; 404 405 if (mainStarAndOrbitingSystemCenter || 406 (planet.getOrbitFocus() == curr.entity && lagrangeParent == null) || 407 lagrangeParent == curr.entity) { 408 NamingTreeNode node = new NamingTreeNode(system); 409 node.entity = planet; 410 node.parent = curr; 411 curr.children.add(node); 412 413 if (lagrangeParent != null && planet.getOrbitFocus() != null) { 414 //float angle1 = planet.getOrbitFocus().getCircularOrbitAngle(); 415 float angle1 = lagrangeParent.getCircularOrbitAngle(); 416 float angle2 = planet.getCircularOrbitAngle(); 417 418 if (Misc.getClosestTurnDirection(angle1, angle2) < 0) { 419 node.lagrangePointType = LagrangePointType.L4; 420 } else { 421 node.lagrangePointType = LagrangePointType.L5; 422 } 423 } 424 425 addChildren(system, node); 426 } 427 } 428 429 OUTER: for (CampaignTerrainAPI terrain : system.getTerrainCopy()) { 430 if (terrain == curr.entity) continue; 431 if (!constellation.allEntitiesAdded.containsKey(terrain)) continue; 432 for (NamingTreeNode n : curr.children) { 433 if (n.entity == terrain) continue OUTER; 434 } 435 436 PlanetAPI lagrangeParent = constellation.lagrangeParentMap.get(terrain); 437 boolean mainStarAndOrbitingSystemCenter = curr.entity == curr.system.getStar() && 438 terrain.getOrbitFocus() == curr.system.getCenter() && 439 lagrangeParent == null; 440 if (mainStarAndOrbitingSystemCenter || 441 (terrain.getOrbitFocus() == curr.entity && lagrangeParent == null) || 442 lagrangeParent == curr.entity) { 443 NamingTreeNode node = new NamingTreeNode(system); 444 node.entity = terrain; 445 node.parent = curr; 446 curr.children.add(node); 447 448 if (lagrangeParent != null && terrain.getOrbitFocus() != null) { 449 //float angle1 = terrain.getOrbitFocus().getCircularOrbitAngle(); 450 float angle1 = lagrangeParent.getCircularOrbitAngle(); 451 float angle2 = terrain.getCircularOrbitAngle(); 452 453 if (Misc.getClosestTurnDirection(angle1, angle2) < 0) { 454 node.lagrangePointType = LagrangePointType.L4; 455 } else { 456 node.lagrangePointType = LagrangePointType.L5; 457 } 458 } 459 460 addChildren(system, node); 461 } 462 } 463 464 Collections.sort(curr.children, new Comparator<NamingTreeNode>() { 465 public int compare(NamingTreeNode o1, NamingTreeNode o2) { 466 Vector2f from = new Vector2f(); 467 if (o1.parent != null && o1.parent.entity != null) { 468 from = o1.parent.entity.getLocation(); 469 if (o1.parent == o1.system.getStar()) { 470 from = o1.system.getCenter().getLocation(); 471 } 472 } 473 float d1 = Misc.getDistance(from, o1.entity.getLocation()); 474 float d2 = Misc.getDistance(from, o2.entity.getLocation()); 475 return (int) Math.signum(d1 - d2); 476 } 477 }); 478 } 479 480 481 //public static boolean isNameSpecial(String name, StarSystemAPI system) { 482 public static boolean isNameSpecial(StarSystemAPI system) { 483 if (system.getConstellation() == null) return true; 484 485 String name = system.getBaseName(); 486 487 NamePick constellationName = system.getConstellation().getNamePick(); 488 String base = constellationName.nameWithRomanSuffixIfAny; 489 if (constellationName.secondaryWithRomanSuffixIfAny != null) { 490 base = constellationName.secondaryWithRomanSuffixIfAny; 491 } 492 if (name.toLowerCase().contains(base.toLowerCase())) { 493 return false; 494 } 495 return true; 496 } 497 498 499 public static void assignSpecialNames(StarSystemAPI system) { 500 Constellation actual = system.getConstellation(); 501 if (actual == null || actual.getNamePick() == null) return; 502 503// if (system.getName().toLowerCase().contains("alpha cirrus")) { 504// System.out.println("fwefwefwefe"); 505// } 506 507 Constellation c = new Constellation(ConstellationType.NORMAL, actual.getAge()); 508 //c.setNamePick(actual.getNamePick()); 509 c.getSystems().add(system); 510 c.setLagrangeParentMap(actual.getLagrangeParentMap()); 511 c.setAllEntitiesAdded(actual.getAllEntitiesAdded()); 512 c.setLeavePickedNameUnused(true); 513 514 NameAssigner namer = new NameAssigner(c); 515 namer.setSpecialNamesProbability(1f); 516 517 //namer.setRenameSystem(false); 518 //namer.setStructuralNameOffset(nameOffset); 519 namer.assignNames(actual.getNamePick().spec.getName(), actual.getNamePick().spec.getSecondary()); 520 } 521} 522 523 524 525 526 527 528 529