Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package data.scripts.ai;
- import com.fs.starfarer.api.Global;
- import com.fs.starfarer.api.combat.CombatEntityAPI;
- import com.fs.starfarer.api.combat.DamageType;
- import com.fs.starfarer.api.combat.GuidedMissileAI;
- import com.fs.starfarer.api.combat.MissileAIPlugin;
- import com.fs.starfarer.api.combat.MissileAPI;
- import com.fs.starfarer.api.combat.ShipAPI;
- import com.fs.starfarer.api.combat.ShipCommand;
- import com.fs.starfarer.api.util.IntervalUtil;
- import java.util.Collections;
- import java.util.List;
- import java.util.ListIterator;
- import org.lwjgl.util.vector.Vector2f;
- import org.lazywizard.lazylib.CollectionUtils;
- import org.lazywizard.lazylib.MathUtils;
- import org.lazywizard.lazylib.VectorUtils;
- import org.lazywizard.lazylib.combat.AIUtils;
- import org.lazywizard.lazylib.combat.CombatUtils;
- public class exigency_MMMAI2 implements MissileAIPlugin, GuidedMissileAI {
- private final static float SHIT_ACCURACY_RANGE = 300f;
- private final static float SHIT_ACCURACY_AMOUNT = 75f;
- // Time until self destructing
- private final static float FUSE_TIME = 10.5f;
- // Our missile object
- private final MissileAPI missile;
- // Our current target (can be null)
- private CombatEntityAPI target;
- private float offtarget;
- private float baseofftarget;
- private float lifetimer;
- private final float offsetAngle;
- private IntervalUtil timer = new IntervalUtil(0.1f, 0.2f);
- public static ShipAPI findBestTarget(MissileAPI missile) {
- ShipAPI source = missile.getSource();
- if (source != null && source.getShipTarget() != null && !source.getShipTarget().isHulk()) {
- return source.getShipTarget();
- }
- ShipAPI closest = null;
- float distance, closestDistance = Float.MAX_VALUE;
- for (ShipAPI tmp : AIUtils.getEnemiesOnMap(missile)) {
- distance = MathUtils.getDistance(tmp, missile.getLocation());
- if (distance < closestDistance) {
- closest = tmp;
- closestDistance = distance;
- }
- }
- return closest;
- }
- public exigency_MMMAI2(MissileAPI missile, ShipAPI launchingShip) {
- this.missile = missile;
- this.offtarget = 20f * (0.6f + 0.4f * (float) Math.random()); // Max initial off target (scatters missiles at launch)
- this.baseofftarget = 20f * (0.6f + 0.4f * (float) Math.random()); // Min off target (makes missiles stay scattered)
- if ((float) Math.random() > 0.5f) {
- this.offtarget *= -1f;
- this.baseofftarget *= -1f;
- }
- this.lifetimer = FUSE_TIME;
- this.offsetAngle = (float) Math.random() * 360f;
- // Support for 'fire at target by clicking on them' behavior
- List<ShipAPI> directTargets = CombatUtils.getShipsWithinRange(launchingShip.getMouseTarget(), 100f);
- if (!directTargets.isEmpty()) {
- Collections.sort(directTargets, new CollectionUtils.SortEntitiesByDistance(launchingShip.getMouseTarget()));
- ListIterator<ShipAPI> iter = directTargets.listIterator();
- while (iter.hasNext()) {
- ShipAPI tmp = iter.next();
- if (!tmp.isHulk() && tmp.getOwner() != launchingShip.getOwner()) {
- setTarget(tmp);
- break;
- }
- }
- }
- // Otherwise, use default MMMAI2 targeting AI
- if (target == null) {
- setTarget(findBestTarget(missile));
- }
- }
- @Override
- public void advance(float amount) {
- if (Global.getCombatEngine().isPaused()) {
- return;
- }
- lifetimer -= amount;
- if (lifetimer <= 0f) {
- Global.getCombatEngine().applyDamage(missile, missile.getLocation(), missile.getHitpoints(), DamageType.OTHER, 0, true, true, missile);
- return;
- }
- timer.advance(amount);
- // Apparently commands still work while fizzling
- if (missile.isFading() || missile.isFizzling()) {
- return;
- }
- // If our current target is lost, assign a new one
- if (target == null || (target instanceof ShipAPI && ((ShipAPI) target).isHulk()) || (missile.getOwner() == target.getOwner()) || !Global.getCombatEngine().isEntityInPlay(target)) {
- setTarget(findBestTarget(missile));
- missile.giveCommand(ShipCommand.ACCELERATE);
- return;
- }
- // Head towards the target, with tail chase guidance
- float distance = MathUtils.getDistance(missile.getLocation(), target.getLocation());
- float offset = 0f;
- if (distance <= SHIT_ACCURACY_RANGE) {
- offset = SHIT_ACCURACY_AMOUNT * (1f - distance / SHIT_ACCURACY_RANGE);
- }
- Vector2f guidedTarget = MathUtils.getPointOnCircumference(target.getLocation(), offset, offsetAngle);
- float angularDistance = MathUtils.getShortestRotation(missile.getFacing(), VectorUtils.getAngle(missile.getLocation(), guidedTarget));
- if (timer.intervalElapsed()) {
- offtarget = (offtarget > 0 ? offtarget - 1 : offtarget + 1); // Reduce off target counter
- }
- float offtargetby = (0f + (offtarget + (baseofftarget * target.getCollisionRadius() / 100f)));
- // Make it slightly more accurate as missile gets closer to target
- if (distance <= target.getCollisionRadius() * 2f) {
- offtargetby *= (distance - target.getCollisionRadius() * 1.5f) / target.getCollisionRadius() + 0.5f;
- }
- if (Math.abs(angularDistance) >= 70f || distance <= target.getCollisionRadius() * 1.5f) {
- missile.setAngularVelocity(angularDistance * 1.5f);
- offtargetby *= 0f;
- }
- float AbsAngD = Math.abs(angularDistance - offtargetby);
- // Point towards target
- if (AbsAngD > 0.5) {
- // Makes missile fly off target
- missile.giveCommand(angularDistance > offtargetby ? ShipCommand.TURN_LEFT : ShipCommand.TURN_RIGHT);
- }
- // Course correction
- if (AbsAngD < 5) {
- float MFlightAng = VectorUtils.getAngle(new Vector2f(0, 0), missile.getVelocity());
- float MFlightCC = MathUtils.getShortestRotation(missile.getFacing(), MFlightAng);
- if (Math.abs(MFlightCC) > 20) {
- missile.giveCommand(MFlightCC < 0 ? ShipCommand.STRAFE_LEFT : ShipCommand.STRAFE_RIGHT);
- }
- }
- // Accelerate if the target is within angle tolerances
- if (Math.abs(angularDistance) <= 90f) {
- missile.giveCommand(ShipCommand.ACCELERATE);
- }
- // Stop turning once missile is on target
- if (AbsAngD < 0.4) {
- missile.setAngularVelocity(0);
- }
- }
- @Override
- public CombatEntityAPI getTarget() {
- return target;
- }
- @Override
- public final void setTarget(CombatEntityAPI target) {
- this.target = target;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement