Starsector API
Loading...
Searching...
No Matches
DwellerCombatPlugin.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.combat.dweller;
2
3import java.util.ArrayList;
4import java.util.EnumSet;
5import java.util.LinkedHashMap;
6import java.util.List;
7
8import java.awt.Color;
9
10import org.lwjgl.opengl.GL11;
11import org.lwjgl.opengl.GL14;
12import org.lwjgl.util.vector.Vector2f;
13
14import com.fs.starfarer.api.Global;
15import com.fs.starfarer.api.combat.BaseCombatLayeredRenderingPlugin;
16import com.fs.starfarer.api.combat.CombatEngineAPI;
17import com.fs.starfarer.api.combat.CombatEngineLayers;
18import com.fs.starfarer.api.combat.CombatEntityAPI;
19import com.fs.starfarer.api.combat.MissileAPI;
20import com.fs.starfarer.api.combat.ShipAPI;
21import com.fs.starfarer.api.combat.ViewportAPI;
22import com.fs.starfarer.api.combat.WeaponAPI;
23import com.fs.starfarer.api.combat.listeners.HullDamageAboutToBeTakenListener;
24import com.fs.starfarer.api.graphics.SpriteAPI;
25import com.fs.starfarer.api.impl.combat.ShipExplosionFlareVisual;
26import com.fs.starfarer.api.impl.combat.ShipExplosionFlareVisual.ShipExplosionFlareParams;
27import com.fs.starfarer.api.util.Misc;
28import com.fs.starfarer.api.util.MutatingValueUtil;
29
31
32 public static Color STANDARD_PART_GLOW_COLOR = new Color(255, 0, 50, 255);
33
34 public static String WEAPON_ACTIVATED = "weapon_activated";
35 public static String SHIELD_ACTIVATED = "shield_activated";
36 public static String SYSTEM_ACTIVATED = "system_activated";
37 public static String FLUX_ACTIVATED = "flux_activated";
38
39 public static interface DCPPlugin {
40 public void advance(DwellerCombatPlugin plugin, float amount);
41 }
42
43
44 public static class WobblyPart extends BaseDwellerShipPart {
45 public WarpingSpriteRendererUtilV2 renderer;
46 public boolean negativeBlend = false;
47 public boolean additiveBlend = false;
48 public MutatingValueUtil spin;
49 public float angle = 0f;
50
51 public WobblyPart(String spriteKey, float scale, float warpMult, Vector2f offset, float facingOffset) {
52 this(spriteKey, scale, 5, 5, warpMult, offset, facingOffset);
53 }
54 public WobblyPart(String spriteKey, float scale, int verticesWide, int verticesTall,
55 float warpMult, Vector2f offset, float facingOffset) {
56 super(offset, facingOffset);
57
58 SpriteAPI sprite = Global.getSettings().getSprite("dweller", spriteKey);
59
60 float width = sprite.getWidth() * scale;
61 float height = sprite.getHeight() * scale;
62 float warpAmt = width * 0.04f * warpMult;
63
64 sprite.setSize(width, height);
65 sprite.setCenter(width/2f, height/2f);
66 renderer = new WarpingSpriteRendererUtilV2(sprite, verticesWide, verticesTall, warpAmt, warpAmt * 1.4f, 1f);
67
68 spin = new MutatingValueUtil(0, 0, 0);
69 }
70
71 public float getAngle() {
72 return angle;
73 }
74 public void setAngle(float angle) {
75 this.angle = angle;
76 }
77 public void setSpin(float min, float max, float rate) {
78 spin = new MutatingValueUtil(min, max, rate);
79 }
80
81 public MutatingValueUtil getSpin() {
82 return spin;
83 }
84
85 public void advance(float amount) {
86 super.advance(amount);
87 spin.advance(amount);
88 this.angle += spin.getValue() * amount;
89 renderer.advance(amount);
90 }
91
92 public void renderImpl(float x, float y, float alphaMult, float angle, CombatEngineLayers layer) {
93 if (layer == CombatEngineLayers.BELOW_INDICATORS_LAYER) {
94 if (negativeBlend) {
95 GL14.glBlendEquation(GL14.GL_FUNC_REVERSE_SUBTRACT);
96 renderer.getSprite().setBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
97 } else {
98 if (additiveBlend) {
99 renderer.getSprite().setAdditiveBlend();
100 } else {
101 renderer.getSprite().setNormalBlend();
102 }
103 }
104
105 renderer.getSprite().setAlphaMult(alphaMult);
106 renderer.getSprite().setColor(color);
107 renderer.getSprite().setAngle(angle + facingOffset + this.angle);
108 renderer.renderAtCenter(x, y);
109
110 if (negativeBlend) {
111 GL14.glBlendEquation(GL14.GL_FUNC_ADD);
112 }
113 }
114 }
115 }
116
117
119 if (entity == null) return null;
120 return getShipMap().get(entity);
121 }
122
123 public static String KEY_SHIP_MAP = "DwellerCombatPlugin_shipMap_key";
124
125 @SuppressWarnings("unchecked")
126 public static LinkedHashMap<CombatEntityAPI, DwellerCombatPlugin> getShipMap() {
127 LinkedHashMap<CombatEntityAPI, DwellerCombatPlugin> map =
128 (LinkedHashMap<CombatEntityAPI, DwellerCombatPlugin>) Global.getCombatEngine().getCustomData().get(KEY_SHIP_MAP);
129 if (map == null) {
130 map = new LinkedHashMap<>();
132 }
133 return map;
134 }
135
136// @SuppressWarnings("unchecked")
137// public static ListMap<DwellerCombatPlugin> getStringToDwellerPluginMap(String key) {
138// ListMap<DwellerCombatPlugin> map =
139// (ListMap<DwellerCombatPlugin>) Global.getCombatEngine().getCustomData().get(key);
140// if (map == null) {
141// map = new ListMap<>();
142// Global.getCombatEngine().getCustomData().put(key, map);
143// }
144// return map;
145// }
146
148 protected float elapsed = 0f;
149
150 protected List<DwellerShipPart> parts = new ArrayList<>();
151
152 protected boolean spawnedShipExplosionParticles = false;
153 protected DCPPlugin plugin = null;
154
155 public Object custom1;
156 public Object custom2;
157 public Object custom3;
158
159
163
164 this.attachedTo = attachedTo;
165
166 if (attachedTo instanceof ShipAPI) {
167 ShipAPI ship = (ShipAPI) attachedTo;
168 ship.addListener(this);
169 }
170
171 getShipMap().put(attachedTo, this);
172 }
173
175 super.init(entity);
176 }
177
178 public float getRenderRadius() {
179 float extra = 300f;
180 return attachedTo.getCollisionRadius() + extra;
181 }
182
183 //protected EnumSet<CombatEngineLayers> layers = EnumSet.of(CombatEngineLayers.BELOW_PHASED_SHIPS_LAYER);
184 //protected EnumSet<CombatEngineLayers> layers = EnumSet.of(CombatEngineLayers.ABOVE_PARTICLES);
185 protected EnumSet<CombatEngineLayers> layers = EnumSet.of(CombatEngineLayers.BELOW_INDICATORS_LAYER);
186 @Override
187 public EnumSet<CombatEngineLayers> getActiveLayers() {
188 return layers;
189 }
190
191
192 protected float sinceTest = 10f;
193 public void advance(float amount) {
194 //if (true) return;
195
196
197 if (Global.getCombatEngine().isPaused() || entity == null || isExpired()) return;
198
199
201
202 elapsed += amount;
203
204// sinceTest += amount;
205// if (Keyboard.isKeyDown(Keyboard.KEY_K) && sinceTest > 1f) {
206// spawnedShipExplosionParticles = false;
207// notifyAboutToTakeHullDamage(null, (ShipAPI) attachedTo, new Vector2f(), 1000000f);
208// sinceTest = 0f;
209// }
210
211// Vector2f aVel = attachedTo.getVelocity();
212// float aSpeed = aVel.length();
213// Vector2f facingDir = Misc.getUnitVectorAtDegreeAngle(attachedTo.getFacing());
214// Vector2f aLoc = new Vector2f(attachedTo.getLocation());
215
216 if (isExpired()) {
217 }
218
219 if (attachedTo instanceof ShipAPI) {
220 ShipAPI ship = (ShipAPI) attachedTo;
221 if (ship.getShield() != null) {
222 ship.setJitterShields(true);
223 ship.setCircularJitter(true);
224 Color color = new Color(255,0,50,255);
225 ship.setJitter(this, color, 1f, 3, 0f);
226 //ship.getShield().applyShieldEffects(null, null, 0f, 2f, 1f);
227 }
228 }
229
230 if (shouldDespawn()) {
231 for (DwellerShipPart part : parts) {
232 part.fadeOut();
233 }
234 } else {
235 if (attachedTo instanceof ShipAPI) {
236 ShipAPI ship = (ShipAPI) attachedTo;
237
239
240 boolean activeWeapons = false;
241 for (WeaponAPI w : ship.getAllWeapons()) {
242 if (w.isDecorative()) continue;
243 if (w.isFiring()) {
244 activeWeapons = true;
245 break;
246 }
247 }
248
249 if (activeWeapons) {
251 }
252
253 if (ship.getShield() != null && ship.getShield().isOn()) {
255 }
256
257 float systemLevel = 0f;
258 if (ship.getSystem() != null) systemLevel = ship.getSystem().getEffectLevel();
259 if (systemLevel > 0) {
261 }
262 setBrightness(systemLevel, SYSTEM_ACTIVATED);
263
264 float fluxLevel = ship.getFluxLevel();
265 if (fluxLevel > 0f) {
267 }
268 setBrightness(fluxLevel, FLUX_ACTIVATED);
269 }
270 }
271
272// float mult = 1f;
273// mult += ((ShipAPI) attachedTo).getSystem().getEffectLevel() * 20f;
274 //if (((ShipAPI) attachedTo).getSystem().isActive()) mult = 10f;
275 for (DwellerShipPart part : parts) {
276 part.advance(amount);
277 }
278
279 if (plugin != null) {
280 plugin.advance(this, amount);
281 }
282 }
283
284
285 public boolean shouldDespawn() {
286 //if (true) return false;
287 if (attachedTo instanceof ShipAPI) {
288 ShipAPI ship = (ShipAPI) attachedTo;
289 return !Global.getCombatEngine().isShipAlive(ship);
290 }
291 if (attachedTo instanceof MissileAPI) {
292 MissileAPI missile = (MissileAPI) attachedTo;
293 return !Global.getCombatEngine().isMissileAlive(missile);
294 }
296 }
297
298 public boolean isExpired() {
299 boolean shouldDespawn = shouldDespawn();
300 if (shouldDespawn) {
301 boolean allFaded = true;
302 for (DwellerShipPart part : parts) {
303 if (!part.getFader().isFadedOut() && part.getAlphaMult() > 0) {
304 allFaded = false;
305 break;
306 }
307 }
308 if (allFaded) {
309 getShipMap().remove(attachedTo);
310 return true;
311 }
312 }
313 return false;
314 }
315
317 //if (true) return;
318
319 //Color color = Color.white;
320 float alphaMult = viewport.getAlphaMult();
321 if (alphaMult <= 0f) return;
322
323 Vector2f aLoc = new Vector2f(attachedTo.getLocation());
324
325 for (DwellerShipPart part : parts) {
326 part.render(aLoc.x, aLoc.y, alphaMult, attachedTo.getFacing() - 90f, layer);
327 }
328 }
329
330
332 return attachedTo;
333 }
334
335 public List<DwellerShipPart> getParts() {
336 return parts;
337 }
338
339 public DwellerShipPart getPart(String id) {
340 for (DwellerShipPart curr : parts) {
341 if (id.equals(curr.getId())) return curr;
342 }
343 return null;
344 }
345
346 public void fadeIn(String ... tags) {
347 for (DwellerShipPart part : getParts(tags)) {
348 part.fadeIn();
349 }
350 }
351 public void fadeOut(String ... tags) {
352 for (DwellerShipPart part : getParts(tags)) {
353 part.fadeOut();
354 }
355 }
356 public void setAlphaMult(float alphaMult, String ... tags) {
357 for (DwellerShipPart part : getParts(tags)) {
358 part.setAlphaMult(alphaMult);
359 }
360 }
361 public void setBrightness(float b, String ... tags) {
362 String key = "";
363 for (String tag : tags) key += tag + "_";
364 if (tags.length == 1) key = tags[0];
365
366 for (DwellerShipPart part : getParts(tags)) {
367 part.getBrightness().shift(key, b, 0.5f, 0.5f, 1f);
368 }
369 }
370
371 public List<DwellerShipPart> getParts(String ... tags) {
372 List<DwellerShipPart> result = new ArrayList<>();
373
374 OUTER: for (DwellerShipPart curr : parts) {
375 for (String tag : tags) {
376 if (curr.hasTag(tag)) {
377 result.add(curr);
378 continue OUTER;
379 }
380 }
381 }
382
383 return result;
384 }
385
386
387 @Override
388 public boolean notifyAboutToTakeHullDamage(Object param, ShipAPI ship, Vector2f point, float damageAmount) {
389 float hull = ship.getHitpoints();
390 if (damageAmount >= hull && !spawnedShipExplosionParticles && ship.getExplosionScale() > 0f) {
391 int numSwirly = 11;
392 int numDark = 11;
393 //numDark = 0;
394 float size = ship.getCollisionRadius() * 0.25f;
395 if (size < 15) size = 15;
396 if (size > 50) size = 50;
397 //if (DwellerCombatStrategyAI.isMaw(ship)) {
398 float durMult = 1f;
399 float flashMult = 1f;
400 if (ship.isCapital()) {
401 size = 100;
402 durMult = 2f;
403 flashMult = 2f;
404 }
405// size = 50;
406// size = 15;
407
408 float baseSize = size;
409
411
412 float rampUp = 0f;
413
414 Color color = DwellerShroud.SHROUD_COLOR;
415
416 for (int i = 0; i < numSwirly; i++) {
417 Vector2f loc = new Vector2f(ship.getLocation());
418 //loc.x += 750f;
419 float scatterMult = 0.5f;
420 //loc = Misc.getPointWithinRadius(loc, baseSize * 1f * scatterMult);
421 loc = Misc.getPointWithinRadius(loc, size * 1f * scatterMult);
422 float s = size * 4f * (0.5f + (float) Math.random() * 0.5f);
423
424 float dur = 0.5f + (float) Math.random() * 0.5f;
425 dur *= durMult;
426
427 size *= 1.25f;
428
429 engine.addSwirlyNebulaParticle(loc, ship.getVelocity(), s, 3f, rampUp, 0f, dur, color, false);
430 }
431
432 size = baseSize;
433 for (int i = 0; i < numDark; i++) {
434 Vector2f loc = new Vector2f(ship.getLocation());
435 //loc.x += 750f;
436 float scatterMult = 0.5f;
437 //loc = Misc.getPointWithinRadius(loc, baseSize * 1f * scatterMult);
438 loc = Misc.getPointWithinRadius(loc, size * 1f * scatterMult);
439 float s = size * 4f * (0.5f + (float) Math.random() * 0.5f);
440
441 float dur = 0.5f + (float) Math.random() * 0.5f;
442 dur *= durMult;
443
444 //size *= 1.1f;
445 size *= 1.25f;
446 //s *= 0.5f;
447
448 engine.addNegativeSwirlyNebulaParticle(loc, ship.getVelocity(), s, 3f, rampUp, 0f, dur, color);
449 }
450
451
452 Vector2f expVel = ship.getVelocity();
453 Vector2f expLoc = ship.getShieldCenterEvenIfNoShield();
454 expLoc = ship.getLocation();
455 float explosionScale = 1f;
456 if (ship.isCapital()) {
457 explosionScale *= 1.7f;
458 } else if (ship.isCruiser()) {
459 explosionScale *= 1.5f;
460 } else if (ship.isDestroyer()) {
461 explosionScale *= 1.5f;
462 }
463
464 Color flashColor = new Color(255,50,100,255);
465 float b = 1f;
466
467 float glowSize = (float) Math.sqrt(ship.getCollisionRadius()) * 15f * 4f;
468 if (ship.isFighter()) glowSize *= 0.5f;
469 glowSize *= explosionScale;
470 glowSize *= flashMult;
471
472 ShipExplosionFlareParams sp = new ShipExplosionFlareParams();
473 //sp.attachedTo = this;
474 float er = (float) Math.sqrt(ship.getCollisionRadius()) * 15f * 4.0f;
475 float mult = 475f/994f;
476 er *= mult;
477 sp.flareWidth = er * 4f * explosionScale;
478 sp.flareHeight = er * 1.6f * explosionScale;
479 sp.color = flashColor;
480 sp.fadeIn = 0.1f;
481 sp.fadeOut = 2f;
482
484 e.getLocation().set(expLoc);
485 e.getVelocity().set(expVel);
486
487 engine.addHitParticle(expLoc, expVel, glowSize * 1f, b, 1.5f * durMult, flashColor);
488 engine.addHitParticle(expLoc, expVel, glowSize * 0.5f, b, 1.5f * durMult, flashColor);
489// if (ship.isFrigate()) { // needs just a little extra oomph
490// engine.addHitParticle(expLoc, expVel, glowSize * 0.5f, b, 1.5f, Color.white);
491// }
492
494 }
495 return false;
496 }
497
498 public DCPPlugin getPlugin() {
499 return plugin;
500 }
501
502 public void setPlugin(DCPPlugin plugin) {
503 this.plugin = plugin;
504 }
505
506}
507
508
509
510
511
512
513
static SettingsAPI getSettings()
Definition Global.java:57
static CombatEngineAPI getCombatEngine()
Definition Global.java:69
static DwellerCombatPlugin getDwellerPluginFor(CombatEntityAPI entity)
boolean notifyAboutToTakeHullDamage(Object param, ShipAPI ship, Vector2f point, float damageAmount)
void render(CombatEngineLayers layer, ViewportAPI viewport)
static LinkedHashMap< CombatEntityAPI, DwellerCombatPlugin > getShipMap()
static Vector2f getPointWithinRadius(Vector2f from, float r)
Definition Misc.java:711
SpriteAPI getSprite(String filename)
void addHitParticle(Vector2f loc, Vector2f vel, float size, float brightness, float duration, Color color)
CombatEntityAPI addLayeredRenderingPlugin(CombatLayeredRenderingPlugin plugin)
boolean isEntityInPlay(CombatEntityAPI entity)
boolean isMissileAlive(MissileAPI missile)
void addSwirlyNebulaParticle(Vector2f loc, Vector2f vel, float size, float endSizeMult, float rampUpFraction, float fullBrightnessFraction, float totalDuration, Color color, boolean expandAsSqrt)
void addNegativeSwirlyNebulaParticle(Vector2f loc, Vector2f vel, float size, float endSizeMult, float rampUpFraction, float fullBrightnessFraction, float totalDuration, Color color)
void setCircularJitter(boolean circular)
void addListener(Object listener)
List< WeaponAPI > getAllWeapons()
void setJitterShields(boolean jitterShields)
void setJitter(Object source, Color color, float intensity, int copies, float range)
void setSize(float width, float height)
void setBlendFunc(int src, int dest)