Guest User

kitchenSINKIIai v1.1

a guest
Dec 11th, 2013
70
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package data.scripts.MissileAI;
  2.  
  3.  
  4. import com.fs.starfarer.api.Global;
  5. import com.fs.starfarer.api.combat.*;
  6. import com.fs.starfarer.api.util.IntervalUtil;
  7. import org.lazywizard.lazylib.MathUtils;
  8. import org.lazywizard.lazylib.combat.CombatUtils;
  9. import org.lwjgl.util.vector.Vector2f;
  10.  
  11. import java.awt.*;
  12. import java.util.ArrayList;
  13. import java.util.Iterator;
  14. import java.util.List;
  15.  
  16. import static jar.UtilityKit.LeadVector;
  17. import static jar.UtilityKit.getEnemyShipInArk;
  18. import static org.lazywizard.lazylib.combat.AIUtils.getNearbyEnemies;
  19. import static org.lwjgl.util.vector.Vector2f.add;
  20.  
  21. public class kitchenSINKIIai implements MissileAIPlugin
  22. {
  23.     // Our missile object
  24.     private final MissileAPI missile;
  25.     // Our current target (can be null)
  26.     private CombatEntityAPI target;
  27.  
  28.  
  29.     /////BEHAVIOUR RELATED FIELDS//////////
  30.  
  31.     //stuff that you can change  (MAIN missile stage AI components)
  32.     private float straighttimer=(float)(7f*Math.random());              //non targeting time
  33.     private IntervalUtil STimer = new IntervalUtil(.3f, .0f);   //rate of countdown
  34.     private final double isEffectedbyflare=Math.random();       //flare stuff
  35.     private boolean flarelockout=false;
  36.     private float oftarget=40f*((float)(.5-Math.random()));    //max initial off target (scatters missiles at launch)
  37.     private float baseoftarget=20f*((float)(.5-Math.random())); //min off target (makes missiles stay scattered)
  38.  
  39.     //when idle (has no target)          //equation used for orbit range  (IdleOrbitBase+(?ColisionRad:0))*(Min:Max)
  40.     private boolean StopOnIdle=false;    //stop movingg forwards //mutualy exclusive with orbit on idle
  41.     private boolean OrbitOnIdle=false;    //orbit source ship
  42.     private boolean StrafeOrbitOnIdle=false;//strafe or thust/turn
  43.     private float IdleOrbitBase=1;       //the base value multiplied by min/max
  44.     private boolean AddColisionRad=true;//add the ship colision radii to IdleOrbitBase
  45.     private float IdleOrbitRandom=((float)Math.random())-.5f;  //adds randomness
  46.     private float IdleOrbitMin=.9f*IdleOrbitRandom;             //minimum as a multiplier
  47.     private float IdleOrbitMax=1.1f*IdleOrbitRandom;            //max ""
  48.     private boolean SpinOnIdle=false;    //spin round
  49.  
  50.     //targeting AI selection
  51.     private boolean SearchOverwrite=false;                     //does weapon range overwrite search range
  52.     public static float searchrange = 2000;                     //how far out this missile can see(only if true)
  53.     private boolean SearchArkOverwrite=false;                  //does weapon range overwrite search range
  54.     public static float SearchArk = 10;                        //how large and ark missile will search
  55.     private static boolean RandomTarget=true;                  //should it pick a random target of all available
  56.     private static boolean TargetingLink=false;                //is its targeting linked to ships lock on target
  57.     private static boolean LaunchMouseTarget=true;             //can a mouse click overwrite targeting settings on launch
  58.     public static ShipAPI findBestTarget(MissileAPI missile)   //what targeting algorithm is used
  59.     {
  60.         if (TargetingLink)   //targeting links to the source ship, don't touch, code
  61.         {
  62.             ShipAPI source = missile.getSource();                             //who launched you?
  63.             if (source != null && source.getShipTarget() != null              //check for nulls
  64.                     && !source.getShipTarget().isHulk()                       //check if its alive
  65.                     && MathUtils.getDistance(source.getShipTarget(), source)  //get range to target
  66.                     <searchrange)                          //check if its in range
  67.                 return source.getShipTarget();
  68.         }
  69.         /////the AI picker/////(you can change this)
  70.         return SPHEREsearch(missile, RandomTarget);     // ARKsearch, SPHEREsearch current possible search algorithms
  71.     }
  72.  
  73.     //flarechasing
  74.     public static final String flare="flare";
  75.     public final float BaseIgnoreChance=.3f;                    //chance that flares cannot effect it by default
  76.     public final float LockCHance=.3f;                          //chance that future flares it encounters wont effect it
  77.     private IntervalUtil Timer = new IntervalUtil(.1f, .0f);    //rate of countdown for off target
  78.     private final boolean StopNTurn=false;                      //when far off target missile will stop and turn to aim
  79.  
  80.     //weaving behaviour
  81.     private final boolean Weave=false;                          //go in a zigzag path (improved over extingency script)
  82.     private float Weavesize=40f;                                //how far of course it will go, in degrees
  83.     private float WeaveFreq=40f;                                //how ofter it cycles (arbitary)
  84.     private float weavecount=0;                                 //misc dont change
  85.  
  86.     //scripts for HardTargeting/orbitrange
  87.     private final float MaxRange=850f;    //max range when it starts to direct aim target
  88.     private final float MinRange=500f;    //min range when it detonates
  89.     private final boolean HardTargeting=true;//will it turn to target once in range
  90.  
  91.     //Heatseeker like behaviour (uses Min/Max range)
  92.     private final boolean Backtarget=true;   //dose it circle around back of ship
  93.     private final float BackAng=45f;                     //min angle from rear
  94.     private final boolean Straferound=false;             //strafe there or turn there
  95.  
  96.     //DRONE script (core behaviour script)
  97.     private final boolean isDrone=false;       //makes missile bob in and out of MinRange and maintain that distance
  98.     private final boolean Orbit=false;         //will the drone strafe around target?
  99.     private double ODir=Math.random();         //direction of strafe .5> left:right //used by SpinOnIdle
  100.     private IntervalUtil OTimer = new IntervalUtil(3f, .01f); //delay between strafe switch
  101.     //used in Backtarget as well
  102.     private final float MinOrbit=.9f;       //how close will the drone move in
  103.     private final float MaxOrbit=1.2f;      //how far will the drone move  away
  104.  
  105.     //weapons
  106.     //controls firing, everything below needs this on
  107.     private final boolean canFire=false;   //is shooting enabled
  108.     //////////////////////////////////////////////////////////////////////////////////////////////////////////
  109.  
  110.     //weaponlist
  111.     //nasty stuff drone uses as weapons
  112.     //replace with projectile cannon like "chaingun" or "vulcan" from vanilla,
  113.     // or your own weapon(no beams)(Ballistic_as_beam are fine)
  114.     private static String [] Guns = {
  115.             "DUMMY1",
  116.             "DUMMY2",
  117.             "chaingun",
  118.             "vulcan",
  119.     };
  120.  
  121.     //and missiles
  122.     private static String [] Missiles = {
  123.             "Linghning",                 //special, shoots lightning bolts
  124.             "harpoon_single",
  125.             "heatseeker",
  126.     };
  127.  
  128.     //////////////////////////////////////////////////////////////////////////////////////////////////////
  129.  
  130.     //weaponpicker
  131.     private float MislChance=.8f;                        //chance of missiles (1-MislChance)*100=%shots missile
  132.     private int MislVolley=1;                            //number of missiles per
  133.     private int ProjVolley=4;                            //number of Projectiles per
  134.     private boolean Missil=(Math.random() > MislChance);                 //is it firing a missile
  135.     private String Projectile = (Missil? Missiles:Guns)  //picks the weapon
  136.             [(int) ((Missil? Missiles:Guns).length * Math.random())];
  137.  
  138.  
  139.     //MIRV/Flechet script (core firing script of a drone missile)
  140.     //dummy weapon  supports missiles and projectiles
  141.     //suggested projectile stats, range:1,  speed:1
  142.     private final float PArk=25;          //ark projectiles fly in
  143.     private final int PNum=1;             //shots per volley
  144.     private int PVolleys=Missil ? MislVolley:ProjVolley;    //volleys/burst fire for drone
  145.     private final float Lifetime=1f;      //how long the projectile being used can stay alive (IMPORTANT)
  146.     //this is a value you must enter it is equal to range/ProjSpeed and works as a multiplier to make
  147.     // firing velocity not overshoot the target (due to long life)
  148.     private final float Leadtime=1f;       //fiddle with this if your projectiles are missing the target
  149.     //determines how far ahead of the target your weapon aims
  150.     private IntervalUtil VTimer = new IntervalUtil(.15f, .01f);         //rate of fire
  151.     private final boolean IsFlechet=true;//are the shots fired by missile aimed or follow missile facing?
  152.     //if IsFlechet=false missile will fire shots at the target ignoring its direction of travel
  153.     private boolean DespawnEmpty=false;      //should it de-spawn the missile once it has run out of ammo
  154.     private boolean SpawnEmpty=false;        //to spawn an empty type subprojectile(casing)
  155.     private boolean canReload=true;          //can reload after a burst
  156.     private IntervalUtil BTimer = new IntervalUtil(1.8f, .01f); //delay between each burst
  157.     public static void emptyspawn(CombatEngineAPI engine, MissileAPI missile)
  158.     {
  159.         engine.spawnProjectile(missile.getSource(),null,//who made you
  160.                 "DUMMY2",                        //empty missile,
  161.                 missile.getLocation(),           //Vector2f firing origin point
  162.                 missile.getFacing(),             //float angle of fire
  163.                 missile.getVelocity());          //Vector2f firing velocity)
  164.     }
  165.     //end of stuff you can change
  166.  
  167.     //////////////////////////////////////////////////////////////////////////////////////////////////////////
  168.  
  169.     //public static float Ark = 30;          //60deg ark   default
  170.  
  171.     boolean newlaunch=true;                //only do mouse target once on a newly launched missile
  172.     public kitchenSINKIIai(MissileAPI missile)
  173.     {
  174.         this.missile = missile;
  175.         if (SearchOverwrite)
  176.         {
  177.             searchrange=missile.getWeapon() != null ? missile.getWeapon().getRange() : searchrange;//based on weapon
  178.         }
  179.  
  180.         if (SearchArkOverwrite)
  181.         {
  182.             SearchArk=5+(missile.getWeapon() != null ? missile.getWeapon().getArc()/4 : SearchArk);     //based on weapon
  183.         }
  184.         //missile.setCollisionClass(CollisionClass.FIGHTER);//hack reclasify as fighter
  185.  
  186.  
  187.         // Support for 'fire at target by clicking on them' behavior
  188.         if (newlaunch=true)
  189.         {
  190.             newlaunch=false;
  191.             //get targets near mouse
  192.             if (LaunchMouseTarget)
  193.             {
  194.                 Vector2f MouseT = missile.getSource().getMouseTarget();
  195.                 if (MathUtils.getDistance(missile,MouseT)<searchrange)
  196.                 {
  197.                     List directTargets = CombatUtils.getShipsWithinRange(
  198.                             MouseT, 100f, true);
  199.  
  200.                     if (!directTargets.isEmpty())
  201.                     {
  202.                         ShipAPI tmp;
  203.                         for (Iterator iter = directTargets.iterator(); iter.hasNext();)
  204.                         {
  205.                             //filter out friendlies
  206.                             tmp = (ShipAPI) iter.next();
  207.                             if (tmp.getOwner() != missile.getSource().getOwner())
  208.                             {
  209.                                 target = tmp;
  210.                                 break;
  211.                             }
  212.                         }
  213.                     }
  214.                 }
  215.             }
  216.         }
  217.  
  218.         // Otherwise, use default targeting AI
  219.         if (target == null)
  220.         {
  221.             target = findBestTarget(missile);
  222.         }
  223.     }
  224.     ///////////////////////////////////////////////////////////////////////////////////////////////////////
  225.  
  226.     //flare finder
  227.  
  228.     public static MissileAPI checkforflare(MissileAPI missile)
  229.     {
  230.         MissileAPI retv = null;                                   //if no flares return null
  231.         CombatEngineAPI engine = Global.getCombatEngine();
  232.         List nearbymissiles = engine.getMissiles();               //(target.getCollisionRadius()*10)
  233.         if (!nearbymissiles.isEmpty())
  234.         {
  235.             MissileAPI tmp;
  236.             for (Iterator iter = nearbymissiles.iterator(); iter.hasNext();)
  237.             {
  238.                 tmp = (MissileAPI) iter.next();
  239.  
  240.                 if ((tmp.getProjectileSpecId()).startsWith(flare) //is it a flare
  241.                         && MathUtils.getDistance(tmp,missile)<300 //is it near your missile
  242.                         && missile.getOwner()!=tmp.getOwner()     //is it en enemy flare
  243.                         && Math.random()>.5)                      //chance of failure prevents all missiles
  244.                 {                                                 //going after one flare at the same time
  245.                     //tmp= (MissileAPI) nearbymissiles.get(0);    //testing code
  246.                     retv = tmp;                                   //return flare
  247.                     break;                                        //stop searching you found your flare
  248.                 }
  249.             }
  250.         }
  251.         return retv;
  252.     }
  253.  
  254.     /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  255.  
  256.     //search for targets in ark in front
  257.     //picks a random target that is in range
  258.     public static ShipAPI ARKsearch(MissileAPI missile, boolean RandomTarget)
  259.     {
  260.         //find targets in ark in front of missile
  261.         ArrayList targets = getEnemyShipInArk(missile, SearchArk, searchrange, true);
  262.  
  263.         int GetNom = RandomTarget ? (int) (targets.size() * Math.random()) : 0;
  264.         if (!targets.isEmpty())
  265.         {   //pick random missile in list
  266.             return (ShipAPI) targets.get(GetNom);
  267.         }
  268.         else return null;
  269.  
  270.     }
  271.  
  272.     ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  273.  
  274.  
  275.     //get ship target or search for closest enemy
  276.     public static ShipAPI SPHEREsearch(MissileAPI missile, boolean RandomTarget)
  277.     {
  278.         List targets = getNearbyEnemies(missile, searchrange, true);
  279.  
  280.         int GetNom = RandomTarget ? (int) (targets.size() * Math.random()) : 0;
  281.         if (!targets.isEmpty())
  282.         {
  283.         return (ShipAPI) targets.get(GetNom);
  284.         }
  285.         else return null;
  286.     }
  287.  
  288.     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  289.  
  290.  
  291.     //main missile AI
  292.  
  293.     //stored variables don't touch
  294.     private boolean BTcutout=false;         //Backtargeting bool
  295.     private boolean Close=true;             //orbiting thruster bool
  296.     private int VCount=0;                   //counter for firing script
  297.     private boolean Loaded=true;            //firing bool
  298.     private boolean CloseIdle=true;             //orbiting thruster bool
  299.     @Override
  300.     public void advance(float amount)
  301.     {
  302.  
  303.         //timer
  304.         Timer.advance(amount);
  305.         STimer.advance(amount);
  306.         VTimer.advance(amount);
  307.         OTimer.advance(amount);
  308.         BTimer.advance(amount);
  309.         weavecount++;
  310.         if (weavecount>4000){weavecount=0;} //arbitary reset
  311.  
  312.         ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  313.  
  314.         //go straight for x after launch
  315.         if (straighttimer>0)
  316.         {
  317.             missile.giveCommand(ShipCommand.ACCELERATE);
  318.             if (STimer.intervalElapsed())
  319.             {straighttimer--;}
  320.             return;
  321.         }
  322.         else
  323.         {
  324.             ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  325.  
  326.  
  327.             // Apparently commands still work while fizzling
  328.             if (missile.isFading() || missile.isFizzling())
  329.             {
  330.                 return;
  331.             }
  332.  
  333.             ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  334.  
  335.  
  336.  
  337.             //find a target
  338.             if (target == null)
  339.             {
  340.                 target = findBestTarget(missile);
  341.             }
  342.  
  343.             /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  344.  
  345.  
  346.             //if missile is susceptible to flare
  347.             if (isEffectedbyflare>BaseIgnoreChance        //can a flare effect it
  348.                     && !flarelockout                      //has it already been set to ignore flares
  349.                     && Timer.intervalElapsed())           //check every .10 sec
  350.  
  351.             {
  352.                 MissileAPI flaretarget = checkforflare(missile);
  353.                 if (flaretarget!=null)
  354.                 {
  355.                     target=flaretarget;         //set flare as target
  356.                     if (LockCHance<(float)Math.random())flarelockout=true;          //ignore future flares
  357.                 }
  358.  
  359.             }
  360.  
  361.             //////////////////////////////////////////////////////////////////////////////////////////////////////////////
  362.  
  363.  
  364.             //pathing ai
  365.             if (target!=null)               //if you have a target
  366.             {
  367.                 //reduction off target/gradual aiming
  368.                 if (Timer.intervalElapsed())
  369.                 {
  370.                     oftarget=(oftarget>0 ? oftarget-1 : oftarget+1); //reduce off target counter;
  371.                 }
  372.  
  373.                 //////////////////////////////////////////////////////////////////////////////////////////////
  374.                 //check if scatter code needed
  375.                 float targetcolision = target.getCollisionRadius();       //get colision radi
  376.                 if (MathUtils.getDistance(missile, target)<75+(targetcolision))
  377.                 {                                                         //cutoff for baseoftarget behaviour
  378.                     baseoftarget=0;      //aim variable if you got in close enough is 0 (ie go hit the enemy target)
  379.                 }
  380.  
  381.                 ///////////////////////////////////////////////////////////////////////////////////////////////
  382.  
  383.  
  384.                 //how much off target will the missiles be
  385.                 float oftargetby = (0 + (oftarget + (baseoftarget * targetcolision / 75)));
  386.  
  387.                 //////////////////////////////////////////////////////////////////////////////////////////
  388.  
  389.                 //aming
  390.                 //1step calculations of various stats
  391.                 Vector2f MVel = missile.getVelocity();
  392.                 Vector2f MLoc = missile.getLocation();
  393.                 Vector2f TLoc = target.getLocation();
  394.                 Vector2f TVel = target.getVelocity();
  395.                 //float MSpeed = (float)Math.sqrt(MVel.lengthSquared());
  396.                 //float TSpeed = (float)Math.sqrt(TVel.lengthSquared());
  397.                 float MFace = missile.getFacing();
  398.                 float TFace = target.getFacing();
  399.                 double TfaceRad = Math.toRadians(TFace);
  400.                 float TCol = target.getCollisionRadius();
  401.                 float sx = (float) (TCol*.5*Math.cos(TfaceRad));
  402.                 float sy = (float) (TCol*.5*Math.sin(TfaceRad));
  403.                 Vector2f TNose = new Vector2f(sx, sy);
  404.                 float RangeToTarget = MathUtils.getDistance(TLoc, MLoc);
  405.                 //float TimeToTarget = RangeToTarget/MSpeed;                      //how long till you hit
  406.  
  407.  
  408.                 //testing InterceptPoint
  409.                 Vector2f Lvec = LeadVector(TLoc, TVel, MLoc, MVel);
  410.  
  411.                 //////////////////////////////////////////////////////////////////////////////////////////
  412.  
  413.                 //override when in range
  414.                 if (HardTargeting && RangeToTarget<MaxRange)
  415.                 {
  416.                     Lvec= multV2f(TVel, Leadtime);
  417.                     baseoftarget=0;
  418.                     oftarget=0;
  419.                     oftargetby=0;
  420.                 }
  421.  
  422.                 //////////////////////////////////////////////////////////////////////////////////////////
  423.  
  424.  
  425.                 //lead target
  426.                 Vector2f TLead = add(TLoc,            //target location+
  427.                         Lvec,       //target speed*time to get to target+
  428.                         null);      // if its too long just assume 3 seconds is long enough to course correct
  429.  
  430.  
  431.  
  432.                 //aim at nose (can be changed to part targeting with a few tweaks)
  433.                 Vector2f TNoseLead = add(TLead, TNose, null);//aim at the nose of the target(optional)
  434.  
  435.                 //main aiming (to find angle you are off target by)
  436.                 float AngleToEnemy = MathUtils.getAngle(MLoc, TNoseLead);
  437.                 float AtTarget = getAngleDifference(  //how far off target you are
  438.                         MFace, AngleToEnemy);          //where missile pointing, where target is in relation
  439.  
  440.                 //for backtargeting
  441.                 if (Backtarget && RangeToTarget<MaxRange)
  442.                 {
  443.                     float AngFromTtoM = MathUtils.getAngle(TLoc, MLoc);       //get angle from target
  444.                     float ToMissile = getAngleDifference(TFace, AngFromTtoM); //to missile
  445.  
  446.                     if (Math.abs(ToMissile)>180-BackAng)   //check if you are behind the target
  447.                     {BTcutout=true;}
  448.                     else if (isDrone)     //override for drones, re enables the AI
  449.                     {BTcutout=false;}
  450.  
  451.                     if (!Straferound && !BTcutout)
  452.                     {
  453.                         AtTarget=AtTarget-(ToMissile>0? 90:-90);
  454.                     }
  455.  
  456.                     if (Straferound && !BTcutout)
  457.                     {
  458.                         missile.giveCommand(ToMissile < 0
  459.                                 ? ShipCommand.STRAFE_LEFT : ShipCommand.STRAFE_RIGHT);
  460.                     }
  461.                 }
  462.  
  463.                 //makes the missile weave
  464.                 if (Weave)
  465.                 {AtTarget=AtTarget+(float)(Math.sin(weavecount/WeaveFreq)*Weavesize);}
  466.  
  467.                 float AbsAngD = Math.abs(AtTarget-oftargetby);
  468.  
  469.  
  470.                 //////////////////////////////////////////////////////////////////////////////////////////////
  471.  
  472.  
  473.                 //point towards target
  474.                 if (AbsAngD > 0.5)
  475.                 {                                  //makes missile fly off target
  476.                     missile.giveCommand(AtTarget > oftargetby
  477.                             ? ShipCommand.TURN_LEFT : ShipCommand.TURN_RIGHT);
  478.                 }
  479.  
  480.                 ////////////////////////////////////////////////////////////////////////////////////////////////////
  481.  
  482.  
  483.                 //correct missile velocity vector to be the same as missile facing
  484.                 if (AbsAngD < 5)
  485.                 {
  486.                     //course correct for missile velocity vector
  487.                     float MFlightAng = MathUtils.getAngle(new Vector2f(0, 0), MVel);
  488.                     float MFlightCC = getAngleDifference(MFace, MFlightAng);
  489.                     if (Math.abs(MFlightCC)>20)
  490.                     {
  491.                         missile.giveCommand(MFlightCC < 0
  492.                                 ? ShipCommand.STRAFE_LEFT : ShipCommand.STRAFE_RIGHT);
  493.                     }
  494.  
  495.                 }
  496.  
  497.                 /////////////////////////////////////////////////////////////////////////////////////////////////
  498.  
  499.  
  500.                 //stop turning once you are on target (way of the hack, ignores missile limitations)
  501.                 if (AbsAngD < 0.4)
  502.                 {
  503.                     missile.setAngularVelocity(0);
  504.                 }
  505.  
  506.                 ///////////////////////////////////////////////////////////////////////////////////////////////
  507.  
  508.                 if((!isDrone && !Straferound)                                 //not a drone or strafingBT
  509.                         || (isDrone && RangeToTarget>MaxRange)                //is out or orbital range
  510.                         || (Backtarget && RangeToTarget>MaxRange && !BTcutout)
  511.                         || BTcutout)                                          //is BTcutout
  512.                 {
  513.                     //acceleration code (stopNturn compatible)
  514.                     if (StopNTurn)
  515.                     {
  516.                         if (AbsAngD < 40)
  517.                         {
  518.                             missile.giveCommand(ShipCommand.ACCELERATE);
  519.                         }
  520.                         if (MVel.lengthSquared()<TVel.lengthSquared())
  521.                         {
  522.                             missile.giveCommand(ShipCommand.ACCELERATE);
  523.                         }
  524.                         if (AbsAngD > 120)        //if you missed stop and turn around
  525.                         {
  526.                             missile.giveCommand(ShipCommand.DECELERATE);
  527.                         }
  528.                     }
  529.                     else{missile.giveCommand(ShipCommand.ACCELERATE);}
  530.                 }
  531.                 /////////////////////////////////////////////////////////////////////////////////////////////////
  532.  
  533.                 else  //move back and forth, if its a drone
  534.                 {
  535.                     if (RangeToTarget<MinRange*MinOrbit){Close=false;} //boolean to achive back and forth motion
  536.                     if (RangeToTarget>MinRange*MaxOrbit){Close=true;}
  537.                     if (Close) {missile.giveCommand(ShipCommand.ACCELERATE);}
  538.                     else {missile.giveCommand(ShipCommand.ACCELERATE_BACKWARDS);}
  539.  
  540.                     /////////////////////////////////////////////////////////////////////////////////////////////////
  541.  
  542.                     //orbit target
  543.                     if (Orbit)
  544.                     {
  545.                         if (OTimer.intervalElapsed())
  546.                         {
  547.                             ODir=Math.random();
  548.                         }
  549.                         missile.giveCommand(ODir < .5
  550.                                 ? ShipCommand.STRAFE_LEFT : ShipCommand.STRAFE_RIGHT);
  551.                     }
  552.                 }
  553.  
  554.                 /////////////////////////////////////////////////////////////////////////////////////////////////
  555.  
  556.  
  557.                 //testcode    spawns particle at aim points
  558.                 CombatEngineAPI engine = Global.getCombatEngine(); //engine
  559.                 //engine.addSmoothParticle(TLead, new Vector2f(0,0), 5, 1, 1, new Color(255,10,15,255));
  560.                 //engine.addSmoothParticle(TNoseLead, new Vector2f(0,0), 5, 1, 1, new Color(93, 255, 40,255));
  561.                 //engine.addSmoothParticle(MLoc, multV2f(MVel, 4), 5, .5f, 1, new Color(248, 244, 255,255));
  562.                 //engine.addSmoothParticle(MLoc, new Vector2f(0,0), 5, .5f, 1, new Color(2, 255, 250,255));
  563.  
  564.  
  565.                 /////////////////////////////////////////////////////////////////////////////////////////////////
  566.  
  567.                 if (canFire) //overriding controll for firing
  568.                 {
  569.                     //reload
  570.                     if (canReload && !Loaded && BTimer.intervalElapsed())
  571.                     {
  572.                         Loaded=true;
  573.                         VCount=0;
  574.                         {
  575.                             //weaponpicker
  576.                             Missil=(Math.random() > MislChance);         //is it firing a missile
  577.                             Projectile = (Missil? Missiles:Guns)         //picks the weapon
  578.                                     [(int) ((Missil? Missiles:Guns).length * Math.random())];
  579.                             PVolleys=Missil ? MislVolley:ProjVolley;
  580.                         }
  581.                     }
  582.  
  583.  
  584.  
  585.                     /////////////////////////////////////////////////////////////////////////////////////////////////
  586.  
  587.  
  588.                     if (Loaded && VTimer.intervalElapsed() && RangeToTarget<MinRange && VCount<PVolleys)
  589.                     {
  590.                         VCount++;
  591.                         {
  592.                             if (Projectile.equals("Linghning"))     //cause lightningbolts!!
  593.                             {
  594.                                 engine.spawnEmpArc(missile.getSource(), MLoc, target, target,
  595.                                         DamageType.ENERGY,
  596.                                         50f,
  597.                                         2000,
  598.                                         10000f, // max range
  599.                                         "tachyon_lance_emp_impact",
  600.                                         20f, // thickness
  601.                                         new Color(255,10,15,255),
  602.                                         new Color(255,255,255,255)
  603.                                 );
  604.                             }
  605.                             else
  606.                             {
  607.                                 //spawn projectiles
  608.                                 int counts=0;         //how many projectiles?
  609.                                 do {
  610.                                     float angRAND= (float) ((PArk*(.5-Math.random())));          //angle of spread
  611.                                     float speedRAND= (float) (((MaxRange-MinRange)/Lifetime)*Math.random());//variance of speed
  612.                                     float PSpeed = (MinRange/Lifetime)+speedRAND;                           //speed of bullets launched
  613.                                     float PAng = (IsFlechet ? missile.getFacing()                //direction of fire
  614.                                             :missile.getFacing()+AtTarget)-angRAND;
  615.                                     float x = (float) (PSpeed*Math.cos(Math.toRadians(PAng)));
  616.                                     float y = (float) (PSpeed*Math.sin(Math.toRadians(PAng)));
  617.                                     Vector2f PVec = new Vector2f(x,y);                     //convert all that into a vector
  618.                                     Vector2f PMVec = add(MVel, PVec, null);                //true Pvec
  619.  
  620.                                     //for missile weapon offset
  621.                                     float xa = (float) (11*Math.cos(Math.toRadians(missile.getFacing()-95)));
  622.                                     float ya = (float) (11*Math.sin(Math.toRadians(missile.getFacing()-95)));
  623.                                     Vector2f MoffVec = new Vector2f(xa,ya);
  624.  
  625.                                     //for projectile weapon ofset
  626.                                     float xb = (float) (25*Math.cos(Math.toRadians(missile.getFacing()+45)));
  627.                                     float yb = (float) (25*Math.sin(Math.toRadians(missile.getFacing()+45)));
  628.                                     Vector2f PoffVec = new Vector2f(xb,yb);
  629.  
  630.                                     Vector2f Lpoint = add(MLoc, Missil ? MoffVec : PoffVec, null);
  631.  
  632.                                     engine.spawnProjectile(
  633.                                             missile.getSource(),
  634.                                             null,                            //who made you
  635.                                             Projectile,                      //spawn the projectile
  636.                                             Lpoint,                            //Vector2f firing origin point
  637.                                             PAng,                            //float angle of fire
  638.                                             PMVec);                          //Vector2f firing velocity
  639.  
  640.                                     /////////////////////////////////////////////////////////////////////////////////////
  641.  
  642.                                     counts++;
  643.  
  644.  
  645.                                     ////////////////////////////////////////////////////////////////////////////////
  646.  
  647.  
  648.                                     //optional explosion/particle glows
  649.                                     //engine.addHitParticle(Lpoint, PMVec,
  650.                                     //        5f,1f,1f,new Color(112, 152, 137,255)); //size, alpha, duration, color
  651.                                     engine.spawnExplosion(Lpoint, PMVec,
  652.                                             new Color(255, 86, 13,255), 15f, .1f);  //color,size,duration(max)
  653.  
  654.                                     //////////////////////////////////////////////////////////////////////////////////
  655.                                 }while (counts<PNum);
  656.                             }
  657.                         }
  658.                         //////////////////////////////////////////////////////////////////////////////////
  659.  
  660.                         //main explosion flash
  661.                         //engine.addHitParticle(MLoc, missile.getVelocity(),10,1f,1f,new Color(255, 12, 25,255));
  662.                     }
  663.  
  664.  
  665.                     //////////////////////////////////////////////////////////////////////////////////
  666.  
  667.  
  668.                     if (VCount>=PVolleys)
  669.                     {
  670.                         Loaded=false;
  671.  
  672.                         if(DespawnEmpty)
  673.                         {
  674.                             if (SpawnEmpty) {emptyspawn(engine,missile);}
  675.                             engine.removeEntity(missile);
  676.                         }
  677.                     }
  678.  
  679.                 }
  680.  
  681.             }
  682.  
  683.  
  684.             //////////////////////////////////////////////////////////////////////////////////////////////////////
  685.  
  686.  
  687.             //if you have no target
  688.             if (target==null && straighttimer<1)
  689.             {
  690.                 if (StopOnIdle)        //stop
  691.                 {missile.giveCommand(ShipCommand.DECELERATE);}
  692.                 else if (OrbitOnIdle)  //orbit source ship
  693.                 {
  694.                     ShipAPI Msource = missile.getSource();
  695.                     float RangeToSource = MathUtils.getDistance(Msource.getLocation(), missile.getLocation());
  696.                     float OIdleRange = IdleOrbitBase + (AddColisionRad ? Msource.getCollisionRadius() : 0);
  697.                     if (RangeToSource<OIdleRange*IdleOrbitMin){CloseIdle=true;} //boolean to achive back and forth motion
  698.                     if (RangeToSource>OIdleRange*IdleOrbitMax){CloseIdle=false;}
  699.  
  700.                     float MSang = getAngleDifference(missile.getFacing(),
  701.                             MathUtils.getAngle(missile.getLocation(),Msource.getLocation()));
  702.                     if (StrafeOrbitOnIdle)
  703.                     {
  704.                         missile.giveCommand(MSang < 0 ? ShipCommand.TURN_LEFT : ShipCommand.TURN_RIGHT);
  705.  
  706.                         if (Math.abs(MSang) > 175)
  707.                         {
  708.                             missile.giveCommand(ODir < .5 ? ShipCommand.STRAFE_LEFT : ShipCommand.STRAFE_RIGHT);
  709.                             missile.giveCommand(CloseIdle ? ShipCommand.ACCELERATE:ShipCommand.ACCELERATE_BACKWARDS);
  710.                         }
  711.                     }
  712.                     else
  713.                     {
  714.                         float OrbitTurnAngle = (ODir < .5 ? 90+(CloseIdle ? 10:-65) : -90-(CloseIdle ? 10:-65));
  715.                         missile.giveCommand(MSang > OrbitTurnAngle ? ShipCommand.TURN_LEFT : ShipCommand.TURN_RIGHT);
  716.                         if (Math.abs(MSang-OrbitTurnAngle)<30) missile.giveCommand(ShipCommand.ACCELERATE);
  717.                         if (Math.abs(MSang-OrbitTurnAngle)>40) missile.giveCommand(ShipCommand.DECELERATE);
  718.                     }
  719.                 }
  720.                 //else                //keep going
  721.                 //{missile.giveCommand(ShipCommand.ACCELERATE);}
  722.  
  723.                 if (SpinOnIdle)     //spin round
  724.                 {missile.giveCommand((ODir > .5 ? ShipCommand.TURN_RIGHT:ShipCommand.TURN_LEFT));}
  725.             }
  726.  
  727.             ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  728.  
  729.  
  730.             //clear target if target is gone
  731.             if (target == null // unset
  732.                     ||  ( missile.getOwner() == target.getOwner() )        // friendly
  733.                     ||  !Global.getCombatEngine().isEntityInPlay(target)   // completely removed
  734.                     || ( target instanceof ShipAPI && ((ShipAPI)target).isHulk() ))//dead
  735.             {
  736.  
  737.                 target = findBestTarget(missile);
  738.                 return;
  739.             }
  740.         }
  741.     }
  742.  
  743.     ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  744.  
  745.  
  746.     // Will be in next LazyLib version
  747.     public static float getAngleDifference(float angle1, float angle2)
  748.     {
  749.         float distance = (angle2 - angle1) + 180f;
  750.         distance = (distance / 360.0f);
  751.         distance = ((distance - (float) Math.floor(distance)) * 360f) - 180f;
  752.         return distance;
  753.     }
  754.  
  755.     ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  756.  
  757.  
  758.     //multiply vectors //own code
  759.     public static Vector2f multV2f(Vector2f Vector1, float Multiplier)
  760.     {
  761.         float v1x = Vector1.getX()*Multiplier;
  762.         float v1y = Vector1.getY()*Multiplier;
  763.         Vector2f v1end = new Vector2f(v1x, v1y);
  764.         return v1end;
  765.     }
  766.  
  767.     /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  768.  
  769. }
RAW Paste Data