89 if (!
entity.isInCurrentLocation())
return;
93 fader.advance(amount);
96 entity.getLocation().x += Misc.getSpeedForBurnLevel(
params.burnLevel) * amount;
102 params.minColor =
new Color(0.5f, 0.3f, 0.75f, 0.85f);
103 params.maxColor =
new Color(0.5f, 0.6f, 1f, 1f);
104 params.spriteColor1 =
new Color(0.3f, 0.5f, 1f, 0.67f);
107 params.minSpeed = 700f;
108 params.maxSpeed = 1500f;
109 params.minSpeed = Misc.getSpeedForBurnLevel(25f);
110 params.maxSpeed = Misc.getSpeedForBurnLevel(35f);
111 params.maxSpeedForTex = Misc.getSpeedForBurnLevel(15f);
112 params.lineLengthFractionOfSpeed = 0.25f;
116 params.burnLevel = 30;
117 params.numParticles = 1000;
119 params.length = 10000f;
120 params.minColor =
new Color(0.5f, 0.3f, 0.75f, 0.1f);
121 params.maxColor =
new Color(0.5f, 0.6f, 1f, 0.5f);
132 Vector2f dir = Misc.getUnitVectorAtDegreeAngle(
entity.getFacing());
138 float x =
entity.getLocation().x;
139 float y =
entity.getLocation().y;
146 SlipstreamParticle p =
new SlipstreamParticle();
147 float fLength = (float) Math.random() * 0.8f;
148 float sign = Math.signum((
float) Math.random() - 0.5f);
150 float r = (float) Math.random() * 0.7f;
151 float fWidth = 0.5f + sign * (1f - (float)Math.sqrt(r)) * fLength * 0.5f;
153 fWidth = 0.5f + sign * r * (0.5f + 0.5f * fLength) * 0.5f;
154 fWidth = (float) Math.random() * 0.8f + 0.1f;
157 float speed = params.minSpeed + (params.maxSpeed -
params.minSpeed) * (
float) Math.random();
159 float dur = params.minDur + (params.maxDur -
params.minDur) * (
float) Math.random();
161 float minDistFromSource = speed * dur * 0.25f;
162 p.loc.set(-fLength * (
params.length - minDistFromSource) - minDistFromSource,
163 fWidth * params.width - params.width / 2f);
169 float angleToEntity = Misc.getAngleInDegrees(p.loc,
entity.getLocation());
170 float turnDir = Misc.getClosestTurnDirection(
entity.getFacing(), angleToEntity);
171 float diff = Math.min(30f, Misc.getAngleDiff(angleToEntity,
entity.getFacing()) * 0.5f);
174 p.vel.set(Misc.getUnitVectorAtDegreeAngle(
entity.getFacing() + turnDir * diff));
183 Iterator<SlipstreamParticle> iter =
particles.iterator();
184 while (iter.hasNext()) {
185 SlipstreamParticle p = iter.next();
186 p.remaining -= amount;
188 if (p.remaining <= 0) {
193 boolean shouldFadeOut =
false;
194 Vector2f toEntity = Vector2f.sub(
entity.getLocation(), p.loc,
new Vector2f());
195 shouldFadeOut = Vector2f.dot(toEntity, p.vel) < 0f;
197 if (p.elapsed > 1f) {
198 p.remaining = Math.min(p.remaining, 0.5f);
202 p.loc.x += p.vel.x * amount;
203 p.loc.y += p.vel.y * amount;
208 float texSpeed = Misc.getSpeedForBurnLevel(
params.burnLevel);
212 float unitsPerOneTexIter = sprite.getWidth();
213 float texUnitsPerSecondForSpeed = texSpeed / unitsPerOneTexIter *
texelsPerPixel;
215 texProgress2 += texUnitsPerSecondForSpeed * amount * 1.9f;
216 texProgress3 += texUnitsPerSecondForSpeed * amount * 0.7f;
219 public void render(CampaignEngineLayers layer, ViewportAPI viewport) {
223 sprite.setNormalBlend();
224 sprite.setColor(
params.spriteColor1);
233 GL11.glDisable(GL11.GL_TEXTURE_2D);
234 GL11.glEnable(GL11.GL_BLEND);
235 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
241 GL11.glLineWidth(Math.max(1f, Math.min(2f, 2f/zoom)));
243 GL11.glEnable(GL11.GL_LINE_SMOOTH);
244 GL11.glBegin(GL11.GL_LINES);
247 if (!viewport.isNearViewport(p.loc, 500))
continue;
248 float a = viewport.getAlphaMult();
249 if (p.remaining <= 0.5f) {
250 a = p.remaining / 0.5f;
251 }
else if (p.elapsed < 1f) {
258 Vector2f start =
new Vector2f(p.loc);
259 Vector2f end =
new Vector2f(p.loc);
260 start.x += p.vel.x * params.lineLengthFractionOfSpeed * 0.1f;
261 start.y += p.vel.y * params.lineLengthFractionOfSpeed * 0.1f;
262 end.x -= p.vel.x * params.lineLengthFractionOfSpeed * 0.9f;
263 end.y -= p.vel.y * params.lineLengthFractionOfSpeed * 0.9f;
265 Misc.setColor(p.color, 0f);
266 GL11.glVertex2f(start.x, start.y);
267 Misc.setColor(p.color, a);
268 GL11.glVertex2f(p.loc.x, p.loc.y);
269 GL11.glVertex2f(p.loc.x, p.loc.y);
270 Misc.setColor(p.color, 0f);
271 GL11.glVertex2f(end.x, end.y);
304 public void renderLayer(SpriteAPI sprite,
float texProgress,
float alpha) {
305 Vector2f from =
new Vector2f(
entity.getLocation());
306 Vector2f to = Misc.getUnitVectorAtDegreeAngle(
entity.getFacing());
308 Vector2f.add(to, from, to);
310 float length1 = 500f;
311 length1 = Math.min(length1, Misc.getDistance(from, to));
312 length1 = Misc.getDistance(from, to);
313 float length2 = params.width / 2f;
314 if (length1 < length2) length1 = length2;
319 length1 = params.length * 0.15f;
320 length2 = params.length - length1;
322 float w1 = length2 * 0.3f;
323 float w2 = length2 * 1.5f;
324 float w3 = length2 * 2.5f;
332 w1 = w2 = w3 =
params.width;
334 float widthMult = 0.3f;
335 w1 = params.width * widthMult;
336 w2 = params.width * (1f - (1f - widthMult) * (length2 / (length1 + length2)));
337 w3 = params.width * 1f;
339 w1 = w2 = w3 =
params.width;
341 float angle =
entity.getFacing() + 180f;
343 Vector2f dest =
new Vector2f(to);
344 Vector2f src =
new Vector2f(from);
346 Vector2f dir = Misc.getUnitVectorAtDegreeAngle(angle);
347 Vector2f dest1 =
new Vector2f(dir);
348 dest1.scale(length1);
349 Vector2f.add(dest1, src, dest1);
350 Vector2f dest2 =
new Vector2f(dir);
351 dest2.scale(length1 + length2);
352 Vector2f.add(dest2, src, dest2);
355 Vector2f perp = Misc.getUnitVectorAtDegreeAngle(angle + 90);
357 GL11.glEnable(GL11.GL_TEXTURE_2D);
359 sprite.bindTexture();
360 GL11.glEnable(GL11.GL_BLEND);
362 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
364 Color color = sprite.getColor();
366 boolean wireframe =
false;
369 GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
370 GL11.glDisable(GL11.GL_TEXTURE_2D);
381 GL11.glBegin(GL11.GL_TRIANGLE_FAN);
382 Misc.setColor(color, alpha * 1f);
383 GL11.glTexCoord2f(tx1 * 0.5f + texProgress, 0.5f);
384 GL11.glVertex2f((src.x + dest1.x)/2f, (src.y + dest1.y)/2f);
386 Misc.setColor(color, alpha * 0f);
387 GL11.glTexCoord2f(0f + texProgress, 0f);
388 GL11.glVertex2f(src.x + perp.x * w1/2f, src.y + perp.y * w1/2f);
389 GL11.glTexCoord2f(0f + texProgress, 1f);
390 GL11.glVertex2f(src.x - perp.x * w1/2f, src.y - perp.y * w1/2f);
392 Misc.setColor(color, alpha * 1f);
393 GL11.glTexCoord2f(tx1 + texProgress, 1f);
394 GL11.glVertex2f(dest1.x - perp.x * w2/2f, dest1.y - perp.y * w2/2f);
395 GL11.glTexCoord2f(tx1 + texProgress, 0f);
396 GL11.glVertex2f(dest1.x + perp.x * w2/2f, dest1.y + perp.y * w2/2f);
398 Misc.setColor(color, alpha * 0f);
399 GL11.glTexCoord2f(0f + texProgress, 0f);
400 GL11.glVertex2f(src.x + perp.x * w1/2f, src.y + perp.y * w1/2f);
404 float th = tx1 * length2 / length1;
408 GL11.glBegin(GL11.GL_TRIANGLE_FAN);
409 Misc.setColor(color, alpha * 1f);
410 GL11.glTexCoord2f(tx1 + texProgress + th * 0.5f, 0.5f);
411 GL11.glVertex2f((dest1.x + dest2.x)/2f, (dest1.y + dest2.y)/2f);
413 Misc.setColor(color, alpha * 1f);
414 GL11.glTexCoord2f(tx1 + texProgress, 0f);
415 GL11.glVertex2f(dest1.x + perp.x * w2/2f, dest1.y + perp.y * w2/2f);
416 GL11.glTexCoord2f(tx1 + texProgress, 1f);
417 GL11.glVertex2f(dest1.x - perp.x * w2/2f, dest1.y - perp.y * w2/2f);
419 Misc.setColor(color, alpha * 0f);
420 GL11.glTexCoord2f(tx1 + texProgress + th, 1f);
421 GL11.glVertex2f(dest2.x - perp.x * w3/2f, dest2.y - perp.y * w3/2f);
422 GL11.glTexCoord2f(tx1 + texProgress + th, 0f);
423 GL11.glVertex2f(dest2.x + perp.x * w3/2f, dest2.y + perp.y * w3/2f);
425 Misc.setColor(color, alpha * 1f);
426 GL11.glTexCoord2f(tx1 + texProgress, 0f);
427 GL11.glVertex2f(dest1.x + perp.x * w2/2f, dest1.y + perp.y * w2/2f);
430 if (wireframe) GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
491 if (other instanceof CampaignFleetAPI) {
492 CampaignFleetAPI fleet = (CampaignFleetAPI) other;
499 if (offset ==
null) {
500 if (fleet.isPlayerFleet()) {
506 float burnBonus = fleet.getFleetData().getBurnLevel() - fleet.getFleetData().getMinBurnLevelUnmodified();
507 if (burnBonus < 0) burnBonus = 0;
508 float maxSpeedWithWind = Misc.getSpeedForBurnLevel(
params.burnLevel + burnBonus + 1.2f);
509 if (fleet.getVelocity().length() >= maxSpeedWithWind) {
513 float fL = offset[0];
514 float fW = offset[1];
516 float intensity = 1f;
518 intensity = (1f - fL) / 0.25f;
519 }
else if (fL < 0.5f) {
520 intensity = fL / 0.5f;
523 intensity *= (1f - fW) / 0.5f;
527 if (intensity <= 0) {
528 if (fleet.isPlayerFleet()) {
534 if (fleet.isPlayerFleet()) {
537 fleet.addFloatingText(
"Entering slipstream", Misc.setAlpha(fleet.getIndicatorColor(), 255), 0.5f);
544 float maxFleetBurn = fleet.getFleetData().getBurnLevel();
545 float currFleetBurn = fleet.getCurrBurnLevel();
547 float maxWindBurn = params.burnLevel * 2f;
549 float currWindBurn = intensity * maxWindBurn;
550 float maxFleetBurnIntoWind = maxFleetBurn - Math.abs(currWindBurn);
551 float seconds = days *
Global.
getSector().getClock().getSecondsPerDay();
555 Vector2f windDir = Misc.getUnitVectorAtDegreeAngle(
entity.getFacing());
556 if (currWindBurn < 0) {
559 Vector2f velDir = Misc.normalise(
new Vector2f(fleet.getVelocity()));
560 velDir.scale(currFleetBurn);
562 float fleetBurnAgainstWind = -1f * Vector2f.dot(windDir, velDir);
564 float accelMult = 0.5f;
572 float windSpeed = Misc.getSpeedForBurnLevel(currWindBurn);
574 Vector2f windVector =
new Vector2f(windDir);
575 windVector.scale(windSpeed);
577 Vector2f vel = fleet.getVelocity();
578 Vector2f diff = Vector2f.sub(windVector, vel,
new Vector2f());
580 float max = diff.length();
581 diff = Misc.normalise(diff);
583 diff.scale(fleet.getAcceleration() * 3f * seconds);
586 if (diff.length() > max) {
587 diff.scale(max / diff.length());
599 if (fleetBurnAgainstWind > maxFleetBurnIntoWind) {
600 accelMult += 0.75f + 0.25f * (fleetBurnAgainstWind - maxFleetBurnIntoWind);
605 windDir.scale(seconds * Math.max(fleet.getTravelSpeed(), fleet.getAcceleration()) * accelMult);
606 fleet.setVelocity(vel.x + windDir.x, vel.y + windDir.y);
609 Color glowColor =
params.spriteColor1;
610 int alpha = glowColor.getAlpha();
612 glowColor = Misc.setAlpha(glowColor, 75);
616 float fleetSpeedAlongWind = Vector2f.dot(windDir, fleet.getVelocity());
617 float fleetSpeed = fleet.getVelocity().length();
619 float matchingWindFraction = fleetSpeedAlongWind/windSpeed;
620 float effectMag = 1f - matchingWindFraction * 0.5f;
621 if (effectMag > 0f) effectMag = 0f;
622 if (effectMag < 0.5f) effectMag = 0.5f;
624 String modId =
"slipstream_" +
entity.getId();
627 Misc.normalise(windDir);
628 float sizeNormal = 10f + 25f * intensity * effectMag;
629 for (FleetMemberViewAPI view : fleet.getViews()) {
630 view.getWindEffectDirX().shift(modId, windDir.x * sizeNormal, durIn, durOut, 1f);
631 view.getWindEffectDirY().shift(modId, windDir.y * sizeNormal, durIn, durOut, 1f);
632 view.getWindEffectColor().shift(modId, glowColor, durIn, durOut, intensity);