Starsector API
Loading...
Searching...
No Matches
LuddicPathBaseManager.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.intel.bases;
2
3import java.util.ArrayList;
4import java.util.Collections;
5import java.util.Comparator;
6import java.util.LinkedHashMap;
7import java.util.LinkedHashSet;
8import java.util.List;
9import java.util.Random;
10
11import com.fs.starfarer.api.EveryFrameScript;
12import com.fs.starfarer.api.Global;
13import com.fs.starfarer.api.campaign.StarSystemAPI;
14import com.fs.starfarer.api.campaign.econ.Industry;
15import com.fs.starfarer.api.campaign.econ.MarketAPI;
16import com.fs.starfarer.api.impl.campaign.DebugFlags;
17import com.fs.starfarer.api.impl.campaign.Tuning;
18import com.fs.starfarer.api.impl.campaign.ids.Factions;
19import com.fs.starfarer.api.impl.campaign.ids.Tags;
20import com.fs.starfarer.api.impl.campaign.intel.BaseEventManager;
21import com.fs.starfarer.api.impl.campaign.intel.events.LuddicPathHostileActivityFactor;
22import com.fs.starfarer.api.util.IntervalUtil;
23import com.fs.starfarer.api.util.Misc;
24import com.fs.starfarer.api.util.Pair;
25import com.fs.starfarer.api.util.WeightedRandomPicker;
26
28
29 public static float LUDDIC_CHURCH_INTEREST_MULT = 0.1f;
31
32 public static float AI_CORE_ADMIN_INTEREST = 10f;
33
34 public static final String KEY = "$core_luddicPathBaseManager";
35
36 public static final float INERTIA_DAYS_MAX = 30f;
37 public static final float INERTIA_DAYS_MIN = 10f;
38
39 public static final float CHECK_DAYS = 10f;
40 public static final float CHECK_PROB = 0.5f;
41
42
45 return (LuddicPathBaseManager) test;
46 }
47
48 protected long start = 0;
49
55
56 @Override
57 protected int getMinConcurrent() {
58 return Global.getSettings().getInt("minLPBases");
59 }
60 @Override
61 protected int getMaxConcurrent() {
62 return Global.getSettings().getInt("maxLPBases");
63 }
64
65 @Override
66 protected float getBaseInterval() {
67 return CHECK_DAYS;
68 }
69
70 @Override
71 protected Object readResolve() {
72 super.readResolve();
73 if (cellChecker == null) {
74 cellChecker = new IntervalUtil(1f, 3f);
75 }
76 if (cells == null) {
77 cells = new LinkedHashMap<MarketAPI, LuddicPathCellsIntel>();
78 }
79 return this;
80 }
81
82 protected IntervalUtil cellChecker = new IntervalUtil(1f, 3f);
83 protected int timesSinceLastChange = 10000;
84 protected int activeMod = 0;
85 protected int sleeperMod = 0;
86
87 @Override
88 public void advance(float amount) {
89 super.advance(amount);
90
91 float days = Misc.getDays(amount);
92 cellChecker.advance(days);
93 if (cellChecker.intervalElapsed()) {
95 if (timesSinceLastChange > 50) {
96 activeMod = Misc.random.nextInt(3);
97 sleeperMod = Misc.random.nextInt(3);
99 }
100
102 }
103 }
104
105 protected LinkedHashMap<MarketAPI, LuddicPathCellsIntel> cells = new LinkedHashMap<MarketAPI, LuddicPathCellsIntel>();
106
107 protected void updateCellStatus() {
108
109 float fraction = Global.getSettings().getFloat("basePatherCellFraction");
110 float minInterest = Global.getSettings().getFloat("minInterestForPatherCells");
111
112 List<Pair<MarketAPI, Float>> marketAndScore = new ArrayList<Pair<MarketAPI,Float>>();
113 int total = 0;
114 for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
115 if (market.getEconGroup() != null) continue;
116 if (market.getSize() < 4) continue;
117 float score = getLuddicPathMarketInterest(market);
118 total++;
119 if (score >= minInterest) {
120 marketAndScore.add(new Pair<MarketAPI, Float>(market, score));
121 }
122 }
123
124 int numActive = Math.round(total * fraction);
125 int numSleeper = numActive;
126
127 numActive += activeMod;
128 numSleeper += sleeperMod;
129
130 LinkedHashSet<MarketAPI> active = new LinkedHashSet<MarketAPI>();
131 LinkedHashSet<MarketAPI> sleeper = new LinkedHashSet<MarketAPI>();
132
133
134 Collections.sort(marketAndScore, new Comparator<Pair<MarketAPI, Float>>() {
135 public int compare(Pair<MarketAPI, Float> o1, Pair<MarketAPI, Float> o2) {
136 return (int) Math.signum(o2.two - o1.two);
137 }
138 });
139
140 int count = 0;
141 for (Pair<MarketAPI, Float> p : marketAndScore) {
142 if (count < numActive) {
143 active.add(p.one);
144 } else if (count < numActive + numSleeper) {
145 sleeper.add(p.one);
146 } else {
147 break;
148 }
149 count++;
150 }
151
152
153 for (MarketAPI market : new ArrayList<MarketAPI>(cells.keySet())) {
154 LuddicPathCellsIntel intel = cells.get(market);
155
156 if (!active.contains(market) && !sleeper.contains(market)) {
157
158 float score = getLuddicPathMarketInterest(market);
159
160 if (intel.getInertiaTime() >= INERTIA_DAYS_MAX ||
161 (intel.getInertiaTime() >= INERTIA_DAYS_MIN && score < minInterest)) {
162 if (!intel.isEnding()) {
163 intel.endAfterDelay();
164 if (market.isPlayerOwned() || DebugFlags.PATHER_BASE_DEBUG) {
166 }
167 }
168 cells.remove(market);
169 } else { // keep already-established cells for up to INERTIA_DAYS_MAX, at the expense of other potential cells
170 if (intel.isSleeper()) {
171 List<MarketAPI> sleeperList = new ArrayList<MarketAPI>(sleeper);
172 for (int i = sleeperList.size() - 1; i >= 0; i--) {
173 MarketAPI other = sleeperList.get(i);
174 LuddicPathCellsIntel otherIntel = cells.get(other);
175 if (otherIntel != null) continue;
176
177 sleeper.remove(other);
178 break;
179 }
180 sleeper.add(market);
181 } else {
182 List<MarketAPI> activeList = new ArrayList<MarketAPI>(active);
183 for (int i = activeList.size() - 1; i >= 0; i--) {
184 MarketAPI other = activeList.get(i);
185 LuddicPathCellsIntel otherIntel = cells.get(other);
186 if (otherIntel != null) continue;
187
188 active.remove(other);
189 break;
190 }
191 active.add(market);
192 }
193 }
194 } else {
195 intel.setInertiaTime(0f);
196 }
197 }
198
199 for (MarketAPI market : active) {
200 LuddicPathCellsIntel intel = cells.get(market);
202 if (intel == null) {
203 intel = new LuddicPathCellsIntel(market, base == null);
204 cells.put(market, intel);
205 }
206 if (base != null) {
207 intel.makeActiveIfPossible();
208 } else {
209 intel.makeSleeper();
210 }
211 }
212
213 for (MarketAPI market : sleeper) {
214 LuddicPathCellsIntel intel = cells.get(market);
215 if (intel == null) {
216 intel = new LuddicPathCellsIntel(market, true);
217 cells.put(market, intel);
218 }
219 intel.makeSleeper();
220 }
221 }
222
223 public static float getLuddicPathMarketInterest(MarketAPI market) {
224 if (market.getFactionId().equals(Factions.LUDDIC_PATH)) return 0f;
225 float total = 0f;
226
227 String aiCoreId = market.getAdmin().getAICoreId();
228 if (aiCoreId != null) {
229 total += AI_CORE_ADMIN_INTEREST;
230 }
231
232 for (Industry ind : market.getIndustries()) {
233 total += ind.getPatherInterest();
234 }
235
236 if (total > 0) {
237 total += new Random(market.getName().hashCode()).nextFloat() * 0.1f;
238 }
239
240 if (market.getFactionId().equals(Factions.LUDDIC_CHURCH)) {
242 }
243
246 }
247
248 return total;
249 }
250
251
252
253 protected Random random = new Random();
254 @Override
256 if (numSpawnChecksToSkip > 0) {
258 return null;
259 }
260
261 if (random.nextFloat() < CHECK_PROB) return null;
262
264 if (system == null) return null;
265
266 String factionId = Factions.LUDDIC_PATH;
267
268 LuddicPathBaseIntel intel = new LuddicPathBaseIntel(system, factionId);
269 if (intel.isDone()) intel = null;
270
271 return intel;
272 }
273
274
278
279 for (StarSystemAPI system : Global.getSector().getStarSystems()) {
280 if (system.hasTag(Tags.THEME_SPECIAL)) continue;
281 if (system.hasTag(Tags.THEME_HIDDEN)) continue;
282
283 float days = Global.getSector().getClock().getElapsedDaysSince(system.getLastPlayerVisitTimestamp());
284 if (days < 45f) continue;
285
286 if (system.getCenter().getMemoryWithoutUpdate().contains(PirateBaseManager.RECENTLY_USED_FOR_BASE)) continue;
287
288 float weight = 0f;
289 if (system.hasTag(Tags.THEME_MISC_SKIP)) {
290 weight = 1f;
291 } else if (system.hasTag(Tags.THEME_MISC)) {
292 weight = 3f;
293 } else if (system.hasTag(Tags.THEME_REMNANT_NO_FLEETS)) {
294 weight = 3f;
295 } else if (system.hasTag(Tags.THEME_RUINS)) {
296 weight = 5f;
297 } else if (system.hasTag(Tags.THEME_CORE_UNPOPULATED)) {
298 weight = 1f;
299 }
300 if (weight <= 0f) continue;
301
302 float usefulStuff = system.getCustomEntitiesWithTag(Tags.OBJECTIVE).size() +
303 system.getCustomEntitiesWithTag(Tags.STABLE_LOCATION).size();
304 if (usefulStuff <= 0) continue;
305
306 if (Misc.hasPulsar(system)) continue;
307 if (Misc.getMarketsInLocation(system).size() > 0) continue;
308
309 float dist = system.getLocation().length();
310
311
312// float distMult = 1f - dist / 20000f;
313// if (distMult > 1f) distMult = 1f;
314// if (distMult < 0.1f) distMult = 0.1f;
315
316 float distMult = 1f;
317
318 if (dist > 36000f) {
319 far.add(system, weight * usefulStuff * distMult);
320 } else {
321 picker.add(system, weight * usefulStuff * distMult);
322 }
323 }
324
325 if (picker.isEmpty()) {
326 picker.addAll(far);
327 }
328
329 return picker.pick();
330 }
331
332
333 protected int numDestroyed = 0;
334 protected int numSpawnChecksToSkip = 0;
335
336 public void incrDestroyed() {
337 numDestroyed++;
340 * 3); // checks happen every 10 days on average, *3 to get months
341 }
342}
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
static SettingsAPI getSettings()
Definition Global.java:57
static SectorAPI getSector()
Definition Global.java:65
static final String THEME_CORE_UNPOPULATED
Definition Tags.java:140
static final String THEME_REMNANT_NO_FLEETS
Definition Tags.java:185
void sendUpdateIfPlayerHasIntel(Object listInfoParam, TextPanelAPI textPanel)
static List< MarketAPI > getMarketsInLocation(LocationAPI location, String factionId)
Definition Misc.java:936
static boolean hasPulsar(StarSystemAPI system)
Definition Misc.java:2411
static float getDays(float amount)
Definition Misc.java:4663
List< StarSystemAPI > getStarSystems()
void set(String key, Object value)