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>();
66 public SectorEntityToken key;
67 public int particlesPerPoint;
69 public Stream(SectorEntityToken key,
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>();
140 protected TimeoutTracker<SectorEntityToken>
disrupted =
new TimeoutTracker<SectorEntityToken>();
148 super.advance(amount);
157 for (CampaignFleetAPI fleet :
entity.getContainingLocation().getFleets()) {
161 float burnLevel = fleet.getCurrBurnLevel();
162 if (burnLevel >= 1) {
164 Vector2f loc = fleet.getLocation();
165 boolean addPoint =
false;
169 StreamPoint last = s.getLastPoint();
170 float dist = Misc.getDistance(loc.x, loc.y, last.x, last.y);
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);
202 public void disrupt(CampaignFleetAPI fleet,
float dur) {
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);
229 if (
entity instanceof CampaignFleetAPI) {
230 CampaignFleetAPI fleet = (CampaignFleetAPI)
entity;
231 containsPointCaching(fleet, fleet.getLocation(), fleet.getRadius());
234 float fleetBurn = fleet.getFleetData().getBurnLevel();
235 if (point.burn > fleetBurn ||
true) {
236 float diff = point.burn - fleetBurn;
237 if (diff > 2) diff = 2;
240 fleet.getStats().addTemporaryModFlat(0.1f,
getModId(),
"In slipstream", diff, fleet.getStats().getFleetwideMaxBurnMod());
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) {
276 float dist = Misc.getDistance(p.x, p.y, point.x, point.y);
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;
327 Color gray = Misc.getGrayColor();
328 Color highlight = Misc.getHighlightColor();
330 Color bad = Misc.getNegativeHighlightColor();
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);