Starsector API
Loading...
Searching...
No Matches
DisposableFleetManager.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.fleets;
2
3import java.util.LinkedHashMap;
4
5import com.fs.starfarer.api.Global;
6import com.fs.starfarer.api.campaign.CampaignFleetAPI;
7import com.fs.starfarer.api.campaign.StarSystemAPI;
8import com.fs.starfarer.api.campaign.ai.CampaignFleetAIAPI;
9import com.fs.starfarer.api.campaign.ai.CampaignFleetAIAPI.EncounterOption;
10import com.fs.starfarer.api.campaign.econ.MarketAPI;
11import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
12import com.fs.starfarer.api.impl.campaign.ids.Tags;
13import com.fs.starfarer.api.impl.campaign.tutorial.TutorialMissionIntel;
14import com.fs.starfarer.api.util.IntervalUtil;
15import com.fs.starfarer.api.util.Misc;
16import com.fs.starfarer.api.util.TimeoutTracker;
17
27
28 public static boolean DEBUG = false;
29
30 public static final String KEY_SYSTEM = "$core_disposableFleetSpawnSystem";
31 public static final String KEY_SPAWN_FP = "$core_disposableFleetSpawnFP";
32 //public static final float MAX_RANGE_FROM_PLAYER_LY = 3f;
34 public static final float DESPAWN_RANGE_LY = MAX_RANGE_FROM_PLAYER_LY + 1.4f;
35
36 protected IntervalUtil tracker2 = new IntervalUtil(0.75f, 1.25f);;
37 protected LinkedHashMap<String, TimeoutTracker<Boolean>> recentSpawns = new LinkedHashMap<String, TimeoutTracker<Boolean>>();
38
39 protected Object readResolve() {
40 super.readResolve();
41 return this;
42 }
43
44 protected float getExpireDaysPerFleet() {
45 return 30f;
46 }
47
48 protected String getSpawnKey(StarSystemAPI system) {
49 return "$core_recentSpawn_" + getSpawnId() + "_" + system.getName();
50 }
51
52 protected void addRecentSpawn(StarSystemAPI system) {
53 String key = getSpawnKey(system);
54 float e = Global.getSector().getMemoryWithoutUpdate().getExpire(key);
55 if (e < 0) e = 0;
57 Global.getSector().getMemoryWithoutUpdate().set(key, true);
58 Global.getSector().getMemoryWithoutUpdate().expire(key, e);
59 }
60
61 protected float getRecentSpawnsForSystem(StarSystemAPI system) {
62 String key = getSpawnKey(system);
63 float e = Global.getSector().getMemoryWithoutUpdate().getExpire(key);
64 if (e < 0) e = 0;
65 return e / getExpireDaysPerFleet();
66 }
67
68 @Override
69 protected int getMaxFleets() {
70 return 100; // limiting is based on spawnRateMult instead
71 }
72
73 @Override
74 protected boolean isOkToDespawnAssumingNotPlayerVisible(CampaignFleetAPI fleet) {
75 if (currSpawnLoc == null) return true;
76 String system = fleet.getMemoryWithoutUpdate().getString(KEY_SYSTEM);
77 float spawnFP = fleet.getMemoryWithoutUpdate().getFloat(KEY_SPAWN_FP);
78 CampaignFleetAPI player = Global.getSector().getPlayerFleet();
79 float playerFP = player.getFleetPoints();
80
81 if (system == null || !system.equals(currSpawnLoc.getName())) return true;
82
83 if (spawnFP >= fleet.getFleetPoints() * 2f) {
84 if (fleet.getAI() instanceof CampaignFleetAIAPI) {
85 CampaignFleetAIAPI ai = (CampaignFleetAIAPI) fleet.getAI();
86 EncounterOption option = ai.pickEncounterOption(null, player, true);
87 if (option == EncounterOption.DISENGAGE) return true;
88 } else {
89 return fleet.getFleetPoints() <= playerFP * 0.5f;
90 }
91 }
92
93 return false;
94 }
95
96 @Override
97 public float getSpawnRateMult() {
98 return spawnRateMult;
99 }
100
101 protected float spawnRateMult = 1f;
102 protected StarSystemAPI currSpawnLoc = null;
103
104 @Override
105 public void advance(float amount) {
106 if (TutorialMissionIntel.isTutorialInProgress()) {
107 return;
108 }
109
110 super.advance(amount);
111
112
113 CampaignFleetAPI player = Global.getSector().getPlayerFleet();
114 if (player == null) return;
115
116 float days = Global.getSector().getClock().convertToDays(amount);
117 if (DEBUG) {
118 days *= 100f;
119 }
120
121 tracker2.advance(days);
122 if (tracker2.intervalElapsed()) {
123 StarSystemAPI closest = pickCurrentSpawnLocation();
124 if (closest != currSpawnLoc) {
125 currSpawnLoc = closest;
126 }
127
128 //List<ManagedFleetData> remove = new ArrayList<ManagedFleetData>();
129 for (ManagedFleetData data : active) {
130 if (Misc.isFleetReturningToDespawn(data.fleet)) continue;
131 // if it's player-visible/in the currently active location,
132 // make it return to source when it's been beat up enough
133 // to be worth despawning
134 //if (isOkToDespawnAssumingNotPlayerVisible(data.fleet)) {
135
136 float fp = data.fleet.getFleetPoints();
137 float spawnFP = data.fleet.getMemoryWithoutUpdate().getFloat(KEY_SPAWN_FP);
138 if (fp < spawnFP * 0.33f) {
139 Misc.giveStandardReturnToSourceAssignments(data.fleet);
140 //remove.add(data);
141 }
142 }
143
144 //active.removeAll(remove);
145
147 }
148 }
149
150 public StarSystemAPI getCurrSpawnLoc() {
151 return currSpawnLoc;
152 }
153
154 protected void updateSpawnRateMult() {
155 if (currSpawnLoc == null) {
156 if (DEBUG) {
157 System.out.println("No target system, spawnRateMult is 1");
158 }
159 spawnRateMult = 1f;
160 return;
161 }
162
163 float desiredNumFleets = getDesiredNumFleetsForSpawnLocation();
165 if (active != null) {
166 float activeInSystem = 0f;
167 for (ManagedFleetData data : active) {
168 if (data.spawnedFor == currSpawnLoc || data.fleet.getContainingLocation() == currSpawnLoc) {
169 activeInSystem++;
170 }
171 }
172 recentSpawns = Math.max(recentSpawns, activeInSystem);
173 }
174
175 spawnRateMult = (float) Math.pow(Math.max(0, (desiredNumFleets - recentSpawns) * 1f), 4f);
176 if (spawnRateMult < 0) spawnRateMult = 0;
177
178 //if (DEBUG || this instanceof DisposableHostileActivityFleetManager) {
179 if (DEBUG) {
180 System.out.println(String.format("ID: %s, system: %s, recent: %s, desired: %s, spawnRateMult: %s",
181 getSpawnId(),
182 currSpawnLoc.getName(),
183 "" + recentSpawns,
184 "" + desiredNumFleets,
185 "" + spawnRateMult));
186 }
187 }
188
189 protected abstract int getDesiredNumFleetsForSpawnLocation();
190
191 protected abstract CampaignFleetAPI spawnFleetImpl();
192 protected abstract String getSpawnId();
193
194 protected StarSystemAPI pickCurrentSpawnLocation() {
196 }
197 protected StarSystemAPI pickNearestPopulatedSystem() {
198 if (Global.getSector().isInNewGameAdvance()) return null;
199 CampaignFleetAPI player = Global.getSector().getPlayerFleet();
200 if (player == null) return null;
201 StarSystemAPI nearest = null;
202 float minDist = Float.MAX_VALUE;
203 for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
204 if (market.isHidden()) continue;
205 if (market.getStarSystem() != null && market.getStarSystem().hasTag(Tags.SYSTEM_ABYSSAL)) continue;
206
207 if (market.isPlayerOwned() && market.getSize() <= 3) continue;
208 if (!market.hasSpaceport()) continue;
209
210 float distToPlayerLY = Misc.getDistanceLY(player.getLocationInHyperspace(), market.getLocationInHyperspace());
211
212 if (distToPlayerLY > MAX_RANGE_FROM_PLAYER_LY) continue;
213
214 if (distToPlayerLY < minDist && market.getStarSystem() != null) {
215 if (market.getStarSystem().getStar() != null) {
216 if (market.getStarSystem().getStar().getSpec().isPulsar()) continue;
217 }
218
219 nearest = market.getStarSystem();
220 minDist = distToPlayerLY;
221 }
222 }
223
224
225 // stick with current system longer unless something else is closer
226 if (nearest == null && currSpawnLoc != null) {
227 float distToPlayerLY = Misc.getDistanceLY(player.getLocationInHyperspace(), currSpawnLoc.getLocation());
228 if (distToPlayerLY <= DESPAWN_RANGE_LY) {
229 nearest = currSpawnLoc;
230 }
231 }
232
233 return nearest;
234 }
235
236 public CampaignFleetAPI spawnFleet() {
237 if (currSpawnLoc == null) return null;
238
239 // otherwise, possible for jump-point dialog to say there's nothing on other side
240 // but there will be by the time the player comes out
241 if (Global.getSector().getPlayerFleet() != null && Global.getSector().getPlayerFleet().isInHyperspaceTransition()) {
242 return null;
243 }
244
245 CampaignFleetAPI fleet = spawnFleetImpl();
246 if (fleet != null) {
247 fleet.getMemoryWithoutUpdate().set(KEY_SYSTEM, currSpawnLoc.getName());
248 fleet.getMemoryWithoutUpdate().set(KEY_SPAWN_FP, fleet.getFleetPoints());
249 }
250
251 // do this even if fleet is null, to avoid non-stop fail-spawning of fleets
252 // if spawnFleetImpl() can't spawn one, for whatever reason
255
256 return fleet;
257 }
258
259 protected String getTravelText(StarSystemAPI system, CampaignFleetAPI fleet) {
260 return "traveling to the " + system.getBaseName() + " star system";
261 }
262
263 protected String getActionInsideText(StarSystemAPI system, CampaignFleetAPI fleet) {
264 boolean patrol = fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_PATROL_FLEET);
265 String verb = "raiding";
266 if (patrol) verb = "patrolling";
267 return verb + " the " + system.getBaseName() + " star system";
268 }
269
270 protected String getActionOutsideText(StarSystemAPI system, CampaignFleetAPI fleet) {
271 boolean patrol = fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_PATROL_FLEET);
272 String verb = "raiding";
273 if (patrol) verb = "patrolling";
274 return verb + " around the " + system.getBaseName() + " star system";
275 }
276
277 protected void setLocationAndOrders(CampaignFleetAPI fleet, float probStartInHyper, float probStayInHyper) {
278 StarSystemAPI system = getCurrSpawnLoc();
279
280 if ((float) Math.random() < probStartInHyper ||
281 (Global.getSector().getPlayerFleet() != null && Global.getSector().getPlayerFleet().isInHyperspace())) {
282 Global.getSector().getHyperspace().addEntity(fleet);
283 } else {
284 system.addEntity(fleet);
285 }
286 fleet.addScript(new DisposableAggroAssignmentAI(fleet, system, this, probStayInHyper));
287 }
288}
289
290
291
292
293
294
295
296
static SectorAPI getSector()
Definition Global.java:59
String getActionOutsideText(StarSystemAPI system, CampaignFleetAPI fleet)
void setLocationAndOrders(CampaignFleetAPI fleet, float probStartInHyper, float probStayInHyper)
LinkedHashMap< String, TimeoutTracker< Boolean > > recentSpawns
String getActionInsideText(StarSystemAPI system, CampaignFleetAPI fleet)
String getTravelText(StarSystemAPI system, CampaignFleetAPI fleet)