Starsector API
Loading...
Searching...
No Matches
BaseSensorGhost.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.ghosts;
2
3import java.util.ArrayList;
4import java.util.List;
5import java.util.Random;
6
7import org.lwjgl.util.vector.Vector2f;
8
9import com.fs.starfarer.api.Global;
10import com.fs.starfarer.api.campaign.CampaignFleetAPI;
11import com.fs.starfarer.api.campaign.CustomCampaignEntityAPI;
12import com.fs.starfarer.api.campaign.LocationAPI;
13import com.fs.starfarer.api.campaign.SectorEntityToken;
14import com.fs.starfarer.api.impl.campaign.abilities.InterdictionPulseAbility;
15import com.fs.starfarer.api.impl.campaign.ids.Entities;
16import com.fs.starfarer.api.impl.campaign.ids.Factions;
17import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
18import com.fs.starfarer.api.impl.campaign.ids.Tags;
19import com.fs.starfarer.api.util.Misc;
20import com.fs.starfarer.api.util.SmoothMovementUtil;
21
22public class BaseSensorGhost implements SensorGhost {
23
24 public static enum DespawnReason {
25 FLEET_IN_RANGE,
26 SCRIPT_ENDED,
27 }
28
30 protected float despawnRange = 100f;
31 protected boolean despawnOutsideSector = true;
32 protected boolean despawnInAbyss = true;
33 protected boolean fleeing = false;
34 protected int fleeBurnLevel = 30;
35 protected float accelMult = 1f;
36 protected transient boolean creationFailed = false;
37
39
40 protected List<GhostBehavior> script = new ArrayList<GhostBehavior>();
42
44 this.manager = manager;
45 this.fleeBurnLevel = fleeBurnLevel;
46 }
47
48 protected Object readResolve() {
49 if (movement == null) {
51 }
52 return this;
53 }
54
55 public void addBehavior(GhostBehavior b) {
56 script.add(b);
57 }
58
59 public void addInterrupt(GhostBehaviorInterrupt interrupt) {
60 if (script.isEmpty()) return;
61 script.get(script.size() - 1).addInterrupt(interrupt);
62 }
63
64 public float getDespawnRange() {
65 return despawnRange;
66 }
67
68 public void setDespawnRange(float despawnRange) {
69 this.despawnRange = despawnRange;
70 }
71
72 public Random getRandom() {
73 Random random = Misc.random;
74 if (manager != null) random = manager.getRandom();
75 return random;
76 }
77
78 public float genSmallSensorProfile() {
79 return 700f + getRandom().nextFloat() * 300f;
80 }
81 public float genMediumSensorProfile() {
82 return 1000f + getRandom().nextFloat() * 500f;
83 }
84 public float genLargeSensorProfile() {
85 return 1500f + getRandom().nextFloat() * 500f;
86 }
87
88 public float genHugeSensorProfile() {
89 return 2500f + getRandom().nextFloat() * 1000f;
90 }
91
92 public float genTinyRadius() {
93 return 10f + getRandom().nextFloat() * 5f;
94 }
95 public float genVerySmallRadius() {
96 return 20f + getRandom().nextFloat() * 10f;
97 }
98 public float genSmallRadius() {
99 return 22f + getRandom().nextFloat() * 28f;
100 }
101 public float genMediumRadius() {
102 return 50f + getRandom().nextFloat() * 25f;
103 }
104 public float genLargeRadius() {
105 return 75f + getRandom().nextFloat() * 25f;
106 }
107
108 public float genFloat(float min, float max) {
109 return min + (max - min) * getRandom().nextFloat();
110 }
111 public float genInt(int min, int max) {
112 return min + getRandom().nextInt(max - min + 1);
113 }
114// public float genRadius(float min, float max) {
115// return min + (max - min) * getRandom().nextFloat();
116// }
117// public int genBurn(int min, int max) {
118// return min + getRandom().nextInt(max - min + 1);
119// }
120 public float genDelay(float base) {
121 return base * (0.75f + 0.5f * getRandom().nextFloat());
122 }
123
124 public boolean placeNearPlayer() {
125 return placeNearPlayer(1400f, 2200f); // 2000 is max range at which sensor ping plays
126 //placeNearPlayer(1000f, 1500f);
127 }
128 public boolean placeNearPlayer(float minDist, float maxDist) {
130
131 Random random = getRandom();
132 Vector2f loc = new Vector2f();
133
134 for (int i = 0; i < 20; i++) {
135 float r = minDist + random.nextFloat() * (maxDist - minDist);
136 loc = Misc.getPointAtRadius(pf.getLocation(), r, random);
137 if (!Misc.isInsideSlipstream(loc, 500f, pf.getContainingLocation())) {
138 break;
139 }
140 }
141 if (Misc.isInsideSlipstream(loc, 500f, pf.getContainingLocation())) {
142 return false;
143 }
144
145 getMovement().getLocation().set(loc);
148
149 return true;
150 }
151
152 public void placeNearEntity(SectorEntityToken entity, float minDist, float maxDist) {
153 Random random = getRandom();
154 Vector2f loc = new Vector2f();
155
156 float r = minDist + random.nextFloat() * (maxDist - minDist);
157 loc = Misc.getPointAtRadius(entity.getLocation(), r, random);
158
159 getMovement().getLocation().set(loc);
162 }
163
164 public void setLoc(Vector2f loc) {
165 getMovement().getLocation().set(loc);
167 }
168 public void setVel(Vector2f vel) {
169 getMovement().getVelocity().set(vel);
171 }
172
173 public void initEntity(float sensorProfile, float radius) {
174 float maxFleetRadius = Global.getSettings().getFloat("maxFleetSelectionRadius");
175 int extraInds = 0;
176 if (radius > maxFleetRadius) {
177 extraInds = (int) Math.round((radius - maxFleetRadius) / 20f);
178 }
179 initEntity(sensorProfile, radius, extraInds);
180 }
181 public void initEntity(float sensorProfile, float radius, int extraSensorInds) {
182 initEntity(sensorProfile, radius, extraSensorInds, Global.getSector().getHyperspace());
183 }
184 public void initEntity(float sensorProfile, float radius, int extraSensorInds, LocationAPI where) {
185 entity = where.addCustomEntity(null, null,
188 entity.setSensorProfile(sensorProfile);
191 entity.setRadius(radius);
193
194 despawnRange = Math.max(100f, sensorProfile * 0.25f);
195 //if (despawnRange > 200f) despawnRange = 200f;
196 despawnRange = 100f;
197
198 if (extraSensorInds > 0) {
200 }
201 }
202
203 public void setNumSensorIndicators(int min, int max, Random random) {
204 if (random == null) random = Misc.random;
205 int num = min + random.nextInt(max - min + 1);
207 }
208
209 protected void reportDespawning(DespawnReason reason, Object param) {
210
211 }
212
213 public void advance(float amount) {
214 if (entity == null) {
215 return;
216 }
218 if (script.isEmpty() ||
221 ) {
223 reportDespawning(DespawnReason.SCRIPT_ENDED, null);
224 entity = null;
225 return;
226 } else {
228 float dist = Misc.getDistance(entity, fleet);
229 dist -= entity.getRadius() + fleet.getRadius();
230 if (dist < despawnRange) {
232 reportDespawning(DespawnReason.FLEET_IN_RANGE, fleet);
233 entity = null;
234 return;
235 }
236 }
237 }
238 }
239
240 if (fleeBurnLevel > 0 && !fleeing &&
242 if (entity.getContainingLocation() != null) {
244 float range = InterdictionPulseAbility.getRange(fleet);
245 float dist = Misc.getDistance(fleet.getLocation(), entity.getLocation());
246 if (dist > range) continue;
247 if (fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.JUST_DID_INTERDICTION_PULSE)) {
248 fleeing = true;
249 script.clear();
251 addBehavior(new GBStayInPlace(0.1f + 0.2f * Misc.random.nextFloat()));
252 addBehavior(new GBGoAwayFrom(3f + Misc.random.nextFloat() * 2f, fleet, fleeBurnLevel));
253 break;
254 }
255 }
256 }
257 }
258
259 if (!script.isEmpty()) {
260 GhostBehavior curr = script.get(0);
261 curr.advance(amount, this);
262
263 if (curr.isDone()) {
264 script.remove(curr);
265 }
266 }
267
268
269 movement.advance(amount);
270// if (this instanceof LeviathanGhost) {
271// Vector2f prev = entity.getLocation();
272// Vector2f next = movement.getLocation();
273// if (Misc.getDistance(prev, next) > 100f) {
274// System.out.println("LOCATION JUMP");
275// movement.advance(amount);
276// }
277// }
278
279
282 //entity.getVelocity().set(0f, 0f);
283 }
284
285
286 public float getAccelMult() {
287 return accelMult;
288 }
289
290 public void setAccelMult(float accelMult) {
291 this.accelMult = accelMult;
292 }
293
294 public void moveTo(Vector2f dest, float maxBurn) {
295 moveTo(dest, null, maxBurn);
296 }
297
298 public void moveTo(Vector2f dest, Vector2f destVel, float maxBurn) {
299 float speed = Misc.getSpeedForBurnLevel(maxBurn);
300 float accelMult = speed / Misc.getSpeedForBurnLevel(20f);;
301 if (accelMult < 0.5f) accelMult = 0.5f;
302 if (accelMult > 10f) accelMult = 10f;
303 movement.setAcceleration(speed * accelMult * this.accelMult);
304 movement.setMaxSpeed(speed);
305 movement.setDest(dest, destVel);
306 }
307
308 public int getMaxBurn() {
310 }
311 public int getCurrBurn() {
312 return (int) Misc.getBurnLevelForSpeed(entity.getVelocity().length());
313 }
314
315 public float getAcceleration() {
316 return movement.getAcceleration();
317 }
318
320 return movement;
321 }
322
324 return entity;
325 }
326
327 public boolean isDone() {
328 return entity == null;
329 }
330
331 public boolean runWhilePaused() {
332 return false;
333 }
334
335 public boolean isDespawnOutsideSector() {
337 }
338
340 this.despawnOutsideSector = despawnOutsideSector;
341 }
342
343 public boolean isDespawnInAbyss() {
344 return despawnInAbyss;
345 }
346
347 public void setDespawnInAbyss(boolean despawnInAbyss) {
348 this.despawnInAbyss = despawnInAbyss;
349 }
350
351 public boolean isCreationFailed() {
352 return creationFailed;
353 }
354
355 public void setCreationFailed() {
356 this.creationFailed = true;
357 if (entity != null && entity.getContainingLocation() != null) {
359 }
360 }
361
362 public List<GhostBehavior> getScript() {
363 return script;
364 }
365
366 public void clearScript() {
367 script.clear();
368 }
369}
370
371
372
static SettingsAPI getSettings()
Definition Global.java:57
static SectorAPI getSector()
Definition Global.java:65
void setNumSensorIndicators(int min, int max, Random random)
void initEntity(float sensorProfile, float radius, int extraSensorInds, LocationAPI where)
BaseSensorGhost(SensorGhostManager manager, int fleeBurnLevel)
void placeNearEntity(SectorEntityToken entity, float minDist, float maxDist)
void moveTo(Vector2f dest, Vector2f destVel, float maxBurn)
void addInterrupt(GhostBehaviorInterrupt interrupt)
void reportDespawning(DespawnReason reason, Object param)
void initEntity(float sensorProfile, float radius, int extraSensorInds)
static final String GLOBAL_INTERDICTION_PULSE_JUST_USED_IN_CURRENT_LOCATION
Definition MemFlags.java:53
static final String FADING_OUT_AND_EXPIRING
Definition Tags.java:341
static boolean isInAbyss(Vector2f loc)
Definition Misc.java:2324
static boolean isInsideSlipstream(Vector2f loc, float radius)
Definition Misc.java:6408
static void fadeAndExpire(SectorEntityToken entity)
Definition Misc.java:3133
static float getDistance(SectorEntityToken from, SectorEntityToken to)
Definition Misc.java:599
static boolean isOutsideSector(Vector2f loc)
Definition Misc.java:6436
static float getBurnLevelForSpeed(float speed)
Definition Misc.java:1652
static Vector2f getPointAtRadius(Vector2f from, float r)
Definition Misc.java:697
static float getSpeedForBurnLevel(float burnLevel)
Definition Misc.java:1671
void setDest(Vector2f dest, Vector2f destVel)
CustomCampaignEntityAPI addCustomEntity(String id, String name, String type, String factionId)
void removeEntity(SectorEntityToken entity)
List< CampaignFleetAPI > getFleets()
void setDetectionRangeDetailsOverrideMult(Float detectionRangeDetailsOverrideMult)
void addScript(EveryFrameScript script)
void setDiscoverable(Boolean discoverable)
void set(String key, Object value)
void advance(float amount, SensorGhost ghost)