Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package data.scripts.MissileAI;
- import com.fs.starfarer.api.Global;
- import com.fs.starfarer.api.combat.*;
- import com.fs.starfarer.api.util.IntervalUtil;
- import org.lazywizard.lazylib.MathUtils;
- import org.lazywizard.lazylib.combat.CombatUtils;
- import org.lwjgl.util.vector.Vector2f;
- import java.awt.*;
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.List;
- import static jar.UtilityKit.LeadVector;
- import static jar.UtilityKit.getEnemyShipInArk;
- import static org.lazywizard.lazylib.combat.AIUtils.getNearbyEnemies;
- import static org.lwjgl.util.vector.Vector2f.add;
- public class kitchenSINKIIai implements MissileAIPlugin
- {
- // Our missile object
- private final MissileAPI missile;
- // Our current target (can be null)
- private CombatEntityAPI target;
- /////BEHAVIOUR RELATED FIELDS//////////
- //stuff that you can change (MAIN missile stage AI components)
- private float straighttimer=(float)(7f*Math.random()); //non targeting time
- private IntervalUtil STimer = new IntervalUtil(.3f, .0f); //rate of countdown
- private final double isEffectedbyflare=Math.random(); //flare stuff
- private boolean flarelockout=false;
- private float oftarget=40f*((float)(.5-Math.random())); //max initial off target (scatters missiles at launch)
- private float baseoftarget=20f*((float)(.5-Math.random())); //min off target (makes missiles stay scattered)
- //when idle (has no target) //equation used for orbit range (IdleOrbitBase+(?ColisionRad:0))*(Min:Max)
- private boolean StopOnIdle=false; //stop movingg forwards //mutualy exclusive with orbit on idle
- private boolean OrbitOnIdle=false; //orbit source ship
- private boolean StrafeOrbitOnIdle=false;//strafe or thust/turn
- private float IdleOrbitBase=1; //the base value multiplied by min/max
- private boolean AddColisionRad=true;//add the ship colision radii to IdleOrbitBase
- private float IdleOrbitRandom=((float)Math.random())-.5f; //adds randomness
- private float IdleOrbitMin=.9f*IdleOrbitRandom; //minimum as a multiplier
- private float IdleOrbitMax=1.1f*IdleOrbitRandom; //max ""
- private boolean SpinOnIdle=false; //spin round
- //targeting AI selection
- private boolean SearchOverwrite=false; //does weapon range overwrite search range
- public static float searchrange = 2000; //how far out this missile can see(only if true)
- private boolean SearchArkOverwrite=false; //does weapon range overwrite search range
- public static float SearchArk = 10; //how large and ark missile will search
- private static boolean RandomTarget=true; //should it pick a random target of all available
- private static boolean TargetingLink=false; //is its targeting linked to ships lock on target
- private static boolean LaunchMouseTarget=true; //can a mouse click overwrite targeting settings on launch
- public static ShipAPI findBestTarget(MissileAPI missile) //what targeting algorithm is used
- {
- if (TargetingLink) //targeting links to the source ship, don't touch, code
- {
- ShipAPI source = missile.getSource(); //who launched you?
- if (source != null && source.getShipTarget() != null //check for nulls
- && !source.getShipTarget().isHulk() //check if its alive
- && MathUtils.getDistance(source.getShipTarget(), source) //get range to target
- <searchrange) //check if its in range
- return source.getShipTarget();
- }
- /////the AI picker/////(you can change this)
- return SPHEREsearch(missile, RandomTarget); // ARKsearch, SPHEREsearch current possible search algorithms
- }
- //flarechasing
- public static final String flare="flare";
- public final float BaseIgnoreChance=.3f; //chance that flares cannot effect it by default
- public final float LockCHance=.3f; //chance that future flares it encounters wont effect it
- private IntervalUtil Timer = new IntervalUtil(.1f, .0f); //rate of countdown for off target
- private final boolean StopNTurn=false; //when far off target missile will stop and turn to aim
- //weaving behaviour
- private final boolean Weave=false; //go in a zigzag path (improved over extingency script)
- private float Weavesize=40f; //how far of course it will go, in degrees
- private float WeaveFreq=40f; //how ofter it cycles (arbitary)
- private float weavecount=0; //misc dont change
- //scripts for HardTargeting/orbitrange
- private final float MaxRange=850f; //max range when it starts to direct aim target
- private final float MinRange=500f; //min range when it detonates
- private final boolean HardTargeting=true;//will it turn to target once in range
- //Heatseeker like behaviour (uses Min/Max range)
- private final boolean Backtarget=true; //dose it circle around back of ship
- private final float BackAng=45f; //min angle from rear
- private final boolean Straferound=false; //strafe there or turn there
- //DRONE script (core behaviour script)
- private final boolean isDrone=false; //makes missile bob in and out of MinRange and maintain that distance
- private final boolean Orbit=false; //will the drone strafe around target?
- private double ODir=Math.random(); //direction of strafe .5> left:right //used by SpinOnIdle
- private IntervalUtil OTimer = new IntervalUtil(3f, .01f); //delay between strafe switch
- //used in Backtarget as well
- private final float MinOrbit=.9f; //how close will the drone move in
- private final float MaxOrbit=1.2f; //how far will the drone move away
- //weapons
- //controls firing, everything below needs this on
- private final boolean canFire=false; //is shooting enabled
- //////////////////////////////////////////////////////////////////////////////////////////////////////////
- //weaponlist
- //nasty stuff drone uses as weapons
- //replace with projectile cannon like "chaingun" or "vulcan" from vanilla,
- // or your own weapon(no beams)(Ballistic_as_beam are fine)
- private static String [] Guns = {
- "DUMMY1",
- "DUMMY2",
- "chaingun",
- "vulcan",
- };
- //and missiles
- private static String [] Missiles = {
- "Linghning", //special, shoots lightning bolts
- "harpoon_single",
- "heatseeker",
- };
- //////////////////////////////////////////////////////////////////////////////////////////////////////
- //weaponpicker
- private float MislChance=.8f; //chance of missiles (1-MislChance)*100=%shots missile
- private int MislVolley=1; //number of missiles per
- private int ProjVolley=4; //number of Projectiles per
- private boolean Missil=(Math.random() > MislChance); //is it firing a missile
- private String Projectile = (Missil? Missiles:Guns) //picks the weapon
- [(int) ((Missil? Missiles:Guns).length * Math.random())];
- //MIRV/Flechet script (core firing script of a drone missile)
- //dummy weapon supports missiles and projectiles
- //suggested projectile stats, range:1, speed:1
- private final float PArk=25; //ark projectiles fly in
- private final int PNum=1; //shots per volley
- private int PVolleys=Missil ? MislVolley:ProjVolley; //volleys/burst fire for drone
- private final float Lifetime=1f; //how long the projectile being used can stay alive (IMPORTANT)
- //this is a value you must enter it is equal to range/ProjSpeed and works as a multiplier to make
- // firing velocity not overshoot the target (due to long life)
- private final float Leadtime=1f; //fiddle with this if your projectiles are missing the target
- //determines how far ahead of the target your weapon aims
- private IntervalUtil VTimer = new IntervalUtil(.15f, .01f); //rate of fire
- private final boolean IsFlechet=true;//are the shots fired by missile aimed or follow missile facing?
- //if IsFlechet=false missile will fire shots at the target ignoring its direction of travel
- private boolean DespawnEmpty=false; //should it de-spawn the missile once it has run out of ammo
- private boolean SpawnEmpty=false; //to spawn an empty type subprojectile(casing)
- private boolean canReload=true; //can reload after a burst
- private IntervalUtil BTimer = new IntervalUtil(1.8f, .01f); //delay between each burst
- public static void emptyspawn(CombatEngineAPI engine, MissileAPI missile)
- {
- engine.spawnProjectile(missile.getSource(),null,//who made you
- "DUMMY2", //empty missile,
- missile.getLocation(), //Vector2f firing origin point
- missile.getFacing(), //float angle of fire
- missile.getVelocity()); //Vector2f firing velocity)
- }
- //end of stuff you can change
- //////////////////////////////////////////////////////////////////////////////////////////////////////////
- //public static float Ark = 30; //60deg ark default
- boolean newlaunch=true; //only do mouse target once on a newly launched missile
- public kitchenSINKIIai(MissileAPI missile)
- {
- this.missile = missile;
- if (SearchOverwrite)
- {
- searchrange=missile.getWeapon() != null ? missile.getWeapon().getRange() : searchrange;//based on weapon
- }
- if (SearchArkOverwrite)
- {
- SearchArk=5+(missile.getWeapon() != null ? missile.getWeapon().getArc()/4 : SearchArk); //based on weapon
- }
- //missile.setCollisionClass(CollisionClass.FIGHTER);//hack reclasify as fighter
- // Support for 'fire at target by clicking on them' behavior
- if (newlaunch=true)
- {
- newlaunch=false;
- //get targets near mouse
- if (LaunchMouseTarget)
- {
- Vector2f MouseT = missile.getSource().getMouseTarget();
- if (MathUtils.getDistance(missile,MouseT)<searchrange)
- {
- List directTargets = CombatUtils.getShipsWithinRange(
- MouseT, 100f, true);
- if (!directTargets.isEmpty())
- {
- ShipAPI tmp;
- for (Iterator iter = directTargets.iterator(); iter.hasNext();)
- {
- //filter out friendlies
- tmp = (ShipAPI) iter.next();
- if (tmp.getOwner() != missile.getSource().getOwner())
- {
- target = tmp;
- break;
- }
- }
- }
- }
- }
- }
- // Otherwise, use default targeting AI
- if (target == null)
- {
- target = findBestTarget(missile);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////////
- //flare finder
- public static MissileAPI checkforflare(MissileAPI missile)
- {
- MissileAPI retv = null; //if no flares return null
- CombatEngineAPI engine = Global.getCombatEngine();
- List nearbymissiles = engine.getMissiles(); //(target.getCollisionRadius()*10)
- if (!nearbymissiles.isEmpty())
- {
- MissileAPI tmp;
- for (Iterator iter = nearbymissiles.iterator(); iter.hasNext();)
- {
- tmp = (MissileAPI) iter.next();
- if ((tmp.getProjectileSpecId()).startsWith(flare) //is it a flare
- && MathUtils.getDistance(tmp,missile)<300 //is it near your missile
- && missile.getOwner()!=tmp.getOwner() //is it en enemy flare
- && Math.random()>.5) //chance of failure prevents all missiles
- { //going after one flare at the same time
- //tmp= (MissileAPI) nearbymissiles.get(0); //testing code
- retv = tmp; //return flare
- break; //stop searching you found your flare
- }
- }
- }
- return retv;
- }
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //search for targets in ark in front
- //picks a random target that is in range
- public static ShipAPI ARKsearch(MissileAPI missile, boolean RandomTarget)
- {
- //find targets in ark in front of missile
- ArrayList targets = getEnemyShipInArk(missile, SearchArk, searchrange, true);
- int GetNom = RandomTarget ? (int) (targets.size() * Math.random()) : 0;
- if (!targets.isEmpty())
- { //pick random missile in list
- return (ShipAPI) targets.get(GetNom);
- }
- else return null;
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //get ship target or search for closest enemy
- public static ShipAPI SPHEREsearch(MissileAPI missile, boolean RandomTarget)
- {
- List targets = getNearbyEnemies(missile, searchrange, true);
- int GetNom = RandomTarget ? (int) (targets.size() * Math.random()) : 0;
- if (!targets.isEmpty())
- {
- return (ShipAPI) targets.get(GetNom);
- }
- else return null;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //main missile AI
- //stored variables don't touch
- private boolean BTcutout=false; //Backtargeting bool
- private boolean Close=true; //orbiting thruster bool
- private int VCount=0; //counter for firing script
- private boolean Loaded=true; //firing bool
- private boolean CloseIdle=true; //orbiting thruster bool
- @Override
- public void advance(float amount)
- {
- //timer
- Timer.advance(amount);
- STimer.advance(amount);
- VTimer.advance(amount);
- OTimer.advance(amount);
- BTimer.advance(amount);
- weavecount++;
- if (weavecount>4000){weavecount=0;} //arbitary reset
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //go straight for x after launch
- if (straighttimer>0)
- {
- missile.giveCommand(ShipCommand.ACCELERATE);
- if (STimer.intervalElapsed())
- {straighttimer--;}
- return;
- }
- else
- {
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Apparently commands still work while fizzling
- if (missile.isFading() || missile.isFizzling())
- {
- return;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //find a target
- if (target == null)
- {
- target = findBestTarget(missile);
- }
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //if missile is susceptible to flare
- if (isEffectedbyflare>BaseIgnoreChance //can a flare effect it
- && !flarelockout //has it already been set to ignore flares
- && Timer.intervalElapsed()) //check every .10 sec
- {
- MissileAPI flaretarget = checkforflare(missile);
- if (flaretarget!=null)
- {
- target=flaretarget; //set flare as target
- if (LockCHance<(float)Math.random())flarelockout=true; //ignore future flares
- }
- }
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //pathing ai
- if (target!=null) //if you have a target
- {
- //reduction off target/gradual aiming
- if (Timer.intervalElapsed())
- {
- oftarget=(oftarget>0 ? oftarget-1 : oftarget+1); //reduce off target counter;
- }
- //////////////////////////////////////////////////////////////////////////////////////////////
- //check if scatter code needed
- float targetcolision = target.getCollisionRadius(); //get colision radi
- if (MathUtils.getDistance(missile, target)<75+(targetcolision))
- { //cutoff for baseoftarget behaviour
- baseoftarget=0; //aim variable if you got in close enough is 0 (ie go hit the enemy target)
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////
- //how much off target will the missiles be
- float oftargetby = (0 + (oftarget + (baseoftarget * targetcolision / 75)));
- //////////////////////////////////////////////////////////////////////////////////////////
- //aming
- //1step calculations of various stats
- Vector2f MVel = missile.getVelocity();
- Vector2f MLoc = missile.getLocation();
- Vector2f TLoc = target.getLocation();
- Vector2f TVel = target.getVelocity();
- //float MSpeed = (float)Math.sqrt(MVel.lengthSquared());
- //float TSpeed = (float)Math.sqrt(TVel.lengthSquared());
- float MFace = missile.getFacing();
- float TFace = target.getFacing();
- double TfaceRad = Math.toRadians(TFace);
- float TCol = target.getCollisionRadius();
- float sx = (float) (TCol*.5*Math.cos(TfaceRad));
- float sy = (float) (TCol*.5*Math.sin(TfaceRad));
- Vector2f TNose = new Vector2f(sx, sy);
- float RangeToTarget = MathUtils.getDistance(TLoc, MLoc);
- //float TimeToTarget = RangeToTarget/MSpeed; //how long till you hit
- //testing InterceptPoint
- Vector2f Lvec = LeadVector(TLoc, TVel, MLoc, MVel);
- //////////////////////////////////////////////////////////////////////////////////////////
- //override when in range
- if (HardTargeting && RangeToTarget<MaxRange)
- {
- Lvec= multV2f(TVel, Leadtime);
- baseoftarget=0;
- oftarget=0;
- oftargetby=0;
- }
- //////////////////////////////////////////////////////////////////////////////////////////
- //lead target
- Vector2f TLead = add(TLoc, //target location+
- Lvec, //target speed*time to get to target+
- null); // if its too long just assume 3 seconds is long enough to course correct
- //aim at nose (can be changed to part targeting with a few tweaks)
- Vector2f TNoseLead = add(TLead, TNose, null);//aim at the nose of the target(optional)
- //main aiming (to find angle you are off target by)
- float AngleToEnemy = MathUtils.getAngle(MLoc, TNoseLead);
- float AtTarget = getAngleDifference( //how far off target you are
- MFace, AngleToEnemy); //where missile pointing, where target is in relation
- //for backtargeting
- if (Backtarget && RangeToTarget<MaxRange)
- {
- float AngFromTtoM = MathUtils.getAngle(TLoc, MLoc); //get angle from target
- float ToMissile = getAngleDifference(TFace, AngFromTtoM); //to missile
- if (Math.abs(ToMissile)>180-BackAng) //check if you are behind the target
- {BTcutout=true;}
- else if (isDrone) //override for drones, re enables the AI
- {BTcutout=false;}
- if (!Straferound && !BTcutout)
- {
- AtTarget=AtTarget-(ToMissile>0? 90:-90);
- }
- if (Straferound && !BTcutout)
- {
- missile.giveCommand(ToMissile < 0
- ? ShipCommand.STRAFE_LEFT : ShipCommand.STRAFE_RIGHT);
- }
- }
- //makes the missile weave
- if (Weave)
- {AtTarget=AtTarget+(float)(Math.sin(weavecount/WeaveFreq)*Weavesize);}
- float AbsAngD = Math.abs(AtTarget-oftargetby);
- //////////////////////////////////////////////////////////////////////////////////////////////
- //point towards target
- if (AbsAngD > 0.5)
- { //makes missile fly off target
- missile.giveCommand(AtTarget > oftargetby
- ? ShipCommand.TURN_LEFT : ShipCommand.TURN_RIGHT);
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- //correct missile velocity vector to be the same as missile facing
- if (AbsAngD < 5)
- {
- //course correct for missile velocity vector
- float MFlightAng = MathUtils.getAngle(new Vector2f(0, 0), MVel);
- float MFlightCC = getAngleDifference(MFace, MFlightAng);
- if (Math.abs(MFlightCC)>20)
- {
- missile.giveCommand(MFlightCC < 0
- ? ShipCommand.STRAFE_LEFT : ShipCommand.STRAFE_RIGHT);
- }
- }
- /////////////////////////////////////////////////////////////////////////////////////////////////
- //stop turning once you are on target (way of the hack, ignores missile limitations)
- if (AbsAngD < 0.4)
- {
- missile.setAngularVelocity(0);
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////
- if((!isDrone && !Straferound) //not a drone or strafingBT
- || (isDrone && RangeToTarget>MaxRange) //is out or orbital range
- || (Backtarget && RangeToTarget>MaxRange && !BTcutout)
- || BTcutout) //is BTcutout
- {
- //acceleration code (stopNturn compatible)
- if (StopNTurn)
- {
- if (AbsAngD < 40)
- {
- missile.giveCommand(ShipCommand.ACCELERATE);
- }
- if (MVel.lengthSquared()<TVel.lengthSquared())
- {
- missile.giveCommand(ShipCommand.ACCELERATE);
- }
- if (AbsAngD > 120) //if you missed stop and turn around
- {
- missile.giveCommand(ShipCommand.DECELERATE);
- }
- }
- else{missile.giveCommand(ShipCommand.ACCELERATE);}
- }
- /////////////////////////////////////////////////////////////////////////////////////////////////
- else //move back and forth, if its a drone
- {
- if (RangeToTarget<MinRange*MinOrbit){Close=false;} //boolean to achive back and forth motion
- if (RangeToTarget>MinRange*MaxOrbit){Close=true;}
- if (Close) {missile.giveCommand(ShipCommand.ACCELERATE);}
- else {missile.giveCommand(ShipCommand.ACCELERATE_BACKWARDS);}
- /////////////////////////////////////////////////////////////////////////////////////////////////
- //orbit target
- if (Orbit)
- {
- if (OTimer.intervalElapsed())
- {
- ODir=Math.random();
- }
- missile.giveCommand(ODir < .5
- ? ShipCommand.STRAFE_LEFT : ShipCommand.STRAFE_RIGHT);
- }
- }
- /////////////////////////////////////////////////////////////////////////////////////////////////
- //testcode spawns particle at aim points
- CombatEngineAPI engine = Global.getCombatEngine(); //engine
- //engine.addSmoothParticle(TLead, new Vector2f(0,0), 5, 1, 1, new Color(255,10,15,255));
- //engine.addSmoothParticle(TNoseLead, new Vector2f(0,0), 5, 1, 1, new Color(93, 255, 40,255));
- //engine.addSmoothParticle(MLoc, multV2f(MVel, 4), 5, .5f, 1, new Color(248, 244, 255,255));
- //engine.addSmoothParticle(MLoc, new Vector2f(0,0), 5, .5f, 1, new Color(2, 255, 250,255));
- /////////////////////////////////////////////////////////////////////////////////////////////////
- if (canFire) //overriding controll for firing
- {
- //reload
- if (canReload && !Loaded && BTimer.intervalElapsed())
- {
- Loaded=true;
- VCount=0;
- {
- //weaponpicker
- Missil=(Math.random() > MislChance); //is it firing a missile
- Projectile = (Missil? Missiles:Guns) //picks the weapon
- [(int) ((Missil? Missiles:Guns).length * Math.random())];
- PVolleys=Missil ? MislVolley:ProjVolley;
- }
- }
- /////////////////////////////////////////////////////////////////////////////////////////////////
- if (Loaded && VTimer.intervalElapsed() && RangeToTarget<MinRange && VCount<PVolleys)
- {
- VCount++;
- {
- if (Projectile.equals("Linghning")) //cause lightningbolts!!
- {
- engine.spawnEmpArc(missile.getSource(), MLoc, target, target,
- DamageType.ENERGY,
- 50f,
- 2000,
- 10000f, // max range
- "tachyon_lance_emp_impact",
- 20f, // thickness
- new Color(255,10,15,255),
- new Color(255,255,255,255)
- );
- }
- else
- {
- //spawn projectiles
- int counts=0; //how many projectiles?
- do {
- float angRAND= (float) ((PArk*(.5-Math.random()))); //angle of spread
- float speedRAND= (float) (((MaxRange-MinRange)/Lifetime)*Math.random());//variance of speed
- float PSpeed = (MinRange/Lifetime)+speedRAND; //speed of bullets launched
- float PAng = (IsFlechet ? missile.getFacing() //direction of fire
- :missile.getFacing()+AtTarget)-angRAND;
- float x = (float) (PSpeed*Math.cos(Math.toRadians(PAng)));
- float y = (float) (PSpeed*Math.sin(Math.toRadians(PAng)));
- Vector2f PVec = new Vector2f(x,y); //convert all that into a vector
- Vector2f PMVec = add(MVel, PVec, null); //true Pvec
- //for missile weapon offset
- float xa = (float) (11*Math.cos(Math.toRadians(missile.getFacing()-95)));
- float ya = (float) (11*Math.sin(Math.toRadians(missile.getFacing()-95)));
- Vector2f MoffVec = new Vector2f(xa,ya);
- //for projectile weapon ofset
- float xb = (float) (25*Math.cos(Math.toRadians(missile.getFacing()+45)));
- float yb = (float) (25*Math.sin(Math.toRadians(missile.getFacing()+45)));
- Vector2f PoffVec = new Vector2f(xb,yb);
- Vector2f Lpoint = add(MLoc, Missil ? MoffVec : PoffVec, null);
- engine.spawnProjectile(
- missile.getSource(),
- null, //who made you
- Projectile, //spawn the projectile
- Lpoint, //Vector2f firing origin point
- PAng, //float angle of fire
- PMVec); //Vector2f firing velocity
- /////////////////////////////////////////////////////////////////////////////////////
- counts++;
- ////////////////////////////////////////////////////////////////////////////////
- //optional explosion/particle glows
- //engine.addHitParticle(Lpoint, PMVec,
- // 5f,1f,1f,new Color(112, 152, 137,255)); //size, alpha, duration, color
- engine.spawnExplosion(Lpoint, PMVec,
- new Color(255, 86, 13,255), 15f, .1f); //color,size,duration(max)
- //////////////////////////////////////////////////////////////////////////////////
- }while (counts<PNum);
- }
- }
- //////////////////////////////////////////////////////////////////////////////////
- //main explosion flash
- //engine.addHitParticle(MLoc, missile.getVelocity(),10,1f,1f,new Color(255, 12, 25,255));
- }
- //////////////////////////////////////////////////////////////////////////////////
- if (VCount>=PVolleys)
- {
- Loaded=false;
- if(DespawnEmpty)
- {
- if (SpawnEmpty) {emptyspawn(engine,missile);}
- engine.removeEntity(missile);
- }
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////////////////////////////////
- //if you have no target
- if (target==null && straighttimer<1)
- {
- if (StopOnIdle) //stop
- {missile.giveCommand(ShipCommand.DECELERATE);}
- else if (OrbitOnIdle) //orbit source ship
- {
- ShipAPI Msource = missile.getSource();
- float RangeToSource = MathUtils.getDistance(Msource.getLocation(), missile.getLocation());
- float OIdleRange = IdleOrbitBase + (AddColisionRad ? Msource.getCollisionRadius() : 0);
- if (RangeToSource<OIdleRange*IdleOrbitMin){CloseIdle=true;} //boolean to achive back and forth motion
- if (RangeToSource>OIdleRange*IdleOrbitMax){CloseIdle=false;}
- float MSang = getAngleDifference(missile.getFacing(),
- MathUtils.getAngle(missile.getLocation(),Msource.getLocation()));
- if (StrafeOrbitOnIdle)
- {
- missile.giveCommand(MSang < 0 ? ShipCommand.TURN_LEFT : ShipCommand.TURN_RIGHT);
- if (Math.abs(MSang) > 175)
- {
- missile.giveCommand(ODir < .5 ? ShipCommand.STRAFE_LEFT : ShipCommand.STRAFE_RIGHT);
- missile.giveCommand(CloseIdle ? ShipCommand.ACCELERATE:ShipCommand.ACCELERATE_BACKWARDS);
- }
- }
- else
- {
- float OrbitTurnAngle = (ODir < .5 ? 90+(CloseIdle ? 10:-65) : -90-(CloseIdle ? 10:-65));
- missile.giveCommand(MSang > OrbitTurnAngle ? ShipCommand.TURN_LEFT : ShipCommand.TURN_RIGHT);
- if (Math.abs(MSang-OrbitTurnAngle)<30) missile.giveCommand(ShipCommand.ACCELERATE);
- if (Math.abs(MSang-OrbitTurnAngle)>40) missile.giveCommand(ShipCommand.DECELERATE);
- }
- }
- //else //keep going
- //{missile.giveCommand(ShipCommand.ACCELERATE);}
- if (SpinOnIdle) //spin round
- {missile.giveCommand((ODir > .5 ? ShipCommand.TURN_RIGHT:ShipCommand.TURN_LEFT));}
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- //clear target if target is gone
- if (target == null // unset
- || ( missile.getOwner() == target.getOwner() ) // friendly
- || !Global.getCombatEngine().isEntityInPlay(target) // completely removed
- || ( target instanceof ShipAPI && ((ShipAPI)target).isHulk() ))//dead
- {
- target = findBestTarget(missile);
- return;
- }
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Will be in next LazyLib version
- public static float getAngleDifference(float angle1, float angle2)
- {
- float distance = (angle2 - angle1) + 180f;
- distance = (distance / 360.0f);
- distance = ((distance - (float) Math.floor(distance)) * 360f) - 180f;
- return distance;
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //multiply vectors //own code
- public static Vector2f multV2f(Vector2f Vector1, float Multiplier)
- {
- float v1x = Vector1.getX()*Multiplier;
- float v1y = Vector1.getY()*Multiplier;
- Vector2f v1end = new Vector2f(v1x, v1y);
- return v1end;
- }
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement