Fractal Softworks Forum

Please login or register.

Login with username, password and session length
Advanced search  

News:

Starsector 0.97a is out! (02/02/24); New blog post: Simulator Enhancements (03/13/24)

Pages: 1 2 [3] 4 5 ... 10

Author Topic: The Radioactive Code Dump  (Read 80460 times)

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
Re: The Radioactive Code Dump
« Reply #30 on: October 25, 2013, 09:51:58 PM »

Cool stuff and thanks very much for sharing with everybody :)

I haven't had time to read through it yet but I love the innovative concepts :)

BTW, for stuff like MIRVs, IIRC the last version of Vacuum had one I built that was a lot more reliable (instead of a collision ray, it did a simple distance search to nearest enemy and released stuff if close enough).  There are other interesting things in there, like a weapon that ignores Shields, projectiles that destroy other projectiles, etc.
Logged
Please check out my SS projects :)
Xeno's Mod Pack

dmaiski

  • Captain
  • ****
  • Posts: 422
  • resistance is futile
    • View Profile
Re: The Radioactive Code Dump
« Reply #31 on: October 26, 2013, 07:49:48 AM »

i thought i should post this here

an absolute basic no frills missile pathing ai  (ok the aim delay code is a bit frilly, but it would not be cute without at least some frills!)

a few notes about missiless:
missiles (to be acurate) need at least
3x acceleration, and turn acceleration when compared to their speed and turn rate
3x or more turn accel compared to rate to avoid wobble

Spoiler
Code: java
   float straighttimer=50*((float)Math.random());      //1 second max non targeting time
    @Override
    public void advance(float amount)
    {

        // Apparently commands still work while fizzling
        if (missile.isFading() || missile.isFizzling())
        {
            return;
        }

        if (straighttimer>0)   //go straight for x milliseconds after launch
        {
            missile.giveCommand(ShipCommand.ACCELERATE);
            straighttimer--;
        }

        if (straighttimer<2)  //once done turn and go blow stuff up
        {
            if (target!=null) //check if you have something to blow up
            {
                //aiming code, lead targeting
                float sx = (float) (target.getCollisionRadius()*.5*Math.cos(Math.toRadians(target.getFacing())));
                float sy = (float) (target.getCollisionRadius()*.5*Math.sin(Math.toRadians(target.getFacing())));
                float angularDistance = getAngleDifference(         //how far of target you are?
                        missile.getFacing(), MathUtils.getAngle(missile.getLocation(),//where you are pointing?
                        (add((add(target.getLocation(),//where your enemy is
                                multV2f(target.getVelocity(),//add on their velocity
                                        MathUtils.getDistance(target.getLocation(),//multiply it by how lon it takes to get there
                                                missile.getLocation()) / missile.getVelocity().lengthSquared()),
                                null)),new Vector2f(sx,sy), null))));   //add some more to aim at the ships nose, increases hit rate significantly



                if (Math.abs(angularDistance) > 0.2)
                {
                    missile.giveCommand(angularDistance > 0            //aim for them
                            ? ShipCommand.TURN_LEFT : ShipCommand.TURN_RIGHT);

                }
                //optinal
                if (Math.abs(angularDistance) < 50)     //check if you are pointing the right way
                {
                missile.giveCommand(ShipCommand.ACCELERATE);     //fly towards them //not optional
                }
            }
        }
        else missile.giveCommand(ShipCommand.DECELERATE);       //else stop

        //reset code   //mesotronik is awsome all praise mesotronik!!
        // If our current target is lost, assign a new one  
        if (target == null // unset
                ||  ( target instanceof ShipAPI && ((ShipAPI)target).isHulk() ) // dead
                ||  ( missile.getOwner() == target.getOwner() ) // friendly
                ||  !Global.getCombatEngine().isEntityInPlay(target) ) // completely removed
        {
            target = findBestTarget(missile);
            return;
        }
    }
[close]
Logged
BISO
(WIP) lots of shiny new weapons ( :-[ i have more weapons then sprites :-[ )

i got a cat pad
its like a mouse pad but better!

dmaiski

  • Captain
  • ****
  • Posts: 422
  • resistance is futile
    • View Profile
Re: The Radioactive Code Dump
« Reply #32 on: October 26, 2013, 02:17:32 PM »

flare chase code


posibly the hardest thing to get to work since lazylib dose not work this(and it takes a while to figure that out)...

Spoiler
Code: java

    public static final String flare="^flare.*?";
    //flarefinder
    public static MissileAPI checkforflare(MissileAPI missile)
    {
        MissileAPI retv = null;
        CombatEngine engine = CombatEngine.getInstance();
        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()).matches(flare) && MathUtils.getDistance(tmp,missile)<300 && missile.getOwner()!=tmp.getOwner())
                //in that order to get max framrate
                {
                    //tmp= (MissileAPI) nearbymissiles.get(0);   //testing code
                     retv = tmp;
                    break;
                }
            }
        }
        return retv;
    }
[close]

