Advertisement
DarkRevenant

Untitled

May 8th, 2014
316
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 7.64 KB | None | 0 0
  1. package data.scripts.weapons;
  2.  
  3. import com.fs.starfarer.api.Global;
  4. import com.fs.starfarer.api.combat.CombatEntityAPI;
  5. import com.fs.starfarer.api.combat.GuidedMissileAI;
  6. import com.fs.starfarer.api.combat.MissileAIPlugin;
  7. import com.fs.starfarer.api.combat.MissileAPI;
  8. import com.fs.starfarer.api.combat.ShipAPI;
  9. import com.fs.starfarer.api.combat.ShipCommand;
  10. import java.util.*;
  11. import org.lazywizard.lazylib.CollectionUtils;
  12. import org.lazywizard.lazylib.MathUtils;
  13. import org.lazywizard.lazylib.VectorUtils;
  14. import org.lazywizard.lazylib.combat.AIUtils;
  15. import org.lazywizard.lazylib.combat.CombatUtils;
  16. import org.lwjgl.util.vector.Vector2f;
  17.  
  18. //Based on LazyWizard's script
  19. public class SeekerAI implements MissileAIPlugin, GuidedMissileAI {
  20.  
  21.     // Our missile object
  22.     private final MissileAPI missile;
  23.     // Our current target (can be null)
  24.     private CombatEntityAPI target;
  25.  
  26.     private final static float ACCELERATION = 1900f;
  27.     private final static float MAX_SPEED = 430f;
  28.     private final static float VELOCITY_DAMPING_FACTOR = 0.05f; // Lower numbers means it will snap in place more abruptly; set it to some negative number if you want it to corkscrew drunkenly
  29.  
  30.     public static ShipAPI findBestTarget(MissileAPI missile) {
  31.         ShipAPI source = missile.getSource();
  32.         if (source != null && source.getShipTarget() != null && !source.getShipTarget().isHulk()) {
  33.             return source.getShipTarget();
  34.         }
  35.  
  36.         return AIUtils.getNearestEnemy(missile);
  37.     }
  38.  
  39.     public SeekerAI(MissileAPI missile, ShipAPI launchingShip) {
  40.         this.missile = missile;
  41.  
  42.         // Support for 'fire at target by clicking on them' behavior
  43.         List<ShipAPI> directTargets = CombatUtils.getShipsWithinRange(launchingShip.getMouseTarget(), 100f);
  44.         if (!directTargets.isEmpty()) {
  45.             Collections.sort(directTargets, new CollectionUtils.SortEntitiesByDistance(launchingShip.getMouseTarget()));
  46.             for (ShipAPI tmp : directTargets) {
  47.                 if (!tmp.isHulk() && tmp.getOwner() != launchingShip.getOwner()) {
  48.                     setTarget(tmp);
  49.                     break;
  50.                 }
  51.             }
  52.         }
  53.  
  54.         // Otherwise, use default Sidewinder targeting AI
  55.         if (target == null) {
  56.             setTarget(findBestTarget(missile));
  57.         }
  58.     }
  59.  
  60.     @Override
  61.     public void advance(float amount) {
  62.         if (missile.isFizzling() || missile.isFading()) {
  63.             return;
  64.         }
  65.  
  66.         // If our current target is lost, assign a new one
  67.         if (target == null // unset
  68.                 || (target instanceof ShipAPI && ((ShipAPI) target).isHulk()) // dead
  69.                 || (missile.getOwner() == target.getOwner()) // friendly
  70.                 || !Global.getCombatEngine().isEntityInPlay(target)) // completely removed
  71.         {
  72.             setTarget(findBestTarget(missile));
  73.             missile.giveCommand(ShipCommand.ACCELERATE);
  74.             return;
  75.         }
  76.  
  77.         // Head towards the target, with target leading
  78.         float distance = MathUtils.getDistance(target.getLocation(), missile.getLocation());
  79.         Vector2f guidedTarget = intercept(missile.getLocation(), missile.getVelocity().length(), ACCELERATION, MAX_SPEED, target.getLocation(), target.getVelocity());
  80.         if (guidedTarget == null) {
  81.             // If the target is unreachable, try to lead anyway
  82.             Vector2f projection = new Vector2f(target.getVelocity());
  83.             float scalar = distance / missile.getVelocity().length();
  84.             projection.scale(scalar);
  85.             guidedTarget = Vector2f.add(target.getLocation(), projection, null);
  86.         }
  87.  
  88.         float velocityFacing = VectorUtils.getFacing(missile.getVelocity());
  89.         float absoluteDistance = MathUtils.getShortestRotation(velocityFacing, VectorUtils.getAngle(missile.getLocation(), guidedTarget));
  90.         float angularDistance = MathUtils.getShortestRotation(missile.getFacing(), VectorUtils.getAngle(missile.getLocation(), guidedTarget));
  91.         float compensationDifference = MathUtils.getShortestRotation(angularDistance, absoluteDistance);
  92.         if (Math.abs(compensationDifference) <= 75f) {
  93.             angularDistance += 0.5f * compensationDifference;
  94.         }
  95.         float absDVel = Math.abs(absoluteDistance);
  96.         float absDAng = Math.abs(angularDistance);
  97.  
  98.         // Turn in the correct direction
  99.         missile.giveCommand(angularDistance < 0 ? ShipCommand.TURN_RIGHT : ShipCommand.TURN_LEFT);
  100.  
  101.         // Always accelerate
  102.         if (absDVel >= 45f || absDAng <= 45f) {
  103.             missile.giveCommand(ShipCommand.ACCELERATE);
  104.         }
  105.  
  106.         // Course correction
  107.         if (absDAng < 5) {
  108.             float MFlightAng = VectorUtils.getAngle(new Vector2f(0, 0), missile.getVelocity());
  109.             float MFlightCC = MathUtils.getShortestRotation(missile.getFacing(), MFlightAng);
  110.             if (Math.abs(MFlightCC) > 20) {
  111.                 missile.giveCommand(MFlightCC < 0 ? ShipCommand.STRAFE_LEFT : ShipCommand.STRAFE_RIGHT);
  112.             }
  113.         }
  114.  
  115.         //Damp angular velocity if we're getting close to the target angle
  116.         if (absDAng < Math.abs(missile.getAngularVelocity()) * VELOCITY_DAMPING_FACTOR) {
  117.             missile.setAngularVelocity(angularDistance / VELOCITY_DAMPING_FACTOR);
  118.         }
  119.     }
  120.  
  121.     public static Vector2f intercept(Vector2f point, float speed, float acceleration, float maxspeed, Vector2f target, Vector2f targetVel) {
  122.         Vector2f difference = new Vector2f(target.x - point.x, target.y - point.y);
  123.  
  124.         float s = speed;
  125.         float a = acceleration / 2f;
  126.         float b = speed;
  127.         float c = difference.length();
  128.         Vector2f solutionSet = quad(a, b, c);
  129.         if (solutionSet != null) {
  130.             float t = Math.min(solutionSet.x, solutionSet.y);
  131.             if (t < 0) {
  132.                 t = Math.max(solutionSet.x, solutionSet.y);
  133.             }
  134.             if (t > 0) {
  135.                 s = acceleration * t;
  136.                 s = s / 2f + speed;
  137.                 s = Math.min(s, maxspeed);
  138.             }
  139.         }
  140.  
  141.         a = targetVel.x * targetVel.x + targetVel.y * targetVel.y - s * s;
  142.         b = 2 * (targetVel.x * difference.x + targetVel.y * difference.y);
  143.         c = difference.x * difference.x + difference.y * difference.y;
  144.  
  145.         solutionSet = quad(a, b, c);
  146.  
  147.         Vector2f intercept = null;
  148.         if (solutionSet != null) {
  149.             float bestFit = Math.min(solutionSet.x, solutionSet.y);
  150.             if (bestFit < 0) {
  151.                 bestFit = Math.max(solutionSet.x, solutionSet.y);
  152.             }
  153.             if (bestFit > 0) {
  154.                 intercept = new Vector2f(target.x + targetVel.x * bestFit, target.y + targetVel.y * bestFit);
  155.             }
  156.         }
  157.  
  158.         return intercept;
  159.     }
  160.  
  161.     public static Vector2f quad(float a, float b, float c) {
  162.         Vector2f solution = null;
  163.         if (Float.compare(Math.abs(a), 0) == 0) {
  164.             if (Float.compare(Math.abs(b), 0) == 0) {
  165.                 solution = (Float.compare(Math.abs(c), 0) == 0) ? new Vector2f(0, 0) : null;
  166.             } else {
  167.                 solution = new Vector2f(-c / b, -c / b);
  168.             }
  169.         } else {
  170.             float d = b * b - 4 * a * c;
  171.             if (d >= 0) {
  172.                 d = (float) Math.sqrt(d);
  173.                 a = 2 * a;
  174.                 solution = new Vector2f((-b - d) / a, (-b + d) / a);
  175.             }
  176.         }
  177.         return solution;
  178.     }
  179.  
  180.     @Override
  181.     public CombatEntityAPI getTarget() {
  182.         return target;
  183.     }
  184.  
  185.     @Override
  186.     public void setTarget(CombatEntityAPI target) {
  187.         this.target = target;
  188.     }
  189. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement