1package com.fs.starfarer.api.impl.combat;
6import org.lwjgl.util.vector.Vector2f;
8import com.fs.starfarer.api.Global;
9import com.fs.starfarer.api.combat.BaseEveryFrameCombatPlugin;
10import com.fs.starfarer.api.combat.CombatEngineAPI;
11import com.fs.starfarer.api.combat.CombatEntityAPI;
12import com.fs.starfarer.api.combat.EveryFrameCombatPlugin;
13import com.fs.starfarer.api.combat.MissileAPI;
14import com.fs.starfarer.api.combat.MutableShipStatsAPI;
15import com.fs.starfarer.api.combat.ShipAPI;
16import com.fs.starfarer.api.combat.ShipSystemAPI;
17import com.fs.starfarer.api.combat.ShipSystemAPI.SystemState;
18import com.fs.starfarer.api.combat.ShipwideAIFlags.AIFlags;
19import com.fs.starfarer.api.combat.WeaponAPI.WeaponType;
20import com.fs.starfarer.api.input.InputEventAPI;
21import com.fs.starfarer.api.util.Misc;
22import com.fs.starfarer.api.util.WeightedRandomPicker;
33 public static final Color
JITTER_COLOR =
new Color(255,155,255,75);
39 return ship.getMutableStats().getSystemRangeBonus().computeEffective(
MINE_RANGE);
42 public void apply(MutableShipStatsAPI stats, String
id, State state,
float effectLevel) {
45 if (stats.getEntity() instanceof ShipAPI) {
46 ship = (ShipAPI) stats.getEntity();
52 float jitterLevel = effectLevel;
53 if (state == State.OUT) {
54 jitterLevel *= jitterLevel;
56 float maxRangeBonus = 25f;
57 float jitterRangeBonus = jitterLevel * maxRangeBonus;
58 if (state == State.OUT) {
61 ship.setJitterUnder(
this,
JITTER_UNDER_COLOR, jitterLevel, 11, 0f, 3f + jitterRangeBonus);
62 ship.setJitter(
this,
JITTER_COLOR, jitterLevel, 4, 0f, 0 + jitterRangeBonus);
64 if (state == State.IN) {
65 }
else if (effectLevel >= 1) {
66 Vector2f target = ship.getMouseTarget();
67 if (ship.getShipAI() !=
null && ship.getAIFlags().hasFlag(AIFlags.SYSTEM_TARGET_COORDS)){
68 target = (Vector2f) ship.getAIFlags().getCustom(AIFlags.SYSTEM_TARGET_COORDS);
71 float dist = Misc.getDistance(ship.getLocation(), target);
72 float max =
getMaxRange(ship) + ship.getCollisionRadius();
74 float dir = Misc.getAngleInDegrees(ship.getLocation(), target);
75 target = Misc.getUnitVectorAtDegreeAngle(dir);
77 Vector2f.add(target, ship.getLocation(), target);
80 target = findClearLocation(ship, target);
87 }
else if (state == State.OUT ) {
92 public void unapply(MutableShipStatsAPI stats, String
id) {
95 public void spawnMine(ShipAPI source, Vector2f mineLoc) {
97 Vector2f currLoc = Misc.getPointAtRadius(mineLoc, 30f + (
float) Math.random() * 30f);
99 float start = (float) Math.random() * 360f;
100 for (
float angle = start; angle < start + 390; angle += 30f) {
101 if (angle != start) {
102 Vector2f loc = Misc.getUnitVectorAtDegreeAngle(angle);
103 loc.scale(50f + (
float) Math.random() * 30f);
104 currLoc = Vector2f.add(mineLoc, loc,
new Vector2f());
107 if (!other.isMine())
continue;
109 float dist = Misc.getDistance(currLoc, other.getLocation());
110 if (dist < other.getCollisionRadius() + 40f) {
115 if (currLoc !=
null) {
119 if (currLoc ==
null) {
120 currLoc = Misc.getPointAtRadius(mineLoc, 30f + (
float) Math.random() * 30f);
126 MissileAPI mine = (MissileAPI) engine.spawnProjectile(source,
null,
129 (
float) Math.random() * 360f,
null);
130 if (source !=
null) {
132 source, WeaponType.MISSILE,
false, mine.getDamage());
138 float fadeInTime = 0.5f;
139 mine.getVelocity().scale(0);
140 mine.fadeOutThenIn(fadeInTime);
147 mine.setFlightTime(mine.getMaxFlightTime() - liveTime);
153 return new BaseEveryFrameCombatPlugin() {
156 public void advance(
float amount, List<InputEventAPI> events) {
161 float jitterLevel = mine.getCurrentBaseAlpha();
162 if (jitterLevel < 0.5f) {
165 jitterLevel = (1f - jitterLevel) * 2f;
168 float jitterRange = 1f - mine.getCurrentBaseAlpha();
170 float maxRangeBonus = 50f;
171 float jitterRangeBonus = jitterRange * maxRangeBonus;
173 c = Misc.setAlpha(c, 70);
175 mine.setJitter(
this, c, jitterLevel, 15, jitterRangeBonus * 0, jitterRangeBonus);
177 if (jitterLevel >= 1 || elapsed > fadeInTime) {
192 if (system.isOutOfAmmo())
return null;
193 if (system.getState() != SystemState.IDLE)
return null;
195 Vector2f target = ship.getMouseTarget();
196 if (target !=
null) {
197 float dist = Misc.getDistance(ship.getLocation(), target);
198 float max =
getMaxRange(ship) + ship.getCollisionRadius();
200 return "OUT OF RANGE";
210 public boolean isUsable(ShipSystemAPI system, ShipAPI ship) {
211 return ship.getMouseTarget() !=
null;
215 private Vector2f findClearLocation(ShipAPI ship, Vector2f dest) {
216 if (isLocationClear(dest))
return dest;
220 WeightedRandomPicker<Vector2f> tested =
new WeightedRandomPicker<Vector2f>();
221 for (
float distIndex = 1; distIndex <= 32f; distIndex *= 2f) {
222 float start = (float) Math.random() * 360f;
223 for (
float angle = start; angle < start + 360; angle += 60f) {
224 Vector2f loc = Misc.getUnitVectorAtDegreeAngle(angle);
225 loc.scale(incr * distIndex);
226 Vector2f.add(dest, loc, loc);
228 if (isLocationClear(loc)) {
234 if (tested.isEmpty())
return dest;
236 return tested.pick();
239 private boolean isLocationClear(Vector2f loc) {
240 for (ShipAPI other : Global.getCombatEngine().getShips()) {
241 if (other.isShuttlePod())
continue;
242 if (other.isFighter())
continue;
250 Vector2f otherLoc = other.getShieldCenterEvenIfNoShield();
251 float otherR = other.getShieldRadiusEvenIfNoShield();
252 if (other.isPiece()) {
253 otherLoc = other.getLocation();
254 otherR = other.getCollisionRadius();
260 float dist = Misc.getDistance(loc, otherLoc);
265 if (dist < r + checkDist) {
269 for (CombatEntityAPI other : Global.getCombatEngine().getAsteroids()) {
270 float dist = Misc.getDistance(loc, other.getLocation());
static SoundPlayerAPI getSoundPlayer()
static CombatEngineAPI getCombatEngine()
static final float MIN_SPAWN_DIST
static final Color JITTER_UNDER_COLOR
static final float MIN_SPAWN_DIST_FRIGATE
float getMaxRange(ShipAPI ship)
void spawnMine(ShipAPI source, Vector2f mineLoc)
void unapply(MutableShipStatsAPI stats, String id)
EveryFrameCombatPlugin createMissileJitterPlugin(final MissileAPI mine, final float fadeInTime)
static float getRange(ShipAPI ship)
float getMineRange(ShipAPI ship)
static final float LIVE_TIME
String getInfoText(ShipSystemAPI system, ShipAPI ship)
static final Color JITTER_COLOR
void apply(MutableShipStatsAPI stats, String id, State state, float effectLevel)
boolean isUsable(ShipSystemAPI system, ShipAPI ship)
SoundAPI playSound(String id, float pitch, float volume, Vector2f loc, Vector2f vel)