001package com.fs.starfarer.api.impl.combat.threat; 002 003import java.util.ArrayList; 004import java.util.List; 005 006import org.lwjgl.util.vector.Vector2f; 007 008import com.fs.starfarer.api.Global; 009import com.fs.starfarer.api.combat.CombatEngineAPI; 010import com.fs.starfarer.api.combat.ShieldAPI; 011import com.fs.starfarer.api.combat.ShipAPI; 012import com.fs.starfarer.api.combat.ShipCommand; 013import com.fs.starfarer.api.combat.ShipSystemAIScript; 014import com.fs.starfarer.api.combat.ShipSystemAPI; 015import com.fs.starfarer.api.combat.ShipwideAIFlags; 016import com.fs.starfarer.api.combat.ShipwideAIFlags.AIFlags; 017import com.fs.starfarer.api.util.IntervalUtil; 018import com.fs.starfarer.api.util.Misc; 019import com.fs.starfarer.api.util.WeightedRandomPicker; 020 021 022public class EnergyLashSystemAI implements ShipSystemAIScript { 023 024 protected ShipAPI ship; 025 protected CombatEngineAPI engine; 026 protected ShipwideAIFlags flags; 027 protected ShipSystemAPI system; 028 protected EnergyLashSystemScript script; 029 030 protected IntervalUtil tracker = new IntervalUtil(0.5f, 1f); 031 032 public void init(ShipAPI ship, ShipSystemAPI system, ShipwideAIFlags flags, CombatEngineAPI engine) { 033 this.ship = ship; 034 this.flags = flags; 035 this.engine = engine; 036 this.system = system; 037 038 script = (EnergyLashSystemScript)system.getScript(); 039 } 040 041 public void advance(float amount, Vector2f missileDangerDir, Vector2f collisionDangerDir, ShipAPI target) { 042 tracker.advance(amount); 043 044 if (tracker.intervalElapsed()) { 045 if (system.getCooldownRemaining() > 0) return; 046 if (system.isOutOfAmmo()) return; 047 if (system.isActive()) return; 048 if (ship.getFluxTracker().isOverloadedOrVenting()) return; 049 050 ShipAPI pick = getWeightedTargets(target).getItemWithHighestWeight(); 051 if (pick != null) { 052 ship.getAIFlags().setFlag(AIFlags.CUSTOM1, 1.5f, pick); 053 ship.giveCommand(ShipCommand.USE_SYSTEM, null, 0); 054 //System.out.println("Lash target: " + pick); 055 } 056 } 057 } 058 059 public List<ShipAPI> getPossibleTargets() { 060 List<ShipAPI> result = new ArrayList<>(); 061 CombatEngineAPI engine = Global.getCombatEngine(); 062 063 List<ShipAPI> ships = engine.getShips(); 064 for (ShipAPI other : ships) { 065 if (other == ship) continue; 066 if (!script.isValidLashTarget(ship, other)) continue; 067 if (!script.isInRange(ship, other)) continue; 068 result.add(other); 069 } 070 return result; 071 } 072 073 public WeightedRandomPicker<ShipAPI> getWeightedTargets(ShipAPI shipTarget) { 074 WeightedRandomPicker<ShipAPI> picker = new WeightedRandomPicker<>(); 075 076 for (ShipAPI other : getPossibleTargets()) { 077 float w = 0f; 078 if (ship.getOwner() == other.getOwner()) { 079 if (ThreatSwarmAI.isAttackSwarm(other)) { 080 RoilingSwarmEffect swarm = RoilingSwarmEffect.getSwarmFor(other); 081 if (swarm != null && !VoltaicDischargeOnFireEffect.isSwarmPhaseMode(other)) { 082 w = 0.5f; 083 } else { 084 continue; 085 } 086 } else { 087 if (other.getSystem() == null) continue; 088 if (!(other.getSystem().getScript() instanceof EnergyLashActivatedSystem)) continue; 089 if (other.getSystem().getCooldownRemaining() > 0) continue; 090 if (other.getSystem().isActive()) continue; 091 if (other.getFluxTracker().isOverloadedOrVenting()) continue; 092 093 EnergyLashActivatedSystem otherSystem = (EnergyLashActivatedSystem) other.getSystem().getScript(); 094 w = otherSystem.getCurrentUsefulnessLevel(ship, other); 095 } 096// if (other.getSystem().getSpecAPI().hasTag(Tags.SHIP_SYSTEM_MOVEMENT)) { 097// } 098// if (other.getSystem().getSpecAPI().hasTag(Tags.SHIP_SYSTEM_OFFENSIVE)) { 099// Object test = ship.getAIFlags().getCustom(AIFlags.MANEUVER_TARGET); 100// if (test instanceof ShipAPI) { 101// ShipAPI otherTarget = (ShipAPI) test; 102// float dist = Misc.getDistance(other.getLocation(), otherTarget.getLocation()); 103// dist -= other.getCollisionRadius() + otherTarget.getCollisionRadius(); 104// if (dist < 1500f) { 105// } 106// } 107// } 108 } else { 109 ShieldAPI targetShield = other.getShield(); 110 boolean targetShieldsFacingUs = targetShield != null && 111 targetShield.isOn() && 112 Misc.isInArc(targetShield.getFacing(), Math.max(30f, targetShield.getActiveArc()), 113 other.getLocation(), ship.getLocation()); 114 if (targetShieldsFacingUs && EnergyLashSystemScript.DAMAGE <= 0) continue; 115 116 float dist = Misc.getDistance(ship.getLocation(), other.getLocation()); 117 dist -= ship.getCollisionRadius() + other.getCollisionRadius(); 118 if (dist < 0) dist = 0; 119 if (other == shipTarget) { 120 w += 0.25f; 121 } 122 if (dist < 1000f) { 123 w += (1f - (dist / 1000f)) * 0.5f; 124 } 125 if (other.isPhased()) { 126 w += 0.5f; 127 } 128 w += 0.01f; 129 } 130 picker.add(other, w); 131 } 132 return picker; 133 } 134 135} 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157