205 if (!
entity.isInCurrentLocation())
return;
209 fader.advance(amount);
218 params.minColor =
new Color(0.5f, 0.3f, 0.75f, 0.85f);
219 params.maxColor =
new Color(0.5f, 0.6f, 1f, 1f);
220 params.spriteColor =
new Color(0.3f, 0.5f, 1f, 1f);
223 params.minSpeed = 700f;
224 params.maxSpeed = 1500f;
228 params.burnLevel = 30;
231 params.minSpeed = Misc.getSpeedForBurnLevel(
params.burnLevel - 5);
232 params.maxSpeed = Misc.getSpeedForBurnLevel(
params.burnLevel + 5);
233 params.lineLengthFractionOfSpeed = 0.25f * Math.max(0.25f, Math.min(1f, 30f / (
float)
params.burnLevel));
237 params.minColor =
new Color(0.5f, 0.3f, 0.75f, 0.1f);
238 params.maxColor =
new Color(0.5f, 0.6f, 1f, 0.5f);
242 params.widthForMaxSpeed = width;
243 params.slowDownInWiderSections =
true;
244 params.widthForMaxSpeedMinMult = 0.5f;
246 params.edgeWidth = 256f;
247 params.spriteColor =
new Color(0.3f, 0.5f, 1f, 0.5f);
248 params.edgeColor =
new Color(0.3f, 0.5f, 1f, 0.75f);
249 params.edgeColor = Color.white;
257 params.areaPerParticle = 10000;
283 float spacing = 200f;
304 for (
int i = 0; i < iter; i++) {
305 float yOff = (float) Math.sin(i * 0.05f);
308 entity.getLocation().y + yOff * 2000f),
342 Vector2f avgLoc =
new Vector2f();
343 for (
int i = 0; i <
segments.size(); i++) {
344 SlipstreamSegment curr =
segments.get(i);
346 Vector2f.add(avgLoc, curr.loc, avgLoc);
351 entity.setLocation(avgLoc.x, avgLoc.y);
363 for (
int i = 0; i <
segments.size(); i++) {
364 SlipstreamSegment prev =
null;
365 if (i > 0) prev =
segments.get(i - 1);
366 SlipstreamSegment curr =
segments.get(i);
367 SlipstreamSegment next =
null;
368 SlipstreamSegment next2 =
null;
369 SlipstreamSegment next3 =
null;
382 curr.dir.set(prev.dir);
385 Vector2f dir = Vector2f.sub(next.loc, curr.loc,
new Vector2f());
386 dir = Misc.normalise(dir);
390 Vector2f dir = curr.dir;
391 Vector2f normal =
new Vector2f(-dir.y, dir.x);
392 curr.normal.set(normal);
395 float texLength = 0f;
396 float e1TexLength = 0f;
397 float e2TexLength = 0f;
399 Vector2f dir2 = Vector2f.sub(curr.loc, prev.loc,
new Vector2f());
400 length = dir2.length();
401 texLength = length / sprite.getWidth();
402 texLength = Math.min(texLength, sprite.getHeight() / curr.width);
404 Vector2f edgeCurr =
new Vector2f(curr.loc);
405 edgeCurr.x += curr.normal.x * curr.width * 0.5f;
406 edgeCurr.y += curr.normal.y * curr.width * 0.5f;
408 Vector2f edgePrev =
new Vector2f(prev.loc);
409 edgePrev.x += prev.normal.x * prev.width * 0.5f;
410 edgePrev.y += prev.normal.y * prev.width * 0.5f;
412 float length2 = Vector2f.sub(edgeCurr, edgePrev,
new Vector2f()).length();
413 e1TexLength = length2 / edge.getWidth() * edge.getHeight() /
params.edgeWidth;
416 edgeCurr =
new Vector2f(curr.loc);
417 edgeCurr.x -= curr.normal.x * curr.width * 0.5f;
418 edgeCurr.y -= curr.normal.y * curr.width * 0.5f;
420 edgePrev =
new Vector2f(prev.loc);
421 edgePrev.x -= prev.normal.x * prev.width * 0.5f;
422 edgePrev.y -= prev.normal.y * prev.width * 0.5f;
424 length2 = Vector2f.sub(edgeCurr, edgePrev,
new Vector2f()).length();
425 e2TexLength = length2 / edge.getWidth() * edge.getHeight() /
params.edgeWidth;
434 curr.lengthToPrev = length;
440 prev.lengthToNext = length;
443 if (next !=
null && next2 !=
null && next3 !=
null) {
444 Vector2f p0 = curr.loc;
445 Vector2f p1 = next.loc;
446 Vector2f p2 = next2.loc;
447 Vector2f p3 = next3.loc;
449 float p1ToP2 = Misc.getAngleInDegrees(p1, p2);
450 float p2ToP3 = Misc.getAngleInDegrees(p2, p3);
451 float diff = Misc.getAngleDiff(p1ToP2, p2ToP3);
452 float adjustment = Math.min(diff, Math.max(diff * 0.25f, diff - 10f));
453 adjustment = diff * 0.5f;
455 float angle = p1ToP2 + Misc.getClosestTurnDirection(p1ToP2, p2ToP3) * adjustment * 1f + 180f;
457 float dist = Misc.getDistance(p2, p1);
458 Vector2f p1Adjusted = Misc.getUnitVectorAtDegreeAngle(angle);
459 p1Adjusted.scale(dist);
460 Vector2f.add(p1Adjusted, p2, p1Adjusted);
461 next.locB = p1Adjusted;
462 }
else if (next !=
null) {
463 next.locB = next.loc;
466 curr.locB =
new Vector2f(curr.loc);
495 if (pf ==
null || !
entity.isInCurrentLocation()) {
505 float viewRadius =
new Vector2f(viewport.getVisibleWidth() * 0.5f, viewport.getVisibleHeight() * 0.5f).length();
506 viewRadius = Math.max(6000f, viewRadius);
508 List<SlipstreamSegment> near =
getSegmentsNear(viewport.getCenter(), viewRadius);
511 for (
int i = 0; i < near.size(); i++) {
512 SlipstreamSegment curr = near.get(i);
514 curr.fader.advance(amount);
516 float r1 = 0.5f + (float) Math.random() * 1f;
517 float r2 = 0.5f + (float) Math.random() * 1f;
518 curr.wobble1.advance(amount * r1);
519 curr.wobble2.advance(amount * r2);
523 Vector2f p1 =
new Vector2f(curr.loc);
524 Vector2f p2 =
new Vector2f(curr.loc);
525 p1.x += curr.normal.x * curr.width * 0.5f;
526 p1.y += curr.normal.y * curr.width * 0.5f;
527 p2.x -= curr.normal.x * curr.width * 0.5f;
528 p2.y -= curr.normal.y * curr.width * 0.5f;
530 p1.x += curr.wobble1.vector.x;
531 p1.y += curr.wobble1.vector.y;
532 p2.x += curr.wobble2.vector.x;
533 p2.y += curr.wobble2.vector.y;
536 float d = Misc.getDistance(p1, p2);
537 curr.wobbledWidth = d - params.edgeWidth * 2f * 0.5f;
538 if (curr.wobbledWidth < d * 0.5f) curr.wobbledWidth = d * 0.5f;
541 if (curr.index > 0) {
542 SlipstreamSegment prev =
segments.get(curr.index - 1);
543 Vector2f prev1 =
new Vector2f(prev.loc);
544 Vector2f prev2 =
new Vector2f(prev.loc);
545 prev1.x += curr.normal.x * curr.width * 0.5f;
546 prev1.y += curr.normal.y * curr.width * 0.5f;
547 prev2.x -= curr.normal.x * curr.width * 0.5f;
548 prev2.y -= curr.normal.y * curr.width * 0.5f;
550 float maxWobbleRadius = Math.min(prev.width, curr.width) * 0.05f;
551 float maxWobble1 = Misc.getDistance(p1, prev1) * 0.33f;
552 float maxWobble2 = Misc.getDistance(p2, prev2) * 0.33f;
553 maxWobble1 = Math.min(maxWobbleRadius, maxWobble1);
554 maxWobble2 = Math.min(maxWobbleRadius, maxWobble2);
555 prev.wobble1.radius.setMax(maxWobble1);
556 prev.wobble2.radius.setMax(maxWobble2);
557 curr.wobble1.radius.setMax(maxWobble1);
558 curr.wobble2.radius.setMax(maxWobble2);
571 boolean useNewSpawnMethod =
true;
574 if (useNewSpawnMethod) {
575 boolean inCurrentLocation =
entity.isInCurrentLocation();
576 boolean inHyperspace =
entity.isInHyperspace();
577 boolean spawnForAllSegments =
false;
579 Vector2f locFrom = viewport.getCenter();
580 float viewRadius =
new Vector2f(viewport.getVisibleWidth() * 0.5f, viewport.getVisibleHeight() * 0.5f).length();
582 viewRadius = Math.max(viewRadius, 10000f);
583 if (!inCurrentLocation) {
586 locFrom =
Global.
getSector().getPlayerFleet().getLocationInHyperspace();
588 float dist = Misc.getDistanceToPlayerLY(
entity);
589 spawnForAllSegments = dist < 2f;
593 if (inCurrentLocation) {
594 float veryNearRadius =
new Vector2f(viewport.getVisibleWidth() * 0.5f, viewport.getVisibleHeight() * 0.5f).length();
603 List<SlipstreamSegment> near;
604 if (spawnForAllSegments) {
605 near =
new ArrayList<SlipstreamSegment>(
segments);
609 Set<SlipstreamSegment> nearSet =
new LinkedHashSet<SlipstreamSegment>(near);
613 Iterator<SlipstreamParticle> iter =
particles.iterator();
614 while (iter.hasNext()) {
615 SlipstreamParticle p = iter.next();
618 if (!nearSet.contains(seg)) {
623 List<SlipstreamParticle> list = particleMap.get(seg);
626 particleMap.put(seg, list);
633 float totalArea = 0f;
634 int nearParticles = 0;
639 for (
int i = 0; i < near.size(); i++) {
640 SlipstreamSegment curr = near.get(i);
641 if (curr.lengthToNext <= 0)
continue;
643 float area = curr.lengthToNext * curr.width;
644 float desiredParticles = area /
params.areaPerParticle;
645 if (desiredParticles < 1) desiredParticles = 1;
647 float particlesInSegment = 0;
648 List<SlipstreamParticle> list = particleMap.get(curr);
650 particlesInSegment = list.size();
657 if (veryNearSet.contains(curr)) mult = 10f;
659 float w = desiredParticles - particlesInSegment;
662 segmentPicker.add(curr, w);
666 nearParticles += particlesInSegment;
670 int numParticlesBasedOnArea = (int) (totalArea /
params.areaPerParticle);
671 int actualDesired = numParticlesBasedOnArea;
672 if (numParticlesBasedOnArea < 10) numParticlesBasedOnArea = 10;
673 if (numParticlesBasedOnArea >
params.maxParticles) numParticlesBasedOnArea =
params.maxParticles;
678 int particlesToAdd = numParticlesBasedOnArea - nearParticles;
682 particlesToAdd = Math.min(particlesToAdd,
params.maxParticles -
particles.size());
685 while (added < particlesToAdd) {
687 SlipstreamSegment seg = segmentPicker.pick();
688 if (seg ==
null)
continue;
690 SlipstreamParticle p =
new SlipstreamParticle();
691 float fLength = (float) Math.random() * 1f;
692 float fWidth = (float) Math.random() * 2f - 1f;
694 float speed = params.minSpeed + (params.maxSpeed -
params.minSpeed) * (
float) Math.random();
695 float dur = params.minDur + (params.maxDur -
params.minDur) * (
float) Math.random();
699 p.dist = seg.totalLength + seg.lengthToNext * fLength;
707 float speedMult = (0.65f + 0.35f * intensity) * wMult;
708 p.speed *= speedMult;
719 float totalArea = 0f;
720 for (
int i = 0; i <
segments.size(); i++) {
721 SlipstreamSegment curr =
segments.get(i);
722 totalArea += curr.lengthToPrev * curr.width;
725 int numParticlesBasedOnArea = (int) (totalArea /
params.areaPerParticle);
726 if (numParticlesBasedOnArea < 10) numParticlesBasedOnArea = 10;
727 if (numParticlesBasedOnArea >
params.maxParticles) numParticlesBasedOnArea =
params.maxParticles;
737 SlipstreamParticle p =
new SlipstreamParticle();
738 float fLength = (float) Math.random() * 1f;
739 float fWidth = (float) Math.random() * 2f - 1f;
741 float speed = params.minSpeed + (params.maxSpeed -
params.minSpeed) * (
float) Math.random();
742 float dur = params.minDur + (params.maxDur -
params.minDur) * (
float) Math.random();
753 float speedMult = (0.65f + 0.35f * intensity) * wMult;
754 p.speed *= speedMult;
823 public void render(CampaignEngineLayers layer, ViewportAPI viewport) {
830 float mx = Mouse.getX();
831 float my = Mouse.getY();
832 float wmx =
Global.
getSector().getViewport().convertScreenXToWorldX(mx);
833 float wmy =
Global.
getSector().getViewport().convertScreenYToWorldY(my);
834 boolean inside =
false;
837 inside |= box.pointNeedsDetailedCheck(
new Vector2f(wmx, wmy));
840 GL11.glDisable(GL11.GL_TEXTURE_2D);
841 GL11.glEnable(GL11.GL_BLEND);
842 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
844 GL11.glPointSize(20f);
845 GL11.glEnable(GL11.GL_POINT_SMOOTH);
847 Misc.setColor(Color.green);
849 Misc.setColor(Color.gray);
852 GL11.glBegin(GL11.GL_POINTS);
853 GL11.glVertex2f(wmx, wmy);
861 float viewRadius =
new Vector2f(viewport.getVisibleWidth() * 0.5f, viewport.getVisibleHeight() * 0.5f).length();
867 List<SlipstreamSegment> near =
getSegmentsNear(viewport.getCenter(), viewRadius);
868 Set<SlipstreamSegment> nearSet =
new LinkedHashSet<SlipstreamSegment>(near);
870 List<List<SlipstreamSegment>> subsections =
new ArrayList<List<SlipstreamSegment>>();
872 List<SlipstreamSegment> subsection =
new ArrayList<SlipstreamSegment>();
873 for (SlipstreamSegment seg : near) {
874 if (prevIndex != seg.index -1) {
875 if (subsection !=
null && !subsection.isEmpty()) {
876 subsections.add(subsection);
878 subsection =
new ArrayList<SlipstreamSegment>();
881 prevIndex = seg.index;
883 if (subsection !=
null && !subsection.isEmpty()) {
884 subsections.add(subsection);
889 sprite.setNormalBlend();
890 sprite.setColor(
params.spriteColor);
893 edge.setNormalBlend();
894 edge.setColor(
params.edgeColor);
898 for (List<SlipstreamSegment> subsection2 : subsections) {
899 renderSegments(sprite, edge, viewport.getAlphaMult(), subsection2);
946 GL11.glDisable(GL11.GL_TEXTURE_2D);
947 GL11.glEnable(GL11.GL_BLEND);
948 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
954 GL11.glLineWidth(Math.max(1f, Math.min(2f, 2f/zoom)));
956 GL11.glEnable(GL11.GL_LINE_SMOOTH);
958 Misc.setColor(
new Color(1f, 1f, 1f, 0.5f));
959 Misc.setColor(Color.white);
969 for (
float offset = -1f;
false && offset <= 1f; offset += 0.1f) {
971 GL11.glBegin(GL11.GL_LINE_STRIP);
973 for (
float len = 0; len <
totalLength; len += incr) {
1026// perp = Misc.interpolateVector(next.normal, next2.normal, f);
1028// perp.scale(offset * params.width * 0.5f);
1031 //p = Misc.interpolateVector(pPrev, p, 0.5f);
1032 //GL11.glVertex2f(p.x + perp.x, p.y + perp.y);
1038 GL11.glVertex2f(p.x, p.y);
1042 Misc.setColor(Color.red);
1043 for (
int i = 0; i <
segments.size() - 3; i+=2) {
1045 SlipstreamSegment prev =
null;
1049 SlipstreamSegment curr =
segments.get(i);
1050 SlipstreamSegment next =
segments.get(i + 1);
1051 SlipstreamSegment next2 =
segments.get(i + 2);
1052 SlipstreamSegment next3 =
segments.get(i + 3);
1058 Vector2f p0 = curr.loc;
1059 Vector2f p1 = next.loc;
1060 Vector2f p2 = next2.loc;
1061 Vector2f p3 = next3.loc;
1079 p0 =
new Vector2f(p0);
1080 p0.x += curr.normal.x * curr.width * 0.5f * offset;
1081 p0.y += curr.normal.y * curr.width * 0.5f * offset;
1083 p2 =
new Vector2f(p2);
1084 p2.x += next2.normal.x * next2.width * 0.5f * offset;
1085 p2.y += next2.normal.y * next2.width * 0.5f * offset;
1087 p1 =
new Vector2f(next.locB);
1088 p1 =
new Vector2f(p1);
1089 p1.x += next.normal.x * next.width * 0.5f * offset;
1090 p1.y += next.normal.y * next.width * 0.5f * offset;
1106 for (
float len = 0; len < curr.lengthToNext + next.lengthToNext; len += incr) {
1107 float t = len / (curr.lengthToNext + next.lengthToNext);
1109 Vector2f p = Misc.bezier(p0, p1, p2, t);
1114 float f = len / curr.lengthToNext;
1117 perp = Misc.interpolateVector(curr.normal, next.normal, f);
1119 f = (len - curr.lengthToNext) / next.lengthToNext;
1120 perp = Misc.interpolateVector(next.normal, next2.normal, f);
1122 perp.scale(offset * curr.width * 0.5f);
1126 GL11.glVertex2f(p.x, p.y);
1255 if (place !=
null) {
1256 Misc.setColor(Color.red);
1257 GL11.glPointSize(40f/zoom);
1258 GL11.glEnable(GL11.GL_POINT_SMOOTH);
1259 GL11.glBegin(GL11.GL_POINTS);
1262 GL11.glVertex2f(p.x, p.y);
1264 Misc.setColor(Color.blue);
1266 GL11.glVertex2f(p.x, p.y);
1270 float withinSeg = place[0] - seg.totalLength;
1271 Vector2f p2 =
new Vector2f(seg.normal.y, -seg.normal.x);
1272 p2.scale(withinSeg);
1273 Vector2f.add(p2, seg.loc, p2);
1274 float width = seg.wobbledWidth;
1275 if (
segments.size() > seg.index + 1) {
1276 SlipstreamSegment next =
segments.get(seg.index + 1);
1277 width = Misc.interpolate(seg.wobbledWidth, next.wobbledWidth,
1278 (place[0] - seg.totalLength) / seg.lengthToNext);
1280 p2.x +=
getNormalAt(place[0]).x * place[1] * width * 0.5f;
1281 p2.y +=
getNormalAt(place[0]).y * place[1] * width * 0.5f;
1282 Misc.setColor(Color.green);
1283 GL11.glVertex2f(p2.x, p2.y);
1312 boolean curvedTrails =
true;
1313 boolean useTex =
false;
1318 GL11.glDisable(GL11.GL_TEXTURE_2D);
1319 GL11.glEnable(GL11.GL_BLEND);
1320 GL11.glLineWidth(Math.max(1f, Math.min(2f, 2f/zoom)));
1322 GL11.glEnable(GL11.GL_LINE_SMOOTH);
1323 GL11.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_NICEST);
1327 if (!curvedTrails) {
1328 GL11.glBegin(GL11.GL_LINES);
1336 GL11.glEnable(GL11.GL_TEXTURE_2D);
1337 GL11.glEnable(GL11.GL_BLEND);
1338 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
1345 for (SlipstreamParticle p :
particles) {
1347 if (seg ==
null || !nearSet.contains(seg))
continue;
1352 float a = viewport.getAlphaMult();
1353 if (p.remaining <= 0.5f) {
1354 a = p.remaining / 0.5f;
1355 }
else if (p.elapsed <
params.particleFadeInTime) {
1356 a = p.elapsed /
params.particleFadeInTime;
1368 float yPos = p.yPos;
1373 GL11.glBegin(GL11.GL_QUAD_STRIP);
1375 if (curr ==
null || !viewport.isNearViewport(curr, p.speed *
params.lineLengthFractionOfSpeed + 50f)) {
1380 float incr = p.speed * params.lineLengthFractionOfSpeed / iter;
1382 for (
float i = 0; i < iter; i++) {
1383 float min = incr * 1f;
1384 float dist = p.dist - i * incr - min;
1386 if (next ==
null)
break;
1394 float a1 = a * (iter - i) / (iter - 1);
1395 if (i == 0) a1 = 0f;
1397 Misc.setColor(p.color, a1);
1398 GL11.glTexCoord2f(0, 0f);
1399 GL11.glVertex2f(curr.x + perp.x * lw, curr.y + perp.y * lw);
1400 GL11.glTexCoord2f(0, 1f);
1401 GL11.glVertex2f(curr.x - perp.x * lw, curr.y - perp.y * lw);
1406 GL11.glBegin(GL11.GL_LINE_STRIP);
1409 if (curr ==
null || !viewport.isNearViewport(curr, p.speed *
params.lineLengthFractionOfSpeed + 50f)) {
1414 float incr = p.speed * params.lineLengthFractionOfSpeed / iter;
1415 for (
float i = 0; i < iter; i++) {
1417 float min = incr * 0.5f;
1418 Vector2f next =
getPointAt(p.dist - i * incr - min, yPos);
1424 float a1 = a * (iter - i) / (iter - 1);
1426 if (i == 0) a1 = 0f;
1428 Misc.setColor(p.color, a1);
1429 GL11.glVertex2f(curr.x, curr.y);
1437 Vector2f start =
getPointAt(p.dist + p.speed *
params.lineLengthFractionOfSpeed * 0.1f, yPos);
1438 if (start ==
null || !viewport.isNearViewport(start, 500))
continue;
1441 if (mid ==
null)
continue;
1442 Vector2f end =
getPointAt(p.dist - p.speed *
params.lineLengthFractionOfSpeed * 0.9f, yPos);
1443 if (end ==
null)
continue;
1445 Misc.setColor(p.color, 0f);
1446 GL11.glVertex2f(start.x, start.y);
1447 Misc.setColor(p.color, a);
1448 GL11.glVertex2f(mid.x, mid.y);
1449 GL11.glVertex2f(mid.x, mid.y);
1450 Misc.setColor(p.color, 0f);
1451 GL11.glVertex2f(end.x, end.y);
1455 if (!curvedTrails) {
1465 GL11.glEnable(GL11.GL_TEXTURE_2D);
1466 sprite.bindTexture();
1467 GL11.glEnable(GL11.GL_BLEND);
1469 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
1470 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
1471 Color color = sprite.getColor();
1477 boolean wireframe =
false;
1480 GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
1481 GL11.glDisable(GL11.GL_TEXTURE_2D);
1482 GL11.glDisable(GL11.GL_BLEND);
1485 boolean subtract =
false;
1488 GL14.glBlendEquation(GL14.GL_FUNC_REVERSE_SUBTRACT);
1492 Color c = Color.black;
1494 GL11.glDisable(GL11.GL_TEXTURE_2D);
1495 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
1497 int alphaInDeep = 255;
1498 int alphaOutside = 0;
1499 HyperspaceTerrainPlugin plugin = (HyperspaceTerrainPlugin) Misc.getHyperspaceTerrain().getPlugin();
1501 GL11.glBegin(GL11.GL_QUAD_STRIP);
1503 for (
int i = 0; i <
segments.size(); i++) {
1504 SlipstreamSegment curr =
segments.get(i);
1505 float a = curr.fader.getBrightness();
1507 if (
entity.isInHyperspace() && plugin.isInClouds(curr.loc, 100f)) {
1508 c = Misc.setAlpha(c, alphaInDeep);
1510 c = Misc.setAlpha(c, alphaOutside);
1513 Vector2f p1 =
new Vector2f(curr.loc);
1514 p1.x += curr.normal.x * curr.width * 0.5f;
1515 p1.y += curr.normal.y * curr.width * 0.5f;
1516 Vector2f p2 =
new Vector2f(curr.loc);
1517 p2.x += curr.normal.x * (curr.width * 0.5f -
params.edgeWidth);
1518 p2.y += curr.normal.y * (curr.width * 0.5f -
params.edgeWidth);
1520 p1.x += curr.wobble1.vector.x;
1521 p1.y += curr.wobble1.vector.y;
1523 Misc.setColor(c, alpha * 0f * a);
1524 GL11.glVertex2f(p1.x, p1.y);
1525 Misc.setColor(c, alpha * 1f * a);
1526 GL11.glVertex2f(p2.x, p2.y);
1531 GL11.glBegin(GL11.GL_QUAD_STRIP);
1533 for (
int i = 0; i <
segments.size(); i++) {
1534 SlipstreamSegment curr =
segments.get(i);
1535 float a = curr.fader.getBrightness();
1537 if (
entity.isInHyperspace() && plugin.isInClouds(curr.loc, 100f)) {
1538 c = Misc.setAlpha(c, alphaInDeep);
1540 c = Misc.setAlpha(c, alphaOutside);
1543 Vector2f p1 =
new Vector2f(curr.loc);
1544 p1.x -= curr.normal.x * curr.width * 0.5f;
1545 p1.y -= curr.normal.y * curr.width * 0.5f;
1546 Vector2f p2 =
new Vector2f(curr.loc);
1547 p2.x -= curr.normal.x * (curr.width * 0.5f -
params.edgeWidth);
1548 p2.y -= curr.normal.y * (curr.width * 0.5f -
params.edgeWidth);
1550 p1.x += curr.wobble2.vector.x;
1551 p1.y += curr.wobble2.vector.y;
1553 Misc.setColor(c, alpha * 0f * a);
1554 GL11.glVertex2f(p1.x, p1.y);
1555 Misc.setColor(c, alpha * 1f * a);
1556 GL11.glVertex2f(p2.x, p2.y);
1560 GL11.glBegin(GL11.GL_QUAD_STRIP);
1562 for (
int i = 0; i <
segments.size(); i++) {
1563 SlipstreamSegment curr =
segments.get(i);
1564 float a = curr.fader.getBrightness();
1566 if (
entity.isInHyperspace() && plugin.isInClouds(curr.loc, 100f)) {
1567 c = Misc.setAlpha(c, alphaInDeep);
1569 c = Misc.setAlpha(c, alphaOutside);
1572 Vector2f p1 =
new Vector2f(curr.loc);
1573 p1.x += curr.normal.x * (curr.width * 0.5f -
params.edgeWidth);
1574 p1.y += curr.normal.y * (curr.width * 0.5f -
params.edgeWidth);
1575 Vector2f p2 =
new Vector2f(curr.loc);
1576 p2.x -= curr.normal.x * (curr.width * 0.5f -
params.edgeWidth);
1577 p2.y -= curr.normal.y * (curr.width * 0.5f -
params.edgeWidth);
1579 Misc.setColor(c, alpha * 1f * a);
1580 GL11.glVertex2f(p1.x, p1.y);
1581 GL11.glVertex2f(p2.x, p2.y);
1589 GL11.glEnable(GL11.GL_TEXTURE_2D);
1590 GL11.glEnable(GL11.GL_BLEND);
1593 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
1594 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
1596 GL11.glBegin(GL11.GL_QUAD_STRIP);
1597 for (
int i = 0; i <
segments.size(); i++) {
1598 SlipstreamSegment curr =
segments.get(i);
1599 float a = curr.fader.getBrightness();
1601 Vector2f p1 =
new Vector2f(curr.loc);
1602 p1.x += curr.normal.x * curr.width * 0.5f;
1603 p1.y += curr.normal.y * curr.width * 0.5f;
1604 Vector2f p2 =
new Vector2f(curr.loc);
1605 p2.x -= curr.normal.x * curr.width * 0.5f;
1606 p2.y -= curr.normal.y * curr.width * 0.5f;
1608 p1.x += curr.wobble1.vector.x;
1609 p1.y += curr.wobble1.vector.y;
1610 p2.x += curr.wobble2.vector.x;
1611 p2.y += curr.wobble2.vector.y;
1613 Misc.setColor(color, alpha * 1f * a);
1614 GL11.glTexCoord2f(curr.tx, 0f);
1615 GL11.glVertex2f(p1.x, p1.y);
1616 GL11.glTexCoord2f(curr.tx, 1f);
1617 GL11.glVertex2f(p2.x, p2.y);
1623 color = edge.getColor();
1624 float wobbleMult = 0.5f;
1626 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
1629 GL11.glBegin(GL11.GL_QUAD_STRIP);
1631 for (
int i = 0; i <
segments.size(); i++) {
1632 SlipstreamSegment curr =
segments.get(i);
1633 float a = curr.fader.getBrightness();
1635 Vector2f p1 =
new Vector2f(curr.loc);
1636 p1.x += curr.normal.x * curr.width * 0.5f;
1637 p1.y += curr.normal.y * curr.width * 0.5f;
1638 Vector2f p2 =
new Vector2f(curr.loc);
1639 p2.x += curr.normal.x * (curr.width * 0.5f -
params.edgeWidth);
1640 p2.y += curr.normal.y * (curr.width * 0.5f -
params.edgeWidth);
1642 p1.x += curr.wobble1.vector.x * wobbleMult;
1643 p1.y += curr.wobble1.vector.y * wobbleMult;
1644 p2.x += curr.wobble1.vector.x * wobbleMult;
1645 p2.y += curr.wobble1.vector.y * wobbleMult;
1647 Misc.setColor(color, alpha * 1f * a);
1648 GL11.glTexCoord2f(curr.txe1, 1f);
1649 GL11.glVertex2f(p1.x, p1.y);
1650 GL11.glTexCoord2f(curr.txe1, 0f);
1651 GL11.glVertex2f(p2.x, p2.y);
1656 GL11.glBegin(GL11.GL_QUAD_STRIP);
1658 for (
int i = 0; i <
segments.size(); i++) {
1659 SlipstreamSegment curr =
segments.get(i);
1660 float a = curr.fader.getBrightness();
1662 Vector2f p1 =
new Vector2f(curr.loc);
1663 p1.x -= curr.normal.x * curr.width * 0.5f;
1664 p1.y -= curr.normal.y * curr.width * 0.5f;
1665 Vector2f p2 =
new Vector2f(curr.loc);
1666 p2.x -= curr.normal.x * (curr.width * 0.5f -
params.edgeWidth);
1667 p2.y -= curr.normal.y * (curr.width * 0.5f -
params.edgeWidth);
1669 p1.x += curr.wobble2.vector.x * wobbleMult;
1670 p1.y += curr.wobble2.vector.y * wobbleMult;
1671 p2.x += curr.wobble2.vector.x * wobbleMult;
1672 p2.y += curr.wobble2.vector.y * wobbleMult;
1674 Misc.setColor(color, alpha * 1f * a);
1675 GL11.glTexCoord2f(curr.txe2, 1f);
1676 GL11.glVertex2f(p1.x, p1.y);
1677 GL11.glTexCoord2f(curr.txe2, 0f);
1678 GL11.glVertex2f(p2.x, p2.y);
1684 GL14.glBlendEquation(GL14.GL_FUNC_ADD);
1687 if (wireframe) GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
1709 float dist = Misc.getDistance(loc,
entity.getLocation());
1714 for (SlipstreamSegment curr : near) {
1715 SlipstreamSegment next =
null;
1716 if (
segments.size() > curr.index + 1) {
1717 next =
segments.get(curr.index + 1);
1719 next =
new SlipstreamSegment();
1721 next.wobbledWidth = curr.wobbledWidth;
1723 next.normal = curr.normal;
1725 next.loc =
new Vector2f(curr.dir);
1726 next.loc.scale(curr.lengthToPrev);
1727 Vector2f.add(next.loc, curr.loc, next.loc);
1729 next.lengthToPrev = curr.lengthToPrev;
1734 Vector2f p1 = curr.loc;
1735 Vector2f p2 = next.loc;
1737 Vector2f currNormalP1 =
new Vector2f(curr.loc);
1738 Vector2f currNormalP2 =
new Vector2f(curr.normal);
1739 currNormalP2.scale(100f);
1740 Vector2f.add(currNormalP2, currNormalP1, currNormalP2);
1742 Vector2f nextNormalP1 =
new Vector2f(next.loc);
1743 Vector2f nextNormalP2 =
new Vector2f(next.normal);
1744 nextNormalP2.scale(100f);
1745 Vector2f.add(nextNormalP2, nextNormalP1, nextNormalP2);
1748 Vector2f dir =
new Vector2f(curr.dir);
1750 Vector2f p4 = Vector2f.add(p3, dir,
new Vector2f());
1752 Vector2f currNormalP = Misc.intersectLines(currNormalP1, currNormalP2, p3, p4);
1753 if (currNormalP ==
null)
continue;
1754 Vector2f nextNormalP = Misc.intersectLines(nextNormalP1, nextNormalP2, p3, p4);
1755 if (nextNormalP ==
null)
continue;
1757 float u = (p3.x - currNormalP.x) * (nextNormalP.x - currNormalP.x) +
1758 (p3.y - currNormalP.y) * (nextNormalP.y - currNormalP.y);
1759 float denom = Vector2f.sub(nextNormalP, currNormalP,
new Vector2f()).length();
1761 if (denom == 0)
continue;
1764 if (u >= 0 && u <= 1) {
1765 Vector2f normalAtP3 = Misc.interpolateVector(curr.normal, next.normal, u);
1766 normalAtP3.scale(100f);
1767 Vector2f p3PlusNormal = Vector2f.add(p3, normalAtP3,
new Vector2f());
1769 Vector2f intersect = Misc.intersectLines(p1, p2, p3, p3PlusNormal);
1770 if (intersect ==
null)
continue;
1772 float distFromLine = Vector2f.sub(intersect, p3,
new Vector2f()).length();
1773 float width = Misc.interpolate(curr.wobbledWidth, next.wobbledWidth, u);
1774 if (distFromLine >= width / 2f)
return null;
1776 float [] result =
new float[2];
1778 result[0] = curr.totalLength + u * next.lengthToPrev;
1779 result[1] = distFromLine / (width / 2f);
1781 float currToLoc = Misc.getAngleInDegrees(p1, p3);
1782 float segDir = Misc.getAngleInDegrees(p1, p2);
1783 if (Misc.getClosestTurnDirection(segDir, currToLoc) < 0) {
1784 result[1] = -result[1];
1864 if (other instanceof CampaignFleetAPI) {
1865 CampaignFleetAPI fleet = (CampaignFleetAPI) other;
1875 if (offset ==
null) {
1876 if (fleet.isPlayerFleet()) {
1891 float distAlong = offset[0];
1892 float yOff = offset[1];
1906 if (intensity <= 0) {
1907 if (fleet.isPlayerFleet()) {
1916 if (fleet.isPlayerFleet()) {
1920 fleet.addFloatingText(
"Entering slipstream", Misc.setAlpha(fleet.getIndicatorColor(), 255), 0.5f);
1928 float maxFleetBurn = fleet.getFleetData().getBurnLevel();
1929 float currFleetBurn = fleet.getCurrBurnLevel();
1931 float maxWindBurn = params.burnLevel * 2f;
1933 float currWindBurn = intensity * maxWindBurn;
1934 float maxFleetBurnIntoWind = maxFleetBurn - Math.abs(currWindBurn);
1935 float seconds = days *
Global.
getSector().getClock().getSecondsPerDay();
1940 Vector2f p2 =
getPointAt(distAlong + 1f, yOff);
1941 if (p1 ==
null || p2 ==
null) {
1942 if (fleet.isPlayerFleet()) {
1952 Vector2f windDir = Misc.getUnitVectorAtDegreeAngle(Misc.getAngleInDegrees(p1, p2));
1953 if (currWindBurn < 0) {
1956 Vector2f velDir = Misc.normalise(
new Vector2f(fleet.getVelocity()));
1958 float baseFleetAccel = fleet.getTravelSpeed();
1959 if (baseFleetAccel < 10f) baseFleetAccel = 10f;
1961 boolean fleetTryingToMove = fleet.getMoveDestination() !=
null &&
1962 Misc.getDistance(fleet.getLocation(), fleet.getMoveDestination()) > fleet.getRadius() + 10f;
1963 if (fleet.isPlayerFleet()) {
1964 fleetTryingToMove &= (
1966 fleet.wasSlowMoving());
1968 float windSpeedReduction = 0f;
1969 if (!fleetTryingToMove) {
1970 Vector2f dest =
new Vector2f(windDir);
1972 Vector2f.add(dest, fleet.getLocation(), dest);
1973 fleet.setMoveDestination(dest.x, dest.y);
1975 Vector2f moveDir = Misc.getUnitVectorAtDegreeAngle(
1976 Misc.getAngleInDegrees(fleet.getLocation(), fleet.getMoveDestination()));
1977 float dot = Vector2f.dot(windDir, moveDir);
1978 if (fleet.wasSlowMoving()) dot = -1f;
1980 float accelBasedMult = fleet.getAcceleration() / baseFleetAccel;
1981 accelBasedMult *= accelBasedMult;
1982 if (accelBasedMult > 1f) accelBasedMult = 1f;
1983 if (accelBasedMult < 0.1f) accelBasedMult = 0.1f;
1984 windSpeedReduction = -dot * fleet.getFleetData().getBurnLevel() * accelBasedMult;
1989 float burnBonus = fleet.getFleetData().getBurnLevel() - fleet.getFleetData().getMinBurnLevel();
1990 if (burnBonus < 0) burnBonus = 0;
1992 float maxSpeedWithWind = Misc.getSpeedForBurnLevel((
params.burnLevel * intensity) + burnBonus);
1993 if (windSpeedReduction > 0) {
1994 maxSpeedWithWind = Misc.getSpeedForBurnLevel(
1995 Math.max(
params.burnLevel * 0.5f * intensity,
params.burnLevel * intensity - windSpeedReduction));
1998 float fleetSpeedAlongWind = Vector2f.dot(windDir, fleet.getVelocity());
1999 if (fleetSpeedAlongWind >= maxSpeedWithWind) {
2006 velDir.scale(currFleetBurn);
2008 float fleetBurnAgainstWind = -1f * Vector2f.dot(windDir, velDir);
2011 float windSpeed = Misc.getSpeedForBurnLevel(currWindBurn);
2013 Vector2f windVector =
new Vector2f(windDir);
2014 windVector.scale(windSpeed);
2016 Vector2f vel = fleet.getVelocity();
2017 Vector2f diff = Vector2f.sub(windVector, vel,
new Vector2f());
2019 float max = diff.length();
2020 diff = Misc.normalise(diff);
2022 diff.scale(fleet.getAcceleration() * 3f * seconds);
2025 if (diff.length() > max) {
2026 diff.scale(max / diff.length());
2037 float accelMult = 0.5f;
2038 if (fleetBurnAgainstWind > maxFleetBurnIntoWind) {
2039 accelMult += 0.75f + 0.25f * (fleetBurnAgainstWind - maxFleetBurnIntoWind);
2047 windDir.scale(seconds * baseFleetAccel * accelMult);
2048 fleet.setVelocity(vel.x + windDir.x, vel.y + windDir.y);
2051 boolean withGlow =
true;
2054 Color glowColor =
params.windGlowColor;
2055 int alpha = glowColor.getAlpha();
2057 glowColor = Misc.setAlpha(glowColor, 75);
2063 if (p1 !=
null && p2 !=
null) {
2064 windDir = Misc.getUnitVectorAtDegreeAngle(Misc.getAngleInDegrees(p1, p2));
2076 String modId =
"slipstream_" +
entity.getId();
2081 float sizeNormal = 5f + 10f * intensity;
2082 for (FleetMemberViewAPI view : fleet.getViews()) {
2083 view.getWindEffectDirX().shift(modId, windDir.x * sizeNormal, durIn, durOut, 1f);
2084 view.getWindEffectDirY().shift(modId, windDir.y * sizeNormal, durIn, durOut, 1f);
2085 view.getWindEffectColor().shift(modId, glowColor, durIn, durOut, 1f);