Starsector API
Loading...
Searching...
No Matches
MineStrikeStats.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.combat;
2
3import java.awt.Color;
4import java.util.List;
5
6import org.lwjgl.util.vector.Vector2f;
7
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;
23
25
26 protected static float MINE_RANGE = 1000f;
27
28 public static final float MIN_SPAWN_DIST = 75f;
29 public static final float MIN_SPAWN_DIST_FRIGATE = 110f;
30
31 public static final float LIVE_TIME = 5f;
32
33 public static final Color JITTER_COLOR = new Color(255,155,255,75);
34 public static final Color JITTER_UNDER_COLOR = new Color(255,155,255,155);
35
36
37 public static float getRange(ShipAPI ship) {
38 if (ship == null) return MINE_RANGE;
39 return ship.getMutableStats().getSystemRangeBonus().computeEffective(MINE_RANGE);
40 }
41
42 public void apply(MutableShipStatsAPI stats, String id, State state, float effectLevel) {
43 ShipAPI ship = null;
44 //boolean player = false;
45 if (stats.getEntity() instanceof ShipAPI) {
46 ship = (ShipAPI) stats.getEntity();
47 } else {
48 return;
49 }
50
51
52 float jitterLevel = effectLevel;
53 if (state == State.OUT) {
54 jitterLevel *= jitterLevel;
55 }
56 float maxRangeBonus = 25f;
57 float jitterRangeBonus = jitterLevel * maxRangeBonus;
58 if (state == State.OUT) {
59 }
60
61 ship.setJitterUnder(this, JITTER_UNDER_COLOR, jitterLevel, 11, 0f, 3f + jitterRangeBonus);
62 ship.setJitter(this, JITTER_COLOR, jitterLevel, 4, 0f, 0 + jitterRangeBonus);
63
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);
69 }
70 if (target != null) {
71 float dist = Misc.getDistance(ship.getLocation(), target);
72 float max = getMaxRange(ship) + ship.getCollisionRadius();
73 if (dist > max) {
74 float dir = Misc.getAngleInDegrees(ship.getLocation(), target);
75 target = Misc.getUnitVectorAtDegreeAngle(dir);
76 target.scale(max);
77 Vector2f.add(target, ship.getLocation(), target);
78 }
79
80 target = findClearLocation(ship, target);
81
82 if (target != null) {
83 spawnMine(ship, target);
84 }
85 }
86
87 } else if (state == State.OUT ) {
88 }
89 }
90
91
92 public void unapply(MutableShipStatsAPI stats, String id) {
93 }
94
95 public void spawnMine(ShipAPI source, Vector2f mineLoc) {
96 CombatEngineAPI engine = Global.getCombatEngine();
97 Vector2f currLoc = Misc.getPointAtRadius(mineLoc, 30f + (float) Math.random() * 30f);
98 //Vector2f currLoc = null;
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());
105 }
106 for (MissileAPI other : Global.getCombatEngine().getMissiles()) {
107 if (!other.isMine()) continue;
108
109 float dist = Misc.getDistance(currLoc, other.getLocation());
110 if (dist < other.getCollisionRadius() + 40f) {
111 currLoc = null;
112 break;
113 }
114 }
115 if (currLoc != null) {
116 break;
117 }
118 }
119 if (currLoc == null) {
120 currLoc = Misc.getPointAtRadius(mineLoc, 30f + (float) Math.random() * 30f);
121 }
122
123
124
125 //Vector2f currLoc = mineLoc;
126 MissileAPI mine = (MissileAPI) engine.spawnProjectile(source, null,
127 "minelayer2",
128 currLoc,
129 (float) Math.random() * 360f, null);
130 if (source != null) {
131 Global.getCombatEngine().applyDamageModifiersToSpawnedProjectileWithNullWeapon(
132 source, WeaponType.MISSILE, false, mine.getDamage());
133// float extraDamageMult = source.getMutableStats().getMissileWeaponDamageMult().getModifiedValue();
134// mine.getDamage().setMultiplier(mine.getDamage().getMultiplier() * extraDamageMult);
135 }
136
137
138 float fadeInTime = 0.5f;
139 mine.getVelocity().scale(0);
140 mine.fadeOutThenIn(fadeInTime);
141
142 Global.getCombatEngine().addPlugin(createMissileJitterPlugin(mine, fadeInTime));
143
144 //mine.setFlightTime((float) Math.random());
145 float liveTime = LIVE_TIME;
146 //liveTime = 0.01f;
147 mine.setFlightTime(mine.getMaxFlightTime() - liveTime);
148
149 Global.getSoundPlayer().playSound("mine_teleport", 1f, 1f, mine.getLocation(), mine.getVelocity());
150 }
151
152 protected EveryFrameCombatPlugin createMissileJitterPlugin(final MissileAPI mine, final float fadeInTime) {
153 return new BaseEveryFrameCombatPlugin() {
154 float elapsed = 0f;
155 @Override
156 public void advance(float amount, List<InputEventAPI> events) {
157 if (Global.getCombatEngine().isPaused()) return;
158
159 elapsed += amount;
160
161 float jitterLevel = mine.getCurrentBaseAlpha();
162 if (jitterLevel < 0.5f) {
163 jitterLevel *= 2f;
164 } else {
165 jitterLevel = (1f - jitterLevel) * 2f;
166 }
167
168 float jitterRange = 1f - mine.getCurrentBaseAlpha();
169 //jitterRange = (float) Math.sqrt(jitterRange);
170 float maxRangeBonus = 50f;
171 float jitterRangeBonus = jitterRange * maxRangeBonus;
172 Color c = JITTER_UNDER_COLOR;
173 c = Misc.setAlpha(c, 70);
174 //mine.setJitter(this, c, jitterLevel, 15, jitterRangeBonus * 0.1f, jitterRangeBonus);
175 mine.setJitter(this, c, jitterLevel, 15, jitterRangeBonus * 0, jitterRangeBonus);
176
177 if (jitterLevel >= 1 || elapsed > fadeInTime) {
178 Global.getCombatEngine().removePlugin(this);
179 }
180 }
181 };
182 }
183
184
185 protected float getMaxRange(ShipAPI ship) {
186 return getMineRange(ship);
187 }
188
189
190 @Override
191 public String getInfoText(ShipSystemAPI system, ShipAPI ship) {
192 if (system.isOutOfAmmo()) return null;
193 if (system.getState() != SystemState.IDLE) return null;
194
195 Vector2f target = ship.getMouseTarget();
196 if (target != null) {
197 float dist = Misc.getDistance(ship.getLocation(), target);
198 float max = getMaxRange(ship) + ship.getCollisionRadius();
199 if (dist > max) {
200 return "OUT OF RANGE";
201 } else {
202 return "READY";
203 }
204 }
205 return null;
206 }
207
208
209 @Override
210 public boolean isUsable(ShipSystemAPI system, ShipAPI ship) {
211 return ship.getMouseTarget() != null;
212 }
213
214
215 private Vector2f findClearLocation(ShipAPI ship, Vector2f dest) {
216 if (isLocationClear(dest)) return dest;
217
218 float incr = 50f;
219
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);
227 tested.add(loc);
228 if (isLocationClear(loc)) {
229 return loc;
230 }
231 }
232 }
233
234 if (tested.isEmpty()) return dest; // shouldn't happen
235
236 return tested.pick();
237 }
238
239 private boolean isLocationClear(Vector2f loc) {
240 for (ShipAPI other : Global.getCombatEngine().getShips()) {
241 if (other.isShuttlePod()) continue;
242 if (other.isFighter()) continue;
243
244// Vector2f otherLoc = other.getLocation();
245// float otherR = other.getCollisionRadius();
246
247// if (other.isPiece()) {
248// System.out.println("ewfewfewfwe");
249// }
250 Vector2f otherLoc = other.getShieldCenterEvenIfNoShield();
251 float otherR = other.getShieldRadiusEvenIfNoShield();
252 if (other.isPiece()) {
253 otherLoc = other.getLocation();
254 otherR = other.getCollisionRadius();
255 }
256
257
258// float dist = Misc.getDistance(loc, other.getLocation());
259// float r = other.getCollisionRadius();
260 float dist = Misc.getDistance(loc, otherLoc);
261 float r = otherR;
262 //r = Math.min(r, Misc.getTargetingRadius(loc, other, false) + r * 0.25f);
263 float checkDist = MIN_SPAWN_DIST;
264 if (other.isFrigate()) checkDist = MIN_SPAWN_DIST_FRIGATE;
265 if (dist < r + checkDist) {
266 return false;
267 }
268 }
269 for (CombatEntityAPI other : Global.getCombatEngine().getAsteroids()) {
270 float dist = Misc.getDistance(loc, other.getLocation());
271 if (dist < other.getCollisionRadius() + MIN_SPAWN_DIST) {
272 return false;
273 }
274 }
275
276 return true;
277 }
278
279
280 public float getFuseTime() {
281 return 3f;
282 }
283
284
285 public float getMineRange(ShipAPI ship) {
286 return getRange(ship);
287 //return MINE_RANGE;
288 }
289
290
291}
292
293
294
295
296
297
298
299
static SoundPlayerAPI getSoundPlayer()
Definition Global.java:43
static CombatEngineAPI getCombatEngine()
Definition Global.java:63
void spawnMine(ShipAPI source, Vector2f mineLoc)
void unapply(MutableShipStatsAPI stats, String id)
EveryFrameCombatPlugin createMissileJitterPlugin(final MissileAPI mine, final float fadeInTime)
String getInfoText(ShipSystemAPI system, ShipAPI ship)
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)