Fractal Softworks Forum

Please login or register.

Login with username, password and session length
Advanced search  

News:

Starsector 0.96a is out! (05/05/23); Blog post: Colony Crises (11/24/23)

Pages: [1] 2

Author Topic: Example Code Request: spawnEmpArc()  (Read 11529 times)

Nekora

  • Ensign
  • *
  • Posts: 28
    • View Profile
Example Code Request: spawnEmpArc()
« on: January 17, 2013, 12:13:31 PM »

Okay, simple request here, can someone make an example of a weapon useing the CombatEntityAPI spawnEmpArc(),

I cant code much but would love to see a lightining weapon (useing em effects but as a weapon not a subsystem).

Also, is it possible to call this from the BeamEffectPlugin or OnHitEffectPlugin? to make an arcing lightning gun or AOE emp bomb/missile/projectile? If so i would love to see examples of this.
Logged

EnderNerdcore

  • Commander
  • ***
  • Posts: 172
    • View Profile
Re: Example Code Request: spawnEmpArc()
« Reply #1 on: January 17, 2013, 12:24:46 PM »

Small correction but it's actually CombatEngineAPI which contains .spawnEmpArc.

You can actually see an example of how the tachyon lance uses this inside the starfarer.api.zip file in your starsector-core folder.

Look under com.fs.starfarer.api.impl.combat TachyonLanceEffect.java
Logged

silentstormpt

  • Admiral
  • *****
  • Posts: 1060
    • View Profile
Re: Example Code Request: spawnEmpArc()
« Reply #2 on: January 17, 2013, 01:12:04 PM »

So I was messing around with the new ability to spawn EMP arcs, and this happened:



Code
//Electrical Damage Plugin, by Psiyon
package data.scripts.plugins;

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

import org.lwjgl.input.Keyboard;
import org.lwjgl.util.vector.Vector2f;

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.EveryFrameCombatPlugin;
import com.fs.starfarer.api.combat.ShipAPI;
import com.fs.starfarer.api.input.InputEventAPI;
import com.fs.starfarer.api.mission.FleetSide;
import com.fs.starfarer.api.util.IntervalUtil;

public class TestCombatPlugin implements EveryFrameCombatPlugin {

/**
* Set this to true to have the plugin actually do stuff.
*/
private static boolean TEST_MODE = true;

private CombatEngineAPI engine;

public void init(CombatEngineAPI engine) {
this.engine = engine;
}



//Generates an interval between 0.5 and 3 seconds.
private IntervalUtil interval = new IntervalUtil(0.5f, 3f);
public void advance(float amount, List events) {
//Makes sure this code doesn't run if test mode is inactive, or if the game is paused.
if (!TEST_MODE) return;
if (engine.isPaused()) return;

//Advances the interval.
interval.advance(amount);

//When the interval has elapsed...
if (interval.intervalElapsed()) {

//cycles through all the ships in play.
List ships = engine.getAllShips();
Iterator it = ships.iterator();

//While there are still more ships to cycle through...
while (it.hasNext()) {
//loads the current ship the iterator is on into the object "ship"
ShipAPI ship = (ShipAPI) it.next();

//If the ship is disabled or is a fighter, we don't want to bother with arcs, so we'll start the loop over
if (ship.isHulk()) continue;
if (ship.isFighter()) continue;

//If the ship has less than an eigth of its HP
if (ship.getHitpoints() <= ship.getMaxHitpoints() / 8f) {
//Gets the center of the ship, needed for spawning the EMP arc.
Vector2f point = new Vector2f(ship.getLocation());

//This randomizes the point's x and y values a bit. Keep in mind, these are world coordinates, and are not relative to the ship.
//This means that the x and y values stored in point aren't always 0,0.
point.x += (ship.getCollisionRadius() / 2f) * (((float) Math.random() * 2f) - 1);
point.y += (ship.getCollisionRadius() / 2f) * (((float) Math.random() * 2f) - 1);

//spawns the arc.
engine.spawnEmpArc(ship, point, ship, ship,
   DamageType.ENERGY,
   0f,
   0f, // emp
   100000f, // max range
   "hit_shield_beam_loop", //Just used a blank sound ID so it'll work with anything.
   12f, // thickness
   new Color(155,100,25,255),
   new Color(255,255,255,255)
   );
   
}

}

}
}
}


Heavily commented so those not very programming-inclined can easily understand.

The plugin is pretty simple: when a ship goes below an eighth of its HP, random EMP arcs will spawn around the ship, creating a cool-looking electrical damage effect.

If you wanted you could totally make it do damage, and even make a healing beam weapon to reverse the ship's continual damage. This new update has a ton of amazing possibilities.

Feel free to use or modify in any way you wish.



