Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package data.scripts.plugins;
- import com.fs.starfarer.api.Global;
- import com.fs.starfarer.api.combat.BaseEveryFrameCombatPlugin;
- import com.fs.starfarer.api.combat.CollisionClass;
- 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.ShieldAPI;
- import com.fs.starfarer.api.combat.ShipAPI;
- import com.fs.starfarer.api.input.InputEventAPI;
- import data.scripts.util.tiandong_Twig;
- import java.awt.Color;
- import java.util.ArrayList;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.Set;
- import org.dark.shaders.light.LightShader;
- import org.dark.shaders.light.StandardLight;
- import org.lazywizard.lazylib.CollisionUtils;
- import org.lazywizard.lazylib.MathUtils;
- import org.lazywizard.lazylib.VectorUtils;
- import org.lazywizard.lazylib.combat.CombatUtils;
- import org.lwjgl.util.vector.Vector2f;
- public class tiandong_WeaponPlugin extends BaseEveryFrameCombatPlugin
- {
- private static final float BURST_FLAK_AREA_DAMAGE = 80f;
- private static final float BURST_FLAK_AREA_EFFECT = 75f;
- private static final float BURST_FLAK_AREA_EFFECT_INNER = 50f;
- private static final float BURST_FLAK_AREA_FORCE = 10f;
- private static final Color BURST_FLAK_COLOR_CORE = new Color(255, 155, 155, 255);
- private static final Color BURST_FLAK_COLOR_PARTICLE = new Color(255, 155, 155, 255);
- private static final float BURST_FLAK_FLASH_DURATION = 0.2f;
- private static final float BURST_FLAK_FUSE_RANGE = 50f;
- private static final String BURST_FLAK_PROJECTILE_ID = "tiandong_burstflak_shot";
- private static final String BURST_FLAK_SOUND_ID = "tiandong_burstflakcannon_explosion";
- private static final String FLARE_PROJECTILE_ID = "tiandong_bulwarkCountermeasure";
- private static final float VISUAL_RADIUS = 150f;
- private static final float INNER_VISUAL_RADIUS = 50f;
- private static final float LOOK_AHEAD_TIME = 0.067f; // Extrapolate projectile position for this long in look-ahead for collisions
- private static final Vector2f ZERO = new Vector2f();
- private final Set<DamagingProjectileAPI> DO_NOT_EXPLODE = new HashSet<>();
- public static void burstFlakExplode(DamagingProjectileAPI projectile, Vector2f point, CombatEngineAPI engine)
- {
- if (point == null)
- {
- return;
- }
- tiandong_EffectsHook.createFlakShockwave(point);
- engine.addHitParticle(point, ZERO, INNER_VISUAL_RADIUS, 1f, BURST_FLAK_FLASH_DURATION, Color.WHITE);
- engine.addHitParticle(point, ZERO, VISUAL_RADIUS, 0.4f, 0.6f, BURST_FLAK_COLOR_CORE);
- Vector2f vel = new Vector2f();
- for (int i = 0; i < 30; i++)
- {
- vel.set(((float) Math.random() * 1.25f + 0.25f) * VISUAL_RADIUS, 0f);
- VectorUtils.rotate(vel, (float) Math.random() * 360f, vel);
- engine.addSmoothParticle(projectile.getLocation(), vel, (float) Math.random() * 2.5f + 2.5f, 1f,
- (float) Math.random() * 0.3f + 0.6f, BURST_FLAK_COLOR_PARTICLE);
- }
- StandardLight light = new StandardLight(projectile.getLocation(), ZERO, ZERO, null);
- light.setColor(BURST_FLAK_COLOR_CORE);
- light.setSize(VISUAL_RADIUS * 1.1f);
- light.setIntensity(0.15f);
- light.fadeOut(0.2f);
- LightShader.addLight(light);
- Global.getSoundPlayer().playSound(BURST_FLAK_SOUND_ID, 1f, 1f, point, projectile.getVelocity());
- List<ShipAPI> ships = CombatUtils.getShipsWithinRange(point, BURST_FLAK_AREA_EFFECT);
- List<CombatEntityAPI> targets = CombatUtils.getAsteroidsWithinRange(point, BURST_FLAK_AREA_EFFECT);
- targets.addAll(CombatUtils.getMissilesWithinRange(point, BURST_FLAK_AREA_EFFECT));
- Iterator<ShipAPI> iter = ships.iterator();
- while (iter.hasNext())
- {
- ShipAPI ship = iter.next();
- if (ship.getCollisionClass() == CollisionClass.NONE)
- {
- iter.remove();
- continue;
- }
- if (!ship.isFighter() && !ship.isDrone())
- {
- continue;
- }
- boolean remove = false;
- for (ShipAPI shp : ships)
- {
- if (shp.getShield() != null && shp != ship)
- {
- if (shp.getShield().isWithinArc(ship.getLocation()) && shp.getShield().isOn()
- && MathUtils.getDistance(ship.getLocation(), shp.getShield().getLocation()) <= shp.getShield().getRadius())
- {
- remove = true;
- }
- }
- }
- if (remove)
- {
- iter.remove();
- }
- }
- ships = tiandong_Twig.getSortedAreaList(point, ships);
- targets.addAll(ships);
- for (CombatEntityAPI tgt : targets)
- {
- /* No friendly fire for flak */
- if (tgt.getOwner() == projectile.getOwner())
- {
- continue;
- }
- float distance = tiandong_Twig.getActualDistance(point, tgt, true);
- float reduction = 1f;
- if (distance > BURST_FLAK_AREA_EFFECT_INNER)
- {
- reduction = (BURST_FLAK_AREA_EFFECT - distance) / (BURST_FLAK_AREA_EFFECT - BURST_FLAK_AREA_EFFECT_INNER);
- }
- if (reduction <= 0f)
- {
- continue;
- }
- boolean shieldHit = false;
- if (tgt instanceof ShipAPI)
- {
- ShipAPI ship = (ShipAPI) tgt;
- if (ship.getShield() != null && ship.getShield().isWithinArc(point))
- {
- shieldHit = true;
- }
- }
- Vector2f damagePoint;
- if (shieldHit)
- {
- ShipAPI ship = (ShipAPI) tgt;
- damagePoint = MathUtils.getPointOnCircumference(null, ship.getShield().getRadius(), VectorUtils.getAngle(ship.getShield().getLocation(), point));
- Vector2f.add(damagePoint, tgt.getLocation(), damagePoint);
- }
- else
- {
- Vector2f projection = VectorUtils.getDirectionalVector(point, tgt.getLocation());
- projection.scale(tgt.getCollisionRadius());
- Vector2f.add(projection, tgt.getLocation(), projection);
- damagePoint = CollisionUtils.getCollisionPoint(point, projection, tgt);
- }
- if (damagePoint == null)
- {
- damagePoint = point;
- }
- engine.applyDamage(tgt, damagePoint, BURST_FLAK_AREA_DAMAGE * reduction, DamageType.FRAGMENTATION, 0f, false, false, projectile.getSource());
- /* Force on projectiles is a little OP for a PD weapon */
- if (!(tgt instanceof DamagingProjectileAPI))
- {
- if (tgt instanceof ShipAPI)
- {
- CombatUtils.applyForce(tiandong_Twig.getRoot((ShipAPI) tgt), VectorUtils.getAngle(point, tgt.getLocation()), BURST_FLAK_AREA_FORCE * reduction);
- }
- else
- {
- CombatUtils.applyForce(tgt, VectorUtils.getAngle(point, tgt.getLocation()), BURST_FLAK_AREA_FORCE * reduction);
- }
- }
- }
- /* Don't want it exploding multiple times, do we? Also cleans up the look of it */
- engine.removeEntity(projectile);
- }
- private CombatEngineAPI engine;
- @Override
- public void advance(float amount, List<InputEventAPI> events)
- {
- if (engine == null)
- {
- return;
- }
- if (engine.isPaused())
- {
- return;
- }
- List<DamagingProjectileAPI> projectiles = engine.getProjectiles();
- /* Clean up do-not-explode set of projectiles as needed */
- List<DamagingProjectileAPI> toRemove = new ArrayList<>();
- for (DamagingProjectileAPI proj : DO_NOT_EXPLODE)
- {
- if (!projectiles.contains(proj)) // No longer exists
- {
- toRemove.add(proj);
- }
- }
- DO_NOT_EXPLODE.removeAll(toRemove);
- int size = projectiles.size();
- for (int i = 0; i < size; i++)
- {
- DamagingProjectileAPI proj = projectiles.get(i);
- String spec = proj.getProjectileSpecId();
- Vector2f loc = proj.getLocation();
- if (spec == null)
- {
- continue;
- }
- switch (spec)
- {
- case BURST_FLAK_PROJECTILE_ID:
- case FLARE_PROJECTILE_ID:
- {
- /* If the projectile already collided with something it's none of our business */
- if (proj.didDamage())
- {
- break;
- }
- if (DO_NOT_EXPLODE.contains(proj))
- {
- break;
- }
- List<CombatEntityAPI> targets = new LinkedList<>();
- List<CombatEntityAPI> asteroids = CombatUtils.getAsteroidsWithinRange(loc, BURST_FLAK_FUSE_RANGE);
- targets.addAll(CombatUtils.getMissilesWithinRange(loc, BURST_FLAK_FUSE_RANGE));
- targets.addAll(CombatUtils.getShipsWithinRange(loc, BURST_FLAK_FUSE_RANGE));
- targets.addAll(asteroids);
- for (CombatEntityAPI target : targets)
- {
- if (target.getCollisionClass() == CollisionClass.NONE)
- {
- continue;
- }
- if (target == proj.getSource()) // No collision checks with own (firing) ship
- {
- continue;
- }
- if (target.getOwner() == proj.getOwner())
- {
- // Don't check friendly projectiles for disarming / proximity fuse
- if (target instanceof DamagingProjectileAPI)
- {
- continue;
- }
- // ... or friendly fighters and drones
- else if (target instanceof ShipAPI)
- {
- ShipAPI ship = (ShipAPI)target;
- if ((ship.isFighter() || ship.isDrone()) && ship.isAlive())
- {
- continue;
- }
- }
- }
- /* Are we about to run into a shield? */
- if (target.getShield() != null)
- {
- Vector2f ahead = new Vector2f(loc).translate(proj.getVelocity().getX() * LOOK_AHEAD_TIME,
- proj.getVelocity().getY() * LOOK_AHEAD_TIME);
- ShieldAPI shield = target.getShield();
- if (CollisionUtils.getCollides(loc, ahead, shield.getLocation(), shield.getRadius())
- && shield.isWithinArc(ahead)) // Yes, we are
- {
- if (target.getOwner() == proj.getOwner() || target.getOwner() > 1) // Neutral or friendly shield, disarm
- {
- DO_NOT_EXPLODE.add(proj);
- }
- else // Hostile shield, blow up
- {
- DO_NOT_EXPLODE.add(proj);
- tiandong_WeaponPlugin.burstFlakExplode(proj, loc, engine);
- }
- break;
- }
- }
- /* Handle any neutral or friendly things we're likely to run into if we've started fading out,
- this prevents double hits where we do direct hit damage *and* explode */
- if ((target.getOwner() == proj.getOwner() || target.getOwner() > 1))
- {
- float distance = tiandong_Twig.getActualDistance(loc, target, true);
- if ((distance <= BURST_FLAK_FUSE_RANGE))
- {
- // Look-ahead hax
- // If we'll impact a neutral or friendly target in 0.067 seconds, deactivate warhead
- Vector2f ahead = new Vector2f(loc).translate(proj.getVelocity().getX() * LOOK_AHEAD_TIME,
- proj.getVelocity().getY() * LOOK_AHEAD_TIME);
- if (CollisionUtils.getCollisionPoint(loc, ahead, target) != null)
- {
- DO_NOT_EXPLODE.add(proj);
- break;
- }
- }
- }
- /* Don't proximity fuse on asteroids, don't even bother checking them */
- if (asteroids.contains(target))
- {
- continue;
- }
- /* Don't explode on neutrals or allies -- unless the projectile is neutral, in which case everything is fair game */
- if ((proj.getOwner() == 0) && (target.getOwner() != 1))
- {
- continue;
- }
- if ((proj.getOwner() == 1) && (target.getOwner() != 0))
- {
- continue;
- }
- /* Check for targets in range */
- float distance = tiandong_Twig.getActualDistance(loc, target, true);
- if ((distance <= BURST_FLAK_FUSE_RANGE))
- {
- DO_NOT_EXPLODE.add(proj);
- tiandong_WeaponPlugin.burstFlakExplode(proj, loc, engine);
- break;
- }
- }
- /* Detonate at the end-of-life, like real flak */
- if (proj.isFading() && !DO_NOT_EXPLODE.contains(proj))
- {
- DO_NOT_EXPLODE.add(proj);
- tiandong_WeaponPlugin.burstFlakExplode(proj, loc, engine);
- break;
- }
- break;
- }
- default:
- }
- }
- }
- @Override
- public void init(CombatEngineAPI engine)
- {
- this.engine = engine;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement