Starsector API
Loading...
Searching...
No Matches
DEMScript.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.combat.dem;
2
3import java.util.ArrayList;
4import java.util.List;
5
6import java.awt.Color;
7
8import org.json.JSONArray;
9import org.json.JSONException;
10import org.json.JSONObject;
11import org.lwjgl.util.vector.Vector2f;
12
13import com.fs.starfarer.api.Global;
14import com.fs.starfarer.api.combat.BaseEveryFrameCombatPlugin;
15import com.fs.starfarer.api.combat.CollisionClass;
16import com.fs.starfarer.api.combat.CombatEngineLayers;
17import com.fs.starfarer.api.combat.CombatEntityAPI;
18import com.fs.starfarer.api.combat.DamageType;
19import com.fs.starfarer.api.combat.GuidedMissileAI;
20import com.fs.starfarer.api.combat.MissileAIPlugin;
21import com.fs.starfarer.api.combat.MissileAPI;
22import com.fs.starfarer.api.combat.ShipAPI;
23import com.fs.starfarer.api.combat.ShipCommand;
24import com.fs.starfarer.api.combat.ShipHullSpecAPI;
25import com.fs.starfarer.api.combat.ShipVariantAPI;
26import com.fs.starfarer.api.combat.ShipwideAIFlags.AIFlags;
27import com.fs.starfarer.api.combat.WeaponAPI;
28import com.fs.starfarer.api.input.InputEventAPI;
29import com.fs.starfarer.api.loading.WeaponGroupSpec;
30import com.fs.starfarer.api.loading.WeaponGroupType;
31import com.fs.starfarer.api.util.Misc;
32
36public class DEMScript extends BaseEveryFrameCombatPlugin implements MissileAIPlugin {
37
38 public static enum State {
39 WAIT,
40 TURN_TO_TARGET,
41 SIGNAL,
42 FIRE,
43 DONE,
44 }
45
46 protected State state = State.WAIT;
48 protected ShipAPI ship;
49 protected WeaponAPI weapon;
51 protected ShipAPI demDrone;
52
53 //protected Vector2f targetingLaserFireOffset = new Vector2f();
54 protected List<Vector2f> targetingLaserFireOffset = new ArrayList<Vector2f>();
55 protected List<Vector2f> targetingLaserSweepAngles = new ArrayList<Vector2f>();
56 protected List<Vector2f> payloadSweepAngles = new ArrayList<Vector2f>();
57 protected List<Float> payloadSweepPhaseShift = new ArrayList<Float>();
58 protected float minDelayBeforeTriggering = 0f;
59 protected boolean useTriggerAngle = false;
60 protected float triggerAngle = 0f;
61 protected float allowedDriftFraction = 0f;
62 protected float triggerDistance = 0f;
63 protected float turnRateBoost = 0f;
64 protected float turnRateMultOnSignal = 1f;
65 protected float targetingLaserArc = 0f;
66 protected float targetingTime = 1f;
67 protected float firingTime = 1f;
68 protected String targetingLaserId;
69 protected String payloadWeaponId;
70 protected float preferredMinFireDistance;
71 protected float preferredMaxFireDistance;
72 protected float targetingLaserRange;
73 protected float payloadSweepRateMult;
74 protected boolean bombPumped;
75 protected boolean fadeOutEngineWhenFiring;
76 protected boolean destroyMissleWhenDoneFiring;
77 protected boolean randomStrafe;
80 protected boolean snapFacingToTargetIfCloseEnough = true;
81 protected Color destroyedExplosionColor;
82
83 protected float elapsedWaiting = 0f;
84 protected float elapsedTargeting = 0f;
85 protected float elapsedFiring = 0f;
86 //protected DamagingProjectileAPI explosion;
87 protected int explosionDelayFrames = 0;
88 protected float strafeDur = 0f;
89 protected float strafeDir = 0f;
90 protected boolean exploded = false;
91
92 protected ShapedExplosionParams p;
93
95 this.missile = missile;
96 this.ship = ship;
97 this.weapon = weapon;
98
99 JSONObject json = missile.getSpec().getBehaviorJSON();
100 //minDelayBeforeTriggering = (float) json.optDouble("minDelayBeforeTriggering", 1f);
101 minDelayBeforeTriggering = getValue(json, "minDelayBeforeTriggering", 1f);
102 allowedDriftFraction = (float) json.optDouble("allowedDriftFraction", 0.33f);
103 //triggerDistance = (float) json.optDouble("triggerDistance", 500f);
104 //preferredMinFireDistance = (float) json.optDouble("preferredMinFireDistance", 0f);
105 triggerDistance = getValue(json, "triggerDistance", 500f);
106
107 try {
108 if (json.optBoolean("withShapedExplosion")) {
109 p = new ShapedExplosionParams();
110 p.load(json);;
111 }
112 } catch (Exception e) {
113 throw new RuntimeException(e);
114 }
115
116 snapFacingToTargetIfCloseEnough = json.optBoolean("snapFacingToTargetIfCloseEnough", false);
117
118 if (json.has("triggerAngle")) {
119 useTriggerAngle = true;
120 triggerAngle = getValue(json, "triggerAngle", 0f);
121 }
122
123 preferredMaxFireDistance = getValue(json, "preferredMaxFireDistance", triggerDistance);
124 preferredMinFireDistance = getValue(json, "preferredMinFireDistance", 0f);
125 if (json.has("targetingLaserRange")) {
126 targetingLaserRange = (float) json.optDouble("targetingLaserRange", 600f);
127 } else {
129 }
130 turnRateBoost = (float) json.optDouble("turnRateBoost", 100f);
131 turnRateMultOnSignal = (float) json.optDouble("turnRateMultOnSignal", 1f);
132 //targetingTime = (float) json.optDouble("targetingTime", 1f);
133 targetingTime = getValue(json, "targetingTime", 1f);
134 firingTime = (float) json.optDouble("firingTime", 1.25f);
135 targetingLaserId = json.optString("targetingLaserId", null);
136 payloadWeaponId = json.optString("payloadWeaponId", null);
137 targetingLaserArc = (float) json.optDouble("targetingLaserArc", 10f);
138 payloadSweepRateMult = (float) json.optDouble("payloadSweepRateMult", 1f);
139 bombPumped = json.optBoolean("bombPumped", false);
140 fadeOutEngineWhenFiring = json.optBoolean("fadeOutEngineWhenFiring", false);
141 destroyMissleWhenDoneFiring = json.optBoolean("destroyMissleWhenDoneFiring", false);
142 randomStrafe = json.optBoolean("randomStrafe", false);
143 randomPayloadSweepPhaseShift = json.optBoolean("randomPayloadSweepPhaseShift", false);
144 payloadCenterSweepOnOriginalOffset = json.optBoolean("payloadCenterSweepOnOriginalOffset", false);
145 if (json.has("destroyedExplosionColor")) {
146 try {
147 destroyedExplosionColor = Misc.optColor(json, "destroyedExplosionColor", null);
148 } catch (Exception e) {
149 throw new RuntimeException(e);
150 }
151 }
152
153 JSONArray arr = json.optJSONArray("targetingLaserFireOffset");
154 if (arr != null) {
155 for (int i = 0; i < arr.length(); i += 2) {
156 Vector2f v = new Vector2f((float) arr.optDouble(i), (float) arr.optDouble(i + 1));
158 }
159 }
160 arr = json.optJSONArray("targetingLaserSweepAngles");
161 if (arr != null) {
162 for (int i = 0; i < arr.length(); i += 2) {
163 Vector2f v = new Vector2f((float) arr.optDouble(i), (float) arr.optDouble(i + 1));
165 }
166 }
167 arr = json.optJSONArray("payloadSweepAngles");
168 if (arr != null) {
169 for (int i = 0; i < arr.length(); i += 2) {
170 Vector2f v = new Vector2f((float) arr.optDouble(i), (float) arr.optDouble(i + 1));
171
174 v.x += orig;
175 v.y += orig;
176 }
177
178 payloadSweepAngles.add(v);
179 }
180 }
182 for (int i = 0; i < payloadSweepAngles.size(); i++) {
183 payloadSweepPhaseShift.add((float) Math.random());
184 }
185 }
186 float maxSpeed = Math.max(50f, missile.getMaxSpeed());
187 float etaMod = -1f * triggerDistance / maxSpeed;
188 missile.setEtaModifier(etaMod);
189 }
190
191 public static float getValue(JSONObject json, String key, float defaultValue) {
192 JSONArray arr = json.optJSONArray(key);
193 if (arr != null) {
194 Vector2f v = new Vector2f((float) arr.optDouble(0), (float) arr.optDouble(1));
195 return v.x + (v.y - v.x) * (float) Math.random();
196 }
197 return (float) json.optDouble(key, defaultValue);
198 }
199
200
201 @Override
202 public void advance(float amount, List<InputEventAPI> events) {
203 if (Global.getCombatEngine().isPaused()) return;
204
205 // so that the AI doesn't treat fizzled missiles as a threat due to the drone still being there
206 if (missile.isFizzling()) {
207 if (demDrone != null) {
209 }
210 }
211
212 boolean doCleanup = state == State.DONE ||
213 (!bombPumped || state.ordinal() < State.FIRE.ordinal()) &&
216 if (doCleanup) {
217 if (demDrone != null) {
219 }
221 return;
222 }
223
224 if (state == State.WAIT && missile.isArmed() && !missile.isFizzling() && !missile.isFading()) {
225 CombatEntityAPI target = null;
226 if (missile.getAI() instanceof GuidedMissileAI) {
228 target = ai.getTarget();
229 }
230 elapsedWaiting += amount;
231
232 if (useTriggerAngle && target != null) {
233 Vector2f from = target.getLocation();
234 if (target instanceof ShipAPI) {
235 from = ((ShipAPI) target).getShieldCenterEvenIfNoShield();
236 }
237 float toMissile = Misc.getAngleInDegrees(from, missile.getLocation());
238 //float diff = Misc.getAngleDiff(target.getFacing(), toMissile);
239 //float toShip = Misc.getAngleInDegrees(from, ship.getLocation());
240 float toShip = Misc.getAngleInDegrees(from, missile.getSpawnLocation());
241 float diff = Misc.getAngleDiff(toShip, toMissile);
242 if (diff >= triggerAngle) {
244 }
245 }
246
247 if (target != null && elapsedWaiting >= minDelayBeforeTriggering) {
248 float dist = Misc.getDistance(target.getLocation(), missile.getLocation());
249 dist -= Global.getSettings().getTargetingRadius(missile.getLocation(), target, false);
250
251 if (dist < triggerDistance) {
253 state = State.TURN_TO_TARGET;
254 fireTarget = target;
255
256 // turn off the normal missile AI; this script is taking over
257 missile.setMissileAI(this);
258
261
262 ShipHullSpecAPI spec = Global.getSettings().getHullSpec("dem_drone");
263 ShipVariantAPI v = Global.getSettings().createEmptyVariant("dem_drone", spec);
264 v.addWeapon("WS 000", targetingLaserId);
266 g.addSlot("WS 000");
267 v.addWeaponGroup(g);
268 v.addWeapon("WS 001", payloadWeaponId);
270 g.addSlot("WS 001");
271 v.addWeaponGroup(g);
272
277 demDrone.getMutableStats().getHullDamageTakenMult().modifyMult("dem", 0f); // so it's non-targetable
278 demDrone.setDrone(true);
279 demDrone.getAIFlags().setFlag(AIFlags.DRONE_MOTHERSHIP, 100000f, ship);
283
294
298
299 if (targetingLaserFireOffset.size() > 0) {
300 WeaponAPI tLaser = demDrone.getWeaponGroupsCopy().get(0).getWeaponsCopy().get(0);
301 tLaser.ensureClonedSpec();
302 tLaser.getSpec().getTurretFireOffsets().clear();
304 }
305 }
306 }
307 } else if (state == State.TURN_TO_TARGET) {
309
312 //missile.getEngineStats().getTurnAcceleration().modifyMult("dem_mult", turnRateMultOnSignal);
313
314 state = State.SIGNAL;
315 }
316 } else if (state == State.SIGNAL) {
317
318 if (targetingLaserSweepAngles.size() > 0) {
319 float progress = elapsedTargeting / targetingTime;
320 WeaponAPI tLaser = demDrone.getWeaponGroupsCopy().get(0).getWeaponsCopy().get(0);
321 tLaser.ensureClonedSpec();
322 tLaser.getSpec().getTurretAngleOffsets().clear();
323 for (Vector2f curr : targetingLaserSweepAngles) {
324 float angle = 0f;
325 if (progress < 0.5f) {
326 angle = curr.x + (curr.y - curr.x) * progress * 2f;
327 } else {
328 angle = curr.x + (curr.y - curr.x) * (1f - progress) * 2f;
329 }
330 tLaser.getSpec().getTurretAngleOffsets().add(angle);
331 }
332 }
333
334 if (targetingLaserRange > 0 && targetingTime > 0) {
336 }
337
338 elapsedTargeting += amount;
340 state = State.FIRE;
342
343 if (!bombPumped) {
344 //missile.flameOut();
350 missile.setFadeTime(0.5f);
352 }
353 }
354 } else if (state == State.FIRE) {
355 //Global.getCombatEngine().setPaused(true);
356
357 if (bombPumped && !exploded && explosionDelayFrames >= 1) {
360
361// ShapedExplosionParams p = new ShapedExplosionParams();
362// p.shapedExplosionNumParticles = 50;
363// p.shapedExplosionMinParticleDur = 0.7f;
364// p.shapedExplosionMaxParticleDur = 1.1f;
365// p.shapedExplosionMinParticleSize = 50f;
366// p.shapedExplosionMaxParticleSize = 70f;
367// p.shapedExplosionColor = new Color(255,40,40,155);
368// p.shapedExplosionArc = 45f;
369// p.shapedExplosionMinParticleVel = 50f;
370// p.shapedExplosionMaxParticleVel = 250f;
371//
374//
375// float speedMult = 1f;
376// p.shapedExplosionMinParticleVel *= speedMult;
377// p.shapedExplosionMaxParticleVel *= speedMult;
378// p.shapedExplosionMinParticleDur /= speedMult;
379// p.shapedExplosionMaxParticleDur /= speedMult;
380 if (p != null) {
382 }
383 exploded = true;
384 }
386
388 float progress = elapsedFiring / firingTime;
389 progress *= 2f;
390 if (progress > 1f) progress = 1f;
392 }
393
394 if (payloadSweepAngles.size() > 0) {
395 WeaponAPI payload = demDrone.getWeaponGroupsCopy().get(1).getWeaponsCopy().get(0);
396 payload.ensureClonedSpec();
397 payload.getSpec().getTurretAngleOffsets().clear();
398 int index = 0;
399 for (Vector2f curr : payloadSweepAngles) {
400 float angle = 0f;
401 float progress = elapsedFiring / firingTime;
402 if (progress < 0.5f) {
403 angle = curr.x + (curr.y - curr.x) * progress * 2f;
404 } else {
405 angle = curr.x + (curr.y - curr.x) * (1f - progress) * 2f;
406 }
408 progress += payloadSweepPhaseShift.get(index);
409 progress = (float) Math.sin(progress * Math.PI * payloadSweepRateMult);
410 progress = Math.abs(progress);
411
412 angle = curr.x + (curr.y - curr.x) * progress;
413 }
414
415
416 payload.getSpec().getTurretAngleOffsets().add(angle);
417 index++;
418 }
419 }
420
421
422 // use payload's normal range as defined in weapon_data.csv
425
426 elapsedFiring += amount;
427 if (elapsedFiring >= firingTime) {
429 state = State.DONE;
430
432 missile.getVelocity().set(0, 0);
433 if (destroyedExplosionColor != null) {
435 }
436 Global.getCombatEngine().applyDamage(missile, missile.getLocation(), 100000f, DamageType.ENERGY, 0f, false, false, demDrone, false);
437 } else {
440 }
441 }
442 }
443
444 doMissileControl(amount);
445 updateDroneState(amount);
446
447 }
448
449 protected void updateDroneState(float amount) {
450 if (demDrone != null) {
451 //System.out.println("FIRE FACING: " + missile.getFacing());
452 //if (explosion == null) {
458 //demDrone.getMouseTarget().set(fireTarget.getLocation());
459 //}
461 dir.scale(1000f);
462 Vector2f.add(dir, missile.getLocation(), dir);
463 demDrone.getMouseTarget().set(dir);
464
465 //demDrone.getMutableStats().getWeaponTurnRateBonus().modifyMult("dem", 0f);
466
467 WeaponAPI tLaser = demDrone.getWeaponGroupsCopy().get(0).getWeaponsCopy().get(0);
468 WeaponAPI payload = demDrone.getWeaponGroupsCopy().get(1).getWeaponsCopy().get(0);
469 tLaser.setFacing(missile.getFacing());
470 payload.setFacing(missile.getFacing());
474 if (firingTime <= 2f) {
476 }
477 tLaser.updateBeamFromPoints();
478 payload.updateBeamFromPoints();
479 }
480 }
481
482 protected void doMissileControl(float amount) {
483 if (state == State.TURN_TO_TARGET || state == State.SIGNAL ||
484 (state == State.FIRE && !bombPumped && !fadeOutEngineWhenFiring)) {
485
488 if (dist < preferredMinFireDistance) {
490 } else if (dist > preferredMaxFireDistance) {
492 } else if (missile.getVelocity().length() > missile.getMaxSpeed() * allowedDriftFraction) {
494 }
496 float diff = Misc.getAngleDiff(missile.getFacing(), dir);
497 float rate = missile.getMaxTurnRate() * amount;
498// float turnDir1 = Misc.getClosestTurnDirection(missile.getFacing(), dir);
499// boolean turningTowardsDesiredFacing = Math.signum(turnDir1) == Math.signum(missile.getAngularVelocity());
500 boolean turningTowardsDesiredFacing = true;
501 //snapFacingToTargetIfCloseEnough = true;
502 boolean phased = fireTarget instanceof ShipAPI && ((ShipAPI)fireTarget).isPhased();
503 if (!phased) {
504 if (diff <= rate * 0.25f && turningTowardsDesiredFacing && snapFacingToTargetIfCloseEnough) {
505 missile.setFacing(dir);
506 } else {
508 }
509 }
510
511 if (randomStrafe) {
512 if (strafeDur <= 0) {
513 float r = (float) Math.random();
514
515 if (strafeDir == 0) {
516 if (r < 0.4f) {
517 strafeDir = 1f;
518 } else if (r < 0.8f) {
519 strafeDir = -1f;
520 } else {
521 strafeDir = 0f;
522 }
523 } else {
524 if (r < 0.8f) {
526 } else {
527 strafeDir = 0f;
528 }
529 }
530
531 strafeDur = 0.5f + (float) Math.random() * 0.5f;
532 //strafeDur *= 0.5f;
533 }
534
535 Vector2f driftDir = Misc.getUnitVectorAtDegreeAngle(missile.getFacing() + 90f);
536 if (strafeDir == 1f) driftDir.negate();
537
538 float distToShip = Misc.getDistance(ship.getLocation(), missile.getLocation());
539 float shipToFireTarget = Misc.getDistance(ship.getLocation(), fireTarget.getLocation());
540 float extra = 0f;
541 if (dist > shipToFireTarget) extra = dist - shipToFireTarget;
542 if (distToShip < ship.getCollisionRadius() * 1f + extra) {
544 float turnDir = Misc.getClosestTurnDirection(away, missile.getFacing());
545 strafeDir = turnDir;
546 }
547
548 float maxDrift = missile.getMaxSpeed() * allowedDriftFraction;
549 float speedInDir = Vector2f.dot(driftDir, missile.getVelocity());
550
551 if (speedInDir < maxDrift) {
552 if (strafeDir == 1f) {
554 } else if (strafeDir == -1f) {
556 }
557 }
558
559 strafeDur -= amount;
560 }
561 }
562 }
563
564 public void advance(float amount) {
565 // MissileAIPlugin.advance()
566 // unused, but just want the missile to have a non-null AI
567 }
568
569
570
571 public static class ShapedExplosionParams {
572 public float shapedExplosionEndSizeMin = 1f;
573 public float shapedExplosionEndSizeMax = 2f;
574 public Color shapedExplosionColor = new Color(255,150,130,155);
575 public int shapedExplosionNumParticles = 200;
576 public float shapedExplosionMinParticleSize = 80;
577 public float shapedExplosionMaxParticleSize = 100;
578 public float shapedExplosionScatter = 100f;
579 public float shapedExplosionMinParticleVel = 100;
580 public float shapedExplosionMaxParticleVel = 350f;
581 public float shapedExplosionMinParticleDur = 1f;
582 public float shapedExplosionMaxParticleDur = 2f;
583 public float shapedExplosionArc = 90f;
584
585 public void load(JSONObject json) throws JSONException {
586 shapedExplosionEndSizeMin = (float)json.optDouble("shapedExplosionEndSizeMin", 1f);
587 shapedExplosionEndSizeMax = (float)json.optDouble("shapedExplosionEndSizeMax", 2f);
588 shapedExplosionNumParticles = json.optInt("shapedExplosionNumParticles");
589 shapedExplosionMinParticleSize = (float)json.optDouble("shapedExplosionMinParticleSize", 80f);
590 shapedExplosionMaxParticleSize = (float)json.optDouble("shapedExplosionMaxParticleSize", 100f);
591 shapedExplosionScatter = (float)json.optDouble("shapedExplosionScatter", 100f);
592 shapedExplosionMinParticleVel = (float)json.optDouble("shapedExplosionMinParticleVel", 100f);
593 shapedExplosionMaxParticleVel = (float)json.optDouble("shapedExplosionMaxParticleVel", 350f);
594 shapedExplosionMinParticleDur = (float)json.optDouble("shapedExplosionMinParticleDur", 1f);
595 shapedExplosionMaxParticleDur = (float)json.optDouble("shapedExplosionMaxParticleDur", 2f);
596 shapedExplosionArc = (float)json.optDouble("shapedExplosionArc", 90f);
597 shapedExplosionColor = Misc.optColor(json, "shapedExplosionColor", null);
598 }
599 }
600
601 public void spawnShapedExplosion(Vector2f loc, float angle, ShapedExplosionParams p) {
602
604 int numParticles = p.shapedExplosionNumParticles;
605 float minSize = p.shapedExplosionMinParticleSize;
606 float maxSize = p.shapedExplosionMaxParticleSize;
607 Color pc = p.shapedExplosionColor;
608
609 float minDur = p.shapedExplosionMinParticleDur;
610 float maxDur = p.shapedExplosionMaxParticleDur;
611
612 float arc = p.shapedExplosionArc;
613 float scatter = p.shapedExplosionScatter;
614 float minVel = p.shapedExplosionMinParticleVel;
615 float maxVel = p.shapedExplosionMaxParticleVel;
616
617 float endSizeMin = p.shapedExplosionEndSizeMin;
618 float endSizeMax = p.shapedExplosionEndSizeMax;
619
620 Vector2f spawnPoint = new Vector2f(loc);
621 for (int i = 0; i < numParticles; i++) {
622 //p.setMaxAge(500 + (int)(Math.random() * 1000f));
623 float angleOffset = (float) Math.random();
624 if (angleOffset > 0.2f) {
625 angleOffset *= angleOffset;
626 }
627 float speedMult = 1f - angleOffset;
628 speedMult = 0.5f + speedMult * 0.5f;
629 angleOffset *= Math.signum((float) Math.random() - 0.5f);
630 angleOffset *= arc/2f;
631 float theta = (float) Math.toRadians(angle + angleOffset);
632 float r = (float) (Math.random() * Math.random() * scatter);
633 float x = (float)Math.cos(theta) * r;
634 float y = (float)Math.sin(theta) * r;
635 Vector2f pLoc = new Vector2f(spawnPoint.x + x, spawnPoint.y + y);
636
637 float speed = minVel + (maxVel - minVel) * (float) Math.random();
638 speed *= speedMult;
639
640 Vector2f pVel = Misc.getUnitVectorAtDegreeAngle((float) Math.toDegrees(theta));
641 pVel.scale(speed);
642
643 float pSize = minSize + (maxSize - minSize) * (float) Math.random();
644 float pDur = minDur + (maxDur - minDur) * (float) Math.random();
645 float endSize = endSizeMin + (endSizeMax - endSizeMin) * (float) Math.random();
646 //Global.getCombatEngine().addSmoothParticle(pLoc, pVel, pSize, 1f, pDur, pc);
647 Global.getCombatEngine().addNebulaParticle(pLoc, pVel, pSize, endSize, 0.1f, 0.5f, pDur, pc);
648 //Global.getCombatEngine().addNebulaSmoothParticle(pLoc, pVel, pSize, endSize, 0.1f, 0.5f, pDur, pc);
649 //Global.getCombatEngine().addSwirlyNebulaParticle(pLoc, pVel, pSize, endSize, 0.1f, 0.5f, pDur, pc, false);
650 }
651 }
652 }
653}
654
655
656
657
658
659
660
661
static SettingsAPI getSettings()
Definition Global.java:57
static CombatEngineAPI getCombatEngine()
Definition Global.java:69
void modifyFlat(String source, float value)
void modifyMult(String source, float value)
void modifyFlat(String source, float value)
static float getValue(JSONObject json, String key, float defaultValue)
void spawnShapedExplosion(Vector2f loc, float angle, ShapedExplosionParams p)
void advance(float amount, List< InputEventAPI > events)
DEMScript(MissileAPI missile, ShipAPI ship, WeaponAPI weapon)
static boolean turnTowardsPointV2(MissileAPI missile, Vector2f point, float angVel)
Definition Misc.java:6546
static Vector2f getUnitVectorAtDegreeAngle(float degrees)
Definition Misc.java:1196
static float getAngleDiff(float from, float to)
Definition Misc.java:1716
static float getDistance(SectorEntityToken from, SectorEntityToken to)
Definition Misc.java:599
static float getClosestTurnDirection(float facing, float desired)
Definition Misc.java:2102
static Color optColor(JSONObject json, String key, Color defaultValue)
Definition Misc.java:2578
static boolean isInArc(float direction, float arc, Vector2f from, Vector2f to)
Definition Misc.java:1722
static float getAngleInDegrees(Vector2f v)
Definition Misc.java:1126
float getTargetingRadius(Vector2f from, CombatEntityAPI target, boolean considerShield)
ShipHullSpecAPI getHullSpec(String hullId)
ShipVariantAPI createEmptyVariant(String hullVariantId, ShipHullSpecAPI hullSpec)
WeaponSpecAPI getWeaponSpec(String weaponId)
ShipAPI createFXDrone(ShipVariantAPI variant)
void applyDamage(CombatEntityAPI entity, Vector2f point, float damageAmount, DamageType damageType, float empAmount, boolean bypassShields, boolean dealsSoftFlux, Object source, boolean playSound)
void removeEntity(CombatEntityAPI entity)
void removePlugin(EveryFrameCombatPlugin plugin)
boolean isEntityInPlay(CombatEntityAPI entity)
void addEntity(CombatEntityAPI entity)
void addNebulaParticle(Vector2f loc, Vector2f vel, float size, float endSizeMult, float rampUpFraction, float fullBrightnessFraction, float totalDuration, Color color)
void setCollisionClass(CollisionClass collisionClass)
void setNoFlameoutOnFizzling(boolean noFlameoutOnFizzling)
void setFizzleTime(float fizzleTime)
void giveCommand(ShipCommand command)
void setNoGlowTime(float noGlowTime)
void setEtaModifier(float etaModifier)
ShipEngineControllerAPI getEngineController()
void setFlightTime(float flightTime)
MutableShipStatsAPI getEngineStats()
DamagingProjectileAPI explode()
void setArmedWhileFizzling(boolean armedWhileFizzling)
void setMissileAI(MissileAIPlugin ai)
void setDestroyedExplosionColorOverride(Color destroyedExplosionColorOverride)
void setMaxFlightTime(float maxFlightTime)
MutableShipStatsAPI getMutableStats()
List< WeaponGroupAPI > getWeaponGroupsCopy()
void setDrone(boolean isDrone)
void setLayer(CombatEngineLayers layer)
void giveCommand(ShipCommand command, Object param, int groupNumber)
void fadeToOtherColor(Object key, Color other, Color contrailColor, float effectLevel, float maxBlend)
void addWeapon(String slotId, String weaponId)
void addWeaponGroup(WeaponGroupSpec group)
boolean isNearViewport(Vector2f loc, float nearDistance)
void setKeepBeamTargetWhileChargingDown(boolean keepTargetWhileChargingDown)
void setScaleBeamGlowBasedOnDamageEffectiveness(boolean scaleGlowBasedOnDamageEffectiveness)