And while I'm at it, Alex (or anyone who knows), do onHitEffect scripts work for missiles too? Or is it only projectiles? Because I can't seem to get my EMP-arc spamming missiles to work, though the script works fine when I add it to a normal weapon.
Logged

LazyWizard

  • Global Moderator
  • Admiral
  • *****
  • Posts: 1362
    • View Profile
    • GitHub Profile
Re: Example Code Request: spawnEmpArc()
« Reply #3 on: January 17, 2013, 01:21:11 PM »

I'm working on a chain lightning example. I'll post the code here when I'm finished. :)
Logged

Nekora

  • Ensign
  • *
  • Posts: 28
    • View Profile
Re: Example Code Request: spawnEmpArc()
« Reply #4 on: January 17, 2013, 01:29:59 PM »

TachyonLanceEffect.java was usefull, as was Combat Engine API, Where i found this little gem
Code
* @param empTargetEntity Target of the EMP arc. If it's a ship, it will randomly pick an engine nozzle/weapon to arc to.
Can also pass in a custom class implementing CombatEntityAPI to visually target the EMP at a specific location (and not do any damage).

the Tachyon lance passes the target ship "beam.getDamageTarget()" as the EMP target to keep the emp bouncing around the ship, (as does the code Psiyon posted) but anyone know a way to pick a random target that is not the beam.getDamageTarget() to set as the emparc target?
Logged

Nekora

  • Ensign
  • *
  • Posts: 28
    • View Profile
Re: Example Code Request: spawnEmpArc()
« Reply #5 on: January 17, 2013, 01:30:54 PM »

I'm working on a chain lightning example. I'll post the code here when I'm finished. :)

Awesome.
Logged

EnderNerdcore

  • Commander
  • ***
  • Posts: 172
    • View Profile
Re: Example Code Request: spawnEmpArc()
« Reply #6 on: January 17, 2013, 01:33:14 PM »

the Tachyon lance passes the target ship "beam.getDamageTarget()" as the EMP target to keep the emp bouncing around the ship, (as does the code Psiyon posted) but anyone know a way to pick a random target that is not the beam.getDamageTarget() to set as the emparc target?
Yes. You'll need to get a list of all ships, make a list of all the ones within whatever range you want, and then pick one at random to arc to.
Logged

Nekora

  • Ensign
  • *
  • Posts: 28
    • View Profile
Re: Example Code Request: spawnEmpArc()
« Reply #7 on: January 17, 2013, 01:41:18 PM »

ah, so useing a function similar to the one psion did in his efffects?
Code
		List ships = engine.getAllShips();	
Iterator it = ships.iterator();
while (it.hasNext()) {
//* range checking here, pass inrantge ships into a Target vairable
}

Also it occours to me, to make a beamweapon with a lightning emp effect, couldnt we make an invisible beam weapon and give it the emp effect, but set the spawn point of the emp effect to the beam weapon emmitter? heck even haveing a faint beam that carrys the lightning would look cool. sort of like an ion beam that carrys the electric charge from your ship to the target so the lightning only shows when there is a valid target for the electricity to ground itself to (ie the beam hits something)... hmm, will have to check how to pull the emmiter location from the beam as that would look epic.

Edit: wait, is it as simple as beam.getFrom()? gona test this
« Last Edit: January 17, 2013, 01:46:37 PM by Nekora »
Logged

Hyph_K31

  • Admiral
  • *****
  • Posts: 1605
  • O' Hear My Name and Tremble! Ug Ug.
    • View Profile
Re: Example Code Request: spawnEmpArc()
« Reply #8 on: January 17, 2013, 01:51:19 PM »

Oooh. if you can make this, would you mind if I used it in my mod?
Logged

"GEDUNE, stop venting in front of your classmates!"

LazyWizard

  • Global Moderator
  • Admiral
  • *****
  • Posts: 1362
    • View Profile
    • GitHub Profile
Re: Example Code Request: spawnEmpArc()
« Reply #9 on: January 17, 2013, 03:04:13 PM »

Here's the code for a beam that creates a chain lightning effect. I tried to keep it easy to customize. :)

Oooh. if you can make this, would you mind if I used it in my mod?

If this was addressed to me: all code I write is free for anyone to use, no attribution necessary (with the exception of things I write for other mod authors, in which case you should ask them first). :)

Code
package data.scripts.weapons;

import com.fs.starfarer.api.combat.BeamAPI;
import com.fs.starfarer.api.combat.BeamEffectPlugin;
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.ShipAPI;
import com.fs.starfarer.api.util.IntervalUtil;
import java.awt.Color;
import java.util.*;
import org.lwjgl.util.vector.Vector2f;

