001package com.fs.starfarer.api.impl.campaign.procgen; 002 003import java.awt.Color; 004import java.util.ArrayList; 005import java.util.List; 006 007import com.fs.starfarer.api.campaign.SectorEntityToken; 008import com.fs.starfarer.api.campaign.StarSystemAPI; 009import com.fs.starfarer.api.impl.campaign.ids.Terrain; 010import com.fs.starfarer.api.impl.campaign.procgen.StarSystemGenerator.GenContext; 011import com.fs.starfarer.api.impl.campaign.procgen.StarSystemGenerator.GenResult; 012import com.fs.starfarer.api.util.WeightedRandomPicker; 013 014public class RingGenPlugin implements TerrainGenPlugin { 015 016 public static class TexAndIndex { 017 public String tex; 018 public int index; 019 } 020 021 public static final String RING_GEN_DATA_KEY = "rgd_key"; 022 public static class RingGenData { 023 public int lastOrbitAddedAt = -1; 024 public float endOfLastRingRadius = -1; 025 public List<SectorEntityToken> lastBatch = null; 026 } 027 028 029 030 protected TexAndIndex getTexAndIndex(TerrainGenDataSpec data) { 031 TexAndIndex result = new TexAndIndex(); 032 WeightedRandomPicker<Integer> indexPicker = new WeightedRandomPicker<Integer>(StarSystemGenerator.random); 033 034 if (data.getId().equals("ring_ice")) { 035 result.tex = "rings_ice0"; 036 indexPicker.add(0); 037 indexPicker.add(1); 038 indexPicker.add(2); 039 indexPicker.add(3); 040 } else if (data.getId().equals("ring_dust")) { 041 result.tex = "rings_dust0"; 042 indexPicker.add(0); 043 indexPicker.add(1); 044 indexPicker.add(2); 045 indexPicker.add(3); 046 } else if (data.getId().equals("ring_special")) { 047 result.tex = "rings_special0"; 048 indexPicker.add(1); 049 } 050 051 result.index = indexPicker.pick(); 052 053 return result; 054 } 055 056 public RingGenData getData(GenContext context) { 057 RingGenData data = null; 058 if (context.customData.get(RING_GEN_DATA_KEY) instanceof RingGenData) { 059 data = (RingGenData) context.customData.get(RING_GEN_DATA_KEY); 060 } 061 if (data == null) { 062 data = new RingGenData(); 063 context.customData.put(RING_GEN_DATA_KEY, data); 064 } 065 return data; 066 } 067 068 069 public GenResult generate(TerrainGenDataSpec terrainData, GenContext context) { 070 StarSystemAPI system = context.system; 071 SectorEntityToken parent = context.center; 072 if (context.parent != null) parent = context.parent; 073 074 float orbitRadius = context.currentRadius; 075 076// if (context.parent != null) { 077// System.out.println("RING RADIUS " + orbitRadius + " INDEX " + context.orbitIndex); 078// } 079 080 float bandWidth = 256f; 081 082 RingGenData data = getData(context); 083 TexAndIndex tex; 084 085 Color color = StarSystemGenerator.getColor(terrainData.getMinColor(), terrainData.getMaxColor()); 086 087 List<SectorEntityToken> rings = new ArrayList<SectorEntityToken>(); 088 float totalWidth = 0f; 089 if (StarSystemGenerator.random.nextFloat() < 0.25f) { 090 // two singles, set apart a bit 091 float spacing = 175f; 092 totalWidth = bandWidth * 2f + spacing; 093 094 float orbitDays = (orbitRadius + totalWidth / 2f) / (15f + 5f * StarSystemGenerator.random.nextFloat()); 095 tex = getTexAndIndex(terrainData); 096 rings.add(system.addRingBand(parent, "misc", tex.tex, 256f, tex.index, color, bandWidth, 097 orbitRadius + bandWidth / 2f, orbitDays, Terrain.RING, null)); 098 099 orbitDays = (orbitRadius + bandWidth / 2f + spacing + bandWidth / 2f) / (15f + 5f * StarSystemGenerator.random.nextFloat()); 100 tex = getTexAndIndex(terrainData); 101 rings.add(system.addRingBand(parent, "misc", tex.tex, 256f, tex.index, color, bandWidth, 102 orbitRadius + bandWidth / 2f + spacing + bandWidth / 2f, orbitDays * 1.2f, Terrain.RING, null)); 103 } else { 104 float numBands = 1; 105 //float pExtraBand = 0.5f; 106 if (orbitRadius > 2000f && StarSystemGenerator.random.nextFloat() > 0.5f) numBands++; 107 if (orbitRadius > 4000f && StarSystemGenerator.random.nextFloat() > 0.5f) numBands++; 108 if (orbitRadius > 6000f && StarSystemGenerator.random.nextFloat() > 0.5f) numBands++; 109 110 //numBands = 3; 111 112 float startingRadius = orbitRadius + bandWidth/2f; 113 float spacing = bandWidth * 0.5f; 114 for (float i = 0; i < numBands; i++) { 115 float currentRadius = startingRadius + i * spacing; 116 float orbitDays = (currentRadius) / (15f + 5f * StarSystemGenerator.random.nextFloat()); 117 tex = getTexAndIndex(terrainData); 118 if (StarSystemGenerator.random.nextFloat() > 0.5f) { 119 if (StarSystemGenerator.random.nextFloat() > 0.5f) { 120 tex = getTexAndIndex(terrainData); 121 } 122 rings.add(system.addRingBand(parent, "misc", tex.tex, 256f, tex.index, color, bandWidth, 123 currentRadius, orbitDays * 1.2f, Terrain.RING, null)); 124 125 if (StarSystemGenerator.random.nextFloat() > 0.5f) { 126 if (StarSystemGenerator.random.nextFloat() > 0.5f) { 127 tex = getTexAndIndex(terrainData); 128 } 129 rings.add(system.addRingBand(parent, "misc", tex.tex, 256f, tex.index, color, bandWidth, 130 currentRadius, orbitDays * 1.4f, Terrain.RING, null)); 131 } 132 } 133 } 134 totalWidth = (numBands - 1f) * spacing + bandWidth; 135 } 136 137 138 if (context.orbitIndex > 0 && data.lastOrbitAddedAt == context.orbitIndex - 1) { 139 float spacing = bandWidth * 0.5f; 140 for (float currRadius = data.endOfLastRingRadius; currRadius <= orbitRadius; currRadius += spacing) { 141 float orbitDays = currRadius / (15f + 5f * StarSystemGenerator.random.nextFloat()); 142 tex = getTexAndIndex(terrainData); 143 rings.add(system.addRingBand(parent, "misc", tex.tex, 256f, tex.index, color, bandWidth, 144 currRadius, orbitDays, Terrain.RING, null)); 145 } 146 147 if (data.lastBatch != null) { 148 rings.addAll(data.lastBatch); 149 // will be re-added after this method returns, pointing to the full set of rings 150 // as being part of one nameable entity 151 for (SectorEntityToken ring : rings) { 152 context.gen.getAllEntitiesAdded().remove(ring); 153 } 154 } 155 } 156 157 data.lastOrbitAddedAt = context.orbitIndex; 158 data.endOfLastRingRadius = orbitRadius + bandWidth; 159 data.lastBatch = new ArrayList<SectorEntityToken>(rings); 160 161 162 GenResult result = new GenResult(); 163 result.onlyIncrementByWidth = false; 164 result.orbitalWidth = totalWidth; 165 result.entities.addAll(rings); 166 return result; 167 } 168 169 public boolean wantsToHandle(TerrainGenDataSpec terrainData, GenContext context) { 170 return terrainData != null && 171 (terrainData.getId().equals("ring_ice") || 172 terrainData.getId().equals("ring_dust") || 173 terrainData.getId().equals("ring_special")); 174 } 175 176}