Starsector API
Loading...
Searching...
No Matches
CoreImmigrationPluginImpl.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.population;
2
3import java.util.ArrayList;
4import java.util.List;
5
6import com.fs.starfarer.api.Global;
7import com.fs.starfarer.api.campaign.comm.CommMessageAPI.MessageClickAction;
8import com.fs.starfarer.api.campaign.econ.ImmigrationPlugin;
9import com.fs.starfarer.api.campaign.econ.MarketAPI;
10import com.fs.starfarer.api.campaign.econ.MarketImmigrationModifier;
11import com.fs.starfarer.api.impl.campaign.ids.Factions;
12import com.fs.starfarer.api.impl.campaign.ids.Strings;
13import com.fs.starfarer.api.impl.campaign.intel.BaseIntelPlugin;
14import com.fs.starfarer.api.impl.campaign.intel.MessageIntel;
15import com.fs.starfarer.api.util.Misc;
16
17public class CoreImmigrationPluginImpl implements ImmigrationPlugin {
18
19 public static float GROWTH_NO_INDUSTRIES = 0.01f;
20 public static float IMMIGRATION_PER_HAZARD = Global.getSettings().getFloat("immigrationPerHazard");
21 public static float HAZARD_SIZE_MULT = Global.getSettings().getFloat("immigrationHazardMultExtraPerColonySizeAbove3");
22
23 public static float INCENTIVE_CREDITS_PER_POINT = Global.getSettings().getFloat("immigrationIncentiveCostPerPoint");
24 public static float INCENTIVE_POINTS_EXTRA = Global.getSettings().getFloat("immigrationIncentivePointsAboveHazardPenalty");
25
26 public static final float FACTION_HOSTILITY_IMPACT = 2f;
27
28 protected MarketAPI market;
29
30
32 this.market = market;
33 }
34
35 public void advance(float days, boolean uiUpdateOnly) {
36// if (market.getName().equals("Umbra")) {
37// System.out.println("ewfwefew");
38// }
39
40// if (market.getName().equals("Jangala")) {
41// System.out.println("wefwefwe");
42// }
43
44 float f = days / 30f; // incoming is per month
45
46 boolean firstTime = !market.wasIncomingSetBefore();
47 Global.getSettings().profilerBegin("Computing incoming");
48 market.setIncoming(computeIncoming(uiUpdateOnly, f));
50
51// if (market.getName().equals("Jangala")) {
52// System.out.println("wefwefwe");
53// }
54
55// if (market.isPlayerOwned()) {
56// //market.setSize(2);
57// while (market.getSize() < 7) {
58// increaseMarketSize();
59// }
60// }
61
62 if (uiUpdateOnly) return;
63
64
65 int iter = 1;
66 if (firstTime) {
67 iter = 100;
68 }
69
70 for (int i = 0; i < iter; i++) {
71
72 if (iter > 1) {
73 f = (iter - i) * 0.1f;
74 }
75
76 PopulationComposition pop = market.getPopulation();
77 PopulationComposition inc = market.getIncoming();
78
79 for (String id : inc.getComp().keySet()) {
80 pop.add(id, inc.get(id) * f);
81 }
82
83// if (market.getName().equals("Ang")) {
84// System.out.println("efwefwefew");
85// }
86 float min = getWeightForMarketSize(market.getSize());
87 float max = getWeightForMarketSize(market.getSize() + 1);
88 //if (market.getSize() >= 10) max = min;
89
90
91 float newWeight = pop.getWeightValue() + inc.getWeightValue() * f;
92 //newWeight = pop.getWeightValue() + inc.getWeightValue() * f + 2000;
93 if (newWeight < min || Global.getSector().isInNewGameAdvance()) newWeight = min;
94 if (newWeight > max) {
96 newWeight = max;
97 }
98 pop.setWeight(newWeight);
99 pop.normalize();
100
101 // up to 5% of the non-faction population gets converted to faction, per month, more or less
102 float conversionFraction = 0.05f * market.getStabilityValue() / 10f;
103 conversionFraction *= f;
104 if (conversionFraction > 0) {
105 pop.add(market.getFactionId(), (pop.getWeightValue() - pop.get(market.getFactionId())) * conversionFraction);
106 }
107
108
109 // add some poor/pirate population at stability below 5
110 float pirateFraction = 0.01f * Math.max(0, (5f - market.getStabilityValue()) / 5f);
111 pirateFraction *= f;
112 if (pirateFraction > 0) {
113 pop.add(Factions.PIRATES, pop.getWeightValue() * pirateFraction);
114 pop.add(Factions.POOR, pop.getWeightValue() * pirateFraction);
115 }
116
117
118 for (String fid : new ArrayList<String>(pop.getComp().keySet())) {
119 if (Global.getSector().getFaction(fid) == null) {
120 pop.getComp().remove(fid);
121 }
122 }
123
124 pop.normalize();
125
126 }
127 }
128
129 public void increaseMarketSize() {
130 if (market.getSize() >= Misc.MAX_COLONY_SIZE || !market.isPlayerOwned()) {
131 market.getPopulation().setWeight(getWeightForMarketSizeStatic(market.getSize()));
132 market.getPopulation().normalize();
133 return;
134 }
135
137
138 if (market.isPlayerOwned()) {
139 MessageIntel intel = new MessageIntel("Colony Growth - " + market.getName(), Misc.getBasePlayerColor());
140 intel.addLine(BaseIntelPlugin.BULLET + "Size increased to %s",
141 Misc.getTextColor(),
142 new String[] {"" + (int)Math.round(market.getSize())},
143 Misc.getHighlightColor());
144
145 intel.setIcon(Global.getSector().getPlayerFaction().getCrest());
146 intel.setSound(BaseIntelPlugin.getSoundMajorPosting());
147 Global.getSector().getCampaignUI().addMessage(intel, MessageClickAction.COLONY_INFO, market);
148 }
149 }
150
151 public static void increaseMarketSize(MarketAPI market) {
152 if (market.getSize() >= Misc.MAX_COLONY_SIZE) return;
153
154 for (int i = 0; i <= 10; i++) {
155 market.removeCondition("population_" + i);
156 }
157 market.removeCondition("population_" + market.getSize());
158 market.addCondition("population_" + (market.getSize() + 1));
159
160 market.setSize(market.getSize() + 1);
161 market.reapplyConditions();
162 market.reapplyIndustries();
163
164 if (market.getSize() >= Misc.MAX_COLONY_SIZE) {
165 market.setImmigrationIncentivesOn(false);
166 }
167 }
168
169 public static void reduceMarketSize(MarketAPI market) {
170 if (market.getSize() <= 3) {
171 return;
172 }
173
174 market.removeCondition("population_" + market.getSize());
175 market.addCondition("population_" + (market.getSize() - 1));
176
177 market.setSize(market.getSize() - 1);
178
179 market.getPopulation().setWeight(getWeightForMarketSizeStatic(market.getSize()));
180 market.getPopulation().normalize();
181
182 market.reapplyConditions();
183 market.reapplyIndustries();
184 }
185
186
187 public static final float ZERO_STABILITY_PENALTY = -5;
188 public static final float MAX_DIST_PENALTY = -5;
189
190 public PopulationComposition computeIncoming(boolean uiUpdateOnly, float f) {
192
193 float stability = market.getStabilityValue();
194
195// if (stability > 0) {
196// inc.getWeight().modifyFlat("inc_st", stability, "Stability");
197// } else {
198// inc.getWeight().modifyFlat("inc_st", ZERO_STABILITY_PENALTY, "Stability");
199// }
200 if (stability < 5) {
201 inc.getWeight().modifyFlat("inc_st", stability - 5, "Instability");
202 }
203
204 int numInd = Misc.getNumIndustries(market);
205 if (numInd <= 0 && GROWTH_NO_INDUSTRIES != 0 && market.getSize() > 3) {
206 float weight = getWeightForMarketSize(market.getSize());
207 float penalty = -Math.round(weight * GROWTH_NO_INDUSTRIES);
208 inc.getWeight().modifyFlat("inc_noInd", penalty, "No industries");
209 }
210
211
212 //inc.getWeight().modifyFlat("inc_size", -market.getSize(), "Colony size");
213
214 float a = Math.round(market.getAccessibilityMod().computeEffective(0f) * 100f) / 100f;
215 int accessibilityMod = (int) (a / Misc.PER_UNIT_SHIPPING);
216 inc.getWeight().modifyFlat("inc_access", accessibilityMod, "Accessibility");
217
218
219 float hazMod = getImmigrationHazardPenalty(market);
220 if (hazMod != 0) {
221 float hazardSizeMult = getImmigrationHazardPenaltySizeMult(market);
222 inc.getWeight().modifyFlat("inc_hazard", hazMod,
223 "Hazard rating (" + Strings.X + Misc.getRoundedValueMaxOneAfterDecimal(hazardSizeMult) +
224 " based on colony size)");
225 }
226
227// float dMult = getDistFromCoreMult(market);
228// float dPenalty = Math.round(dMult * MAX_DIST_PENALTY);
229// if (dPenalty > 0) {
230// inc.getWeight().modifyFlat("inc_dist", -dPenalty, "Distance from core worlds");
231// }
232
233 MarketAPI biggestInSystem = null;
234 List<MarketAPI> inReach = Global.getSector().getEconomy().getMarketsWithSameGroup(market);
235 //Global.getSettings().profilerEnd();
236 for (MarketAPI curr : inReach) {
237 if (curr == market) continue;
238
239 if (curr.getFaction().isHostileTo(market.getFaction())) continue;
240
241 if (Misc.getDistanceLY(curr.getLocationInHyperspace(), market.getLocationInHyperspace()) <= 0) {
242 if (biggestInSystem == null || curr.getSize() > biggestInSystem.getSize()) {
243 biggestInSystem = curr;
244 }
245 }
246 }
247
248// float hostileFactions = 0;
249// for (FactionAPI faction : Global.getSector().getAllFactions()) {
250// if (faction.getCustomBoolean(Factions.CUSTOM_HOSTILITY_IMPACT_ON_GROWTH)) {
251// if (faction.isHostileTo(market.getFaction())) {
252// hostileFactions++;
253// }
254// }
255// }
256//
257// if (hostileFactions > 0) {
258// inc.getWeight().modifyFlat("inc_hosfac", -hostileFactions * FACTION_HOSTILITY_IMPACT,
259// "Open hostilities with major factions");
260// }
261
262 if (biggestInSystem != null) {
263 float sDiff = biggestInSystem.getSize() - market.getSize();
264 sDiff *= 2;
265 if (sDiff > 0) {
266 inc.getWeight().modifyFlat("inc_insys", sDiff, "Larger non-hostile colony in same system");
267 } else if (sDiff < 0) {
268 //inc.getWeight().modifyFlat("inc_insys", sDiff, "Smaller non-hostile market in same system");
269 }
270 }
271// else if (biggestInReach != null) {
272// float sDiff = biggestInReach.getSize() - market.getSize();
273// if (sDiff > 0) {
274// inc.getWeight().modifyFlat("inc_inreach", sDiff, "Larger non-hostile market within reach");
275// } else if (sDiff < 0) {
276// //inc.getWeight().modifyFlat("inc_inreach", sDiff, "Smaller non-hostile market within reach");
277// }
278// }
279
280 // so that the "baseline" incoming composition is based on the number of industries
281 // thus each industry can use a per-industry modifier without having outsize influence
282 // for example Farming can bring in X more Luddic Church immigration, and the impact
283 // this has will be diminished if there are more industries beyond Farming
284 float numIndustries = market.getIndustries().size();
285 inc.add(Factions.PIRATES, 1f * numIndustries);
286 inc.add(Factions.POOR, 1f * numIndustries);
287
288 String bulkFaction = Factions.INDEPENDENT;
289 if (market.getFaction().isHostileTo(bulkFaction)) {
290 bulkFaction = market.getFactionId();
291 }
292 inc.add(bulkFaction, 10f * numIndustries);
293
294 applyIncentives(inc, uiUpdateOnly, f);
295
296
297 for (MarketImmigrationModifier mod : market.getAllImmigrationModifiers()) {
298 mod.modifyIncoming(market, inc);
299 }
300
301// if (market.getName().equals("Mazalot")) {
302// System.out.println("wefwefwe");
303// }
304
305 for (String fid : new ArrayList<String>(inc.getComp().keySet())) {
306 if (Global.getSector().getFaction(fid) == null) {
307 inc.getComp().remove(fid);
308 }
309 }
310
312
313 return inc;
314 }
315
316
317 public static float getImmigrationHazardPenalty(MarketAPI market) {
318 float hazMod = Math.round((market.getHazardValue() - 1f) / IMMIGRATION_PER_HAZARD);
319 if (hazMod < 0) hazMod = 0;
320 float hazardSizeMult = getImmigrationHazardPenaltySizeMult(market);
321 return -hazMod * hazardSizeMult;
322 }
323
324 public static float getImmigrationHazardPenaltySizeMult(MarketAPI market) {
325 float hazardSizeMult = 1f + (market.getSize() - 3f) * HAZARD_SIZE_MULT;
326 return hazardSizeMult;
327 }
328
329
330
331
332 protected void applyIncentives(PopulationComposition inc, boolean uiUpdateOnly, float f) {
333// if (market.getName().equals("Jangala")) {
334// System.out.println("ewfwfew");
335// }
336 if (!market.isImmigrationIncentivesOn()) return;
337 if (market.getSize() >= Misc.MAX_COLONY_SIZE) {
338 market.setImmigrationIncentivesOn(false);
339 return;
340 }
341
342
344 //float cost = INCENTIVE_CREDITS_PER_POINT * points * f;
345 float cost = market.getImmigrationIncentivesCost() * f;
346
347 if (points > 0) {
348 inc.getWeight().modifyFlat("inc_incentives", points, "Hazard pay");
349 if (!uiUpdateOnly) {
350 market.setIncentiveCredits(market.getIncentiveCredits() + cost);
351 }
352 }
353
354 }
355
356 public float getPopulationPointsForFraction(float fraction) {
357 float min = getWeightForMarketSize(market.getSize());
358 float max = getWeightForMarketSize(market.getSize() + 1);
359
360 return (max - min) * fraction;
361 }
362
363 public float getFractionForPopulationPoints(float points) {
364 float min = getWeightForMarketSize(market.getSize());
365 float max = getWeightForMarketSize(market.getSize() + 1);
366
367 return points / (max - min);
368 }
369
370 public static float getWeightForMarketSizeStatic(float size) {
371 //return (float) (100f * Math.pow(2, size - 3));
372 return (float) (300f * Math.pow(2, size - 3));
373 }
374 public float getWeightForMarketSize(float size) {
375 return getWeightForMarketSizeStatic(size);
376// if (size <= 1) return 100;
377// if (size == 2) return 200;
378// if (size == 3) return 400;
379// if (size == 4) return 800;
380// if (size == 5) return 1600;
381// if (size == 6) return 3200;
382// if (size == 7) return 6400;
383// if (size == 8) return 12800;
384// if (size == 9) return 25600;
385// if (size == 10) return 51200;
386// if (size == 11) return 102400;
387// return 100000;
388 }
389
390}
391
392
393
394
395
396
static SettingsAPI getSettings()
Definition Global.java:51
static SectorAPI getSector()
Definition Global.java:59
void applyIncentives(PopulationComposition inc, boolean uiUpdateOnly, float f)