public class ChainLightningEffect implements BeamEffectPlugin
{
    // If true, don't hit the same ship twice in the same burst
    private static final boolean IGNORE_SAME_SHIP_IN_BURST = true;
    // If true, pick a random enemy in range to be the next link in the chain
    private static final boolean PICK_RANDOM_ENEMY_IN_RANGE = false;
    // How long must the beam be fired for before it will start a second chain?
    private static final float TIME_BETWEEN_BURSTS = .3f;
    // How far can the initial chain travel to hit an enemy?
    private static final float INITIAL_CHAIN_RANGE = 1000f;
    // How much of its previous max length will each chain retain?
    private static final float RANGE_RETENTION_PER_CHAIN = .75f;
    // How much damage will each chain do, compared to the previous?
    private static final float DAMAGE_RETENTION_PER_CHAIN = .85f;
    // How many chains should we limit the weapon to generating?
    private static final int MAXIMUM_CHAINS_PER_BURST = 5;
    // What color is the core of the arc?
    private static final Color CORE_COLOR = new Color(255, 255, 255, 255);
    // What color is the fringe of the arc?
    private static final Color FRINGE_COLOR = new Color(85, 25, 215, 255);
    private IntervalUtil fireInterval = new IntervalUtil(TIME_BETWEEN_BURSTS, TIME_BETWEEN_BURSTS);

    private static float getDistance(Vector2f point1, Vector2f point2)
    {
        return (float) Math.hypot(point1.x - point2.x, point1.y - point2.y);
    }

    private static List getEnemiesInRange(CombatEntityAPI ship, float range,
            int side, CombatEngineAPI engine)
    {
        List enemies = new ArrayList(), allShips = engine.getShips();
        ShipAPI tmp;

        // Iterate through all ships on the battlefield
        for (int x = 0; x < allShips.size(); x++)
        {
            tmp = (ShipAPI) allShips.get(x);

            // Filter through and find active enemies that are within range
            if (!tmp.isHulk() && !tmp.isShuttlePod() && ship.getOwner() != side
                    && getDistance(ship.getLocation(), tmp.getLocation()) <= range)
            {
                enemies.add(tmp);
            }
        }

        return enemies;
    }

    @Override
    public void advance(float amount, CombatEngineAPI engine, BeamAPI beam)
    {
        CombatEntityAPI target = beam.getDamageTarget();

        // Check that we hit something and that it wasn't a shield hit
        if (target != null && target instanceof ShipAPI
                && (target.getShield() == null || !target.getShield().isWithinArc(beam.getTo())))
        {
            if (beam.getBrightness() >= 1f)
            {
                fireInterval.advance(amount);
                if (fireInterval.intervalElapsed())
                {
                    // Count how many links are in the chain so far
                    int numStrikes = 0;

                    // Source of the current lightning chain
                    Vector2f source = beam.getFrom();
                    // Victim of the current lightning chain
                    CombatEntityAPI currentVictim = target;

                    float range = INITIAL_CHAIN_RANGE;
                    // Ensure we keep the same DPS as listed in the weapon's stats tooltip
                    float damage = beam.getWeapon().getDerivedStats().getDps()
                            * beam.getSource().getMutableStats().getBeamWeaponDamageMult().getModifiedValue()
                            * TIME_BETWEEN_BURSTS;
                    float emp = beam.getWeapon().getDerivedStats().getEmpPerSecond()
                            * TIME_BETWEEN_BURSTS;

                    // This is used to prevent hitting the same target twice
                    // if IGNORE_SAME_SHIP_IN_BURST is set to true
                    Set struck = new HashSet();

                    do
                    {
                        // Spawn this chain's lightning arc
                        engine.spawnEmpArc(beam.getSource(), source,
                                currentVictim, currentVictim,
                                DamageType.ENERGY, damage, emp, 100000f,
                                "tachyon_lance_emp_impact", 15f,
                                FRINGE_COLOR, CORE_COLOR);

                        // Check that we haven't hit our chain limit
                        if (++numStrikes >= MAXIMUM_CHAINS_PER_BURST)
                        {
                            return;
                        }

                        // Reduce the stats of the next chain
                        range *= RANGE_RETENTION_PER_CHAIN;
                        damage *= DAMAGE_RETENTION_PER_CHAIN;
                        emp *= DAMAGE_RETENTION_PER_CHAIN;

                        // Find our next victim
                        source = currentVictim.getLocation();
                        List enemies = getEnemiesInRange(currentVictim, range,
                                beam.getSource().getOwner(), engine);
                        enemies.remove(currentVictim);

                        // Remove enemies that have already been struck once
                        // (only if IGNORE_SAME_SHIP_IN_BURST is true)
                        if (IGNORE_SAME_SHIP_IN_BURST)
                        {
                            struck.add(currentVictim);
                            enemies.removeAll(struck);
                        }

                        // Remove enemies who would block or avoid a strike
                        ShipAPI tmp;
                        for (Iterator iter = enemies.iterator(); iter.hasNext();)
                        {
                            tmp = (ShipAPI) iter.next();
                            if ((tmp.getShield() != null && tmp.getShield().isOn()
                                    && tmp.getShield().isWithinArc(source))
                                    || (tmp.getPhaseCloak() != null
                                    && tmp.getPhaseCloak().isActive()))
                            {
                                iter.remove();
                            }
                        }

                        // Pick a random valid enemy in range
                        if (!enemies.isEmpty())
                        {
                            if (PICK_RANDOM_ENEMY_IN_RANGE)
                            {
                                currentVictim = (ShipAPI) enemies.get((int) (Math.random() * enemies.size()));
                            }
                            else
                            {
                                ShipAPI closest = null;
                                float distance, closestDistance = Float.MAX_VALUE;

                                // Find the closest enemy in range
                                for (int x = 0; x < enemies.size(); x++)
                                {
                                    tmp = (ShipAPI) enemies.get(x);

                                    distance = getDistance(tmp.getLocation(),
                                            currentVictim.getLocation());

                                    // This ship is closer than the previous best
                                    if (distance < closestDistance)
                                    {
                                        closest = tmp;
                                        closestDistance = distance;
                                    }
                                }

                                currentVictim = closest;
                            }
                            // No enemies in range, end the chain
                        }
                        else
                        {
                            currentVictim = null;
                        }
                    }
                    while (currentVictim != null);
                }
            }
        }
    }
}

