453 Vector2f avgLoc =
new Vector2f();
454 for (
int i = 0; i <
segments.size(); i++) {
455 SlipstreamSegment curr =
segments.get(i);
457 Vector2f.add(avgLoc, curr.loc, avgLoc);
462 entity.setLocation(avgLoc.x, avgLoc.y);
474 for (
int i = 0; i <
segments.size(); i++) {
475 SlipstreamSegment prev =
null;
476 if (i > 0) prev =
segments.get(i - 1);
477 SlipstreamSegment curr =
segments.get(i);
478 SlipstreamSegment next =
null;
479 SlipstreamSegment next2 =
null;
480 SlipstreamSegment next3 =
null;
491 if (curr.dir ==
null) curr.dir =
new Vector2f();
492 if (curr.normal ==
null) curr.normal =
new Vector2f();
496 curr.dir.set(prev.dir);
499 Vector2f dir = Vector2f.sub(next.loc, curr.loc,
new Vector2f());
500 dir = Misc.normalise(dir);
504 Vector2f dir = curr.dir;
505 if (prev ==
null || next ==
null) {
506 curr.normal.set(-dir.y, dir.x);
508 Vector2f avg = Vector2f.add(prev.dir, curr.dir,
new Vector2f());
510 curr.normal.set(-avg.y, avg.x);
516 float texLength = 0f;
517 float e1TexLength = 0f;
518 float e2TexLength = 0f;
520 Vector2f dir2 = Vector2f.sub(curr.loc, prev.loc,
new Vector2f());
521 length = dir2.length();
522 texLength = length / sprite.getWidth();
524 texLength = Math.min(texLength, sprite.getHeight() / curr.width);
527 Vector2f edgeCurr =
new Vector2f(curr.loc);
528 edgeCurr.x += curr.normal.x * curr.width * 0.5f;
529 edgeCurr.y += curr.normal.y * curr.width * 0.5f;
531 Vector2f edgePrev =
new Vector2f(prev.loc);
532 edgePrev.x += prev.normal.x * prev.width * 0.5f;
533 edgePrev.y += prev.normal.y * prev.width * 0.5f;
535 float length2 = Vector2f.sub(edgeCurr, edgePrev,
new Vector2f()).length();
536 e1TexLength = length2 / edge.getWidth() * edge.getHeight() /
params.edgeWidth;
539 edgeCurr =
new Vector2f(curr.loc);
540 edgeCurr.x -= curr.normal.x * curr.width * 0.5f;
541 edgeCurr.y -= curr.normal.y * curr.width * 0.5f;
543 edgePrev =
new Vector2f(prev.loc);
544 edgePrev.x -= prev.normal.x * prev.width * 0.5f;
545 edgePrev.y -= prev.normal.y * prev.width * 0.5f;
547 length2 = Vector2f.sub(edgeCurr, edgePrev,
new Vector2f()).length();
548 e2TexLength = length2 / edge.getWidth() * edge.getHeight() /
params.edgeWidth;
557 curr.lengthToPrev = length;
563 prev.lengthToNext = length;
566 if (next !=
null && next2 !=
null && next3 !=
null) {
567 Vector2f p0 = curr.loc;
568 Vector2f p1 = next.loc;
569 Vector2f p2 = next2.loc;
570 Vector2f p3 = next3.loc;
572 float p1ToP2 = Misc.getAngleInDegrees(p1, p2);
573 float p2ToP3 = Misc.getAngleInDegrees(p2, p3);
574 float diff = Misc.getAngleDiff(p1ToP2, p2ToP3);
575 float adjustment = Math.min(diff, Math.max(diff * 0.25f, diff - 10f));
576 adjustment = diff * 0.5f;
578 float angle = p1ToP2 + Misc.getClosestTurnDirection(p1ToP2, p2ToP3) * adjustment * 1f + 180f;
580 float dist = Misc.getDistance(p2, p1);
581 Vector2f p1Adjusted = Misc.getUnitVectorAtDegreeAngle(angle);
582 p1Adjusted.scale(dist);
583 Vector2f.add(p1Adjusted, p2, p1Adjusted);
584 next.locB = p1Adjusted;
585 }
else if (next !=
null) {
586 next.locB = next.loc;
589 curr.locB =
new Vector2f(curr.loc);
622 if (pf ==
null || !entity.isInCurrentLocation()) {
624 for (
int i = 0; i <
segments.size(); i++) {
625 SlipstreamSegment curr =
segments.get(i);
626 curr.fader.advance(amount);
638 float viewRadius =
new Vector2f(viewport.getVisibleWidth() * 0.5f, viewport.getVisibleHeight() * 0.5f).length();
639 viewRadius = Math.max(6000f, viewRadius);
641 List<SlipstreamSegment> near =
getSegmentsNear(viewport.getCenter(), viewRadius);
644 for (
int i = 0; i <
segments.size(); i++) {
648 SlipstreamSegment curr =
segments.get(i);
649 curr.fader.advance(amount);
652 HyperspaceTerrainPlugin plugin = (HyperspaceTerrainPlugin) Misc.getHyperspaceTerrain().getPlugin();
665 for (
int i = 0; i < near.size(); i++) {
666 SlipstreamSegment curr = near.get(i);
668 if (entity.isInHyperspace() && !curr.fader.isFadedOut() &&
669 curr.fader.getBrightness() * curr.bMult > 0.05f && curr.bMult > 0f) {
671 curr.loc, curr.width * 0.5f +
params.edgeWidth + 100f,
673 1f - curr.fader.getBrightness(), -1f);
679 float r1 = 0.5f + (float) Math.random() * 1f;
680 float r2 = 0.5f + (float) Math.random() * 1f;
681 curr.wobble1.advance(amount * r1);
682 curr.wobble2.advance(amount * r2);
686 Vector2f p1 =
new Vector2f(curr.loc);
687 Vector2f p2 =
new Vector2f(curr.loc);
688 p1.x += curr.normal.x * curr.width * 0.5f;
689 p1.y += curr.normal.y * curr.width * 0.5f;
690 p2.x -= curr.normal.x * curr.width * 0.5f;
691 p2.y -= curr.normal.y * curr.width * 0.5f;
693 p1.x += curr.wobble1.vector.x;
694 p1.y += curr.wobble1.vector.y;
695 p2.x += curr.wobble2.vector.x;
696 p2.y += curr.wobble2.vector.y;
700 float d = Misc.getDistance(p1, p2);
702 curr.wobbledWidth = d - params.edgeWidth * 2f * 0.25f;
703 if (curr.wobbledWidth < d * 0.5f) curr.wobbledWidth = d * 0.5f;
706 if (curr.index > 0) {
707 SlipstreamSegment prev =
segments.get(curr.index - 1);
708 Vector2f prev1 =
new Vector2f(prev.loc);
709 Vector2f prev2 =
new Vector2f(prev.loc);
710 prev1.x += prev.normal.x * prev.width * 0.5f;
711 prev1.y += prev.normal.y * prev.width * 0.5f;
712 prev2.x -= prev.normal.x * prev.width * 0.5f;
713 prev2.y -= prev.normal.y * prev.width * 0.5f;
715 float wobbleMult = 0.33f;
717 float maxWobbleRadius = Math.min(prev.width, curr.width) * 0.05f;
718 float maxWobble1 = Misc.getDistance(p1, prev1) * wobbleMult;
719 float maxWobble2 = Misc.getDistance(p2, prev2) * wobbleMult;
720 maxWobble1 = Math.min(maxWobbleRadius, maxWobble1);
721 maxWobble2 = Math.min(maxWobbleRadius, maxWobble2);
723 if (curr.index <
segments.size() - 1) {
724 SlipstreamSegment next =
segments.get(curr.index + 1);
725 Vector2f next1 =
new Vector2f(next.loc);
726 Vector2f next2 =
new Vector2f(next.loc);
727 next1.x += next.normal.x * next.width * 0.5f;
728 next1.y += next.normal.y * next.width * 0.5f;
729 next2.x -= next.normal.x * next.width * 0.5f;
730 next2.y -= next.normal.y * next.width * 0.5f;
731 maxWobbleRadius = Math.min(next.width, curr.width) * 0.05f;
732 float maxWobble1A = Misc.getDistance(p1, next1) * wobbleMult;
733 float maxWobble2A = Misc.getDistance(p2, next2) * wobbleMult;
734 maxWobble1 = Math.min(maxWobble1, maxWobble1A);
735 maxWobble2 = Math.min(maxWobble2, maxWobble2A);
738 prev.wobble1.radius.setMax(maxWobble1);
739 prev.wobble2.radius.setMax(maxWobble2);
740 curr.wobble1.radius.setMax(maxWobble1);
741 curr.wobble2.radius.setMax(maxWobble2);
754 boolean useNewSpawnMethod =
true;
757 if (useNewSpawnMethod) {
758 boolean inCurrentLocation = entity.isInCurrentLocation();
759 boolean inHyperspace = entity.isInHyperspace();
760 boolean spawnForAllSegments =
false;
762 Vector2f locFrom = viewport.getCenter();
763 float viewRadius =
new Vector2f(viewport.getVisibleWidth() * 0.5f, viewport.getVisibleHeight() * 0.5f).length();
765 viewRadius = Math.max(viewRadius, 10000f);
766 if (!inCurrentLocation) {
769 locFrom =
Global.
getSector().getPlayerFleet().getLocationInHyperspace();
771 float dist = Misc.getDistanceToPlayerLY(entity);
772 spawnForAllSegments = dist < 2f;
776 if (inCurrentLocation) {
777 float veryNearRadius =
new Vector2f(viewport.getVisibleWidth() * 0.5f, viewport.getVisibleHeight() * 0.5f).length();
786 List<SlipstreamSegment> near;
787 if (spawnForAllSegments) {
788 near =
new ArrayList<SlipstreamSegment>(
segments);
792 Set<SlipstreamSegment> nearSet =
new LinkedHashSet<SlipstreamSegment>(near);
796 Iterator<SlipstreamParticle> iter =
particles.iterator();
797 while (iter.hasNext()) {
798 SlipstreamParticle p = iter.next();
801 if (!nearSet.contains(seg)) {
806 List<SlipstreamParticle> list = particleMap.get(seg);
809 particleMap.put(seg, list);
816 float totalArea = 0f;
817 int nearParticles = 0;
822 for (
int i = 0; i < near.size(); i++) {
823 SlipstreamSegment curr = near.get(i);
824 if (curr.lengthToNext <= 0)
continue;
826 float area = curr.lengthToNext * curr.width;
827 float desiredParticles = area /
params.areaPerParticle;
828 if (desiredParticles < 1) desiredParticles = 1;
830 float particlesInSegment = 0;
831 List<SlipstreamParticle> list = particleMap.get(curr);
833 particlesInSegment = list.size();
840 if (veryNearSet.contains(curr)) mult = 10f;
842 float w = desiredParticles - particlesInSegment;
845 segmentPicker.add(curr, w);
849 nearParticles += particlesInSegment;
853 int numParticlesBasedOnArea = (int) (totalArea /
params.areaPerParticle);
854 int actualDesired = numParticlesBasedOnArea;
855 if (numParticlesBasedOnArea < 10) numParticlesBasedOnArea = 10;
856 if (numParticlesBasedOnArea >
params.maxParticles) numParticlesBasedOnArea =
params.maxParticles;
861 int particlesToAdd = numParticlesBasedOnArea - nearParticles;
865 particlesToAdd = Math.min(particlesToAdd,
params.maxParticles -
particles.size());
868 while (added < particlesToAdd) {
870 SlipstreamSegment seg = segmentPicker.pick();
871 if (seg ==
null)
continue;
873 SlipstreamParticle p =
new SlipstreamParticle();
874 float fLength = (float) Math.random() * 1f;
875 float fWidth = (float) Math.random() * 2f - 1f;
877 float speed = params.minSpeed + (params.maxSpeed -
params.minSpeed) * (
float) Math.random();
878 float dur = params.minDur + (params.maxDur -
params.minDur) * (
float) Math.random();
882 p.dist = seg.totalLength + seg.lengthToNext * fLength;
890 float speedMult = (0.65f + 0.35f * intensity) * wMult;
891 p.speed *= speedMult;
902 float totalArea = 0f;
903 for (
int i = 0; i <
segments.size(); i++) {
904 SlipstreamSegment curr =
segments.get(i);
905 totalArea += curr.lengthToPrev * curr.width;
908 int numParticlesBasedOnArea = (int) (totalArea /
params.areaPerParticle);
909 if (numParticlesBasedOnArea < 10) numParticlesBasedOnArea = 10;
910 if (numParticlesBasedOnArea >
params.maxParticles) numParticlesBasedOnArea =
params.maxParticles;
920 SlipstreamParticle p =
new SlipstreamParticle();
921 float fLength = (float) Math.random() * 1f;
922 float fWidth = (float) Math.random() * 2f - 1f;
924 float speed = params.minSpeed + (params.maxSpeed -
params.minSpeed) * (
float) Math.random();
925 float dur = params.minDur + (params.maxDur -
params.minDur) * (
float) Math.random();
936 float speedMult = (0.65f + 0.35f * intensity) * wMult;
937 p.speed *= speedMult;
1059 public void render(CampaignEngineLayers layer, ViewportAPI viewport) {
1065 if (bMult <= 0f)
return;
1067 if (
false &&
builder !=
null) {
1084 if (
true &&
false) {
1086 float mx = Mouse.getX();
1087 float my = Mouse.getY();
1088 float wmx =
Global.
getSector().getViewport().convertScreenXToWorldX(mx);
1089 float wmy =
Global.
getSector().getViewport().convertScreenYToWorldY(my);
1090 boolean inside =
false;
1092 box.renderDebug(1f);
1093 inside |= box.pointNeedsDetailedCheck(
new Vector2f(wmx, wmy));
1096 GL11.glDisable(GL11.GL_TEXTURE_2D);
1097 GL11.glEnable(GL11.GL_BLEND);
1098 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
1100 GL11.glPointSize(20f);
1101 GL11.glEnable(GL11.GL_POINT_SMOOTH);
1103 Misc.setColor(Color.green);
1105 Misc.setColor(Color.gray);
1108 GL11.glBegin(GL11.GL_POINTS);
1109 GL11.glVertex2f(wmx, wmy);
1117 float viewRadius =
new Vector2f(viewport.getVisibleWidth() * 0.5f, viewport.getVisibleHeight() * 0.5f).length();
1123 List<SlipstreamSegment> near =
getSegmentsNear(viewport.getCenter(), viewRadius);
1124 Set<SlipstreamSegment> nearSet =
new LinkedHashSet<SlipstreamSegment>(near);
1126 List<List<SlipstreamSegment>> subsections =
new ArrayList<List<SlipstreamSegment>>();
1127 int prevIndex = -10;
1128 List<SlipstreamSegment> subsection =
new ArrayList<SlipstreamSegment>();
1129 for (SlipstreamSegment seg : near) {
1130 if (prevIndex != seg.index - 1) {
1131 if (subsection !=
null && !subsection.isEmpty()) {
1132 subsections.add(subsection);
1134 subsection =
new ArrayList<SlipstreamSegment>();
1136 subsection.add(seg);
1137 prevIndex = seg.index;
1139 if (subsection !=
null && !subsection.isEmpty()) {
1140 subsections.add(subsection);
1144 sprite0.setNormalBlend();
1145 sprite0.setColor(
params.spriteColor);
1147 sprite1.setNormalBlend();
1148 sprite1.setColor(
params.spriteColor);
1150 sprite2.setNormalBlend();
1151 sprite2.setColor(
params.spriteColor);
1154 edge.setNormalBlend();
1155 edge.setColor(
params.edgeColor);
1159 for (List<SlipstreamSegment> subsection2 : subsections) {
1160 renderSegments(sprite0, sprite1, sprite2, edge, viewport.getAlphaMult(), subsection2, 0f,
false);
1207 GL11.glDisable(GL11.GL_TEXTURE_2D);
1208 GL11.glEnable(GL11.GL_BLEND);
1209 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
1215 GL11.glLineWidth(Math.max(1f, Math.min(2f, 2f/zoom)));
1217 GL11.glEnable(GL11.GL_LINE_SMOOTH);
1219 Misc.setColor(
new Color(1f, 1f, 1f, 0.5f));
1220 Misc.setColor(Color.white);
1230 for (
float offset = -1f;
false && offset <= 1f; offset += 0.1f) {
1232 GL11.glBegin(GL11.GL_LINE_STRIP);
1234 for (
float len = 0; len <
totalLength; len += incr) {
1287// perp = Misc.interpolateVector(next.normal, next2.normal, f);
1289// perp.scale(offset * params.width * 0.5f);
1292 //p = Misc.interpolateVector(pPrev, p, 0.5f);
1293 //GL11.glVertex2f(p.x + perp.x, p.y + perp.y);
1299 GL11.glVertex2f(p.x, p.y);
1303 Misc.setColor(Color.red);
1304 for (
int i = 0; i <
segments.size() - 3; i+=2) {
1306 SlipstreamSegment prev =
null;
1310 SlipstreamSegment curr =
segments.get(i);
1311 SlipstreamSegment next =
segments.get(i + 1);
1312 SlipstreamSegment next2 =
segments.get(i + 2);
1313 SlipstreamSegment next3 =
segments.get(i + 3);
1319 Vector2f p0 = curr.loc;
1320 Vector2f p1 = next.loc;
1321 Vector2f p2 = next2.loc;
1322 Vector2f p3 = next3.loc;
1340 p0 =
new Vector2f(p0);
1341 p0.x += curr.normal.x * curr.width * 0.5f * offset;
1342 p0.y += curr.normal.y * curr.width * 0.5f * offset;
1344 p2 =
new Vector2f(p2);
1345 p2.x += next2.normal.x * next2.width * 0.5f * offset;
1346 p2.y += next2.normal.y * next2.width * 0.5f * offset;
1348 p1 =
new Vector2f(next.locB);
1349 p1 =
new Vector2f(p1);
1350 p1.x += next.normal.x * next.width * 0.5f * offset;
1351 p1.y += next.normal.y * next.width * 0.5f * offset;
1367 for (
float len = 0; len < curr.lengthToNext + next.lengthToNext; len += incr) {
1368 float t = len / (curr.lengthToNext + next.lengthToNext);
1370 Vector2f p = Misc.bezier(p0, p1, p2, t);
1375 float f = len / curr.lengthToNext;
1378 perp = Misc.interpolateVector(curr.normal, next.normal, f);
1380 f = (len - curr.lengthToNext) / next.lengthToNext;
1381 perp = Misc.interpolateVector(next.normal, next2.normal, f);
1383 perp.scale(offset * curr.width * 0.5f);
1387 GL11.glVertex2f(p.x, p.y);
1516 if (place !=
null) {
1517 Misc.setColor(Color.red);
1518 GL11.glPointSize(40f/zoom);
1519 GL11.glEnable(GL11.GL_POINT_SMOOTH);
1520 GL11.glBegin(GL11.GL_POINTS);
1523 GL11.glVertex2f(p.x, p.y);
1525 Misc.setColor(Color.blue);
1527 GL11.glVertex2f(p.x, p.y);
1531 float withinSeg = place[0] - seg.totalLength;
1532 Vector2f p2 =
new Vector2f(seg.normal.y, -seg.normal.x);
1533 p2.scale(withinSeg);
1534 Vector2f.add(p2, seg.loc, p2);
1535 float width = seg.wobbledWidth;
1536 if (
segments.size() > seg.index + 1) {
1537 SlipstreamSegment next =
segments.get(seg.index + 1);
1538 width = Misc.interpolate(seg.wobbledWidth, next.wobbledWidth,
1539 (place[0] - seg.totalLength) / seg.lengthToNext);
1541 p2.x +=
getNormalAt(place[0]).x * place[1] * width * 0.5f;
1542 p2.y +=
getNormalAt(place[0]).y * place[1] * width * 0.5f;
1543 Misc.setColor(Color.green);
1544 GL11.glVertex2f(p2.x, p2.y);
1574 boolean curvedTrails =
true;
1575 boolean useTex =
false;
1581 GL11.glDisable(GL11.GL_TEXTURE_2D);
1582 GL11.glEnable(GL11.GL_BLEND);
1583 GL11.glLineWidth(Math.max(1f, Math.min(2f, 2f/zoom)));
1585 GL11.glEnable(GL11.GL_LINE_SMOOTH);
1586 GL11.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_NICEST);
1590 if (!curvedTrails) {
1591 GL11.glBegin(GL11.GL_LINES);
1599 GL11.glEnable(GL11.GL_TEXTURE_2D);
1600 GL11.glEnable(GL11.GL_BLEND);
1601 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
1607 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
1610 for (SlipstreamParticle p :
particles) {
1612 if (seg ==
null || !nearSet.contains(seg))
continue;
1617 float a = viewport.getAlphaMult();
1618 if (p.remaining <= 0.5f) {
1619 a = p.remaining / 0.5f;
1620 }
else if (p.elapsed <
params.particleFadeInTime) {
1621 a = p.elapsed /
params.particleFadeInTime;
1634 float yPos = p.yPos;
1639 GL11.glBegin(GL11.GL_QUAD_STRIP);
1641 if (curr ==
null || !viewport.isNearViewport(curr, p.speed *
params.lineLengthFractionOfSpeed + 50f)) {
1646 float incr = p.speed * params.lineLengthFractionOfSpeed / iter;
1648 for (
float i = 0; i < iter; i++) {
1649 float min = incr * 1f;
1650 float dist = p.dist - i * incr - min;
1652 if (next ==
null)
break;
1660 float a1 = a * (iter - i) / (iter - 1);
1661 if (i == 0) a1 = 0f;
1663 Misc.setColor(p.color, a1);
1664 GL11.glTexCoord2f(0, 0f);
1665 GL11.glVertex2f(curr.x + perp.x * lw, curr.y + perp.y * lw);
1666 GL11.glTexCoord2f(0, 1f);
1667 GL11.glVertex2f(curr.x - perp.x * lw, curr.y - perp.y * lw);
1672 GL11.glBegin(GL11.GL_LINE_STRIP);
1675 if (curr ==
null || !viewport.isNearViewport(curr, p.speed *
params.lineLengthFractionOfSpeed + 50f)) {
1680 float incr = p.speed * params.lineLengthFractionOfSpeed / iter;
1681 for (
float i = 0; i < iter; i++) {
1683 float min = incr * 0.5f;
1684 Vector2f next =
getPointAt(p.dist - i * incr - min, yPos);
1690 float a1 = a * (iter - i) / (iter - 1);
1692 if (i == 0) a1 = 0f;
1694 Misc.setColor(p.color, a1);
1695 GL11.glVertex2f(curr.x, curr.y);
1703 Vector2f start =
getPointAt(p.dist + p.speed *
params.lineLengthFractionOfSpeed * 0.1f, yPos);
1704 if (start ==
null || !viewport.isNearViewport(start, 500))
continue;
1707 if (mid ==
null)
continue;
1708 Vector2f end =
getPointAt(p.dist - p.speed *
params.lineLengthFractionOfSpeed * 0.9f, yPos);
1709 if (end ==
null)
continue;
1711 Misc.setColor(p.color, 0f);
1712 GL11.glVertex2f(start.x, start.y);
1713 Misc.setColor(p.color, a);
1714 GL11.glVertex2f(mid.x, mid.y);
1715 GL11.glVertex2f(mid.x, mid.y);
1716 Misc.setColor(p.color, 0f);
1717 GL11.glVertex2f(end.x, end.y);
1721 if (!curvedTrails) {
1748 SpriteAPI edge,
float alpha, List<SlipstreamSegment>
segments,
float extraTX,
boolean forMap) {
1752 if (bMult <= 0f)
return;
1755 GL11.glEnable(GL11.GL_TEXTURE_2D);
1756 GL11.glEnable(GL11.GL_BLEND);
1759 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
1766 boolean wireframe =
false;
1769 GL11.glLineWidth(1f);
1770 GL11.glEnable(GL11.GL_LINE_SMOOTH);
1771 GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
1772 GL11.glDisable(GL11.GL_TEXTURE_2D);
1773 GL11.glDisable(GL11.GL_BLEND);
1775 Misc.setColor(Color.yellow);
1776 GL11.glEnable(GL11.GL_LINE_SMOOTH);
1778 GL11.glBegin(GL11.GL_LINE_STRIP);
1779 for (SlipstreamSegment curr :
segments) {
1780 GL11.glVertex2f(curr.loc.x, curr.loc.y);
1785 boolean subtract =
false;
1788 GL14.glBlendEquation(GL14.GL_FUNC_REVERSE_SUBTRACT);
1793 GL11.glEnable(GL11.GL_TEXTURE_2D);
1794 GL11.glEnable(GL11.GL_BLEND);
1798 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
1802 sprite0.bindTexture();
1803 Color color = sprite0.getColor();
1804 GL11.glBegin(GL11.GL_QUAD_STRIP);
1805 for (
int i = 0; i <
segments.size(); i++) {
1806 SlipstreamSegment curr =
segments.get(i);
1807 float a = curr.fader.getBrightness() * curr.bMult * bMult;
1808 if (i == 0 || i ==
segments.size() - 1) a = 0f;
1810 Vector2f p1 =
new Vector2f(curr.loc);
1811 p1.x += curr.normal.x * curr.width * 0.5f;
1812 p1.y += curr.normal.y * curr.width * 0.5f;
1813 Vector2f p2 =
new Vector2f(curr.loc);
1814 p2.x -= curr.normal.x * curr.width * 0.5f;
1815 p2.y -= curr.normal.y * curr.width * 0.5f;
1818 p1.x += curr.wobble1.vector.x;
1819 p1.y += curr.wobble1.vector.y;
1820 p2.x += curr.wobble2.vector.x;
1821 p2.y += curr.wobble2.vector.y;
1824 Misc.setColor(color, alpha * 1f * a);
1825 GL11.glTexCoord2f(curr.tx + extraTX, 0f);
1826 GL11.glVertex2f(p1.x, p1.y);
1827 GL11.glTexCoord2f(curr.tx + extraTX, 1f);
1828 GL11.glVertex2f(p2.x, p2.y);
1833 sprite1.bindTexture();
1834 color = sprite1.getColor();
1835 GL11.glBegin(GL11.GL_QUAD_STRIP);
1836 for (
int i = 0; i <
segments.size(); i++) {
1837 SlipstreamSegment curr =
segments.get(i);
1838 float a = curr.fader.getBrightness() * curr.bMult * bMult;
1839 if (i == 0 || i ==
segments.size() - 1) a = 0f;
1841 Vector2f p1 =
new Vector2f(curr.loc);
1842 p1.x += curr.normal.x * curr.width * 0.5f;
1843 p1.y += curr.normal.y * curr.width * 0.5f;
1844 Vector2f p2 =
new Vector2f(curr.loc);
1845 p2.x -= curr.normal.x * curr.width * 0.5f;
1846 p2.y -= curr.normal.y * curr.width * 0.5f;
1848 p1.x += curr.wobble1.vector.x;
1849 p1.y += curr.wobble1.vector.y;
1850 p2.x += curr.wobble2.vector.x;
1851 p2.y += curr.wobble2.vector.y;
1853 Misc.setColor(color, alpha * 1f * a);
1855 GL11.glVertex2f(p1.x, p1.y);
1857 GL11.glVertex2f(p2.x, p2.y);
1861 sprite2.bindTexture();
1862 color = sprite2.getColor();
1863 GL11.glBegin(GL11.GL_QUAD_STRIP);
1864 for (
int i = 0; i <
segments.size(); i++) {
1865 SlipstreamSegment curr =
segments.get(i);
1866 float a = curr.fader.getBrightness() * curr.bMult * bMult;
1867 if (i == 0 || i ==
segments.size() - 1) a = 0f;
1869 Vector2f p1 =
new Vector2f(curr.loc);
1870 p1.x += curr.normal.x * curr.width * 0.5f;
1871 p1.y += curr.normal.y * curr.width * 0.5f;
1872 Vector2f p2 =
new Vector2f(curr.loc);
1873 p2.x -= curr.normal.x * curr.width * 0.5f;
1874 p2.y -= curr.normal.y * curr.width * 0.5f;
1876 p1.x += curr.wobble1.vector.x;
1877 p1.y += curr.wobble1.vector.y;
1878 p2.x += curr.wobble2.vector.x;
1879 p2.y += curr.wobble2.vector.y;
1881 Misc.setColor(color, alpha * 1f * a);
1883 GL11.glVertex2f(p1.x, p1.y);
1885 GL11.glVertex2f(p2.x, p2.y);
1892 color = edge.getColor();
1893 float wobbleMult = 0.5f;
1896 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
1898 GL11.glBegin(GL11.GL_QUAD_STRIP);
1900 for (
int i = 0; i <
segments.size(); i++) {
1901 SlipstreamSegment curr =
segments.get(i);
1902 float a = curr.fader.getBrightness() * curr.bMult * bMult;
1903 if (i == 0 || i ==
segments.size() - 1) a = 0f;
1916 Vector2f p1 =
new Vector2f(curr.loc);
1917 Vector2f p2 =
new Vector2f(curr.loc);
1918 p1.x += curr.normal.x * curr.width * 0.5f;
1919 p1.y += curr.normal.y * curr.width * 0.5f;
1920 p2.x += curr.normal.x * (curr.width * 0.5f -
params.edgeWidth);
1921 p2.y += curr.normal.y * (curr.width * 0.5f -
params.edgeWidth);
1927 p1.x += curr.wobble1.vector.x * wobbleMult;
1928 p1.y += curr.wobble1.vector.y * wobbleMult;
1929 p2.x += curr.wobble1.vector.x * wobbleMult;
1930 p2.y += curr.wobble1.vector.y * wobbleMult;
1933 Misc.setColor(color, alpha * 1f * a);
1934 GL11.glTexCoord2f(curr.txe1, 1f);
1935 GL11.glVertex2f(p1.x, p1.y);
1936 GL11.glTexCoord2f(curr.txe1, 0f);
1937 GL11.glVertex2f(p2.x, p2.y);
1942 GL11.glBegin(GL11.GL_QUAD_STRIP);
1944 for (
int i = 0; i <
segments.size(); i++) {
1945 SlipstreamSegment curr =
segments.get(i);
1946 float a = curr.fader.getBrightness() * curr.bMult * bMult;
1947 if (i == 0 || i ==
segments.size() - 1) a = 0f;
1949 Vector2f p1 =
new Vector2f(curr.loc);
1950 p1.x -= curr.normal.x * curr.width * 0.5f;
1951 p1.y -= curr.normal.y * curr.width * 0.5f;
1952 Vector2f p2 =
new Vector2f(curr.loc);
1953 p2.x -= curr.normal.x * (curr.width * 0.5f -
params.edgeWidth);
1954 p2.y -= curr.normal.y * (curr.width * 0.5f -
params.edgeWidth);
1957 p1.x += curr.wobble2.vector.x * wobbleMult;
1958 p1.y += curr.wobble2.vector.y * wobbleMult;
1959 p2.x += curr.wobble2.vector.x * wobbleMult;
1960 p2.y += curr.wobble2.vector.y * wobbleMult;
1963 Misc.setColor(color, alpha * 1f * a);
1964 GL11.glTexCoord2f(curr.txe2, 1f);
1965 GL11.glVertex2f(p1.x, p1.y);
1966 GL11.glTexCoord2f(curr.txe2, 0f);
1967 GL11.glVertex2f(p2.x, p2.y);
1973 GL14.glBlendEquation(GL14.GL_FUNC_ADD);
1976 if (wireframe) GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
2007 float dist = Misc.getDistance(loc, entity.getLocation());
2010 List<SlipstreamSegment> near =
getSegmentsNear(loc, extraRangeForCheck);
2012 for (SlipstreamSegment curr : near) {
2013 SlipstreamSegment next =
null;
2014 if (
segments.size() > curr.index + 1) {
2015 next =
segments.get(curr.index + 1);
2017 next =
new SlipstreamSegment();
2019 next.wobbledWidth = curr.wobbledWidth;
2021 next.normal = curr.normal;
2023 next.loc =
new Vector2f(curr.dir);
2024 next.loc.scale(curr.lengthToPrev);
2025 Vector2f.add(next.loc, curr.loc, next.loc);
2027 next.lengthToPrev = curr.lengthToPrev;
2032 Vector2f p1 = curr.loc;
2033 Vector2f p2 = next.loc;
2035 Vector2f currNormalP1 =
new Vector2f(curr.loc);
2036 Vector2f currNormalP2 =
new Vector2f(curr.normal);
2037 currNormalP2.scale(100f);
2038 Vector2f.add(currNormalP2, currNormalP1, currNormalP2);
2040 Vector2f nextNormalP1 =
new Vector2f(next.loc);
2041 Vector2f nextNormalP2 =
new Vector2f(next.normal);
2042 nextNormalP2.scale(100f);
2043 Vector2f.add(nextNormalP2, nextNormalP1, nextNormalP2);
2046 Vector2f dir =
new Vector2f(curr.dir);
2048 Vector2f p4 = Vector2f.add(p3, dir,
new Vector2f());
2050 Vector2f currNormalP = Misc.intersectLines(currNormalP1, currNormalP2, p3, p4);
2051 if (currNormalP ==
null)
continue;
2052 Vector2f nextNormalP = Misc.intersectLines(nextNormalP1, nextNormalP2, p3, p4);
2053 if (nextNormalP ==
null)
continue;
2055 float u = (p3.x - currNormalP.x) * (nextNormalP.x - currNormalP.x) +
2056 (p3.y - currNormalP.y) * (nextNormalP.y - currNormalP.y);
2057 float denom = Vector2f.sub(nextNormalP, currNormalP,
new Vector2f()).length();
2059 if (denom == 0)
continue;
2062 if (u >= 0 && u <= 1) {
2063 Vector2f normalAtP3 = Misc.interpolateVector(curr.normal, next.normal, u);
2064 normalAtP3.scale(100f);
2065 Vector2f p3PlusNormal = Vector2f.add(p3, normalAtP3,
new Vector2f());
2067 Vector2f intersect = Misc.intersectLines(p1, p2, p3, p3PlusNormal);
2068 if (intersect ==
null)
continue;
2070 float distFromLine = Vector2f.sub(intersect, p3,
new Vector2f()).length();
2071 float width = Misc.interpolate(curr.wobbledWidth, next.wobbledWidth, u);
2072 width += extraWidthForSegments;
2073 if (distFromLine >= width / 2f && !allowOutsideStream)
return null;
2075 float [] result =
new float[2];
2077 result[0] = curr.totalLength + u * next.lengthToPrev;
2078 result[1] = distFromLine / (width / 2f);
2080 float currToLoc = Misc.getAngleInDegrees(p1, p3);
2081 float segDir = Misc.getAngleInDegrees(p1, p2);
2082 if (Misc.getClosestTurnDirection(segDir, currToLoc) < 0) {
2083 result[1] = -result[1];
2124 if (other.hasTag(Tags.UNAFFECTED_BY_SLIPSTREAM))
return;
2127 if (other.isPlayerFleet()) {
2133 if (other instanceof CampaignFleetAPI) {
2134 CampaignFleetAPI fleet = (CampaignFleetAPI) other;
2144 if (offset ==
null) {
2145 if (fleet.isPlayerFleet()) {
2157 float distAlong = offset[0];
2158 float yOff = offset[1];
2172 if (intensity <= 0.05f) {
2173 if (fleet.isPlayerFleet()) {
2179 preventOtherTerrainFromAffecting(fleet);
2180 fleet.getMemoryWithoutUpdate().set(SustainedBurnAbility.SB_NO_STOP,
true, 0.1f);
2181 fleet.getMemoryWithoutUpdate().set(SustainedBurnAbility.SB_NO_SLOW,
true, 0.1f);
2183 if (fleet.isPlayerFleet()) {
2187 String text =
"Entering slipstream";
2188 if (
params.enteringSlipstreamTextOverride !=
null) {
2189 text =
params.enteringSlipstreamTextOverride;
2192 if (
params.enteringSlipstreamTextDurationOverride !=
null) {
2193 dur =
params.enteringSlipstreamTextDurationOverride;
2195 if (!text.isEmpty()) {
2196 fleet.addFloatingText(text, Misc.setAlpha(fleet.getIndicatorColor(), 255), dur);
2205 float maxFleetBurn = fleet.getFleetData().getBurnLevel();
2206 float currFleetBurn = fleet.getCurrBurnLevel();
2208 boolean reversePolarity = Misc.isReversePolarity(fleet);
2210 float maxWindBurn = params.burnLevel * 2f;
2211 float currWindBurn = intensity * maxWindBurn;
2212 float maxFleetBurnIntoWind = maxFleetBurn - Math.abs(currWindBurn);
2213 float seconds = days *
Global.
getSector().getClock().getSecondsPerDay();
2219 Vector2f p2 =
getPointAt(distAlong + 1f, yOff);
2220 if (reversePolarity) {
2224 if (p1 ==
null || p2 ==
null) {
2225 if (fleet.isPlayerFleet()) {
2233 Vector2f windDir = Misc.getUnitVectorAtDegreeAngle(Misc.getAngleInDegrees(p1, p2));
2234 if (currWindBurn < 0) {
2238 Vector2f velDir = Misc.normalise(
new Vector2f(fleet.getVelocity()));
2240 float baseFleetAccel = fleet.getTravelSpeed();
2241 if (baseFleetAccel < 10f) baseFleetAccel = 10f;
2243 boolean fleetTryingToMove = fleet.getMoveDestination() !=
null &&
2244 Misc.getDistance(fleet.getLocation(), fleet.getMoveDestination()) > fleet.getRadius() + 10f;
2245 if (fleet.isPlayerFleet()) {
2246 fleetTryingToMove &= (
2248 fleet.wasSlowMoving()
2251 String key =
"$slipstream_moveToYOffset";
2252 if (fleetTryingToMove && fleet.getMoveDestination() !=
null) {
2253 float mx = Mouse.getX();
2254 float my = Mouse.getY();
2255 float wmx =
Global.
getSector().getViewport().convertScreenXToWorldX(mx);
2256 float wmy =
Global.
getSector().getViewport().convertScreenYToWorldY(my);
2258 if (desired !=
null) {
2260 fleet.getMemoryWithoutUpdate().set(key,
true, 0.2f);
2265 if (!fleet.getMemoryWithoutUpdate().getBoolean(key)) {
2271 float windSpeedReduction = 0f;
2272 if (!fleetTryingToMove) {
2273 Vector2f dest =
new Vector2f(windDir);
2275 if (playerDesiredYOffset <= 1f && playerDesiredYOffset >= -1f) {
2276 float currOffset = offset[1];
2278 float sign = Math.signum(diff);
2279 if (reversePolarity) {
2282 float mult = Math.min(Math.abs(diff) * 1f, 1f);
2283 dest = Misc.rotateAroundOrigin(dest, Math.min(60f, 60f * mult * 1f) * sign);
2285 Vector2f.add(dest, fleet.getLocation(), dest);
2286 fleet.setMoveDestination(dest.x, dest.y);
2288 Vector2f moveDir = Misc.getUnitVectorAtDegreeAngle(
2289 Misc.getAngleInDegrees(fleet.getLocation(), fleet.getMoveDestination()));
2290 float dot = Vector2f.dot(windDir, moveDir);
2291 if (fleet.wasSlowMoving()) dot = -1f;
2293 float accelBasedMult = fleet.getAcceleration() / baseFleetAccel;
2294 accelBasedMult *= accelBasedMult;
2295 if (accelBasedMult > 1f) accelBasedMult = 1f;
2296 if (accelBasedMult < 0.1f) accelBasedMult = 0.1f;
2297 windSpeedReduction = -dot * fleet.getFleetData().getBurnLevel() * accelBasedMult;
2302 float burnBonus = fleet.getFleetData().getBurnLevel() - fleet.getFleetData().getMinBurnLevel();
2303 if (burnBonus < 0) burnBonus = 0;
2305 float maxSpeedWithWind = Misc.getSpeedForBurnLevel((
params.burnLevel * intensity) + burnBonus);
2306 if (windSpeedReduction > 0) {
2307 maxSpeedWithWind = Misc.getSpeedForBurnLevel(
2308 Math.max(
params.burnLevel * 0.5f * intensity,
params.burnLevel * intensity - windSpeedReduction));
2311 if (reversePolarity) {
2312 float polarityMult = fleet.getMemoryWithoutUpdate().getFloat(ReversePolarityToggle.POLARITY_SPEED_MULT);
2313 maxSpeedWithWind *= polarityMult;
2318 float fleetSpeedAlongWind = Vector2f.dot(windDir, fleet.getVelocity());
2319 if (fleetSpeedAlongWind >= maxSpeedWithWind) {
2326 velDir.scale(currFleetBurn);
2331 float windSpeed = Misc.getSpeedForBurnLevel(currWindBurn);
2333 Vector2f windVector =
new Vector2f(windDir);
2334 windVector.scale(windSpeed);
2336 Vector2f vel = fleet.getVelocity();
2357 float accelMult = 0.5f + 2f * intensity;
2358 accelMult += 0.25f * 20f * intensity;
2373 float extraAccelMult =
params.accelerationMult;
2374 windDir.scale(seconds * baseFleetAccel * accelMult * extraAccelMult);
2376 if (extraAccelMult > 1f) {
2377 float windAccelAmountThisFrame = windDir.length();
2378 float maxAccelThisFrame = maxSpeedWithWind - fleetSpeedAlongWind;
2380 if (windAccelAmountThisFrame > maxAccelThisFrame) {
2381 float accelThisFrameMult = maxAccelThisFrame / Math.max(1f, windAccelAmountThisFrame);
2382 if (accelThisFrameMult > 1f) accelThisFrameMult = 1f;
2383 windDir.scale(accelThisFrameMult);
2387 fleet.setVelocity(vel.x + windDir.x, vel.y + windDir.y);
2389 fleet.getStats().addTemporaryModMult(0.1f, getModId() +
"_1",
2391 fleet.getStats().getDynamic().getStat(Stats.FUEL_USE_NOT_SHOWN_ON_MAP_MULT));
2395 boolean withGlow =
true;
2396 withGlow = !
params.forceNoWindVisualEffectOnFleets;
2399 Color glowColor =
params.windGlowColor;
2400 if (fleet.getMemoryWithoutUpdate().contains(ReversePolarityToggle.POLARITY_WIND_GLOW_COLOR_KEY)) {
2401 glowColor = (Color) fleet.getMemoryWithoutUpdate().get(ReversePolarityToggle.POLARITY_WIND_GLOW_COLOR_KEY);
2404 int alpha = glowColor.getAlpha();
2406 glowColor = Misc.setAlpha(glowColor, 75);
2412 if (reversePolarity) {
2416 if (p1 !=
null && p2 !=
null) {
2417 windDir = Misc.getUnitVectorAtDegreeAngle(Misc.getAngleInDegrees(p1, p2));
2429 String modId =
"slipstream_" + entity.getId();
2434 float sizeNormal = 5f + 10f * intensity;
2435 for (FleetMemberViewAPI view : fleet.getViews()) {
2436 view.getWindEffectDirX().shift(modId, windDir.x * sizeNormal, durIn, durOut, 1f);
2437 view.getWindEffectDirY().shift(modId, windDir.y * sizeNormal, durIn, durOut, 1f);
2438 view.getWindEffectColor().shift(modId, glowColor, durIn, durOut, 1f);
2450 SensorGhost ghost = SensorGhostManager.getGhostFor(other);
2451 if (ghost ==
null)
return;
2453 if (other.hasTag(Tags.UNAFFECTED_BY_SLIPSTREAM))
return;
2461 if (offset ==
null) {
2465 float distAlong = offset[0];
2466 float yOff = offset[1];
2473 if (intensity <= 0) {
2477 float maxFleetBurn = ghost.getMaxBurn();
2478 float currFleetBurn = ghost.getCurrBurn();
2480 float maxWindBurn = params.burnLevel * 2f;
2482 float currWindBurn = intensity * maxWindBurn;
2483 float maxFleetBurnIntoWind = maxFleetBurn - Math.abs(currWindBurn);
2484 float seconds = days *
Global.
getSector().getClock().getSecondsPerDay();
2487 Vector2f p2 =
getPointAt(distAlong + 1f, yOff);
2488 if (p1 ==
null || p2 ==
null) {
2492 Vector2f windDir = Misc.getUnitVectorAtDegreeAngle(Misc.getAngleInDegrees(p1, p2));
2493 if (currWindBurn < 0) {
2496 Vector2f velDir = Misc.normalise(
new Vector2f(other.getVelocity()));
2497 float baseFleetAccel = ghost.getAcceleration();
2498 if (baseFleetAccel < 10f) baseFleetAccel = 10f;
2500 velDir.scale(currFleetBurn);
2502 float fleetBurnAgainstWind = -1f * Vector2f.dot(windDir, velDir);
2505 float windSpeed = Misc.getSpeedForBurnLevel(currWindBurn);
2506 Vector2f windVector =
new Vector2f(windDir);
2507 windVector.scale(windSpeed);
2509 Vector2f vel = other.getVelocity();
2510 Vector2f diff = Vector2f.sub(windVector, vel,
new Vector2f());
2511 float max = diff.length();
2512 diff = Misc.normalise(diff);
2513 diff.scale(ghost.getAcceleration() * 3f * seconds);
2514 if (diff.length() > max) {
2515 diff.scale(max / diff.length());
2517 float accelMult = 0.5f + 2f * intensity;
2518 if (fleetBurnAgainstWind > maxFleetBurnIntoWind) {
2519 accelMult += 0.25f * (fleetBurnAgainstWind - maxFleetBurnIntoWind);
2521 windDir.scale(seconds * baseFleetAccel * accelMult);
2523 ghost.getMovement().getVelocity().set(vel.x + windDir.x, vel.y + windDir.y);
2860 public void renderOnMap(
float factor,
float alphaMult,
boolean forRadar, Vector2f radarCenter) {
2864 Set<SlipstreamSegment> nearSet =
new LinkedHashSet<SlipstreamSegment>();
2868 nearSet =
new LinkedHashSet<SlipstreamSegment>(
getSegmentsNear(radarCenter, radius));
2869 for (SlipstreamSegment curr : nearSet) {
2870 curr.discovered =
true;
2872 if (nearSet.isEmpty())
return;
2875 List<SlipstreamSegment> list =
new ArrayList<SlipstreamSegment>();
2876 int incr = Math.min(
segments.size() / 10, 5);
2878 if (incr < 1) incr = 1;
2879 for (
int i = 0; i <
segments.size(); i+=incr) {
2880 SlipstreamSegment curr =
segments.get(i);
2881 if (forRadar && !nearSet.contains(curr))
continue;
2892 List<List<SlipstreamSegment>> subsections =
new ArrayList<List<SlipstreamSegment>>();
2893 int prevIndex = -10;
2894 List<SlipstreamSegment> subsection =
new ArrayList<SlipstreamSegment>();
2895 for (SlipstreamSegment seg : list) {
2896 if (prevIndex != seg.index - 1) {
2897 if (subsection !=
null && !subsection.isEmpty()) {
2898 subsections.add(subsection);
2900 subsection =
new ArrayList<SlipstreamSegment>();
2902 subsection.add(seg);
2903 prevIndex = seg.index;
2905 if (subsection !=
null && !subsection.isEmpty()) {
2906 subsections.add(subsection);
2909 float texOffset = 0f;
2910 FaderUtil fader =
Global.
getSector().getCampaignUI().getSharedFader();
2911 float b = fader.getBrightness();
2914 if (fader.getState() == State.IN) {
2916 }
else if (fader.getState() == State.OUT) {
2924 GL11.glPushMatrix();
2925 GL11.glScalef(factor, factor, 1f);
2927 for (List<SlipstreamSegment> subsection2 : subsections) {
2955 float widthMult = 1f;
2956 float lengthPerArrowMult = 1f;
2957 float minFactor = 0.012f;
2958 if (factor < minFactor) {
2959 widthMult = minFactor / factor;
2960 lengthPerArrowMult = 2f;
2963 float lengthPerArrow = 700f;
2965 lengthPerArrow *= lengthPerArrowMult;
2966 float start =
segments.get(0).totalLength;
2969 start = (float) (Math.floor(start / lengthPerArrow) * lengthPerArrow);
2970 end = (float) (Math.ceil(end/ lengthPerArrow) * lengthPerArrow);
2971 if (end - start < lengthPerArrow)
return;
2974 Color color =
params.mapColor;
2977 GL11.glDisable(GL11.GL_TEXTURE_2D);
2978 GL11.glEnable(GL11.GL_BLEND);
2979 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
2982 GL11.glEnable(GL11.GL_POLYGON_SMOOTH);
2983 GL11.glHint(GL11.GL_POLYGON_SMOOTH_HINT, GL11.GL_NICEST);
2985 float fadeDist = 500f;
2987 GL11.glBegin(GL11.GL_TRIANGLES);
2988 for (
float len = start; len < end; len += lengthPerArrow) {
2989 Vector2f p0 =
getPointAt(len + phase * lengthPerArrow, 0f);
2990 Vector2f p1 =
getPointAt(len + phase * lengthPerArrow + 10f, 0f);
2991 if (p0 ==
null || p1 ==
null)
continue;
2993 float w =
getWidth(len + phase * lengthPerArrow) * widthMult;
2994 float triLength = lengthPerArrow * 0.33f;
2995 triLength = lengthPerArrow * 1f;
2996 triLength = Math.min(lengthPerArrow, (w + lengthPerArrow) / 2f);
3000 if (len + phase * lengthPerArrow - start < fadeDist) {
3001 a *= (len + phase * lengthPerArrow - start) / fadeDist;
3003 if (len + phase * lengthPerArrow > end - fadeDist) {
3004 a *= (end - (len + phase * lengthPerArrow)) / fadeDist;
3006 if (a <= 0f)
continue;
3011 Vector2f t0 =
getPointAt(len + phase * lengthPerArrow + triLength/2f, 0f);
3012 if (t0 ==
null)
continue;
3014 Vector2f dir = Misc.getUnitVector(p0, t0);
3015 Vector2f perp =
new Vector2f(-dir.y, dir.x);
3017 Vector2f t1 =
new Vector2f(p0);
3018 Vector2f t2 =
new Vector2f(p0);
3019 Vector2f t3 =
new Vector2f(p0);
3020 float backOffset = 0f;
3022 backOffset = triLength * 0.1f;
3023 t3.x -= dir.x * backOffset;
3024 t3.y -= dir.y * backOffset;
3026 t1.x += perp.x * w/2f;
3027 t1.y += perp.y * w/2f;
3028 t1.x -= dir.x * triLength/2f;
3029 t1.y -= dir.y * triLength/2f;
3031 t2.x -= perp.x * w/2f;
3032 t2.y -= perp.y * w/2f;
3033 t2.x -= dir.x * triLength/2f;
3034 t2.y -= dir.y * triLength/2f;
3045 Misc.setColor(color, alphaMult * 1f * a);
3046 GL11.glVertex2f(t0.x, t0.y);
3047 Misc.setColor(color, alphaMult * 0f * a);
3048 GL11.glVertex2f(t1.x, t1.y);
3049 GL11.glVertex2f(t3.x, t3.y);
3051 Misc.setColor(color, alphaMult * 1f * a);
3052 GL11.glVertex2f(t0.x, t0.y);
3053 Misc.setColor(color, alphaMult * 0f * a);
3054 GL11.glVertex2f(t2.x, t2.y);
3055 GL11.glVertex2f(t3.x, t3.y);
3080 GL11.glEnable(GL11.GL_TEXTURE_2D);
3081 GL11.glEnable(GL11.GL_BLEND);
3082 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
3089 GL11.glBegin(GL11.GL_QUAD_STRIP);
3090 for (
float len = start; len < end; len += incr) {
3093 if (p0 ==
null || p1 ==
null)
continue;
3095 Vector2f dir = Misc.getUnitVector(p0, p1);
3096 Vector2f perp =
new Vector2f(-dir.y, dir.x);
3099 Vector2f p2 =
new Vector2f(p0);
3100 Vector2f p3 =
new Vector2f(p0);
3101 p2.x += perp.x * w * 0.5f;
3102 p2.y += perp.y * w * 0.5f;
3103 p3.x -= perp.x * w * 0.5f;
3104 p3.y -= perp.y * w * 0.5f;
3107 if (len - start < fadeDist) {
3108 a *= (len - start) / fadeDist;
3110 if (len > end - fadeDist) {
3111 a *= (end - len) / fadeDist;
3114 Misc.setColor(color, alphaMult * a * 0.5f);
3115 GL11.glTexCoord2f(0f, 0f);
3116 GL11.glVertex2f(p2.x, p2.y);
3117 GL11.glTexCoord2f(0f, 1f);
3118 GL11.glVertex2f(p3.x, p3.y);
3122 GL11.glDisable(GL11.GL_POLYGON_SMOOTH);
3130 if (fleet !=
null && entity.isInCurrentLocation()) {
3131 Vector2f loc = fleet.getLocation();
3133 float outerPlaybackRange = (float) getSpec().getCustom().optDouble(
"outsideSoundRange", 1000f);
3136 float innerVolume = 0f;
3137 float innerPitch = 1f;
3138 float outerVolume = 0f;
3139 float outerPitch = 1f;
3141 SlipstreamSegment segment =
null;
3142 List<SlipstreamSegment> near =
getSegmentsNear(loc, outerPlaybackRange + 2000f);
3143 float pointProximityOuterVolume = 0f;
3144 for (SlipstreamSegment curr : near) {
3145 float dist = Misc.getDistance(loc, curr.loc);
3146 float check = curr.wobbledWidth / 2f + outerPlaybackRange;
3148 float volume = 1f - dist / check;
3149 volume *= curr.bMult * curr.fader.getBrightness();
3150 if (volume > pointProximityOuterVolume) {
3151 pointProximityOuterVolume = volume;
3159 outerVolume = pointProximityOuterVolume;
3162 float f = Math.abs(coords[1]);
3166 float minPitch = (float) getSpec().getCustom().optDouble(
"minPitch", 0.5f);
3167 float maxPitch = (float) getSpec().getCustom().optDouble(
"maxPitch", 1.25f);
3169 innerVolume = 0f + 1f * (Math.min(1f, intensity * 2f) * wMult);
3170 innerPitch = minPitch + (1f - minPitch) * intensity * wMult;
3171 if (innerPitch > maxPitch) innerPitch = maxPitch;
3173 if (intensity >= 0.5f) {
3177 float distFromStream = 0f;
3178 distFromStream =
getWidth(coords[0]) * 0.5f * (f - 1f);
3179 if (distFromStream < outerPlaybackRange) {
3180 float intensity = 1f - distFromStream / outerPlaybackRange;
3181 outerVolume = 0f + 1f * (intensity * wMult);
3185 innerVolume *= fMult;
3186 outerVolume *= fMult;
3187 outerVolume = Math.max(outerVolume, pointProximityOuterVolume);
3189 outerVolume = Math.min(outerVolume, 1f - innerVolume);
3192 if (innerVolume < 0) innerVolume = 0;
3193 if (innerVolume > 1) innerVolume = 1;
3194 if (outerVolume > 1) outerVolume = 1;
3195 if (outerVolume < 0) outerVolume = 0;
3205 float loopFade = 0.5f;
3207 String soundId = getSpec().getLoopOne();
3209 float filterMult = innerVolume;
3210 if (innerVolume > 0f) {
3216 }
else if (outerVolume > 0.5f) {
3217 filterMult = Math.min(1f, (outerVolume - 0.5f) * 4f);
3220 if (innerVolume > 0) {
3221 float gain = (float) getSpec().getCustom().optDouble(
"gain", 0.75f);
3222 float gainHF = (float) getSpec().getCustom().optDouble(
"gainHF", 0.5f);
3225 Math.max(0f, 1f - (1f - gain) * innerVolume),
3226 Math.max(0f, 1f - Math.min(1f - gainHF, innerVolume)));
3231 if (soundId !=
null && innerVolume > 0f) {
3233 getLoopOneVolume() * innerVolume, fleet.getLocation(), Misc.ZERO, loopFade, loopFade);
3235 soundId = getSpec().getLoopTwo();
3236 if (soundId !=
null && outerVolume > 0f) {
3237 Vector2f playbackLoc = fleet.getLocation();
3238 if (segment !=
null) playbackLoc = segment.loc;
3240 getLoopTwoVolume() * outerVolume, playbackLoc, Misc.ZERO, loopFade, loopFade);
3243 float suppressionMult = innerVolume;
3244 suppressionMult = filterMult;
3245 Global.
getSector().getCampaignUI().suppressMusic(getSpec().getMusicSuppression() * suppressionMult);
3271 List<List<SlipstreamSegment>> sections =
new ArrayList<List<SlipstreamSegment>>();
3273 boolean currSectionIsBreak =
false;
3274 List<SlipstreamSegment> list =
new ArrayList<SlipstreamSegment>();
3275 for (
int i = 0; i <
segments.size(); i++) {
3276 SlipstreamSegment curr =
segments.get(i);
3277 boolean currSegmentIsBreak = curr.bMult <= 0f;
3278 if (list.isEmpty()) {
3279 currSectionIsBreak = currSegmentIsBreak;
3281 if (currSectionIsBreak == currSegmentIsBreak) {
3284 if (!list.isEmpty()) {
3287 list =
new ArrayList<SlipstreamSegment>();
3292 boolean prevSectionWasLongEnough =
false;
3293 for (List<SlipstreamSegment> section : sections) {
3294 boolean sectionIsBreak = section.get(0).bMult <= 0;
3295 float sectionLength = section.get(section.size() - 1).
totalLength - section.get(0).totalLength;
3297 if (sectionIsBreak && prevSectionWasLongEnough && sectionLength >= 1000f) {
3298 Vector2f loc =
new Vector2f(section.get(0).loc);
3299 Vector2f dir =
new Vector2f(section.get(0).dir);
3300 dir.scale(Math.min(1000f, sectionLength * 0.4f));
3301 Vector2f.add(dir, loc, loc);
3305 if (!sectionIsBreak && section.size() >= 10f) {
3306 prevSectionWasLongEnough =
true;
3308 prevSectionWasLongEnough =
false;
3311 if (prevSectionWasLongEnough) {
3312 List<SlipstreamSegment> section = sections.get(sections.size() - 1);
3313 Vector2f loc =
new Vector2f(section.get(section.size() - 1).loc);
3314 Vector2f dir =
new Vector2f(section.get(section.size() - 1).dir);
3316 Vector2f.add(dir, loc, loc);