Starsector API
Loading...
Searching...
No Matches
TriadShieldStatsBackup.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.combat;
2
3import java.awt.Color;
4import java.util.ArrayList;
5import java.util.EnumSet;
6import java.util.List;
7
8import org.lwjgl.opengl.GL11;
9import org.lwjgl.util.vector.Vector2f;
10
11import com.fs.starfarer.api.Global;
12import com.fs.starfarer.api.combat.BaseCombatLayeredRenderingPlugin;
13import com.fs.starfarer.api.combat.BoundsAPI;
14import com.fs.starfarer.api.combat.CombatEngineLayers;
15import com.fs.starfarer.api.combat.CombatEntityAPI;
16import com.fs.starfarer.api.combat.DamageAPI;
17import com.fs.starfarer.api.combat.MutableShipStatsAPI;
18import com.fs.starfarer.api.combat.ShipAPI;
19import com.fs.starfarer.api.combat.ShipSystemAPI;
20import com.fs.starfarer.api.combat.ViewportAPI;
21import com.fs.starfarer.api.combat.BoundsAPI.SegmentAPI;
22import com.fs.starfarer.api.combat.listeners.DamageTakenModifier;
23import com.fs.starfarer.api.graphics.SpriteAPI;
24import com.fs.starfarer.api.util.FaderUtil;
25import com.fs.starfarer.api.util.FlickerUtilV2;
26import com.fs.starfarer.api.util.Misc;
27
29
30 public static float SIDE_LENGTH = 16f;
31 public static float INSIDE_ALPHA = 0.25f;
32
33 public static class ShieldPieceConnection {
34 public ShieldPiece from;
35 public ShieldPiece to;
36 public float baseLength = 0f;
37
38 public ShieldPieceConnection(ShieldPiece from, ShieldPiece to) {
39 this.from = from;
40 this.to = to;
41 baseLength = Misc.getDistance(from.offset, to.offset);
42 baseLength *= 0.9f + (float) Math.random() * 0.2f;
43 }
44
45 public void advance(float amount) {
46 Vector2f fLoc = from.getAdjustedOffset();
47 Vector2f tLoc = to.getAdjustedOffset();
48 float length = Misc.getDistance(fLoc, tLoc);
49 float diff = length - baseLength;
50
51 float k = 1f;
52 float accel = diff * k;
53
54 Vector2f dir = Misc.getUnitVectorAtDegreeAngle(Misc.getAngleInDegrees(fLoc, tLoc));
55
56 dir.scale(accel * amount);
57 Vector2f.add(from.vel, dir, from.vel);
58 dir.negate();
59 Vector2f.add(to.vel, dir, to.vel);
60
61
62 float maxOff = 20f;
63 from.off.x += from.vel.x * amount;
64 from.off.y += from.vel.y * amount;
65 if (from.off.length() > maxOff) from.off.scale(maxOff / from.off.length());
66
67 to.off.x += to.vel.x * amount;
68 to.off.y += to.vel.y * amount;
69 if (to.off.length() > maxOff) to.off.scale(maxOff / to.off.length());
70 }
71 }
72
73 public static class ShieldPiece {
74 public ShipAPI ship;
75 public Vector2f offset = new Vector2f();
76
77 public Vector2f off = new Vector2f(); // secondary offset due to movement of individual triangles
78 public Vector2f vel = new Vector2f();
79
80 public SpriteAPI sprite;
81 public boolean upsideDown = false;
82
83 public float side;
84 public Vector2f p1, p2, p3;
85 public float baseAlphaMult = 1f;
86 public float p1Alpha = 1f;
87 public float p2Alpha = 1f;
88 public float p3Alpha = 1f;
89
90 public FaderUtil fader;
91 public FlickerUtilV2 flicker;
92
93 public ShieldPiece(ShipAPI ship, boolean upsideDown, float x, float y, float side) {
94 this.ship = ship;
95 this.side = side;
96 offset.set(x, y);
97 this.upsideDown = upsideDown;
98
99
100 fader = new FaderUtil(0f, 0.25f, 0.25f);
101 fader.setBrightness((float) Math.random() * 1f);
102 fader.setBounce(true, true);
103 fader.fadeIn();
104
105 flicker = new FlickerUtilV2();
106
107 //sprite = Global.getSettings().getSprite("misc", "fx_shield_piece");
108 sprite = Global.getSettings().getSprite("graphics/hud/line8x8.png");
109 //sprite = Global.getSettings().getSprite("graphics/hud/line32x32.png");
110
111 // updside down means the flat side is on the left
112 // p1 is always the lone point, p2->p3 the flat side on the left/right
113 // triangles are arranged as if ship is pointed at a 0 degree angle, i.e. facing right
114 float height = (float) (side * Math.sqrt(3f) / 2f);
115 if (upsideDown) {
116 p1 = new Vector2f(x + height/2f, y);
117 p2 = new Vector2f(x - height/2f - 1, y - side/2f);
118 p3 = new Vector2f(x - height/2f - 1, y + side/2f);
119 } else {
120 p1 = new Vector2f(x - height/2f, y);
121 p2 = new Vector2f(x + height/2f, y - side/2f);
122 p3 = new Vector2f(x + height/2f, y + side/2f);
123 }
124 updatePointAlpha();
125 }
126
127 public void updatePointAlpha() {
128 //if (true) return;
129 BoundsAPI bounds = ship.getExactBounds();
130 bounds.update(new Vector2f(0, 0), 0f);
131 p1Alpha = getPointAlpha(p1);
132 p2Alpha = getPointAlpha(p2);
133 p3Alpha = getPointAlpha(p3);
134
135 baseAlphaMult = Math.max(p1Alpha, p2Alpha);
136 baseAlphaMult = Math.max(baseAlphaMult, p3Alpha);
137// if (baseAlphaMult > 0) {
138// p1Alpha = p2Alpha = p3Alpha = 1f;
139// }
140 }
141 public float getPointAlpha(Vector2f p) {
142 BoundsAPI bounds = ship.getExactBounds();
143
144 float minDist = Float.MAX_VALUE;
145 List<Vector2f> boundsPoints = new ArrayList<Vector2f>();
146 for (SegmentAPI segment : bounds.getSegments()) {
147 Vector2f n = Misc.closestPointOnSegmentToPoint(segment.getP1(), segment.getP2(), p);
148 float dist = Misc.getDistance(n, p);
149 if (dist < minDist) minDist = dist;
150
151 boundsPoints.add(segment.getP1());
152 }
153 boundsPoints.add(bounds.getSegments().get(bounds.getSegments().size() - 1).getP2());
154
155 float minAlphaAt = SIDE_LENGTH * 1f;
156 float minAlpha = 0f;
157 boolean inBounds = Misc.isPointInBounds(p, boundsPoints);
158 if (inBounds) {
159 //if (true) return 1f;
160// minAlpha = INSIDE_ALPHA;
161// minAlpha = 0.25f;
162 minAlphaAt = SIDE_LENGTH * 2f;
163 minAlphaAt = 0f;
164 }
165
166 if (minDist > minAlphaAt) {
167 return minAlpha;
168 }
169
170
171 return Math.max(minAlpha, 1f - Math.min(1f, minDist / (minAlphaAt * 2f)));
172
173 //return Math.max(minAlpha, 1f - minDist / minAlphaAt);
174 }
175
176 public Vector2f getAdjustedOffset() {
177 return Vector2f.add(offset, off, new Vector2f());
178 }
179
180 public Vector2f getCenter() {
181 Vector2f result = new Vector2f(offset);
182 Misc.rotateAroundOrigin(result, ship.getFacing());
183 Vector2f.add(ship.getLocation(), result, result);
184 return result;
185 }
186
187 public void advance(float amount) {
188 fader.advance(amount * (0.5f + 0.5f * (float) Math.random()));
189 //flicker.advance(amount);
190 }
191
196 public void render(float alphaMult) {
197 Color color = new Color(255, 165, 100, 255);
198 color = new Color(100, 165, 255, 255);
199 //color = new Color(0, 0, 255, 255);
200 //color = Misc.scaleAlpha(color, 0.5f);
201
202// float size = 14f;
203// float x = offset.x;
204// float y = offset.y;
205// sprite.setSize(size, size);
206// sprite.setColor(color);
207// sprite.setAdditiveBlend();
208// sprite.setNormalBlend();
209// sprite.setAngle(-90);
210// if (upsideDown) {
211// sprite.setAngle(-90 + 180f);
212// }
213// sprite.setAlphaMult(alphaMult);
214// sprite.renderAtCenter(x, y);
215
216 if (true) {
217// p1Alpha = p2Alpha = p3Alpha = 1f;
218// baseAlphaMult = 1f;
219// alphaMult = 1f;
220 GL11.glPushMatrix();
221 GL11.glTranslatef(off.x, off.y, 0f);
222
223 for (int i = 0; i < 2; i++) {
224 GL11.glEnable(GL11.GL_TEXTURE_2D);
225 sprite.bindTexture();
226 GL11.glEnable(GL11.GL_BLEND);
227 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
228// if (i == 0) {
229// GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
230// }
231
232// float sin = (float) Math.sin(Math.toRadians(30f));
233// float cos = (float) Math.sin(Math.toRadians(30f));
234 float t = 9f;
235 float a = 0.25f;
236 if (i == 1) {
237 t = 4f;
238 a = 1f;
239 }
240
241 //float in = (float) (Math.sin(Math.toRadians(30f)) * t);
242 if (upsideDown) {
243 GL11.glBegin(GL11.GL_QUAD_STRIP);
244
245 Misc.setColor(color, alphaMult * p1Alpha * a);
246 GL11.glTexCoord2f(0f, 0f);
247 GL11.glVertex2f(p1.x, p1.y);
248 GL11.glTexCoord2f(0f, 1f);
249 GL11.glVertex2f(p1.x - t, p1.y);
250
251 Misc.setColor(color, alphaMult * p2Alpha * a);
252 GL11.glTexCoord2f(0f, 0f);
253 GL11.glVertex2f(p2.x, p2.y);
254 GL11.glTexCoord2f(0f, 1f);
255 GL11.glVertex2f(p2.x + t * 0.5f, p2.y + t);
256
257 Misc.setColor(color, alphaMult * p3Alpha * a);
258 GL11.glTexCoord2f(0f, 0f);
259 GL11.glVertex2f(p3.x, p3.y);
260 GL11.glTexCoord2f(0f, 1f);
261 GL11.glVertex2f(p3.x + t * 0.5f, p3.y - t);
262
263 Misc.setColor(color, alphaMult * p1Alpha * a);
264 GL11.glTexCoord2f(0f, 0f);
265 GL11.glVertex2f(p1.x, p1.y);
266 GL11.glTexCoord2f(0f, 1f);
267 GL11.glVertex2f(p1.x - t, p1.y);
268
269 GL11.glEnd();
270 } else {
271 GL11.glBegin(GL11.GL_QUAD_STRIP);
272
273 Misc.setColor(color, alphaMult * p1Alpha * a);
274 GL11.glTexCoord2f(0f, 0f);
275 GL11.glVertex2f(p1.x, p1.y);
276 GL11.glTexCoord2f(0f, 1f);
277 GL11.glVertex2f(p1.x + t, p1.y);
278
279 Misc.setColor(color, alphaMult * p2Alpha * a);
280 GL11.glTexCoord2f(0f, 0f);
281 GL11.glVertex2f(p2.x, p2.y);
282 GL11.glTexCoord2f(0f, 1f);
283 GL11.glVertex2f(p2.x - t * 0.5f, p2.y + t);
284
285 Misc.setColor(color, alphaMult * p3Alpha * a);
286 GL11.glTexCoord2f(0f, 0f);
287 GL11.glVertex2f(p3.x, p3.y);
288 GL11.glTexCoord2f(0f, 1f);
289 GL11.glVertex2f(p3.x - t * 0.5f, p3.y - t);
290
291 Misc.setColor(color, alphaMult * p1Alpha * a);
292 GL11.glTexCoord2f(0f, 0f);
293 GL11.glVertex2f(p1.x, p1.y);
294 GL11.glTexCoord2f(0f, 1f);
295 GL11.glVertex2f(p1.x + t, p1.y);
296
297 GL11.glEnd();
298 }
299 }
300
301 GL11.glPopMatrix();
302 return;
303 }
304
305
306 GL11.glDisable(GL11.GL_TEXTURE_2D);
307 GL11.glEnable(GL11.GL_BLEND);
308 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
309 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
310
311// GL11.glColor4ub((byte)color.getRed(),
312// (byte)color.getGreen(),
313// (byte)color.getBlue(),
314// (byte)(color.getAlpha() * alphaMult));
315
316 alphaMult *= baseAlphaMult;
317 //alphaMult *= 0.67f + 0.33f * fader.getBrightness();
318
319
320 GL11.glBegin(GL11.GL_TRIANGLES);
321 {
322 float i = 0f;
323 float j = 0f;
324// alphaMult *= 0.2f;
325// float incr = 0.5f;
326// for (float i = -incr; i <= incr; i+=incr) {
327// for (float j = -incr; j <= incr; j+=incr) {
328 Misc.setColor(color, alphaMult * p1Alpha);
329 GL11.glVertex2f(p1.x + i, p1.y + j);
330 Misc.setColor(color, alphaMult * p2Alpha);
331 GL11.glVertex2f(p2.x + i, p2.y + j);
332 Misc.setColor(color, alphaMult * p3Alpha);
333 GL11.glVertex2f(p3.x + i, p3.y + j);
334// }
335// }
336 }
337 GL11.glEnd();
338
339// GL11.glBegin(GL11.GL_TRIANGLES);
340// {
341// Misc.setColor(color, alphaMult * p1Alpha);
342// GL11.glVertex2f(p1.x, p1.y);
343// Misc.setColor(color, alphaMult * p2Alpha);
344// GL11.glVertex2f(p2.x, p2.y);
345// Misc.setColor(color, alphaMult * p3Alpha);
346// GL11.glVertex2f(p3.x, p3.y);
347// }
348// GL11.glEnd();
349
350// GL11.glBegin(GL11.GL_QUADS);
351// {
352// GL11.glVertex2f(x, y);
353// GL11.glVertex2f(x, y + h);
354// GL11.glVertex2f(x + w, y + h);
355// GL11.glVertex2f(x + w, y);
356// }
357// GL11.glEnd();
358 }
359 }
360
361
362 public static class TriadShieldVisuals extends BaseCombatLayeredRenderingPlugin {
363 public ShipAPI ship;
364 public TriadShieldStatsBackup script;
365 public List<ShieldPiece> pieces = new ArrayList<ShieldPiece>();
366 public List<ShieldPieceConnection> connections = new ArrayList<ShieldPieceConnection>();
367
368 public TriadShieldVisuals(ShipAPI ship, TriadShieldStatsBackup script) {
369 this.ship = ship;
370 this.script = script;
371 addShieldPieces();
372 }
373
374 public void addShieldPieces() {
375 pieces.clear();
376
377 SIDE_LENGTH = 20f;
378 //SIDE_LENGTH = 10f;
379 //SIDE_LENGTH = 120f;
380
381 float side = SIDE_LENGTH;
382 float height = (float) (side * Math.sqrt(3f) / 2f);
383 float centerFromBottom = (float) (Math.sin(Math.toRadians(30f)) * height);
384 //centerFromBottom = side/2f;
385 int gridHeight = (int) (ship.getCollisionRadius() / side) * 2;
386 if (gridHeight / 2 != 0) gridHeight++;
387 if (gridHeight < 6) gridHeight = 6;
388 int gridWidth = (int) (ship.getCollisionRadius() / height) * 2;
389 if (gridWidth / 2 != 0) gridWidth++;
390 if (gridWidth < 6) gridWidth = 6;
391 for (int i = -gridWidth/2; i < gridWidth/2; i++) {
392 for (int j = -gridHeight/2; j < gridHeight/2; j++) {
393 float lowX = i * height + height/2f;
394 float highX = (i + 1) * height + height/2f;
395 float centerY = j * side + side/2f;
396 ShieldPiece piece = new ShieldPiece(ship, true, lowX + centerFromBottom, centerY, side - 2f);
397 if (piece.baseAlphaMult > 0) {
398 pieces.add(piece);
399 }
400
401 if (j != gridHeight/2 - 1) {
402 centerY += side/2f;
403 piece = new ShieldPiece(ship, false, highX - centerFromBottom, centerY, side - 2f);
404 if (piece.baseAlphaMult > 0) {
405 pieces.add(piece);
406 }
407 }
408 }
409 }
410
411 float maxDist = SIDE_LENGTH * 1.2f;
412 for (int i = 0; i < pieces.size() - 1; i++) {
413 ShieldPiece curr = pieces.get(i);
414 for (int j = i + 1; j < pieces.size(); j++) {
415 ShieldPiece other = pieces.get(j);
416 if (curr == other) continue;
417 if (Misc.getDistance(curr.offset, other.offset) > maxDist) continue;
418
419 ShieldPieceConnection conn = new ShieldPieceConnection(curr, other);
420 connections.add(conn);
421 }
422 }
423 }
424
425 @Override
426 public EnumSet<CombatEngineLayers> getActiveLayers() {
427 return EnumSet.of(CombatEngineLayers.ABOVE_SHIPS_AND_MISSILES_LAYER);
428 }
429 @Override
430 public boolean isExpired() {
431 return false;
432 }
433 @Override
434 public float getRenderRadius() {
435 return ship.getCollisionRadius() + 100f;
436 }
437
438 @Override
439 public void advance(float amount) {
440 entity.getLocation().set(ship.getLocation());
441 if (Global.getCombatEngine().isPaused()) return;
442
443 for (ShieldPiece piece : pieces) {
444 piece.advance(amount);
445 }
446
447 for (ShieldPieceConnection conn : connections) {
448 conn.advance(amount);
449 }
450 }
451
452 @Override
453 public void render(CombatEngineLayers layer, ViewportAPI viewport) {
454 float alphaMult = viewport.getAlphaMult();
455
456 ShipSystemAPI system = ship.getPhaseCloak();
457 if (system == null) system = ship.getSystem();
458 alphaMult *= system.getEffectLevel();
459 if (alphaMult <= 0f) return;
460
461 GL11.glPushMatrix();
462 GL11.glTranslatef(ship.getLocation().x, ship.getLocation().y, 0);
463 GL11.glRotatef(ship.getFacing(), 0, 0, 1);
464
465 for (ShieldPiece piece : pieces) {
466 piece.render(alphaMult);
467 }
468 GL11.glPopMatrix();
469
470// Color color = Color.red;
471// color = Misc.scaleAlpha(color, 0.5f);
472//
473// float x = ship.getLocation().x - ship.getCollisionRadius() * 0.5f;
474// float y = ship.getLocation().y - ship.getCollisionRadius() * 0.5f;
475// float w = ship.getCollisionRadius();
476// float h = ship.getCollisionRadius();
477//
478// GL11.glDisable(GL11.GL_TEXTURE_2D);
479// GL11.glEnable(GL11.GL_BLEND);
480// GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
481//
482//
483// GL11.glColor4ub((byte)color.getRed(),
484// (byte)color.getGreen(),
485// (byte)color.getBlue(),
486// (byte)(color.getAlpha() * alphaMult));
487//
488// GL11.glBegin(GL11.GL_QUADS);
489// {
490// GL11.glVertex2f(x, y);
491// GL11.glVertex2f(x, y + h);
492// GL11.glVertex2f(x + w, y + h);
493// GL11.glVertex2f(x + w, y);
494// }
495// GL11.glEnd();
496 }
497 }
498
499 protected TriadShieldVisuals visuals = null;
500
501 public String modifyDamageTaken(Object param, CombatEntityAPI target, DamageAPI damage, Vector2f point, boolean shieldHit) {
502 return null;
503 }
504
505 public void apply(MutableShipStatsAPI stats, String id, State state, float effectLevel) {
506 ShipAPI ship = null;
507 boolean player = false;
508 if (stats.getEntity() instanceof ShipAPI) {
509 ship = (ShipAPI) stats.getEntity();
510 player = ship == Global.getCombatEngine().getPlayerShip();
511 id = id + "_" + ship.getId();
512 } else {
513 return;
514 }
515
516 if (visuals == null) {
517 visuals = new TriadShieldVisuals(ship, this);
519 ship.addListener(this);
520 }
521
522
523
525 return;
526 }
527
528 if (state == State.COOLDOWN || state == State.IDLE) {
529 unapply(stats, id);
530 return;
531 }
532
533 ShipSystemAPI system = ship.getPhaseCloak();
534 if (system == null) system = ship.getSystem();
535
536
537 if (state == State.IN || state == State.ACTIVE) {
538
539 } else if (state == State.OUT) {
540
541 }
542 }
543
544
545 public void unapply(MutableShipStatsAPI stats, String id) {
546 ShipAPI ship = null;
547 boolean player = false;
548 if (stats.getEntity() instanceof ShipAPI) {
549 ship = (ShipAPI) stats.getEntity();
550 player = ship == Global.getCombatEngine().getPlayerShip();
551 id = id + "_" + ship.getId();
552 } else {
553 return;
554 }
555
556
557 }
558
559 public StatusData getStatusData(int index, State state, float effectLevel) {
560 return null;
561 }
562
563}
static SettingsAPI getSettings()
Definition Global.java:57
static CombatEngineAPI getCombatEngine()
Definition Global.java:69
void apply(MutableShipStatsAPI stats, String id, State state, float effectLevel)
String modifyDamageTaken(Object param, CombatEntityAPI target, DamageAPI damage, Vector2f point, boolean shieldHit)
StatusData getStatusData(int index, State state, float effectLevel)
void setBrightness(float brightness)
void setBounce(boolean up, boolean down)
static Vector2f getUnitVectorAtDegreeAngle(float degrees)
Definition Misc.java:1196
static float getDistance(SectorEntityToken from, SectorEntityToken to)
Definition Misc.java:599
static float getAngleInDegrees(Vector2f v)
Definition Misc.java:1126
SpriteAPI getSprite(String filename)
void update(Vector2f location, float facing)
CombatEntityAPI addLayeredRenderingPlugin(CombatLayeredRenderingPlugin plugin)
void addListener(Object listener)