Edit: Fixed bugs where it would try to strike phased ships and avoided shielded ships with their shields off.
Edit 2: Lightning now arcs to the closest enemy (or optionally to a random enemy in range)
« Last Edit: January 17, 2013, 04:41:49 PM by LazyWizard »
Logged

silentstormpt

  • Admiral
  • *****
  • Posts: 1060
    • View Profile
Re: Example Code Request: spawnEmpArc()
« Reply #10 on: January 17, 2013, 03:35:14 PM »

Now, to make this into a Beastbeam and infect other ships  8)
Logged

Nekora

  • Ensign
  • *
  • Posts: 28
    • View Profile
Re: Example Code Request: spawnEmpArc()
« Reply #11 on: January 17, 2013, 04:44:44 PM »

Here's the code for a beam that creates a chain lightning effect. I tried to keep it easy to customize. :)

Thanks for the quick work there, however when i try to implement this i keep getting an obscure error, obviously im doing something wrong. Ive done a quick search but couldnt find a guide on how to add custom weapon effects to a mod, So i need to compile this to a class file and add it to the api Jar?
Logged

LazyWizard

  • Global Moderator
  • Admiral
  • *****
  • Posts: 1362
    • View Profile
    • GitHub Profile
Re: Example Code Request: spawnEmpArc()
« Reply #12 on: January 17, 2013, 04:50:11 PM »

Here's the code for a beam that creates a chain lightning effect. I tried to keep it easy to customize. :)

Thanks for the quick work there, however when i try to implement this i keep getting an obscure error, obviously im doing something wrong. Ive done a quick search but couldnt find a guide on how to add custom weapon effects to a mod, So i need to compile this to a class file and add it to the api Jar?

Just save the code I posted as ChainLightningEffect.java in the data/scripts/weapons/ folder. Then open the weapon file of the beam you want to use this effect and add this line:
Code
"beamEffect":"data.scripts.weapons.ChainLightningEffect",
Logged

Nekora

  • Ensign
  • *
  • Posts: 28
    • View Profile
Re: Example Code Request: spawnEmpArc()
« Reply #13 on: January 17, 2013, 05:08:25 PM »

Just save the code I posted as ChainLightningEffect.java in the data/scripts/weapons/ folder. Then open the weapon file of the beam you want to use this effect and add this line:
Code
"beamEffect":"data.scripts.weapons.ChainLightningEffect",

would you beleve i had / instead of . in the effect refrence field >_< thank, i have no idea why i made that mistake.
Logged

Hyph_K31

  • Admiral
  • *****
  • Posts: 1605
  • O' Hear My Name and Tremble! Ug Ug.
    • View Profile
Re: Example Code Request: spawnEmpArc()
« Reply #14 on: January 17, 2013, 10:27:57 PM »

It was the idea of using a beam to carry an EMP arc that got my attention, because that would suit a weapon in my mod perfectly.

Also it occours to me, to make a beamweapon with a lightning emp effect, couldnt we make an invisible beam weapon and give it the emp effect, but set the spawn point of the emp effect to the beam weapon emmitter? heck even haveing a faint beam that carrys the lightning would look cool. sort of like an ion beam that carrys the electric charge from your ship to the target so the lightning only shows when there is a valid target for the electricity to ground itself to (ie the beam hits something)... hmm, will have to check how to pull the emmiter location from the beam as that would look epic.

Edit: wait, is it as simple as beam.getFrom()? gona test this
Logged

"GEDUNE, stop venting in front of your classmates!"
Pages: [1] 2