1package com.fs.starfarer.api.impl.campaign.terrain;
4import java.util.ArrayList;
5import java.util.EnumSet;
6import java.util.HashMap;
7import java.util.Iterator;
8import java.util.LinkedHashMap;
12import org.lwjgl.util.vector.Vector2f;
14import com.fs.starfarer.api.Global;
15import com.fs.starfarer.api.campaign.CampaignEngineLayers;
16import com.fs.starfarer.api.campaign.CampaignFleetAPI;
17import com.fs.starfarer.api.campaign.CampaignTerrainAPI;
18import com.fs.starfarer.api.campaign.LocationAPI;
19import com.fs.starfarer.api.campaign.SectorEntityToken;
20import com.fs.starfarer.api.combat.ViewportAPI;
21import com.fs.starfarer.api.ui.TooltipMakerAPI;
22import com.fs.starfarer.api.util.Misc;
23import com.fs.starfarer.api.util.TimeoutTracker;
36 if (location ==
null)
return null;
42 if (slipstream !=
null) {
48 public static class StreamPoint {
50 public float daysLeft;
53 public StreamPoint(
float x,
float y,
float daysLeft,
float burn,
float width) {
56 this.daysLeft = daysLeft;
62 public static class Stream {
63 transient public float minX, minY, maxX, maxY;
64 public List<StreamPoint> points =
new ArrayList<StreamPoint>();
67 public int particlesPerPoint;
71 this.particlesPerPoint = particlesPerPoint;
75 Object readResolve() {
76 minX = Float.MAX_VALUE;
77 minY = Float.MAX_VALUE;
78 maxX = -Float.MAX_VALUE;
79 maxY = -Float.MAX_VALUE;
80 for (StreamPoint p : points) {
86 public boolean isEmpty() {
87 return points.isEmpty();
90 public StreamPoint getLastPoint() {
91 if (isEmpty())
return null;
92 return points.get(points.size() - 1);
95 public StreamPoint getFirstPoint() {
96 if (isEmpty())
return null;
100 private void updateMinMax(StreamPoint p) {
101 if (p.x < minX) minX = p.x;
102 if (p.y < minY) minY = p.y;
103 if (p.x > maxX) maxX = p.x;
104 if (p.y > maxY) maxY = p.y;
107 public void addPoint(StreamPoint p) {
112 public boolean isNearViewport(ViewportAPI v,
float pad) {
113 float x = v.getLLX();
114 float y = v.getLLY();
115 float w = v.getVisibleWidth();
116 float h = v.getVisibleHeight();
118 if (minX > x + w + pad)
return false;
119 if (minY > y + h + pad)
return false;
120 if (maxX < x - pad)
return false;
121 if (maxY < y - pad)
return false;
126 public boolean couldContainLocation(Vector2f loc,
float radius) {
127 if (minX > loc.x + radius)
return false;
128 if (minY > loc.y + radius)
return false;
129 if (maxX < loc.x - radius)
return false;
130 if (maxY < loc.y - radius)
return false;
136 protected Map<SectorEntityToken, Stream>
streams =
new LinkedHashMap<SectorEntityToken, Stream>();
137 transient protected Map<SectorEntityToken, StreamPoint>
containsCache =
new HashMap<SectorEntityToken, StreamPoint>();
148 super.advance(amount);
161 float burnLevel = fleet.getCurrBurnLevel();
162 if (burnLevel >= 1) {
164 Vector2f loc = fleet.getLocation();
165 boolean addPoint =
false;
169 StreamPoint last = s.getLastPoint();
176 StreamPoint p =
new StreamPoint(loc.x, loc.y, 0.25f,
184 Iterator<Stream> iter1 =
streams.values().iterator();
185 while (iter1.hasNext()) {
186 Stream s = iter1.next();
188 advancePoints(s, days);
206 private void advancePoints(Stream s,
float days) {
207 Iterator<StreamPoint> iter2 = s.points.iterator();
208 while (iter2.hasNext()) {
209 StreamPoint p = iter2.next();
212 if (p.daysLeft <= 0) {
221 s =
new Stream(key, 50);
235 if (point.burn > fleetBurn ||
true) {
236 float diff = point.burn - fleetBurn;
237 if (diff > 2) diff = 2;
253 return containsPointCaching(
null, point, radius);
256 private boolean containsPointCaching(
SectorEntityToken key, Vector2f point,
float radius) {
260 if (
true)
return false;
263 StreamPoint result =
null;
264 for (Stream s :
streams.values()) {
265 if (s.key == key)
continue;
267 if (!s.couldContainLocation(point, radius))
continue;
268 for (StreamPoint p : s.points) {
277 if (dist < p.width && maxBurn < p.burn) {
284 if (result !=
null && key !=
null) {
288 return result !=
null;
293 Object readResolve() {
294 layers = EnumSet.of(CampaignEngineLayers.TERRAIN_7);
297 containsCache =
new HashMap<SectorEntityToken, StreamPoint>();
302 Object writeReplace() {
306 transient private EnumSet<CampaignEngineLayers> layers = EnumSet.of(CampaignEngineLayers.TERRAIN_7);
313 return super.stacksWithSelf();
318 return Float.MAX_VALUE;
333 tooltip.
addPara(
"Reduces the range at which fleets inside it can be detected by %s.", pad,
337 tooltip.
addPara(
"Does not stack with other similar terrain effects.", pad);
static SettingsAPI getSettings()
static SectorAPI getSector()
boolean isPreventedFromAffecting(SectorEntityToken other)
TimeoutTracker< SectorEntityToken > disrupted
Map< SectorEntityToken, Stream > streams
static SlipstreamTerrainPlugin getSlipstreamPlugin(LocationAPI location)
boolean isTooltipExpandable()
String getNameForTooltip()
EnumSet< CampaignEngineLayers > getActiveLayers()
boolean containsEntity(SectorEntityToken other)
transient Map< SectorEntityToken, StreamPoint > containsCache
void init(String terrainId, SectorEntityToken entity, Object param)
void createTooltip(TooltipMakerAPI tooltip, boolean expanded)
TimeoutTracker< SectorEntityToken > getDisrupted()
void disrupt(CampaignFleetAPI fleet, float dur)
Stream getStream(SectorEntityToken key)
boolean containsPoint(Vector2f point, float radius)
static final float WIDTH_GROWTH_PER_DAY
void applyEffect(SectorEntityToken entity, float days)
String getEffectCategory()
void advance(float amount)
static CampaignTerrainAPI getSlipstream(LocationAPI location)
static final String LOCATION_SLIPSTREAM_KEY
static final float MAX_POINT_DIST
static final float MIN_POINT_DIST
static Color getNegativeHighlightColor()
static Color getGrayColor()
static float getDistance(SectorEntityToken from, SectorEntityToken to)
static Color getHighlightColor()
Color getColor(String id)
float convertToDays(float realSeconds)
FleetDataAPI getFleetData()
MutableFleetStatsAPI getStats()
CampaignTerrainPlugin getPlugin()
Map< String, Object > getPersistentData()
List< CampaignFleetAPI > getFleets()
CampaignClockAPI getClock()
LocationAPI getContainingLocation()
StatBonus getFleetwideMaxBurnMod()
void addTemporaryModFlat(float durInDays, String source, float value, StatBonus stat)