hints: put a 10 step timer in to stop it lagging evrything (eats processing power like thothing else...) (this also makes it more lag friendly then vanilla missile ai)
« Last Edit: October 26, 2013, 02:23:00 PM by dmaiski »
Logged
BISO
(WIP) lots of shiny new weapons ( :-[ i have more weapons then sprites :-[ )

i got a cat pad
its like a mouse pad but better!

silentstormpt

  • Admiral
  • *****
  • Posts: 1060
    • View Profile
Re: The Radioactive Code Dump
« Reply #33 on: October 28, 2013, 11:44:19 AM »

OnHitCriticalRequires testing.

Its really easy to setup. Make a OnHit java and init this class, just provide the required data for it to work, once your done, you can make it run by using (OnHitCritical.initCritSystem()) inside the OnHit(). once the projectile/missile hits it should run this code and check if it crits.

The sound hashmaps should be filled with the desired sounds you want when it crits a ship.
You can also change the Crit damage (currently at 200%) and the chance (0.05 or 5%).

The chance of Crit is based on the Ships CR, Crews Skills and Weapons RoF:
Code: java
((CRITPERCENT * crewMaxXP) / weaponRoF) * currentCR;

Spoiler
Code: java
package data.scripts.plugins;

//import com.fs.starfarer.api.combat.BeamAPI;
import com.fs.starfarer.api.Global;
import com.fs.starfarer.api.combat.CombatEngineAPI;
import com.fs.starfarer.api.combat.CombatEntityAPI;
import com.fs.starfarer.api.combat.DamageType;
import com.fs.starfarer.api.combat.DamagingProjectileAPI;
import com.fs.starfarer.api.combat.MissileAPI;
import com.fs.starfarer.api.combat.MutableStat.StatMod;
import com.fs.starfarer.api.combat.ShipAPI;
import com.fs.starfarer.api.combat.WeaponAPI;
import com.fs.starfarer.api.combat.WeaponAPI.WeaponSize;
import java.awt.Color;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import org.lazywizard.lazylib.MathUtils;

public class OnHitCritical {
    
    private float CRITPERCENT = 0.05f;
    private float CRITMULT = 2f;
    private CombatEngineAPI engine = null;
    private DamagingProjectileAPI proj = null;
    private MissileAPI missile = null;
    private WeaponAPI weapon = null;
//    private BeamAPI beam;
    private ShipAPI owner = null;
    private CombatEntityAPI target = null;
    
    // Sound on High Explosive explosion  
    private static final Map SOUND_IDS_HE = new HashMap();  
    static  
    {  
        SOUND_IDS_HE.put("isFrigate", "explosion_ship");  
        SOUND_IDS_HE.put("isDestroyer", "explosion_ship");  
        SOUND_IDS_HE.put("isCruiser", "explosion_ship");  
        SOUND_IDS_HE.put("isCapital", "explosion_ship");  
    }  
    // Sound on Energy explosion  
    private static final Map SOUND_IDS_ENERGY = new HashMap();  
    static  
    {  
        SOUND_IDS_ENERGY.put("isFrigate", "explosion_ship");  
        SOUND_IDS_ENERGY.put("isDestroyer", "explosion_ship");  
        SOUND_IDS_ENERGY.put("isCruiser", "explosion_ship");  
        SOUND_IDS_ENERGY.put("isCapital", "explosion_ship");  
    }
    
    public OnHitCritical(DamagingProjectileAPI proj, ShipAPI owner, CombatEngineAPI engine, CombatEntityAPI target)
    {
        this.proj = proj;
        this.owner = owner;
        this.weapon = this.proj.getWeapon();
        this.engine = engine;
        this.target = target;
    }//OnHitCritical(DamagingProjectileAPI proj, ShipAPI owner, CombatEngineAPI engine, CombatEntityAPI target)
    
    public OnHitCritical(MissileAPI missile, ShipAPI owner, CombatEngineAPI engine, CombatEntityAPI target)
    {
        this.missile = missile;
        this.owner = owner;
        this.weapon = this.missile.getWeapon();
        this.engine = engine;
        this.target = target;
    }//OnHitCritical(MissileAPI missile, ShipAPI owner, CombatEngineAPI engine, CombatEntityAPI target)
    
//    public onHitCritical(BeamAPI beam, ShipAPI owner, CombatEngineAPI engine, CombatEntityAPI target)
//    {
//        this.beam = beam;
//        this.owner = owner;
//        this.engine = engine;
//        this.target = target;
//    }//onHitCritical(BeamAPI beam, ShipAPI owner, CombatEngineAPI engine, CombatEntityAPI target)
    
    public void initCritSystem()
    {
        //does the ship exist?
        if(owner != null)
        {
            //Check, is this for Projectiles?
            if(proj != null)
            {
                if(isCrit())
                {
                    this.CritSystem(proj);
                }
            }//IF
            //IF not then its for Missiles.
            else
            {
                if(isCrit())
                {
                    this.CritSystem(missile);
                }
            }//ELSE
        }//IF
    }//initCritSystem()
    
    private float getCritChance()
    {          
        if(weapon.getDamageType().equals(DamageType.FRAGMENTATION) ||  
                weapon.getDamageType().equals(DamageType.KINETIC) ||  
                weapon.getDamageType().equals(DamageType.OTHER))  
        {  
            return 0f;  
        }  
          
        float weaponRoF = weapon.getDerivedStats().getRoF();  
            
        StatMod crewBonus;  
        crewBonus = owner.getMutableStats().getAutofireAimAccuracy().getFlatStatMod("crew skill bonus");
        float currentCR = owner.getCurrentCR();
          
        // Green crew don't grant a bonus
        float crewMaxXP = 0f;
        if (crewBonus != null)  
        {  
            //Goes from 0f to 1f - thanks Alex and Lazy for the help  
            crewMaxXP = crewBonus.getValue();  
        }  
          
        //slower shooting weapons should not surpass limit of 5%  
        if (weaponRoF < 1f)  
        {  
            weaponRoF = 1f;  
        }  
          
        //This means that, if the crew is elite and the current CR is 100 its ((0.05f * 1) \ 1) * 1 that means 5%,  
        //if the crew is actually lower skilled, the current CR is lower and the weapon's RoF is higher the chances get lower.  
        return ((CRITPERCENT * crewMaxXP) / weaponRoF) * currentCR;
    }//getCritChance()
    
    public void addCritPercent(float addvalue)
    {
        this.CRITPERCENT += addvalue;
    }//addCritPercent(float addvalue)
    
    public void addCritMult(float addvalue)
    {
        this.CRITMULT += addvalue;
    }//addCritMult(float addvalue)
    
    private boolean isCrit()
    {
        Random r = new Random();
        float CritChance = r.nextFloat();  
          
        if(CritChance <= getCritChance())  
        {  
            return true;  
        }//IF
        else  
        {  
            return false;  
        }//ELSE
    }//isCrit()
    
    public void CritSystem (DamagingProjectileAPI proj)  
    {  
        float explosionSize = 0f;
        ShipAPI enemyShip = (ShipAPI)this.target;
        float weaponRoF = weapon.getDerivedStats().getRoF();  
          
        //Lets make sure we dont get a REALLY HUGE Crit text  
        if (weaponRoF < 1f)  
        {  
            weaponRoF = 1f;  
        }  
          
        if(weapon.getSize().equals(WeaponSize.SMALL))  
        {  
            explosionSize = MathUtils.getRandomNumberInRange(20f, 30f) / weaponRoF;  
        }  
        else if(weapon.getSize().equals(WeaponSize.MEDIUM))  
        {  
            explosionSize = MathUtils.getRandomNumberInRange(30f, 40f) / weaponRoF;  
        }  
        else if(weapon.getSize().equals(WeaponSize.LARGE))  
        {  
            explosionSize = MathUtils.getRandomNumberInRange(40f, 50f) / weaponRoF;  
        }  
          
        engine.addFloatingText(proj.getLocation(), "CRITICAL HIT", explosionSize, Color.RED, proj.getDamageTarget(), 0f, 0f);  
          
        if(weapon.getDamageType().equals(DamageType.HIGH_EXPLOSIVE))  
        {  
            if(enemyShip.isFrigate()) {    
                CritSystemEffects(enemyShip,  
                        proj,  
                        weapon.getDamageType(),  
                        SOUND_IDS_HE.get("isFrigate").toString(),  
                        explosionSize);  
            }  
            else if(enemyShip.isDestroyer()) {  
                CritSystemEffects(enemyShip,  
                        proj,  
                        weapon.getDamageType(),  
                        SOUND_IDS_HE.get("isDestroyer").toString(),  
                        explosionSize);  
            }  
            else if(enemyShip.isCruiser()) {  
                CritSystemEffects(enemyShip,  
                        proj,  
                        weapon.getDamageType(),  
                        SOUND_IDS_HE.get("isCruiser").toString(),  
                        explosionSize);  
            }  
            else if(enemyShip.isCapital()) {  
                CritSystemEffects(enemyShip,  
                        proj,  
                        weapon.getDamageType(),  
                        SOUND_IDS_HE.get("isCapital").toString(),  
                        explosionSize);  
            }  
        }  
        else if(weapon.getDamageType().equals(DamageType.ENERGY))  
        {  
            if(enemyShip.isFrigate()) {    
                CritSystemEffects(enemyShip,  
                        proj,  
                        weapon.getDamageType(),  
                        SOUND_IDS_ENERGY.get("isFrigate").toString(),  
                        explosionSize);  
            }  
            else if(enemyShip.isDestroyer()) {  
                CritSystemEffects(enemyShip,  
                        proj,  
                        weapon.getDamageType(),  
                        SOUND_IDS_ENERGY.get("isDestroyer").toString(),  
                        explosionSize);  
            }  
            else if(enemyShip.isCruiser()) {  
                CritSystemEffects(enemyShip,  
                        proj,  
                        weapon.getDamageType(),  
                        SOUND_IDS_ENERGY.get("isCruiser").toString(),  
                        explosionSize);  
            }  
            else if(enemyShip.isCapital()) {  
                CritSystemEffects(enemyShip,  
                        proj,  
                        weapon.getDamageType(),  
                        SOUND_IDS_ENERGY.get("isCapital").toString(),  
                        explosionSize);  
            }  
        }  
    }//CritSystem (DamagingProjectileAPI proj)
    
    public void CritSystem(MissileAPI missile)
    {
       float explosionSize = 0f;
        ShipAPI enemyShip = (ShipAPI)this.target;
        float weaponRoF = weapon.getDerivedStats().getRoF();  
          
        //Lets make sure we dont get a REALLY HUGE Crit text  
        if (weaponRoF < 1f)  
        {  
            weaponRoF = 1f;  
        }  
          
        if(weapon.getSize().equals(WeaponSize.SMALL))  
        {  
            explosionSize = MathUtils.getRandomNumberInRange(20f, 30f) / weaponRoF;  
        }  
        else if(weapon.getSize().equals(WeaponSize.MEDIUM))  
        {  
            explosionSize = MathUtils.getRandomNumberInRange(30f, 40f) / weaponRoF;  
        }  
        else if(weapon.getSize().equals(WeaponSize.LARGE))  
        {  
            explosionSize = MathUtils.getRandomNumberInRange(40f, 50f) / weaponRoF;  
        }  
          
        engine.addFloatingText(missile.getLocation(), "CRITICAL HIT", explosionSize, Color.RED, missile.getDamageTarget(), 0f, 0f);  
          
        if(weapon.getDamageType().equals(DamageType.HIGH_EXPLOSIVE))  
        {  
            if(enemyShip.isFrigate()) {    
                CritSystemEffects(enemyShip,  
                        missile,  
                        weapon.getDamageType(),  
                        SOUND_IDS_HE.get("isFrigate").toString(),  
                        explosionSize);  
            }  
            else if(enemyShip.isDestroyer()) {  
                CritSystemEffects(enemyShip,  
                        missile,  
                        weapon.getDamageType(),  
                        SOUND_IDS_HE.get("isDestroyer").toString(),  
                        explosionSize);  
            }  
            else if(enemyShip.isCruiser()) {  
                CritSystemEffects(enemyShip,  
                        missile,  
                        weapon.getDamageType(),  
                        SOUND_IDS_HE.get("isCruiser").toString(),  
                        explosionSize);  
            }  
            else if(enemyShip.isCapital()) {  
                CritSystemEffects(enemyShip,  
                        missile,  
                        weapon.getDamageType(),  
                        SOUND_IDS_HE.get("isCapital").toString(),  
                        explosionSize);  
            }  
        }  
        else if(weapon.getDamageType().equals(DamageType.ENERGY))  
        {  
            if(enemyShip.isFrigate()) {    
                CritSystemEffects(enemyShip,  
                        missile,  
                        weapon.getDamageType(),  
                        SOUND_IDS_ENERGY.get("isFrigate").toString(),  
                        explosionSize);  
            }  
            else if(enemyShip.isDestroyer()) {  
                CritSystemEffects(enemyShip,  
                        missile,  
                        weapon.getDamageType(),  
                        SOUND_IDS_ENERGY.get("isDestroyer").toString(),  
                        explosionSize);  
            }  
            else if(enemyShip.isCruiser()) {  
                CritSystemEffects(enemyShip,  
                        missile,  
                        weapon.getDamageType(),  
                        SOUND_IDS_ENERGY.get("isCruiser").toString(),  
                        explosionSize);  
            }  
            else if(enemyShip.isCapital()) {  
                CritSystemEffects(enemyShip,  
                        missile,  
                        weapon.getDamageType(),  
                        SOUND_IDS_ENERGY.get("isCapital").toString(),  
                        explosionSize);  
            }  
        }
    }//CritSystem(MissileAPI missile)
    
    public void CritSystemEffects(ShipAPI ship, DamagingProjectileAPI proj, DamageType dmgtype, String ExplosionSoundID, float explosionSize)
    {
        if(weapon.getDamageType().equals(DamageType.HIGH_EXPLOSIVE))  
        {  
            float damage = proj.getDamageAmount() * CRITMULT;  
            float emp = proj.getEmpAmount() * CRITMULT;  
  
            // Apply damage and slow the projectile  
            // Note: BALLISTIC_AS_BEAM projectiles won't be slowed!  
            engine.applyDamage(owner,  
                    proj.getLocation(),
                    damage,
                    proj.getDamageType(),  
                    emp,
                    true,
                    true,
                    proj.getSource());  
  
            proj.getVelocity().scale(1.5f - 1.0f);  
              
            engine.spawnExplosion(  
                    proj.getLocation(),  
                    ship.getVelocity(),  
                    Color.ORANGE,  
                    1f,  
                    1.5f);  
  
            // Play Explosion sound  
            Global.getSoundPlayer().playSound(ExplosionSoundID,  
                    1f,  
                    1f,  
                    proj.getLocation(),  
                    ship.getVelocity());  
  
        }  
        else if(weapon.getDamageType().equals(DamageType.ENERGY))  
        {  
            float damage = proj.getDamageAmount() * CRITMULT;  
            float emp = proj.getEmpAmount() * CRITMULT;  
  
            // Apply damage and slow the projectile  
            // Note: BALLISTIC_AS_BEAM projectiles won't be slowed!  
            engine.applyDamage(ship,  
                    proj.getLocation(),  
                    damage,  
                    proj.getDamageType(),  
                    emp,  
                    true,  
                    true,  
                    proj.getSource());  
  
            proj.getVelocity().scale(1.5f - 1.0f);  
              
            engine.spawnExplosion(  
                    proj.getLocation(),  
                    ship.getVelocity(),  
                    Color.blue,  
                    1f,  
                    1.5f);  
  
            // Play Crit Explosion  
            Global.getSoundPlayer().playSound(ExplosionSoundID,  
                    1f,  
                    1f,  
                    proj.getLocation(),  
                    ship.getVelocity());  
        }
    }//CritSystemEffects(ShipAPI ship, DamagingProjectileAPI proj, DamageType dmgtype, String ExplosionSoundID, float explosionSize)
    
    public void CritSystemEffects(ShipAPI ship, MissileAPI missile, DamageType dmgtype, String ExplosionSoundID, float explosionSize)
    {
        if(weapon.getDamageType().equals(DamageType.HIGH_EXPLOSIVE))  
        {  
            float damage = missile.getDamageAmount() * CRITMULT;  
            float emp = missile.getEmpAmount() * CRITMULT;  
  
            // Apply damage and slow the projectile  
            // Note: BALLISTIC_AS_BEAM projectiles won't be slowed!  
            engine.applyDamage(owner,  
                    missile.getLocation(),
                    damage,
                    missile.getDamageType(),  
                    emp,
                    true,
                    true,
                    missile.getSource());  
  
            missile.getVelocity().scale(1.5f - 1.0f);
              
            engine.spawnExplosion(  
                    missile.getLocation(),  
                    ship.getVelocity(),  
                    Color.ORANGE,  
                    1f,  
                    1.5f);  
  
            // Play Explosion sound  
            Global.getSoundPlayer().playSound(ExplosionSoundID,  
                    1f,  
                    1f,  
                    missile.getLocation(),  
                    ship.getVelocity());  
  
        }  
        else if(weapon.getDamageType().equals(DamageType.ENERGY))  
        {  
            float damage = missile.getDamageAmount() * CRITMULT;  
            float emp = missile.getEmpAmount() * CRITMULT;  
  
            // Apply damage and slow the projectile  
            // Note: BALLISTIC_AS_BEAM projectiles won't be slowed!  
            engine.applyDamage(ship,  
                    missile.getLocation(),  
                    damage,  
                    missile.getDamageType(),  
                    emp,  
                    true,  
                    true,  
                    missile.getSource());  
  
            missile.getVelocity().scale(1.5f - 1.0f);  
              
            engine.spawnExplosion(  
                    missile.getLocation(),  
                    ship.getVelocity(),  
                    Color.blue,  
                    1f,  
                    1.5f);  
  
            // Play Crit Explosion  
            Global.getSoundPlayer().playSound(ExplosionSoundID,  
                    1f,  
                    1f,  
                    missile.getLocation(),  
                    ship.getVelocity());  
        }
    }//CritSystemEffects(ShipAPI ship, MissileAPI missile, DamageType dmgtype, String ExplosionSoundID, float explosionSize)
    
    public float getCRITPERCENT()
    {
        return this.CRITPERCENT;
    }
    
    public void increaseCRITPERCENT(float amount)
    {
        this.CRITPERCENT += amount;
    }
    
    public float getCRITMULT()
    {
        return this.CRITMULT;
    }
    
    public void changeCRITMULT(float amount)
    {
        this.CRITMULT = amount;
    }
}//CLASS
[close]
« Last Edit: November 10, 2013, 10:27:58 AM by silentstormpt »
Logged

dmaiski

  • Captain
  • ****
  • Posts: 422
  • resistance is futile
    • View Profile
Re: The Radioactive Code Dump
« Reply #34 on: November 04, 2013, 09:07:24 AM »

From the diseased minds of the BISO Asylum for the Destructively Inclined
(otherwhise known as the BISO Institute for Weapons Reaserch and Development)

we bring you BreederRounds:
(said breeder rounds during testing, made to allways go into a runaway)

end stage of that particular test
Spoiler

theres a ship in there... someshere
-using large moveback
-using 100% chance of respawn
[close]

we thought of writing a technical spec document detailing their known behaviour* but we found this funny picture of a Hemogeny reaserch technician that had a less then non-fatal mishap with one of these while reaserching a captured BISO Breeder Cannon:

Spoiler
[close]

real technical specs:
Spoiler
-on hit it will have a chance of respawning
--spawning friends aimed at the enemy hull
--if it hits shield it is unlikely to happen,
-if it hits an astroid or missile it will breed like crazy
--subsequently blow up the asteroid with a wall of shrapnel

sugestion: do not use on guns with more then 10 damage per roud, and for gods sake dont use it with high explosive ammo...
will add pics of it in action later
[close]
Spoiler
Code: java
package data.scripts.onhiteffects;

import com.fs.starfarer.api.combat.*;
import org.lazywizard.lazylib.MathUtils;
import org.lwjgl.util.vector.Vector2f;

import static org.lwjgl.util.vector.Vector2f.add;
import static org.lwjgl.util.vector.Vector2f.sub;

public class BreederRound implements OnHitEffectPlugin {


    public void onHit(DamagingProjectileAPI projectile, CombatEntityAPI target,
                      Vector2f point, boolean shieldHit, CombatEngineAPI engine) {

        float angularDistance = //getAngleDifference(projectile.getFacing(),
                (MathUtils.getAngle(projectile.getLocation(), target.getLocation()));

        if (target instanceof ShipAPI && shieldHit)    //not much to do if you hit a shield, no metal to multiply on
        {
            if ((float) Math.random() > 0.4f)     //multiply initial chance
            {
                Vector2f moveback=add(point, multV2f(sub(point, target.getLocation(), null),
                        (.6f)),null); //move back my 20% + col radius
                do{
                    {
                        float angRAND= (float) ((50*(.5-Math.random())));     //angle of spread
                        //float velRAND= (float) ((.6+.5*(.5-Math.random()))*(.3+(Math.abs(angRAND)/100)));
                        //float splashVEL = 155f*velRAND;    //speed of bullets launched
                        float misFFACE = angularDistance-angRAND;
                        //float x = (float) (splashVEL*Math.cos(Math.toRadians(misFFACE)));
                        //float y = (float) (splashVEL*Math.sin(Math.toRadians(misFFACE)));
                        //Vector2f vecFIRE = new Vector2f(x,y);
                        engine.spawnProjectile(projectile.getSource(), projectile.getWeapon(),projectile.getWeapon().getId(),
                                moveback,
                                misFFACE,            //float   angle of spread
                                null

                                //multV2f(multV2f(missile.getVelocity(),1),velRAND)           //Vector2f  aditional velocity
                                //add(multV2f(missile.getVelocity(), 1), multRanV2f(missile.getVelocity(),1,.5f),null)
                        );
                    }
                }
                while ((float) Math.random() > 0.9f); //chance of multiple clones
            }
        }
        else if (target instanceof ShipAPI) {   //only if hits ship

            if ((float) Math.random() > 0.47f)         //multiply initial chance     //very tiny chance of runaway multiplication
            {
                Vector2f moveback=add(point, multV2f(sub(point, target.getLocation(), null),
                        (.6f)),null); //move back my 20% + col radius
                do{
                    {
                        float angRAND= (float) ((50*(.5-Math.random())));     //angle of spread
                        //float velRAND= (float) ((.6+.5*(.5-Math.random()))*(.3+(Math.abs(angRAND)/100)));
                        //float splashVEL = 155f*velRAND;    //speed of bullets launched
                        float misFFACE = angularDistance-angRAND;
                        //float x = (float) (splashVEL*Math.cos(Math.toRadians(misFFACE)));
                        //float y = (float) (splashVEL*Math.sin(Math.toRadians(misFFACE)));
                        //Vector2f vecFIRE = new Vector2f(x,y);
                        engine.spawnProjectile(projectile.getSource(), projectile.getWeapon(),projectile.getWeapon().getId(),
                                moveback,
                                misFFACE,            //float   angle of spread
                                null

                                //multV2f(multV2f(missile.getVelocity(),1),velRAND)           //Vector2f  aditional velocity
                                //add(multV2f(missile.getVelocity(), 1), multRanV2f(missile.getVelocity(),1,.5f),null)
                        );
                    }
                }
                while ((float) Math.random() > 0.6f); //chance of multiple clones
            }
        }
        else   //if you hit asteroid or missile, breed like crazy
            if ((float) Math.random() > 0.4f)           //multiply initial chance
            {
                Vector2f moveback = add(point, multV2f(sub(point, target.getLocation(), null), 0.65f),null);
                // 0.75f will occasionally produce a stray shot while breeding more death
                do{
                    {
                        float angRAND= (float) ((90*(.5-Math.random())));     //angle of spread
                        //float velRAND= (float) ((.6+.5*(.5-Math.random()))*(.3+(Math.abs(angRAND)/100)));
                        //float splashVEL = 155f*velRAND;    //speed of bullets launched
                        float misFFACE = angularDistance-angRAND;
                        //float x = (float) (splashVEL*Math.cos(Math.toRadians(misFFACE)));
                        //float y = (float) (splashVEL*Math.sin(Math.toRadians(misFFACE)));
                        engine.spawnProjectile(projectile.getSource(), projectile.getWeapon(),projectile.getWeapon().getId(),
                                moveback,
                                misFFACE,            //float   angle of spread
                                null

                                //multV2f(multV2f(missile.getVelocity(),1),velRAND)           //Vector2f  aditional velocity
                                //add(multV2f(missile.getVelocity(), 1), multRanV2f(missile.getVelocity(),1,.5f),null)
                        );
                    }
                }
                while ((float) Math.random() > 0.5f); //&& !(target instanceof ShipAPI)); //chance of multiple clones
            }

    }

    //in next lazylib
    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   scale can not be used in static methods...
    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;
    }

}

[close]


(1-[chance to multiply])^([chance to respawn]^-1)=[chance a new bullet will be spawned before original is dead]
>.5 will cascade into uncontrollable multiplication (allways)
>.15 chance to cascade into uncontrollable (rare)
<.10 never cascade into uncontrollable



btw im back from vacation, expect more crazy later
« Last Edit: November 05, 2013, 01:51:09 PM by dmaiski »
Logged
BISO
(WIP) lots of shiny new weapons ( :-[ i have more weapons then sprites :-[ )

i got a cat pad
its like a mouse pad but better!

dmaiski

  • Captain
  • ****
  • Posts: 422
  • resistance is futile
    • View Profile
Re: The Radioactive Code Dump
« Reply #35 on: November 06, 2013, 04:32:25 PM »

im re-writing all my scripts from scratch using beter/more accurate/fixed methods

ill put them all in one post


(this is a new script(also the base for all the others))
basic long range point defence missile ai
it can hit a missile with a harpoon 99% of the time at 1000<range effectivness drops as missiles get too close
the primary point of this ai is to make and improve targeting and pathing of a missile
(it has an extreme level of tracking ability and accuracy)
Spoiler
pictures of it in action
Spoiler


yes that is a vanilla harpoon,
red dot(target lead),
green dot(nose of target (part targeting)),
white line(velocity vector of the missile),
streaking on dots indicates distance moved in last second
[close]

aditional notes:
multitargeting code in there (if missile has more then one posible target, it will pick random of all possible)
single use mouse targeting (only on launch: missile can take a target that you clicked on/near to (100m radius) (got this from MesoTronik))

LRPDai
Spoiler
Code: java
package data.scripts.MissileAI;


import com.fs.starfarer.api.Global;
import com.fs.starfarer.api.combat.*;
import org.lazywizard.lazylib.MathUtils;
import org.lazywizard.lazylib.combat.CombatUtils;
import org.lwjgl.util.vector.Vector2f;

import java.awt.*;
import java.util.*;

//import static jar.CustomAPI.LeadVector;
import static jar.CustomAPI.getEnemyMissilesInArk;
import static org.lwjgl.util.vector.Vector2f.add;

public class LRPDai implements MissileAIPlugin
{
    // Our missile object
    private final MissileAPI missile;
    // Our current target (can be null)
    private MissileAPI target;

    public static float searchrange = 500; //500 range default

    public static float Ark = 30;          //60deg ark   default

    boolean newlaunch=true;                //only do mouse target once on a newly launched missile

    public LRPDai(MissileAPI missile)
    {
        this.missile = missile;
        searchrange=missile.getWeapon().getRange();     //based on weapon
        Ark=5+missile.getWeapon().getArc()/4;           //based on weapon

        // Support for 'fire at target by clicking on them' behavior
        if (newlaunch=true)
        {
            newlaunch=false;
            //get targets near mouse
            java.util.List directTargets = CombatUtils.getMissilesWithinRange(
                    missile.getSource().getMouseTarget(), 100f, true);

            if (!directTargets.isEmpty())
            {
                MissileAPI tmp;
                for (Iterator iter = directTargets.iterator(); iter.hasNext(); )
                {
                    //filter out friendlies
                    tmp = (MissileAPI) iter.next();
                    if (tmp.getOwner() != missile.getSource().getOwner())
                    {
                        target = tmp;
                        break;
                    }
                }
            }
        }

        // Otherwise, use default targeting AI
        if (target == null)
        {
            target = findBestTarget(missile);
        }
    }
    
    
    public static MissileAPI findBestTarget(MissileAPI missile)
    {
        //find targets in ark in front of missile
        ArrayList targets = getEnemyMissilesInArk(missile, Ark, searchrange, true);
        if (!targets.isEmpty())
        {   //pick random missile in list     //replace with .get(0) for nearest
            return (MissileAPI) targets.get((int)(targets.size()*Math.random()));
        }                                                                        
        else return null;

    }

    @Override
    public void advance(float amount)
    {
        // Apparently commands still work while fizzling
        if (missile.isFading() || missile.isFizzling())
        {
            return;
        }

        //find a target
        if (target == null)
        {
            target = findBestTarget(missile);
        }



        if (target!=null ) //if you have a target
        {
            //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();
            double TfaceRad = Math.toRadians(target.getFacing());
            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);

            //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

            float AbsAngD = Math.abs(AtTarget);


            //////////////////////////////////////////////////////////////////////////////////////////////


            //point towards target
            if (AbsAngD > 0.5)
            {
                missile.giveCommand(AtTarget > 0
                        ? ShipCommand.TURN_LEFT : ShipCommand.TURN_RIGHT);
            }

            if (AbsAngD < 5)
            {


                //course correct for missile velocity vector (some bugs when severly off target)
                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);
            }

            ///////////////////////////////////////////////////////////////////////////////////////////////


            //acceleration code
            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);
            }



            /////////////////////////////////////////////////////////////////////////////////////////////////


            //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));
        }


        //clear target code if target is gone
        if (target == null // unset
                ||  ( missile.getOwner() == target.getOwner() )        // friendly
                ||  !Global.getCombatEngine().isEntityInPlay(target) ) // completely removed
        {

            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;
    }
    //find intercept between a missile and a target
    //adapted from code by Jens Seiler
    //http://jaran.de/goodbits/2011/07/17/calculating-an-intercept-course-to-a-target-with-constant-direction-and-velocity-in-a-2-dimensional-plane/
    //have fun if you want to actually understand what going on
    //basicaly gets where T will be by the time M gets to it
    public static Vector2f LeadVector(Vector2f TLoc, Vector2f TVel, Vector2f MLoc, Vector2f MVel)
    {
        //get missiles speed
        float MSpeed = (float)Math.sqrt(MVel.lengthSquared());

        //separate out the vectors
        float Tx = TLoc.getX();
        float Ty = TLoc.getY();
        float Mx = MLoc.getX();
        float My = MLoc.getY();

        float TVx = TVel.getX();
        float TVy = TVel.getY();
        float MVx = MVel.getX();
        float MVy = MVel.getY();

        //subtract position vectors
        float x1 = Tx - Mx;
        float y1 = Ty - My;

        //quadratic fun
        float h1 = TVx*TVx + TVy*TVy - MSpeed*MSpeed;
        if (h1==0)
        {
            h1= (float) .00001;
        }

        float minusMHalf = -(x1*TVx + y1*TVy)/h1;  // h2/h1

        float discriminant = minusMHalf * minusMHalf - (x1*x1 + y1*y1)/h1; // (h2/h1)^2-h3/h1 (ie D)

        //can they intersect?
        if (discriminant < 0)
        {
            return TLoc;
        }


        double root = Math.sqrt(discriminant);

        double t1 = minusMHalf + root;
        double t2 = minusMHalf - root;

        double tMin = Math.min(t1, t2);
        double tMax = Math.max(t1, t2);
        //which of the 2 is smaller
        double time = tMin > 0 ? tMin : tMax;

        //can return -ve time (this is less then useful)
        if (time < 0)
        {
            return TLoc;
        }

        //calculate vector
        return new Vector2f((float)(time * TVx), (float)(time * TVy));
    }
}
[close]
[close]
« Last Edit: November 20, 2013, 08:03:08 PM by dmaiski »
Logged
BISO
(WIP) lots of shiny new weapons ( :-[ i have more weapons then sprites :-[ )

i got a cat pad
its like a mouse pad but better!

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
Re: The Radioactive Code Dump
« Reply #36 on: November 09, 2013, 07:49:17 PM »

That is really awesome.  Does it need to update every frame, or is performance a non-issue?  I have a PD missile system in Vacuum I'd really like to test with that, to see if it or something like it might be a bit cheaper than the current AI.  Oh, and I presume that I have to reference that in the PROJ file?

Also, a request. 

Can you write a PD AI that will:

Target Missiles, Fighters and Ships (by size) while taking into account Friendly Fire?

I just want to see a working example of something like that- simple-but-important target-priority behaviors.
Logged
Please check out my SS projects :)
Xeno's Mod Pack

dmaiski

  • Captain
  • ****
  • Posts: 422
  • resistance is futile
    • View Profile
Re: The Radioactive Code Dump
« Reply #37 on: November 10, 2013, 06:37:47 AM »

ive tested this ai out with my bombard missiles (im posting that ai in next post)
it handles numbers up to 500 active missiles without much lag, so preformance is a non issue for this ai as far as i can see.

an example of a search for (whatever you want) targets:
needs to be compiled into a jar, inbuild compiler dose not like
Code: java
//get target example
    //this makes a list of all targets that fit the criteria
    //get(0) gets you the first target on list(closest one if sortbydistance is true)
    public static ArrayList<CombatEntityAPI> getTargets
    (MissileAPI missile, float Searchrange)
    {
        //the actual list that it will return <CombatEntityAPI>
        // makes it general purpose able to return anything that is on the combat field
        ArrayList<CombatEntityAPI> enemies = new ArrayList<CombatEntityAPI>();
       
       
       
       
        //this is where your missile is
        Vector2f loc = missile.getLocation();

        //getting what you want to search through
        ArrayList<CombatEntityAPI> posible = new ArrayList<CombatEntityAPI>();
        //lazylib is convenient, gets everything you want in Searchrange
        posible.addAll(getNearbyEnemyMissiles(missile, Searchrange, true));
       
        List<ShipAPI> ships = getNearbyEnemies(missile, Searchrange, true);

        //filters through the ship list and puts it in size order (maintaining distance to point)
        for ( ShipAPI enemy : ships)
        {
            //criteria to add to list (you can put anything that will return a true/false here)
            if (enemy.isDrone())
            {
                posible.add(enemy);  //add to posibles
            }
        }
       
        for ( ShipAPI enemy : ships)
        {
            //criteria to add to list (you can put anything that will return a true/false here)
            if (enemy.isFighter())
            {
                posible.add(enemy);  //add to posibles
            }
        }
       
        for ( ShipAPI enemy : ships)
        {
            //criteria to add to list (you can put anything that will return a true/false here)
            if (enemy.isFrigate())
            {
                posible.add(enemy);  //add to posibles
            }
        }
       
        for ( ShipAPI enemy : ships)
        {
            //criteria to add to list (you can put anything that will return a true/false here)
            if (enemy.isDestroyer())
            {
                posible.add(enemy);  //add to posibles
            }
        }

        for ( ShipAPI enemy : ships)
        {
            //criteria to add to list (you can put anything that will return a true/false here)
            if (enemy.isCruiser())
            {
                posible.add(enemy);  //add to posibles
            }
        }

        for ( ShipAPI enemy : ships)
        {
            //criteria to add to list (you can put anything that will return a true/false here)
            if (enemy.isCapital())
            {
                posible.add(enemy);  //add to posibles
            }
        }

        /*
        //filter through the posibles list
        for ( CombatEntityAPI enemy : posible)
        {
            //criteria to add to list (you can put anything that will return a true/false here)
            if (yourcriteria)
            {
                enemies.add(enemy);
            }
        }
        */
       
        //since you just want the missiles, then the nearest ship in size order, without additional filter steps
        //you do
        enemies.addAll(posible);
        //makes the lists (wich are in order) return to you
        return enemies;
    }

to implement into a mod:
place the java file in the mod(dose not mater where)
in mod plugin:
Code: java
    public static final String LRPDai_MISSILE_ID = "SM_lrmPD_m";  //name of the missile that will use that AI
    public static final String BOMBARDai_MISSILE_ID = "SM_SCbombard_m";//""
    @Override
    public PluginPick pickMissileAI(MissileAPI missile,       //picks the ai
                                    ShipAPI launchingShip)
    {
        if (LRPDai_MISSILE_ID.equals(missile.getProjectileSpecId()))     //missile
        {
            return new PluginPick(new LRPDai(missile), CampaignPlugin.PickPriority.MOD_SPECIFIC);     //Ai for that missile
        }
        if (BOMBARDai_MISSILE_ID.equals(missile.getProjectileSpecId()))     //another missile
        {
            return new PluginPick(new BOMBARDai(missile), CampaignPlugin.PickPriority.MOD_SPECIFIC);    //another ai
        }
        return null;
    }

anyway dumping more code...
« Last Edit: November 10, 2013, 08:26:45 AM by dmaiski »
Logged
BISO
(WIP) lots of shiny new weapons ( :-[ i have more weapons then sprites :-[ )

i got a cat pad
its like a mouse pad but better!

dmaiski

  • Captain
  • ****
  • Posts: 422
  • resistance is futile
    • View Profile
Re: The Radioactive Code Dump
« Reply #38 on: November 10, 2013, 07:03:36 AM »

more dumping of stuff
note: i will add my UtilityKit methods bellow, it contains stuff that i commonly use in these scripts, if the file asks for an import from the UtilityKit, just find it in there and stick it in (or compile the utility kit into a jar and have it get from there)
i try to get all the times i use it but sometimes ill miss stuff (also it makes things faster if you are going to fiddle with the scripts)

utility kit:
Spoiler
Code: java
package jar;

import com.fs.starfarer.api.Global;
import com.fs.starfarer.api.combat.*;
import org.lazywizard.lazylib.CollectionUtils;
import org.lazywizard.lazylib.MathUtils;
import org.lwjgl.util.vector.Vector2f;

import java.util.ArrayList;
import java.util.Collections;

import static org.lazywizard.lazylib.combat.AIUtils.getEnemyMissilesOnMap;
import static org.lazywizard.lazylib.combat.AIUtils.getNearbyEnemyMissiles;
import static org.lwjgl.util.vector.Vector2f.add;


public class UtilityKit {
    public static ArrayList<CombatEntityAPI> getEnemyMissilesInVectorRadius(MissileAPI missile, float searchrange, boolean sortByDistance)
    {

        ArrayList<CombatEntityAPI> enemies = new ArrayList<CombatEntityAPI>();
        float x = (float) (searchrange/2*Math.cos(Math.toRadians(missile.getFacing())));
        float y = (float) (searchrange/2*Math.sin(Math.toRadians(missile.getFacing())));
        Vector2f rangefinder = new Vector2f(x, y);


        for ( MissileAPI enemy : getNearbyEnemyMissiles(missile, searchrange))
        {
            if (enemy.getOwner()!=missile.getOwner()
                    && MathUtils.getDistance(enemy, add(missile.getLocation(), rangefinder, null)) < searchrange)
            {
                enemies.add(enemy);
            }
        }
        if (sortByDistance)
        {
            Collections.sort(enemies,
                    new CollectionUtils.SortEntitiesByDistance(missile.getLocation()));
        }


        return enemies;
    }
    public static ArrayList<CombatEntityAPI> getEnemyMissilesInArk(MissileAPI missile, float Ark, float searchrange, boolean sortByDistance)
    {

        ArrayList<CombatEntityAPI> enemies = new ArrayList<CombatEntityAPI>();
        float face = missile.getFacing();
        Vector2f loc = missile.getLocation();

        for ( MissileAPI enemy : getNearbyEnemyMissiles(missile, searchrange))
        {
            if (enemy.getOwner()!=missile.getOwner()
                    && Math.abs(getAngleDifference(face, MathUtils.getAngle(loc, enemy.getLocation())))<Ark)
            {
                enemies.add(enemy);
            }
        }
        if (sortByDistance)
        {
            Collections.sort(enemies,
                    new CollectionUtils.SortEntitiesByDistance(missile.getLocation()));
        }


        return enemies;
    }
    // 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;
    }

    //find intercept between a missile and a target
    //adapted from code by Jens Seiler
    //http://jaran.de/goodbits/2011/07/17/calculating-an-intercept-course-to-a-target-with-constant-direction-and-velocity-in-a-2-dimensional-plane/
    //have fun if you want to actually understand what going on
    //basicaly gets where T will be by the time M gets to it
    public static Vector2f LeadVector(Vector2f TLoc, Vector2f TVel, Vector2f MLoc, Vector2f MVel)
    {
        //get missiles speed
        float MSpeed = (float)Math.sqrt(MVel.lengthSquared());

        //separate out the vectors
        float Tx = TLoc.getX();
        float Ty = TLoc.getY();
        float Mx = MLoc.getX();
        float My = MLoc.getY();

        float TVx = TVel.getX();
        float TVy = TVel.getY();
        float MVx = MVel.getX();
        float MVy = MVel.getY();

        //subtract position vectors
        float x1 = Tx - Mx;
        float y1 = Ty - My;

        //quadratic fun
        float h1 = TVx*TVx + TVy*TVy - MSpeed*MSpeed;
        if (h1==0)
        {
            h1= (float) .00001;
        }

        float minusMHalf = -(x1*TVx + y1*TVy)/h1;  // h2/h1

        float discriminant = minusMHalf * minusMHalf - (x1*x1 + y1*y1)/h1; // (h2/h1)^2-h3/h1 (ie D)

        //can they intersect?
        if (discriminant < 0)
        {
            return TLoc;
        }


        double root = Math.sqrt(discriminant);

        double t1 = minusMHalf + root;
        double t2 = minusMHalf - root;

        double tMin = Math.min(t1, t2);
        double tMax = Math.max(t1, t2);
        //which of the 2 is smaller
        double time = tMin > 0 ? tMin : tMax;

        //can return -ve time (this is less then useful)
        if (time < 0)
        {
            return TLoc;
        }

        //calculate vector
        return new Vector2f((float)(time * TVx), (float)(time * TVy));
    }

    //lists enemies with weapon range on ship
    public static ArrayList<ShipAPI> getEnemiesWithWeaponRange(ShipAPI ship, boolean sortByDistance)
    {
        CombatEngineAPI engine= Global.getCombatEngine();
        ArrayList<ShipAPI> enemies = new ArrayList<ShipAPI>();

        for ( ShipAPI enemy : engine.getShips())
        {
            float distance = MathUtils.getDistance(enemy, ship);
            if (enemy.getOwner()!=ship.getOwner()
                    && distance<3000)
            {
                for (WeaponAPI weap: enemy.getAllWeapons())
                {
                    if(weap.getType()!= WeaponAPI.WeaponType.MISSILE
                            && weap.getRange()>distance)
                    {
                        enemies.add(enemy);
                        break;
                    }
                }
            }
        }
        if (sortByDistance)
        {
            Collections.sort(enemies,
                    new CollectionUtils.SortEntitiesByDistance(ship.getLocation()));
        }

        return enemies;
    }

    public static boolean targetInArk(ShipAPI ship, Vector2f target)
    {
        float distance = MathUtils.getDistance(ship, target);

        for (WeaponAPI weap: ship.getAllWeapons())
        {
            if(weap.getType()!= WeaponAPI.WeaponType.MISSILE
                    && weap.getRange()>distance
                    && !weap.hasAIHint(WeaponAPI.AIHints.PD)
                    && weap.distanceFromArc(target)==0)
            {
                return true;
            }
        }
        return false;
    }
    //gets how many weapons are aming at ship
    public static float getThreatOfWeapons(ShipAPI ship)
    {
        float num=0;
        for (ShipAPI enemy : getEnemiesWithWeaponRange(ship,false))
        {
            if (targetInArk(enemy, ship.getLocation()))
            {
                num++;
            }
        }
        return num;
    }
}
[close]

Bombardment Missile AI:
unlike the PD ai this AI is intentionaly made to not be able to hit a barn with a minigun at 5m
the missiles are guided(but they will stray off target by a good bit)
ai uses same targeting script as LRPDai but with some changes to its implementation in the pathing ai
has a timer that makes missiles fly out without activating pathing script for a bit (to make them spread out)
best used with launchers that fire swarms of high speed, low damage missiles
(can be made into artillery if missiles are set up to flameout as soon as they gain target)
Spoiler

Code: java
package data.scripts.MissileAI;


import com.fs.starfarer.api.Global;
import com.fs.starfarer.api.combat.*;
import org.lazywizard.lazylib.MathUtils;
import org.lazywizard.lazylib.combat.AIUtils;
import org.lazywizard.lazylib.combat.CombatUtils;
import org.lwjgl.util.vector.Vector2f;

import java.util.Iterator;
import java.util.List;

//import static jar.UtilityKit.LeadVector;
import static org.lwjgl.util.vector.Vector2f.add;

public class BOMBARDai implements MissileAIPlugin
{
    // Our missile object
    private final MissileAPI missile;
    // Our current target (can be null)
    private CombatEntityAPI target;

    public static float searchrange = 500; //500 range default

    //public static float Ark = 30;          //60deg ark   default

    boolean newlaunch=true;                //only do mouse target once on a newly launched missile

    public BOMBARDai(MissileAPI missile)
    {
        this.missile = missile;
        searchrange=missile.getWeapon().getRange();     //based on weapon
        //Ark=5+missile.getWeapon().getArc()/4;           //based on weapon

        // Support for 'fire at target by clicking on them' behavior
        if (newlaunch=true)
        {
            newlaunch=false;
            //get targets near mouse
            java.util.List directTargets = CombatUtils.getShipsWithinRange(
                    missile.getSource().getMouseTarget(), 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);
        }
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////


    //stuff
    float straighttimer=50*((float)Math.random());      //1/2 second max non targeting time
    final double isEffectedbyflare=Math.random();
    float flarelockout=0;
    float timer=0;
    float oftarget=300*((float)(.5-Math.random()));
    float baseoftarget=40*((float)(.5-Math.random()));
    public static final String flare="flare";

    //////////////////////////////////////////////////////////////////////////////////////////////////////////


    //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;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /* turned off for this AI
    //search for targets in ark in front
    public static MissileAPI findBestTarget(MissileAPI missile)
    {
        //find targets in ark in front of missile
        ArrayList targets = getEnemyMissilesInArk(missile, Ark, searchrange, true);
        if (!targets.isEmpty())
        {   //pick random missile in list     //replace with .get(0) for nearest
            return (MissileAPI) targets.get((int)(targets.size()*Math.random()));
        }
        else return null;

    }
    */
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////


    //get ship target or search for closest enemy
    public static ShipAPI findBestTarget(MissileAPI missile)
    {
        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
                <missile.getWeapon().getRange())                          //check if its in range
        {
            return source.getShipTarget();
        }

        return AIUtils.getNearestEnemy(missile);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////


    //main missile AI
    @Override
    public void advance(float amount)
    {

        //10 step timer
        timer++;
        if (timer>10){timer=0;}

        ///////////////////////////////////////////////////////////////////////////////////////////////////////////


        // Apparently commands still work while fizzling
        if (missile.isFading() || missile.isFizzling())
        {
            return;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////


        //go straight for x after launch
        if (straighttimer>0)
        {
            missile.giveCommand(ShipCommand.ACCELERATE);
            straighttimer--;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////


        //find a target
        if (target == null)
        {
            target = findBestTarget(missile);
        }

        /////////////////////////////////////////////////////////////////////////////////////////////////////////////


        //if missile is susceptible to flare
        if (isEffectedbyflare>0.4           //can a flare effect it
                && flarelockout==0          //has it already been set to ignore flares
                && timer==0                 //check every 10 frames
                && straighttimer<2)         //its not flying without ai in straight line
        {
            timer++;
            MissileAPI flaretarget = checkforflare(missile);
            if (flaretarget!=null)
            {
                target=flaretarget;         //set flare as target
                flarelockout++;             //ignore future flares
            }

        }

        //////////////////////////////////////////////////////////////////////////////////////////////////////////////


        //pathing ai
        if (straighttimer<2)  //check if you are going straight
        {
            if (target!=null ) //if you have a target
            {
                //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();
                double TfaceRad = Math.toRadians(target.getFacing());
                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);

                //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

                float AbsAngD = Math.abs(AtTarget);


                //////////////////////////////////////////////////////////////////////////////////////////////


                //check if scatter code needed
                float targetcolision = target.getCollisionRadius();       //get colision radi
                if (MathUtils.getDistance(missile, target)<75+(200*target.getCollisionRadius()/100))
                {                                                         //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 * target.getCollisionRadius() / 75)));

                //////////////////////////////////////////////////////////////////////////////////////////


                //point towards target
                if (AbsAngD > 0.5)
                {                                  //makes missile fly off target
                    missile.giveCommand(AtTarget > oftargetby
                            ? ShipCommand.TURN_LEFT : ShipCommand.TURN_RIGHT);
                    oftarget=(oftarget>0 ? oftarget-1 : oftarget+1); //reduce off target counter
                }

                ////////////////////////////////////////////////////////////////////////////////////////////////////


                //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 < oftargetby
                                ? 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);
                }

                ///////////////////////////////////////////////////////////////////////////////////////////////


                //acceleration code  (this missile allays accelerates, so ignore the rest)
                //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);
                }
                */


                /////////////////////////////////////////////////////////////////////////////////////////////////


                //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));

            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////


            //stop if you have no target
            else missile.giveCommand(ShipCommand.DECELERATE);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////////////////


        //clear target if target is gone
        if (target == null // unset
                ||  ( missile.getOwner() == target.getOwner() )        // friendly
                ||  !Global.getCombatEngine().isEntityInPlay(target) ) // completely removed
        {

            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;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////

   //find intercept between a missile and a target
    //adapted from code by Jens Seiler
    //http://jaran.de/goodbits/2011/07/17/calculating-an-intercept-course-to-a-target-with-constant-direction-and-velocity-in-a-2-dimensional-plane/
    //have fun if you want to actually understand what going on
    //basicaly gets where T will be by the time M gets to it
    public static Vector2f LeadVector(Vector2f TLoc, Vector2f TVel, Vector2f MLoc, Vector2f MVel)
    {
        //get missiles speed
        float MSpeed = (float)Math.sqrt(MVel.lengthSquared());

        //separate out the vectors
        float Tx = TLoc.getX();
        float Ty = TLoc.getY();
        float Mx = MLoc.getX();
        float My = MLoc.getY();

        float TVx = TVel.getX();
        float TVy = TVel.getY();
        float MVx = MVel.getX();
        float MVy = MVel.getY();

        //subtract position vectors
        float x1 = Tx - Mx;
        float y1 = Ty - My;

        //quadratic fun
        float h1 = TVx*TVx + TVy*TVy - MSpeed*MSpeed;
        if (h1==0)
        {
            h1= (float) 0000.1;
        }

        float minusMHalf = -(x1*TVx + y1*TVy)/h1;  // h2/h1

        float discriminant = minusMHalf * minusMHalf - (x1*x1 + y1*y1)/h1; // (h2/h1)^2-h3/h1 (ie D)

        //can they intersect?
        if (discriminant < 0)
        {
            return TLoc;
        }


        double root = Math.sqrt(discriminant);

        double t1 = minusMHalf + root;
        double t2 = minusMHalf - root;

        double tMin = Math.min(t1, t2);
        double tMax = Math.max(t1, t2);
        //which of the 2 is smaller
        double time = tMin > 0 ? tMin : tMax;

        //can return -ve time (this is less then useful)
        if (time < 0)
        {
            return TLoc;
        }

        //calculate vector
        return new Vector2f((float)(time * TVx), (float)(time * TVy));
    }
}
[close]

regenerative/organic armor:
this script is rather unique, it should be applied to a weapon (that dose not shoot) and fitted to a ship, multiple systems allow faster repair (at the cost of loosing more weapon slots and OP) it has 2 parts to its effect and set up to be easily modable

to implement put somewhere in mod then add:
"everyFrameEffect":"wherever you put it.AbsorptionArmor",
to the .wpn file like any other onhit/weapon effect

part 1:
redistributes armor from healthy cells to nearby damaged cells if healthy cell is above a set % hp
costs 1 flux per point (miniscule)
part 2:
repairs damaged cells as long as they have not been destroyed
costs 10 flux per armor point

bugfixed,
stopped code for energy cost to redistribute armor, it gets costly(uncontrollable overloads, folover of flux counters, buggy)
failsafes so it dose not cause crash through -ve and 101% armor color bugs
Spoiler
Code: java
package data.scripts.plugins;



import com.fs.starfarer.api.Global;
import com.fs.starfarer.api.combat.*;
import com.fs.starfarer.api.util.IntervalUtil;

import java.awt.*;

/*
to be put on a weapon that will execute script on a ship
multiple weapons will increase the efficiency
 */
public class AbsorptionArmor implements EveryFrameWeaponEffectPlugin
{
    //engine
    private CombatEngineAPI engine= Global.getCombatEngine();

    //////////////////////////////////////////////////////////////////////////////////////////////

    //timers
    private IntervalUtil fasttimer = new IntervalUtil(.1f, .11f);
    private IntervalUtil slowtimer = new IntervalUtil(.15f, .16f);

    //////////////////////////////////////////////////////////////////////////////////////////////



    //main armor effect
    float lastcycle=0;
    @Override
    public void advance(float v, CombatEngineAPI engineAPI, WeaponAPI weaponAPI)
    {
        //ship
        ShipAPI ship;
        ship=weaponAPI.getShip();

        //////////////////////////////////////////////////////////////////////////////////////////////

        //stats of system
        float FluPerAPoint = 10;    //how much 1 armor point is worth in terms of flux
        //float ReBaArmRate = .005f;  //how fast armor rebalanced  max 1 for instant
        float MaxFlux = .8f;        //cap for this system being active
        float RegenRate = .002f;    //rate armor regenerates as a decimal
        float activeRate = .005f;    //how fast active armor balancer works
        float MinHealthActive = .4f;//minimum health for active armor sharing
        float weaponsizemult = 1f;
        //weapon size multiplier
        WeaponAPI.WeaponSize weapsize = weaponAPI.getSize();
        if (weapsize.equals(WeaponAPI.WeaponSize.SMALL)) {weaponsizemult=.5f;}
        if (weapsize.equals(WeaponAPI.WeaponSize.MEDIUM)){weaponsizemult=1f;}
        if (weapsize.equals(WeaponAPI.WeaponSize.LARGE)) {weaponsizemult=2f;}

        //////////////////////////////////////////////////////////////////////////////////////////////

        //game is paused dont do anything  //weapon is disabled ""
        if (engine.isPaused() || weaponAPI.isDisabled())
        {
            return;
        }

        //////////////////////////////////////////////////////////////////////////////////////////////

        //if(ship.getSystem().isActive()) optional link to ship system
        {
            //advance timers
            slowtimer.advance(v);
            fasttimer.advance(v);

            //////////////////////////////////////////////////////////////////////////////////////////////

            //main code
            if (fasttimer.intervalElapsed())
            {
                //stuff that is used alot
                ArmorGridAPI armorgrid = ship.getArmorGrid();
                float armorrating = armorgrid.getArmorRating();
                float MaxCell = armorgrid.getMaxArmorInCell();

                //////////////////////////////////////////////////////////////////////////////////////////

                //armor grid stats
                int maxX = armorgrid.getLeftOf()+armorgrid.getRightOf();
                int maxY = armorgrid.getAbove()+armorgrid.getBelow();

                //////////////////////////////////////////////////////////////////////////////////////////

                //avarage armor of ship hull
                float armorcells = 0;               //number of cells ship has
                for (int X=0; X<maxX; X++){for (int Y=0; Y<maxY; Y++){armorcells++;}}
                //float ReBalArmor = curarmor/armorcells;

                //////////////////////////////////////////////////////////////////////////////////////////

                //adjusted stats
                float adjust = weaponsizemult*Math.min(125 / armorcells, 4); //max increase of rate (prevents 100x rate on small ship)
                FluPerAPoint = 10;    //how much 1 armor point is worth in terms of flux
                //float ReBaArmRate = .005f;  //how fast armor rebalanced  max 1 for instant
                MaxFlux = .8f;        //cap for this system being active
                RegenRate = .002f*adjust;    //rate armor regenerates as a decimal
                activeRate = .005f*adjust;    //how fast active armor balancer works
                MinHealthActive = .4f*adjust;//minimum health for active armor sharing

                //////////////////////////////////////////////////////////////////////////////////////////

                //basic armor state of ship
                float curarmor = getTotalArmor(ship);
                //float ArmLost = armorgrid.getArmorRating()-curarmor;  //how much armor was damaged

                //////////////////////////////////////////////////////////////////////////////////////////

                //calculate regen rate based on flux (prevents cells from filling up sequentially at low flux)
                float FluxRemaining = (ship.getFluxTracker().getMaxFlux()*MaxFlux) - ship.getFluxTracker().getCurrFlux();
                //float FluxToRepairMax = ArmLost * FluPerAPoint;
                float NormRepPerFrame = (MaxCell * RegenRate)
                        *((MaxFlux-ship.getFluxTracker().getFluxLevel())/MaxFlux);//aditional level of repair decrease
                //float FluxToRepairNorm = NormRepPerFrame * FluPerAPoint * armorcells;
                //float FluxForRep = (FluxToRepairMax < FluxToRepairNorm ? FluxToRepairMax : FluxToRepairNorm);

                //easier, more accurate  (compares the cost to repair in last cycle to amount of flux left)
                if (lastcycle==0) {lastcycle=NormRepPerFrame*armorcells*FluPerAPoint;}
                float FluxForRep = lastcycle;
                float FluxToRepairNorm = lastcycle;
                float RepRate = (FluxForRep<FluxRemaining ? NormRepPerFrame:NormRepPerFrame*(FluxRemaining/FluxToRepairNorm));

                //////////////////////////////////////////////////////////////////////////////////////////


                //armor manager
                float next=0;
                lastcycle=0; //clears lastcycle
                //active cycle (needs to be separate)
                for (int X=0; X<maxX; X++)       //
                {                                //cycle through all armor cells on ship
                    for (int Y=0; Y<maxY; Y++)   //
                    {
                        float cur = armorgrid.getArmorValue(X, Y); //health of current cell
                        //Active ReBalArmor
                        //mover armor from nearby cells to damaged ones
                        //can be tied to an if statement
                        {
                            //take armor of nearby healthy cells
                            float Forwardsum=0;
                            for (int Xa=(X==0? X:X-1); Xa<maxX && Xa>=0 && Xa<=X+1; Xa++)
                            {
                                for (int Ya=(Y==0? Y:Y-1); Ya<maxY && Ya>=0 && Ya<=Y+1; Ya++)
                                {
                                    float cell = armorgrid.getArmorValue(Xa, Ya);
                                    if (cell>cur && armorgrid.getArmorFraction(Xa, Ya)>MinHealthActive)
                                    {
                                        float diff = (cell - cur)*activeRate;
                                        next = (cell-diff);
                                        armorgrid.setArmorValue(Xa, Ya, next>0? next:0);
                                        Forwardsum+=diff;
                                        //ship.getFluxTracker().increaseFlux(diff*FluPerAPoint*.1f, true);
                                        //uses 1/10th of the normal flux to move armor around (too costly in flux)
                                    }
                                }
                            }
                            next = (cur + Forwardsum);
                            armorgrid.setArmorValue(X, Y, next<MaxCell? next:MaxCell); //add it to cell
                        }
                    }
                }

                /////////////////////////////////////////////////////////////////////////////////////


                //passive cycle
                for (int X=0; X<maxX; X++)       //
                {                                //cycle through all armor cells on ship
                    for (int Y=0; Y<maxY; Y++)   //
                    {
                        float cur = armorgrid.getArmorValue(X, Y); //health of current cell

                        //only do repair if cell health is more then 0 prevents immortal ship syndrome
                        if (cur>0)
                        {
                            //regen armor
                            if (cur<MaxCell)
                            {
                                next = cur + RepRate;          //how much armor should be regenerated


                                armorgrid.setArmorValue(X, Y, next<MaxCell? next:MaxCell);
                                float fluxuse = (next - cur) * FluPerAPoint;
                                ship.getFluxTracker().increaseFlux(fluxuse, true);
                                lastcycle+=fluxuse;
                            }
                        }

                    }
                }

                /////////////////////////////////////////////////////////////////////////////////////

                //test
                if (slowtimer.intervalElapsed())
                {
                engine.addFloatingText(ship.getLocation(), "armorcells  " + armorcells + " armorrating  " + armorrating + " curentarmor  " + curarmor +" MaxCell  "+ MaxCell +"  waeposizemult  "+weaponsizemult, 20f, Color.RED, ship, 1f, .5f);
                }

            }
        }
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////////

    //gets total armor of a ship
    public static float getTotalArmor(ShipAPI ship)
    {
        ArmorGridAPI armorgrid = ship.getArmorGrid();
        float sum=0;
        int maxX = armorgrid.getLeftOf()+armorgrid.getRightOf();
        int maxY = armorgrid.getAbove()+armorgrid.getBelow();

        for (int X=0; X<maxX; X++)
        {
            for (int Y=0; Y<maxY; Y++)
            {
                sum += armorgrid.getArmorValue(X, Y);
            }
        }
        return sum;
    }

}
[close]

« Last Edit: November 20, 2013, 08:03:37 PM by dmaiski »
Logged
BISO
(WIP) lots of shiny new weapons ( :-[ i have more weapons then sprites :-[ )

i got a cat pad
its like a mouse pad but better!

dmaiski

  • Captain
  • ****
  • Posts: 422
  • resistance is futile
    • View Profile
Re: The Radioactive Code Dump
« Reply #39 on: November 10, 2013, 04:05:07 PM »

 >:( hit post length limit  >:(

similar to the armor manager, but more simple
when installed onto a ship, if ship reaches 95% flux this will vent the flux without overloding ship or vent weapon disable effect
meant to be used with weapons that have limited ammo (intended as a single use emergency system)
Spoiler
Code: java
package data.scripts.plugins;



import com.fs.starfarer.api.Global;
import com.fs.starfarer.api.combat.*;
import com.fs.starfarer.api.util.IntervalUtil;

import java.awt.*;

/*
to be put on a weapon that will execute script on a ship
multiple weapons will increase the efficiency
 */
public class AuxilaryFluxVents implements EveryFrameWeaponEffectPlugin
{
    //engine
    private CombatEngineAPI engine= Global.getCombatEngine();

    //////////////////////////////////////////////////////////////////////////////////////////////

    //timers
    private IntervalUtil fasttimer = new IntervalUtil(.05f, .06f);
    private IntervalUtil slowtimer = new IntervalUtil(.15f, .16f);

    //////////////////////////////////////////////////////////////////////////////////////////////



    //main armor effect
    boolean fired=false;
    @Override
    public void advance(float v, CombatEngineAPI engineAPI, WeaponAPI weaponAPI)
    {
        //ship
        ShipAPI ship;
        ship=weaponAPI.getShip();

        //////////////////////////////////////////////////////////////////////////////////////////////


        //weapon size multiplier
        float weaponsizemult = 1;
        WeaponAPI.WeaponSize weapsize = weaponAPI.getSize();
        if (weapsize.equals(WeaponAPI.WeaponSize.SMALL)) {weaponsizemult=.5f;}
        if (weapsize.equals(WeaponAPI.WeaponSize.MEDIUM)){weaponsizemult=1f;}
        if (weapsize.equals(WeaponAPI.WeaponSize.LARGE)) {weaponsizemult=2f;}
        //stats of system
        float rate = .01f*weaponsizemult; //how fast vent happens (20x this number)
        float minflux = .1f; //lowest value of flux it can get to
        float maxflux = .95f;
        FluxTrackerAPI flux = ship.getFluxTracker();

        //////////////////////////////////////////////////////////////////////////////////////////////

        //game is paused dont do anything
        if (engine.isPaused())
        {
            return;
        }

        //////////////////////////////////////////////////////////////////////////////////////////////

        //if(ship.getSystem().isActive()) optional link to ship system
        {
            //advance timers
            //slowtimer.advance(v);
            fasttimer.advance(v);
            if (fasttimer.intervalElapsed())
            {
                //////////////////////////////////////////////////////////////////////////////////////////////

                //controls for flux vent
                if (!fired)  //if weapon has not fired
                {
                    //if flux is to high fire

                    if ((ship.getFluxTracker().getFluxLevel()>maxflux && weaponAPI.getAmmo()>0))
                    {weaponAPI.isFiring();fired=true;
                        weaponAPI.setRemainingCooldownTo(100);
                        weaponAPI.setAmmo(weaponAPI.getAmmo()-1);
                        flux.setCurrFlux(flux.getMaxFlux());}//forces all other systems on ship on
                    //record that you fired
                    if (weaponAPI.isFiring()){fired=true;}
                }

                //////////////////////////////////////////////////////////////////////////////////////////////


                //main vent code
                float FVsec = (flux.getMaxFlux()*.05f)*rate;
                if (fired && ship.getFluxTracker().getFluxLevel()>minflux)
                {
                    //prevents firing
                    weaponAPI.setRemainingCooldownTo(100);
                    {
                        flux.decreaseFlux(FVsec);
                    }
                }

                //////////////////////////////////////////////////////////////////////////////////////////////


                //if venting done
                if (fired && ship.getFluxTracker().getFluxLevel()<minflux)
                {
                    fired=false;
                    weaponAPI.setRemainingCooldownTo(0); //if now at minflux firing is allowed
                }

                //test
                slowtimer.advance(v);
                if (slowtimer.intervalElapsed())
                {
                    engine.addFloatingText(ship.getLocation(), "FVsec  " + FVsec + "rate  " + rate, 20f, Color.RED, ship, 1f, .5f);
            }
            }
        }
    }
}
[/spoiler]
[close]
« Last Edit: November 10, 2013, 05:01:55 PM by dmaiski »
Logged
BISO
(WIP) lots of shiny new weapons ( :-[ i have more weapons then sprites :-[ )

i got a cat pad
its like a mouse pad but better!

silentstormpt

  • Admiral
  • *****
  • Posts: 1060
    • View Profile
Re: The Radioactive Code Dump
« Reply #40 on: November 10, 2013, 05:15:13 PM »

>:( hit post length limit  >:(

similar to the armor manager, but more simple
when installed onto a ship, if ship reaches 95% flux this will vent the flux without overloding ship or vent weapon disable effect
meant to be used with weapons that have limited ammo (intended as a single use emergency system)
Spoiler
Code: java
package data.scripts.plugins;



import com.fs.starfarer.api.Global;
import com.fs.starfarer.api.combat.*;
import com.fs.starfarer.api.util.IntervalUtil;

import java.awt.*;

/*
to be put on a weapon that will execute script on a ship
multiple weapons will increase the efficiency
 */
public class AuxilaryFluxVents implements EveryFrameWeaponEffectPlugin
{
    //engine
    private CombatEngineAPI engine= Global.getCombatEngine();

    //////////////////////////////////////////////////////////////////////////////////////////////

    //timers
    private IntervalUtil fasttimer = new IntervalUtil(.05f, .06f);
    private IntervalUtil slowtimer = new IntervalUtil(.15f, .16f);

    //////////////////////////////////////////////////////////////////////////////////////////////



    //main armor effect
    boolean fired=false;
    @Override
    public void advance(float v, CombatEngineAPI engineAPI, WeaponAPI weaponAPI)
    {
        //ship
        ShipAPI ship;
        ship=weaponAPI.getShip();

        //////////////////////////////////////////////////////////////////////////////////////////////


        //weapon size multiplier
        float weaponsizemult = 1;
        WeaponAPI.WeaponSize weapsize = weaponAPI.getSize();
        if (weapsize.equals(WeaponAPI.WeaponSize.SMALL)) {weaponsizemult=.5f;}
        if (weapsize.equals(WeaponAPI.WeaponSize.MEDIUM)){weaponsizemult=1f;}
        if (weapsize.equals(WeaponAPI.WeaponSize.LARGE)) {weaponsizemult=2f;}
        //stats of system
        float rate = .01f*weaponsizemult; //how fast vent happens (20x this number)
        float minflux = .1f; //lowest value of flux it can get to
        float maxflux = .95f;
        FluxTrackerAPI flux = ship.getFluxTracker();

        //////////////////////////////////////////////////////////////////////////////////////////////

        //game is paused dont do anything
        if (engine.isPaused())
        {
            return;
        }

        //////////////////////////////////////////////////////////////////////////////////////////////

        //if(ship.getSystem().isActive()) optional link to ship system
        {
            //advance timers
            //slowtimer.advance(v);
            fasttimer.advance(v);
            if (fasttimer.intervalElapsed())
            {
                //////////////////////////////////////////////////////////////////////////////////////////////

                //controls for flux vent
                if (!fired)  //if weapon has not fired
                {
                    //if flux is to high fire

                    if ((ship.getFluxTracker().getFluxLevel()>maxflux && weaponAPI.getAmmo()>0))
                    {weaponAPI.isFiring();fired=true;
                        weaponAPI.setRemainingCooldownTo(100);
                        weaponAPI.setAmmo(weaponAPI.getAmmo()-1);
                        flux.setCurrFlux(flux.getMaxFlux());}//forces all other systems on ship on
                    //record that you fired
                    if (weaponAPI.isFiring()){fired=true;}
                }

                //////////////////////////////////////////////////////////////////////////////////////////////


                //main vent code
                float FVsec = (flux.getMaxFlux()*.05f)*rate;
                if (fired && ship.getFluxTracker().getFluxLevel()>minflux)
                {
                    //prevents firing
                    weaponAPI.setRemainingCooldownTo(100);
                    {
                        flux.decreaseFlux(FVsec);
                    }
                }

                //////////////////////////////////////////////////////////////////////////////////////////////


                //if venting done
                if (fired && ship.getFluxTracker().getFluxLevel()<minflux)
                {
                    fired=false;
                    weaponAPI.setRemainingCooldownTo(0); //if now at minflux firing is allowed
                }

                //test
                slowtimer.advance(v);
                if (slowtimer.intervalElapsed())
                {
                    engine.addFloatingText(ship.getLocation(), "FVsec  " + FVsec + "rate  " + rate, 20f, Color.RED, ship, 1f, .5f);
            }
            }
        }
    }
}
[/spoiler]
[close]
Heres a challenge, make a AI and a hull mod or ship system that the higher the flux amount, the more damage it does with its weapons, the AI should try to get as close as it can get to overloading to maximize damage output, this also means it will pull shields and fire to get flux fast then turns into a suicidal berserker that ignores defense to do damage instead.
Logged

dmaiski

  • Captain
  • ****
  • Posts: 422
  • resistance is futile
    • View Profile
Re: The Radioactive Code Dump
« Reply #41 on: November 10, 2013, 05:27:57 PM »

not really that easy, needs to override the ships main AI somehow, and thats too much work since you would need to write the whole thing from scratch

look at mutable ship stats, its posible to make shipwide weapon boost that is based on flux,
an ai for that is just a flux tracker and a if(flux>x) ship.useSystem()

example of such
Spoiler
rudimentary AI for a system
implement with:
"aiScript":"data.shipsystems.scripts.ai.ArmorAI",
in .system file
Spoiler
Code: java
package data.shipsystems.scripts.ai;

import com.fs.starfarer.api.combat.*;
import com.fs.starfarer.api.util.IntervalUtil;
import org.lwjgl.util.vector.Vector2f;



public class ExampleAI implements ShipSystemAIScript {

    private ShipAPI ship;
    private CombatEngineAPI engine;
    private ShipwideAIFlags flags;
    private ShipSystemAPI system;

    private IntervalUtil tracker = new IntervalUtil(0.5f, 1f);

    public void init(ShipAPI ship, ShipSystemAPI system, ShipwideAIFlags flags, CombatEngineAPI engine) {
        this.ship = ship;
        this.flags = flags;
        this.engine = engine;
        this.system = system;
    }

    @SuppressWarnings("unchecked")
    public void advance(float amount, Vector2f missileDangerDir, Vector2f collisionDangerDir, ShipAPI target)
    {
        if (ship.getShield().isOn())
        {ship.useSystem();}

    }
}
[close]

example stat mod
Spoiler
Code: java
package data.shipsystems.scripts;


import com.fs.starfarer.api.combat.MutableShipStatsAPI;
import com.fs.starfarer.api.plugins.ShipSystemStatsScript;

public class Example implements ShipSystemStatsScript {

    public void apply(MutableShipStatsAPI stats, String id, State state, float effectLevel)
    {
        stats.getShieldArcBonus().modifyMult(id, 360);
    }

    public void unapply(MutableShipStatsAPI stats, String id)
    {
        stats.getShieldArcBonus().unmodify(id);
    }

    public StatusData getStatusData(int index, State state, float effectLevel) {
        if (index == 0) {
            return new StatusData("dose x now", false);
        }

        return null;
    }
}
[close]
[close]
« Last Edit: November 10, 2013, 05:39:38 PM by dmaiski »
Logged
BISO
(WIP) lots of shiny new weapons ( :-[ i have more weapons then sprites :-[ )

i got a cat pad
its like a mouse pad but better!

etherealblade

  • Commander
  • ***
  • Posts: 134
    • View Profile
Re: The Radioactive Code Dump
« Reply #42 on: November 18, 2013, 12:57:28 AM »

DRONE missiles
stays at a set distance and blasts the enemy ships appart
who needs fighters anyways?


Spoiler
Code: java
int timer = 0;  //needs to be outside of advance() to work as a timer
int timer2 = (int) (600*Math.random());  //random start point for strafing
public void advance(float amount)
        {
        timer++;

        if (MathUtils.getDistance(
                add(target.getLocation(), target.getVelocity(), null),              //blow up the enemy ship
                add(missile.getLocation(), multV2f(missile.getVelocity(),3), null))
                < 600
                && MathUtils.getDistance(
                missile.getLocation(),                     //don't blow up your own ship
                missile.getSource().getLocation())
                >missile.getSource().getCollisionRadius()+5
                && timer==1
                )
        {
            timer++;
                CombatEngine engine = CombatEngine.getInstance();          //engine

                String MBRC_p = "MBRC2";      //dummy weapon

                {

                    {
                        int counts = 1;
                        do {
                            float angRAND= (float) ((25*(.5-Math.random())));     //angle of spread
                            float velRAND= (float) (1+.5*(.5-Math.random()));      //variance of projectile speeds
                            float splashVEL = 255f*velRAND;    //speed of bullets launched
                            float misFFACE = missile.getFacing()-angRAND;
                            float x = (float) (splashVEL*Math.cos(Math.toRadians(misFFACE)));
                            float y = (float) (splashVEL*Math.sin(Math.toRadians(misFFACE)));
                            Vector2f vecFIRE = new Vector2f(x,y);
                            engine.spawnProjectile(null, null,MBRC_p,
                                    missile.getLocation(),          //Vector2f firing point
                                    misFFACE,            //float   angle of spread
                                    add(missile.getVelocity(), vecFIRE, null)

                                    //multV2f(multV2f(missile.getVelocity(),1),velRAND)           //Vector2f  aditional velocity
                                    //add(multV2f(missile.getVelocity(), 1), multRanV2f(missile.getVelocity(),1,.5f),null)
                            );
                            counts++;
                        }while (counts<2);         //2x pew pew


                        //engine.removeEntity(missile); //make missile go poof
                    }
                    //lightning
                    // float emp = missile.getEmpAmount();
                    //float dam = missile.getDamageAmount();

                    //engine.spawnEmpArc(missile.getSource(), missile.getLocation(), target, target,
                    // DamageType.ENERGY,dam/4, emp/4,
                    //10000f, "tachyon_lance_emp_impact",20f, new Color(255,10,15,255),new Color(255,100,100,255));
                }
                //to stop missile shooting again
                //engine.removeEntity(missile);   //make missile go poof

                //missile.flameOut();               //make missile flame out
                return;
        }
        if (timer>40)
        {timer=0;}
        
        //missile pathing code
        if (Math.abs(angularDistance) < 100      //get in close
                && MathUtils.getDistance(missile.getLocation(), target.getLocation())
                >320+100/target.getCollisionRadius()*target.getCollisionRadius())
        {
            missile.giveCommand(ShipCommand.ACCELERATE);
        }
        if (Math.abs(angularDistance) < 100     //keep distance
                && MathUtils.getDistance(missile.getLocation(), target.getLocation())
                <280+100/target.getCollisionRadius()*target.getCollisionRadius())
        {
            missile.giveCommand(ShipCommand.ACCELERATE_BACKWARDS);
        }

        if (Math.abs(angularDistance) < 100   //strafe
                && MathUtils.getDistance(missile.getLocation(), target.getLocation())<400+target.getCollisionRadius())
        {
            missile.giveCommand(timer2 > 300 ? ShipCommand.STRAFE_LEFT : ShipCommand.STRAFE_RIGHT);
        }
        timer2++;
        if (timer2>600)
        {
            timer2=0;
        }
        }
[close]

Where do I put this juicy goodness in my weapons files? Add it as a missile? or to the weapon itself?
Logged
Spoiler

[close]

dmaiski

  • Captain
  • ****
  • Posts: 422
  • resistance is futile
    • View Profile
Re: The Radioactive Code Dump
« Reply #43 on: November 18, 2013, 08:44:50 AM »

Where do I put this juicy goodness in my weapons files? Add it as a missile? or to the weapon itself?

same way as previous, all missile ai use this unless otherwhise stated
Spoiler
to implement into a mod:
place the .java(ie code) file in the mod(does not mater where)
in mod plugin:
Code: (java)
view plaincopy to clipboardprint?

        public static final String LRPDai_MISSILE_ID = "SM_lrmPD_m";  //name of the missile that will use that AI 
        public static final String BOMBARDai_MISSILE_ID = "SM_SCbombard_m";//"" 
        @Override 
        public PluginPick pickMissileAI(MissileAPI missile,       //picks the ai 
                                        ShipAPI launchingShip) 
        { 
            if (LRPDai_MISSILE_ID.equals(missile.getProjectileSpecId()))     //missile 
            { 
                return new PluginPick(new LRPDai(missile), CampaignPlugin.PickPriority.MOD_SPECIFIC);     //Ai for that missile 
            } 
            if (BOMBARDai_MISSILE_ID.equals(missile.getProjectileSpecId()))     //another missile 
            { 
                return new PluginPick(new BOMBARDai(missile), CampaignPlugin.PickPriority.MOD_SPECIFIC);    //another ai 
            } 
            return null; 
        } 
[close]

you may need to tack it onto a target getter and misc wrapper from some of the missile AI that i have posted recently
(i have not gotten around to re-writing that one for it to be just a copy>paste implement job yet)
if you can wait till thursday ill probably have it done up by then, atm too much other stuff I am doing


on that note, MINEai
(makes mines that shoot projectiles or missiles in 360 deg ark)
basic components of other mirv type missile mounted weapon AI
a number of improvments and simplifications over old version
Spoiler
Code: java
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.AIUtils;
import org.lazywizard.lazylib.combat.CombatUtils;
import org.lwjgl.util.vector.Vector2f;

import java.awt.*;
import java.util.Iterator;
import java.util.List;

import static jar.UtilityKit.LeadVector;
import static org.lwjgl.util.vector.Vector2f.add;

public class MINEai implements MissileAIPlugin
{
    // Our missile object
    private final MissileAPI missile;

    private final float MaxDetRange=250;     //max range of the blast
    private final float MinDetRange=100;     //max range for best damage
    private final float SeperationRange=350; //seperation between mines

    public MINEai(MissileAPI missile)
    {
        this.missile = missile;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////


    //stuff
    float range1 = 0;
    float range2 = 0;
    boolean trigger = false;
    boolean deathcode = false;
    private IntervalUtil minetimer = new IntervalUtil(.1f, .11f);
    ShipAPI enemy=null;

    //////////////////////////////////////////////////////////////////////////////////////////////////////////

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////


    //main missile AI
    @Override
    public void advance(float amount)
    {

        ///////////////////////////////////////////////////////////////////////////////////////////////////////////

        //housekeeping stuff
        minetimer.advance(amount);                         //timer
        CombatEngineAPI engine = Global.getCombatEngine(); //engine

        // Apparently commands still work while fizzling
        if (missile.isFading() || missile.isFizzling())
        {
            return;
        }

        //missile location (used lots)
        Vector2f MLoc = missile.getLocation();

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////


        //intelligent distribution code
        MissileAPI near = AIUtils.getNearestMissile(missile);  //find the nearest missile to you

        if (near != null                                       //check if there are any nearby mines
                && near.getProjectileSpecId().equals(missile.getProjectileSpecId())    //is it same type as you
                && MathUtils.getDistance(near, MLoc) < SeperationRange)             //is it too close
        {
            //if true move away from them
            float angularDistance = getAngleDifference(       //find the missile relative direction
                    missile.getFacing(), MathUtils.getAngle(MLoc,
                    (near.getLocation())));
            if (Math.abs(angularDistance) < 175)             //facing towards it
            {
                missile.giveCommand(angularDistance < 0f
                        ? ShipCommand.TURN_LEFT : ShipCommand.TURN_RIGHT);   //turn away
            }
            if (Math.abs(angularDistance) > 135)                             //if facing away from it
            {
                missile.giveCommand(ShipCommand.ACCELERATE);                 //then move forwards
            }
            if (Math.abs(angularDistance) < 45)                              //facing towards it
            {
                missile.giveCommand(ShipCommand.ACCELERATE_BACKWARDS);       //then move backwards
            }
        }
        else    //if enough separation achieved
        {
            missile.giveCommand(ShipCommand.DECELERATE);              //mine dose not move
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////


        //enemy tracking code
        if (minetimer.intervalElapsed()) //run once every 3 frames to prevent fun stuff
        {
            /////////////////////////////////////////////////////////////////////////////////////////////////////////


            //new target aquisition
            //if you have no enemy, look for the nearest enemy
            if (enemy==null && AIUtils.getNearestEnemy(missile)!=null && AIUtils.getNearestEnemy(missile).isAlive())
            {
                //check its in range
                float targetfinder = MathUtils.getDistance(AIUtils.getNearestEnemy(missile), MLoc);
                if (targetfinder < 300)
                {
                    enemy=AIUtils.getNearestEnemy(missile);                //remember that enemy
                }
                if (targetfinder > 300)                                    //else restart
                {
                    return;
                }

            }

            /////////////////////////////////////////////////////////////////////////////////////////////////////////

            //once you have a target
            if (enemy != null)
            {
                //////////////////////////////////////////////////////////////////////////////////////////////////////


                //housekeeping/misc
                //check its the same enemy as previous
                if (enemy!=AIUtils.getNearestEnemy(missile))
                {
                    deathcode=true;      //if a second enemy comes closer then first
                    trigger=true;        //detonate
                }

                //check enemy has not died
                if (!enemy.isAlive() |  enemy.isHulk())
                {
                    enemy=null;      //if tracking enemy is dead, reset
                    range1=0;
                    deathcode=false;
                    trigger=false;
                }

                //////////////////////////////////////////////////////////////////////////////////////////////////////

                //rangetracker (part1)
                //tracks how close enemy is (predicts where the enemy will be next frame to get its motion)
                if (!deathcode && range1==0 && enemy!=null
                        && MathUtils.getDistance(enemy, MLoc)< MaxDetRange*.9f)  //find out if there are enemy in range
                {
                    range1 = MathUtils.getDistance(enemy, MLoc);     //store range to target
                }
            }

            //////////////////////////////////////////////////////////////////////////////////////////////////////


            if (!deathcode && range1!=0)    //for all grouped in here
            {
                //when enemy is close enough go boom
                if (range1<MinDetRange)
                {
                    trigger=true;       //make it go boom
                    deathcode=true;     //stop tracking
                }

                //////////////////////////////////////////////////////////////////////////////////////////////////////


                //rangetracker (cont)
                //find get the range to target now
                range2 = MathUtils.getDistance(enemy,MLoc);


                if (range1>range2)
                {
                    //predict its motion based on velocity
                    float range3 = MathUtils.getDistance(Vector2f.add(
                            enemy.getLocation(), multV2f(enemy.getVelocity(), .5f), null), // its velocity
                            MLoc)-enemy.getCollisionRadius();             //distance to missile

                    //compare new range to curent range
                    if (range1<range3)   //if it mover away explode
                    {
                        trigger=true;
                        deathcode=true;
                        return;
                    }
                    else {range1=range2;}               //store new target range, if it got closer
                }
                else//if its moving away
                {
                    trigger=true;       //make it go boom
                    deathcode=true;     //stop tracking
                }

                //if damaged below 90%hp while in range, detonate
                if (missile.getMaxHitpoints()*0.9>missile.getHitpoints())
                {
                    trigger=true;
                    deathcode=true;
                }
            }

            /////////////////////////////////////////////////////////////////////////////////////////////////////////////


            //explosion code
            if (trigger && MathUtils.getDistance(
                    missile,AIUtils.getNearestAlly(missile))>MaxDetRange*.8f)//don't blow up your own ships)
            {
                //for projectiles
                {
                    //dummy weapon  supports missiles and projectiles
                    //suggested projectile stats, range:1,  speed:1
                    String Projectile = "DUMMY1";
                    {
                        {
                            //spawn projectiles
                            int counts=0;
                            do {
                                float angRAND= (float) ((360*(.5-Math.random()))); //angle of spread
                                float speedRAND= (float) ((MaxDetRange-MinDetRange)*Math.random());//variance of speed
                                float PSpeed = MinDetRange+speedRAND;             //speed of bullets launched
                                float PAng = missile.getFacing()-angRAND;         //direction of fire
                                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(missile.getVelocity(), PVec, null); //true Pvec
                                engine.spawnProjectile(
                                        missile.getSource(),
                                        missile.getWeapon(),             //who made you
                                        Projectile,                      //spawn the projectile
                                        MLoc,                            //Vector2f firing origin point
                                        PAng,                            //float angle of fire
                                        PMVec);                          //Vector2f firing velocity

                                /////////////////////////////////////////////////////////////////////////////////////

                                counts++;


                                ////////////////////////////////////////////////////////////////////////////////
                                //optional explosion/particle glows
                                engine.addHitParticle(MLoc, PMVec,
                                        15f,1f,1f,new Color(112, 152, 137,255)); //size, alpha, duration, color
                                engine.spawnExplosion(MLoc, PMVec,
                                        new Color(255, 86, 13,255), 15f, 1f);  //color,size,duration(max)

                                //////////////////////////////////////////////////////////////////////////////////
                            }while (counts<100); //how many projectiles?
                        }
                    }
                    //////////////////////////////////////////////////////////////////////////////////

                    //main explosion flash
                    engine.addHitParticle(MLoc, missile.getVelocity(),MaxDetRange,1f,1f,new Color(255, 12, 25,255));

                    //////////////////////////////////////////////////////////////////////////////////

                    //to stop missile shooting again
                    engine.removeEntity(missile);   //make missile go poof
                    //missile.flameOut();               //make missile flame out
                    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;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
[close]
« Last Edit: November 18, 2013, 01:37:32 PM by dmaiski »
Logged
BISO
(WIP) lots of shiny new weapons ( :-[ i have more weapons then sprites :-[ )

i got a cat pad
its like a mouse pad but better!

etherealblade

  • Commander
  • ***
  • Posts: 134
    • View Profile
Re: The Radioactive Code Dump
« Reply #44 on: November 19, 2013, 11:10:27 PM »

Patience is a virtue I like to strive to live by. I'd be happy whenever your got around to it. 8D
Logged
Spoiler

[close]
Pages: 1 2 [3] 4 5 ... 10