Advertisement
DarkRevenant

Untitled

Jun 21st, 2014
258
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 6.97 KB | None | 0 0
  1. package data.scripts.ai;
  2.  
  3. import com.fs.starfarer.api.Global;
  4. import com.fs.starfarer.api.combat.CombatEntityAPI;
  5. import com.fs.starfarer.api.combat.DamageType;
  6. import com.fs.starfarer.api.combat.GuidedMissileAI;
  7. import com.fs.starfarer.api.combat.MissileAIPlugin;
  8. import com.fs.starfarer.api.combat.MissileAPI;
  9. import com.fs.starfarer.api.combat.ShipAPI;
  10. import com.fs.starfarer.api.combat.ShipCommand;
  11. import com.fs.starfarer.api.util.IntervalUtil;
  12.  
  13. import java.util.Collections;
  14. import java.util.List;
  15. import java.util.ListIterator;
  16. import org.lwjgl.util.vector.Vector2f;
  17.  
  18. import org.lazywizard.lazylib.CollectionUtils;
  19. import org.lazywizard.lazylib.MathUtils;
  20. import org.lazywizard.lazylib.VectorUtils;
  21. import org.lazywizard.lazylib.combat.AIUtils;
  22. import org.lazywizard.lazylib.combat.CombatUtils;
  23.  
  24. public class exigency_MMMAI2 implements MissileAIPlugin, GuidedMissileAI {
  25.  
  26.     private final static float SHIT_ACCURACY_RANGE = 300f;
  27.     private final static float SHIT_ACCURACY_AMOUNT = 75f;
  28.     // Time until self destructing
  29.     private final static float FUSE_TIME = 10.5f;
  30.     // Our missile object
  31.     private final MissileAPI missile;
  32.     // Our current target (can be null)
  33.     private CombatEntityAPI target;
  34.     private float offtarget;
  35.     private float baseofftarget;
  36.     private float lifetimer;
  37.     private final float offsetAngle;
  38.     private IntervalUtil timer = new IntervalUtil(0.1f, 0.2f);
  39.  
  40.     public static ShipAPI findBestTarget(MissileAPI missile) {
  41.         ShipAPI source = missile.getSource();
  42.         if (source != null && source.getShipTarget() != null && !source.getShipTarget().isHulk()) {
  43.             return source.getShipTarget();
  44.         }
  45.  
  46.         ShipAPI closest = null;
  47.         float distance, closestDistance = Float.MAX_VALUE;
  48.  
  49.         for (ShipAPI tmp : AIUtils.getEnemiesOnMap(missile)) {
  50.             distance = MathUtils.getDistance(tmp, missile.getLocation());
  51.             if (distance < closestDistance) {
  52.                 closest = tmp;
  53.                 closestDistance = distance;
  54.             }
  55.         }
  56.  
  57.         return closest;
  58.     }
  59.  
  60.     public exigency_MMMAI2(MissileAPI missile, ShipAPI launchingShip) {
  61.         this.missile = missile;
  62.         this.offtarget = 20f * (0.6f + 0.4f * (float) Math.random());       // Max initial off target (scatters missiles at launch)
  63.         this.baseofftarget = 20f * (0.6f + 0.4f * (float) Math.random());   // Min off target (makes missiles stay scattered)
  64.         if ((float) Math.random() > 0.5f) {
  65.             this.offtarget *= -1f;
  66.             this.baseofftarget *= -1f;
  67.         }
  68.         this.lifetimer = FUSE_TIME;
  69.         this.offsetAngle = (float) Math.random() * 360f;
  70.  
  71.         // Support for 'fire at target by clicking on them' behavior
  72.         List<ShipAPI> directTargets = CombatUtils.getShipsWithinRange(launchingShip.getMouseTarget(), 100f);
  73.         if (!directTargets.isEmpty()) {
  74.             Collections.sort(directTargets, new CollectionUtils.SortEntitiesByDistance(launchingShip.getMouseTarget()));
  75.             ListIterator<ShipAPI> iter = directTargets.listIterator();
  76.             while (iter.hasNext()) {
  77.                 ShipAPI tmp = iter.next();
  78.                 if (!tmp.isHulk() && tmp.getOwner() != launchingShip.getOwner()) {
  79.                     setTarget(tmp);
  80.                     break;
  81.                 }
  82.             }
  83.         }
  84.  
  85.         // Otherwise, use default MMMAI2 targeting AI
  86.         if (target == null) {
  87.             setTarget(findBestTarget(missile));
  88.         }
  89.     }
  90.  
  91.     @Override
  92.     public void advance(float amount) {
  93.         if (Global.getCombatEngine().isPaused()) {
  94.             return;
  95.         }
  96.  
  97.         lifetimer -= amount;
  98.         if (lifetimer <= 0f) {
  99.             Global.getCombatEngine().applyDamage(missile, missile.getLocation(), missile.getHitpoints(), DamageType.OTHER, 0, true, true, missile);
  100.             return;
  101.         }
  102.  
  103.         timer.advance(amount);
  104.  
  105.         // Apparently commands still work while fizzling
  106.         if (missile.isFading() || missile.isFizzling()) {
  107.             return;
  108.         }
  109.  
  110.         // If our current target is lost, assign a new one
  111.         if (target == null || (target instanceof ShipAPI && ((ShipAPI) target).isHulk()) || (missile.getOwner() == target.getOwner()) || !Global.getCombatEngine().isEntityInPlay(target)) {
  112.             setTarget(findBestTarget(missile));
  113.             missile.giveCommand(ShipCommand.ACCELERATE);
  114.             return;
  115.         }
  116.  
  117.         // Head towards the target, with tail chase guidance
  118.         float distance = MathUtils.getDistance(missile.getLocation(), target.getLocation());
  119.         float offset = 0f;
  120.         if (distance <= SHIT_ACCURACY_RANGE) {
  121.             offset = SHIT_ACCURACY_AMOUNT * (1f - distance / SHIT_ACCURACY_RANGE);
  122.         }
  123.         Vector2f guidedTarget = MathUtils.getPointOnCircumference(target.getLocation(), offset, offsetAngle);
  124.         float angularDistance = MathUtils.getShortestRotation(missile.getFacing(), VectorUtils.getAngle(missile.getLocation(), guidedTarget));
  125.  
  126.         if (timer.intervalElapsed()) {
  127.             offtarget = (offtarget > 0 ? offtarget - 1 : offtarget + 1); // Reduce off target counter
  128.         }
  129.  
  130.         float offtargetby = (0f + (offtarget + (baseofftarget * target.getCollisionRadius() / 100f)));
  131.  
  132.         // Make it slightly more accurate as missile gets closer to target
  133.         if (distance <= target.getCollisionRadius() * 2f) {
  134.             offtargetby *= (distance - target.getCollisionRadius() * 1.5f) / target.getCollisionRadius() + 0.5f;
  135.         }
  136.  
  137.         if (Math.abs(angularDistance) >= 70f || distance <= target.getCollisionRadius() * 1.5f) {
  138.             missile.setAngularVelocity(angularDistance * 1.5f);
  139.             offtargetby *= 0f;
  140.         }
  141.  
  142.         float AbsAngD = Math.abs(angularDistance - offtargetby);
  143.  
  144.         // Point towards target
  145.         if (AbsAngD > 0.5) {
  146.             // Makes missile fly off target
  147.             missile.giveCommand(angularDistance > offtargetby ? ShipCommand.TURN_LEFT : ShipCommand.TURN_RIGHT);
  148.         }
  149.  
  150.         // Course correction
  151.         if (AbsAngD < 5) {
  152.             float MFlightAng = VectorUtils.getAngle(new Vector2f(0, 0), missile.getVelocity());
  153.             float MFlightCC = MathUtils.getShortestRotation(missile.getFacing(), MFlightAng);
  154.             if (Math.abs(MFlightCC) > 20) {
  155.                 missile.giveCommand(MFlightCC < 0 ? ShipCommand.STRAFE_LEFT : ShipCommand.STRAFE_RIGHT);
  156.             }
  157.         }
  158.  
  159.         // Accelerate if the target is within angle tolerances
  160.         if (Math.abs(angularDistance) <= 90f) {
  161.             missile.giveCommand(ShipCommand.ACCELERATE);
  162.         }
  163.  
  164.         // Stop turning once missile is on target
  165.         if (AbsAngD < 0.4) {
  166.             missile.setAngularVelocity(0);
  167.         }
  168.     }
  169.  
  170.     @Override
  171.     public CombatEntityAPI getTarget() {
  172.         return target;
  173.     }
  174.  
  175.     @Override
  176.     public final void setTarget(CombatEntityAPI target) {
  177.         this.target = target;
  178.     }
  179. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement