98 JSONObject json =
missile.getSpec().getBehaviorJSON();
107 if (json.optBoolean(
"withShapedExplosion")) {
108 p =
new ShapedExplosionParams();
111 }
catch (Exception e) {
112 throw new RuntimeException(e);
117 if (json.has(
"triggerAngle")) {
124 if (json.has(
"targetingLaserRange")) {
129 turnRateBoost = (float) json.optDouble(
"turnRateBoost", 100f);
133 firingTime = (float) json.optDouble(
"firingTime", 1.25f);
138 bombPumped = json.optBoolean(
"bombPumped",
false);
144 if (json.has(
"destroyedExplosionColor")) {
147 }
catch (Exception e) {
148 throw new RuntimeException(e);
152 JSONArray arr = json.optJSONArray(
"targetingLaserFireOffset");
154 for (
int i = 0; i < arr.length(); i += 2) {
155 Vector2f v =
new Vector2f((
float) arr.optDouble(i), (
float) arr.optDouble(i + 1));
159 arr = json.optJSONArray(
"targetingLaserSweepAngles");
161 for (
int i = 0; i < arr.length(); i += 2) {
162 Vector2f v =
new Vector2f((
float) arr.optDouble(i), (
float) arr.optDouble(i + 1));
166 arr = json.optJSONArray(
"payloadSweepAngles");
168 for (
int i = 0; i < arr.length(); i += 2) {
169 Vector2f v =
new Vector2f((
float) arr.optDouble(i), (
float) arr.optDouble(i + 1));
185 float maxSpeed = Math.max(50f,
missile.getMaxSpeed());
187 missile.setEtaModifier(etaMod);
201 public void advance(
float amount, List<InputEventAPI> events) {
211 boolean doCleanup =
state == State.DONE ||
224 CombatEntityAPI target =
null;
225 if (
missile.getAI() instanceof GuidedMissileAI) {
226 GuidedMissileAI ai = (GuidedMissileAI)
missile.getAI();
227 target = ai.getTarget();
232 Vector2f from = target.getLocation();
233 if (target instanceof ShipAPI) {
234 from = ((ShipAPI) target).getShieldCenterEvenIfNoShield();
236 float toMissile = Misc.getAngleInDegrees(from,
missile.getLocation());
239 float toShip = Misc.getAngleInDegrees(from,
missile.getSpawnLocation());
240 float diff = Misc.getAngleDiff(toShip, toMissile);
247 float dist = Misc.getDistance(target.getLocation(),
missile.getLocation());
251 missile.setMaxFlightTime(10000f);
252 state = State.TURN_TO_TARGET;
264 WeaponGroupSpec g =
new WeaponGroupSpec(WeaponGroupType.LINKED);
268 g =
new WeaponGroupSpec(WeaponGroupType.LINKED);
273 demDrone.setLayer(CombatEngineLayers.ABOVE_SHIPS_AND_MISSILES_LAYER);
276 demDrone.getMutableStats().getHullDamageTakenMult().modifyMult(
"dem", 0f);
278 demDrone.getAIFlags().setFlag(AIFlags.DRONE_MOTHERSHIP, 100000f,
ship);
279 demDrone.getMutableStats().getEnergyWeaponDamageMult().applyMods(
ship.getMutableStats().getMissileWeaponDamageMult());
280 demDrone.getMutableStats().getMissileWeaponDamageMult().applyMods(
ship.getMutableStats().getMissileWeaponDamageMult());
281 demDrone.getMutableStats().getBallisticWeaponDamageMult().applyMods(
ship.getMutableStats().getMissileWeaponDamageMult());
282 demDrone.setCollisionClass(CollisionClass.NONE);
283 demDrone.giveCommand(ShipCommand.SELECT_GROUP,
null, 0);
287 WeaponAPI tLaser =
demDrone.getWeaponGroupsCopy().get(0).getWeaponsCopy().get(0);
288 tLaser.ensureClonedSpec();
289 tLaser.getSpec().getTurretFireOffsets().clear();
294 }
else if (
state == State.TURN_TO_TARGET) {
295 float angle = Misc.getAngleInDegrees(
missile.getLocation(),
fireTarget.getLocation());
301 state = State.SIGNAL;
303 }
else if (
state == State.SIGNAL) {
307 WeaponAPI tLaser =
demDrone.getWeaponGroupsCopy().get(0).getWeaponsCopy().get(0);
308 tLaser.ensureClonedSpec();
309 tLaser.getSpec().getTurretAngleOffsets().clear();
312 if (progress < 0.5f) {
313 angle = curr.x + (curr.y - curr.x) * progress * 2f;
315 angle = curr.x + (curr.y - curr.x) * (1f - progress) * 2f;
317 tLaser.getSpec().getTurretAngleOffsets().add(angle);
328 demDrone.giveCommand(ShipCommand.SELECT_GROUP,
null, 1);
334 missile.setNoFlameoutOnFizzling(
true);
341 }
else if (
state == State.FIRE) {
377 if (progress > 1f) progress = 1f;
378 missile.getEngineController().fadeToOtherColor(
this, Misc.zeroColor, Misc.zeroColor, progress, 1f);
382 WeaponAPI payload =
demDrone.getWeaponGroupsCopy().get(1).getWeaponsCopy().get(0);
383 payload.ensureClonedSpec();
384 payload.getSpec().getTurretAngleOffsets().clear();
389 if (progress < 0.5f) {
390 angle = curr.x + (curr.y - curr.x) * progress * 2f;
392 angle = curr.x + (curr.y - curr.x) * (1f - progress) * 2f;
397 progress = Math.abs(progress);
399 angle = curr.x + (curr.y - curr.x) * progress;
403 payload.getSpec().getTurretAngleOffsets().add(angle);
410 demDrone.getMutableStats().getBeamWeaponRangeBonus().unmodifyFlat(
"dem");
419 missile.getVelocity().set(0, 0);
426 missile.setArmedWhileFizzling(
false);
447 Vector2f dir = Misc.getUnitVectorAtDegreeAngle(
missile.getFacing());
449 Vector2f.add(dir,
missile.getLocation(), dir);
454 WeaponAPI tLaser =
demDrone.getWeaponGroupsCopy().get(0).getWeaponsCopy().get(0);
455 WeaponAPI payload =
demDrone.getWeaponGroupsCopy().get(1).getWeaponsCopy().get(0);
456 tLaser.setFacing(
missile.getFacing());
457 payload.setFacing(
missile.getFacing());
458 tLaser.setKeepBeamTargetWhileChargingDown(
true);
459 payload.setKeepBeamTargetWhileChargingDown(
true);
460 tLaser.setScaleBeamGlowBasedOnDamageEffectiveness(
false);
462 payload.setScaleBeamGlowBasedOnDamageEffectiveness(
false);
464 tLaser.updateBeamFromPoints();
465 payload.updateBeamFromPoints();
470 if (
state == State.TURN_TO_TARGET ||
state == State.SIGNAL ||
476 missile.giveCommand(ShipCommand.ACCELERATE_BACKWARDS);
478 missile.giveCommand(ShipCommand.ACCELERATE);
480 missile.giveCommand(ShipCommand.DECELERATE);
482 float dir = Misc.getAngleInDegrees(
missile.getLocation(),
fireTarget.getLocation());
483 float diff = Misc.getAngleDiff(
missile.getFacing(), dir);
484 float rate =
missile.getMaxTurnRate() * amount;
487 boolean turningTowardsDesiredFacing =
true;
500 float r = (float) Math.random();
505 }
else if (r < 0.8f) {
518 strafeDur = 0.5f + (float) Math.random() * 0.5f;
522 Vector2f driftDir = Misc.getUnitVectorAtDegreeAngle(
missile.getFacing() + 90f);
525 float distToShip = Misc.getDistance(
ship.getLocation(),
missile.getLocation());
526 float shipToFireTarget = Misc.getDistance(
ship.getLocation(),
fireTarget.getLocation());
528 if (dist > shipToFireTarget) extra = dist - shipToFireTarget;
529 if (distToShip <
ship.getCollisionRadius() * 1f + extra) {
530 float away = Misc.getAngleInDegrees(
ship.getLocation(),
missile.getLocation());
531 float turnDir = Misc.getClosestTurnDirection(away,
missile.getFacing());
536 float speedInDir = Vector2f.dot(driftDir,
missile.getVelocity());
538 if (speedInDir < maxDrift) {
540 missile.giveCommand(ShipCommand.STRAFE_RIGHT);
542 missile.giveCommand(ShipCommand.STRAFE_LEFT);
591 int numParticles =
p.shapedExplosionNumParticles;
592 float minSize =
p.shapedExplosionMinParticleSize;
593 float maxSize =
p.shapedExplosionMaxParticleSize;
594 Color pc =
p.shapedExplosionColor;
596 float minDur =
p.shapedExplosionMinParticleDur;
597 float maxDur =
p.shapedExplosionMaxParticleDur;
599 float arc =
p.shapedExplosionArc;
600 float scatter =
p.shapedExplosionScatter;
601 float minVel =
p.shapedExplosionMinParticleVel;
602 float maxVel =
p.shapedExplosionMaxParticleVel;
604 float endSizeMin =
p.shapedExplosionEndSizeMin;
605 float endSizeMax =
p.shapedExplosionEndSizeMax;
607 Vector2f spawnPoint =
new Vector2f(loc);
608 for (
int i = 0; i < numParticles; i++) {
610 float angleOffset = (float) Math.random();
611 if (angleOffset > 0.2f) {
612 angleOffset *= angleOffset;
614 float speedMult = 1f - angleOffset;
615 speedMult = 0.5f + speedMult * 0.5f;
616 angleOffset *= Math.signum((
float) Math.random() - 0.5f);
617 angleOffset *= arc/2f;
618 float theta = (float) Math.toRadians(angle + angleOffset);
619 float r = (float) (Math.random() * Math.random() * scatter);
620 float x = (float)Math.cos(theta) * r;
621 float y = (float)Math.sin(theta) * r;
622 Vector2f pLoc =
new Vector2f(spawnPoint.x + x, spawnPoint.y + y);
624 float speed = minVel + (maxVel - minVel) * (
float) Math.random();
627 Vector2f pVel = Misc.getUnitVectorAtDegreeAngle((
float) Math.toDegrees(theta));
630 float pSize = minSize + (maxSize - minSize) * (
float) Math.random();
631 float pDur = minDur + (maxDur - minDur) * (
float) Math.random();
632 float endSize = endSizeMin + (endSizeMax - endSizeMin) * (
float) Math.random();