Starsector API
Loading...
Searching...
No Matches
ConvulsiveLungeSystemAI.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.combat.dweller;
2
3import org.lwjgl.util.vector.Vector2f;
4
5import com.fs.starfarer.api.Global;
6import com.fs.starfarer.api.combat.CombatEngineAPI;
7import com.fs.starfarer.api.combat.ShipAPI;
8import com.fs.starfarer.api.combat.ShipCommand;
9import com.fs.starfarer.api.combat.ShipSystemAIScript;
10import com.fs.starfarer.api.combat.ShipSystemAPI;
11import com.fs.starfarer.api.combat.ShipwideAIFlags;
12import com.fs.starfarer.api.combat.ShipwideAIFlags.AIFlags;
13import com.fs.starfarer.api.util.IntervalUtil;
14import com.fs.starfarer.api.util.Misc;
15
16
25
26 public static float HULL_LOSS_FOR_PULLBACK = 0.25f;
27 public static float MAW_LUNGE_ARC = 30f;
28
29 public static class SharedLungeAIData {
30 public float usedByMawToAttack;
31 public float usedByMawToPullBack;
32 }
33
34 public static SharedLungeAIData getSharedData() {
35 String key = "lunge_AI_shared";
36 SharedLungeAIData data = (SharedLungeAIData)Global.getCombatEngine().getCustomData().get(key);
37 if (data == null) {
38 data = new SharedLungeAIData();
39 Global.getCombatEngine().getCustomData().put(key, data);
40 }
41 return data;
42 }
43
44 public static float MIN_AGGRO_USE_INTERVAL = 5f;
45
46 public static float USE_SCORE_PER_USE = 20f;
47 public static float USE_SCORE_THRESHOLD = 45f;
48
49
50 protected ShipAPI ship;
55
56 protected float sinceUsedForAttackOrMove = 100f;
57 protected float recentAggroUseScore = 0f;
58 protected boolean allowAggroUse = true;
59
60 protected IntervalUtil tracker = new IntervalUtil(0.75f, 1.25f);
61
62 protected float hullLevelAtPrevSystemUse = 1f;
63 protected float prevHardFluxLevel = 0f;
64
66 this.ship = ship;
67 this.flags = flags;
68 this.engine = engine;
69 this.system = system;
70
72 }
73
74 public void advance(float amount, Vector2f missileDangerDir, Vector2f collisionDangerDir, ShipAPI target) {
75 if (ship == null) return;
76
77 tracker.advance(amount);
78
80
81 boolean isMaw = DwellerCombatStrategyAI.isMaw(ship);
82
83 if (isMaw) {
84 recentAggroUseScore -= amount;
87 allowAggroUse = true;
89 allowAggroUse = false;
90 }
91 }
92
93 SharedLungeAIData data = getSharedData();
94 float now = Global.getCombatEngine().getTotalElapsedTime(false);
95
96 boolean forceUseForPullback = !isMaw && data.usedByMawToPullBack + 0.1f > now;
97 boolean forceUseForAttack = !isMaw && data.usedByMawToAttack + 0.1f > now;
98
99 if (ship.getFluxLevel() > 0.95f && ship.getHullLevel() > 0.25f &&
100 ship.getShield() != null && ship.getShield().isOn()) {
102 ship.getAIFlags().setFlag(AIFlags.DO_NOT_USE_SHIELDS, 3f);
103 forceUseForPullback = true;
104 }
105
106 if (tracker.intervalElapsed() || forceUseForPullback || forceUseForAttack) {
107 if (!isSystemUsable()) return;
109
110 float hullLevel = ship.getHullLevel();
111
113
114 float hardFluxLevel = ship.getHardFluxLevel();
115 float fluxLevel = ship.getFluxLevel();
116
117 boolean useSystemForPullback = hullLevel <= hullLevelAtPrevSystemUse - HULL_LOSS_FOR_PULLBACK;
118
119 if (((hardFluxLevel >= prevHardFluxLevel && hardFluxLevel >= 0.33f) || fluxLevel > 0.65f) &&
120 ship.getAIFlags().hasFlag(AIFlags.BACKING_OFF)) {// && (float) Math.random() > 0.75f) {
121 if (target != null) {
122 float dist = Misc.getDistance(ship.getLocation(), target.getLocation());
123 dist -= ship.getCollisionRadius() + target.getCollisionRadius();
124 if (dist < 1000f || hardFluxLevel > prevHardFluxLevel + 0.02f) {
125 useSystemForPullback = true;
126 }
127 }
128 }
129
130 prevHardFluxLevel = hardFluxLevel;
131
132 useSystemForPullback |= forceUseForPullback;
133
134 if (useSystemForPullback) {
135 float angle = ship.getFacing() + 180f;
136 if (target != null) {
138 }
139 if (missileDangerDir != null) {
140 angle = Misc.getAngleInDegrees(missileDangerDir) + 180f;
141 }
142
143 if (isMaw && Misc.getAngleDiff(ship.getFacing() + 180f, angle) > MAW_LUNGE_ARC * 0.5f) {
144 return;
145 }
146
147
148 Vector2f point = Misc.getUnitVectorAtDegreeAngle(angle);
149 point.scale(2000f);
150 Vector2f.add(point, ship.getLocation(), point);
151
152 giveCommand(point);
153 hullLevelAtPrevSystemUse = hullLevel;
154
155 if (isMaw) {
156 data.usedByMawToPullBack = now;
157 }
158 return;
159 }
160
161
162 boolean useSystemForAttackOrMovement = false;
163
164 float arc = 30f;
165 float checkDist = 700f;
166 if (!isMaw && forceUseForAttack) checkDist = 300f;
167 boolean blocked = false;
168 float angle = ship.getFacing();
169 Vector2f dir = Misc.getUnitVectorAtDegreeAngle(angle);
170 if (target != null) {
172 }
173
174
175
176 for (ShipAPI other : Global.getCombatEngine().getShips()) {
177 if (other.isFighter()) continue;
178
179 if (other.getOwner() != ship.getOwner() &&
180 (!other.isHulk() || (isMaw && other.getMassWithModules() < ship.getMass() * 0.25f)) &&
181 (ship.getHullSize().ordinal() > other.getHullSize().ordinal() || (!isMaw && forceUseForAttack)) &&
182 ship.getHullLevel() > 0.5f &&
183 other != target) {
184 continue;
185 }
186
187
188 float dist = Misc.getDistance(ship.getLocation(), other.getLocation());
189 dist -= (ship.getCollisionRadius() + other.getCollisionRadius()) * 0.6f;
190 if (dist > checkDist) continue;
191
192 if (Misc.isInArc(angle, arc, ship.getLocation(), other.getLocation())) {
193 blocked = true;
194 break;
195 }
196 }
197
198 float speed = ship.getVelocity().length();
199 float speedInDir = Vector2f.dot(dir, ship.getVelocity());
200 boolean aligned = speedInDir > speed * 0.65f && speed >= ship.getMaxSpeed() * 0.9f;
201
202 useSystemForAttackOrMovement = !blocked && aligned;
204 useSystemForAttackOrMovement = false;
205 }
206
207 //if (!isMaw && (float) Math.random() > 0.1f) useSystemForAttackOrMovement = false;
208 if (!isMaw) useSystemForAttackOrMovement = false;
209 useSystemForAttackOrMovement |= (forceUseForAttack && !blocked);
210
211
212 if (useSystemForAttackOrMovement) {
213 if (isMaw && Misc.getAngleDiff(ship.getFacing(), angle) > MAW_LUNGE_ARC * 0.5f) {
214 return;
215 }
216
217 Vector2f point = Misc.getUnitVectorAtDegreeAngle(angle);
218 point.scale(2000f);
219 Vector2f.add(point, ship.getLocation(), point);
220
221 giveCommand(point);
222
223 if (isMaw) {
224 data.usedByMawToAttack = now;
225 }
228 return;
229 }
230
231
232 }
233 }
234
235 public boolean isSystemUsable() {
236 if (system.getCooldownRemaining() > 0) return false;
237 if (system.isOutOfAmmo()) return false;
238 if (system.isActive()) return false;
239 return true;
240 }
241
242 public void giveCommand(Vector2f target) {
243 if (ship.getAIFlags() != null) {
244 ship.getAIFlags().setFlag(AIFlags.SYSTEM_TARGET_COORDS, 1f, target);
245 }
247 }
248
249}
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
static CombatEngineAPI getCombatEngine()
Definition Global.java:69
void advance(float amount, Vector2f missileDangerDir, Vector2f collisionDangerDir, ShipAPI target)
void init(ShipAPI ship, ShipSystemAPI system, ShipwideAIFlags flags, CombatEngineAPI engine)
static Vector2f getUnitVectorAtDegreeAngle(float degrees)
Definition Misc.java:1196
static float getAngleDiff(float from, float to)
Definition Misc.java:1716
static float getDistance(SectorEntityToken from, SectorEntityToken to)
Definition Misc.java:599
static boolean isInArc(float direction, float arc, Vector2f from, Vector2f to)
Definition Misc.java:1722
static float getAngleInDegrees(Vector2f v)
Definition Misc.java:1126
float getTotalElapsedTime(boolean includePaused)
void giveCommand(ShipCommand command, Object param, int groupNumber)