Starsector API
Loading...
Searching...
No Matches
PopulationAndInfrastructure.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.econ.impl;
2
3import java.awt.Color;
4import java.util.ArrayList;
5import java.util.List;
6
7import org.json.JSONArray;
8import org.json.JSONException;
9import org.lwjgl.util.vector.Vector2f;
10
11import com.fs.starfarer.api.EveryFrameScript;
12import com.fs.starfarer.api.Global;
13import com.fs.starfarer.api.campaign.FactionDoctrineAPI;
14import com.fs.starfarer.api.campaign.SectorEntityToken;
15import com.fs.starfarer.api.campaign.SpecialItemData;
16import com.fs.starfarer.api.campaign.econ.CommodityMarketDataAPI;
17import com.fs.starfarer.api.campaign.econ.CommodityOnMarketAPI;
18import com.fs.starfarer.api.campaign.econ.Industry;
19import com.fs.starfarer.api.campaign.econ.MarketAPI;
20import com.fs.starfarer.api.campaign.econ.MarketImmigrationModifier;
21import com.fs.starfarer.api.campaign.listeners.ColonyOtherFactorsListener;
22import com.fs.starfarer.api.characters.MarketConditionSpecAPI;
23import com.fs.starfarer.api.characters.MutableCharacterStatsAPI;
24import com.fs.starfarer.api.combat.MutableStat;
25import com.fs.starfarer.api.combat.MutableStat.StatMod;
26import com.fs.starfarer.api.impl.campaign.econ.CommRelayCondition;
27import com.fs.starfarer.api.impl.campaign.econ.impl.ConstructionQueue.ConstructionQueueItem;
28import com.fs.starfarer.api.impl.campaign.fleets.FleetFactoryV3;
29import com.fs.starfarer.api.impl.campaign.ids.Commodities;
30import com.fs.starfarer.api.impl.campaign.ids.Conditions;
31import com.fs.starfarer.api.impl.campaign.ids.Entities;
32import com.fs.starfarer.api.impl.campaign.ids.Factions;
33import com.fs.starfarer.api.impl.campaign.ids.Industries;
34import com.fs.starfarer.api.impl.campaign.ids.Items;
35import com.fs.starfarer.api.impl.campaign.ids.Stats;
36import com.fs.starfarer.api.impl.campaign.ids.Tags;
37import com.fs.starfarer.api.impl.campaign.population.PopulationComposition;
38import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator;
39import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.AddedEntity;
40import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator.EntityLocation;
41import com.fs.starfarer.api.loading.IndustrySpecAPI;
42import com.fs.starfarer.api.ui.TooltipMakerAPI;
43import com.fs.starfarer.api.ui.TooltipMakerAPI.StatModValueGetter;
44import com.fs.starfarer.api.util.Misc;
45import com.fs.starfarer.api.util.Pair;
46
47
48public class PopulationAndInfrastructure extends BaseIndustry implements MarketImmigrationModifier {
49
50 public static float OFFICER_BASE_PROB = Global.getSettings().getFloat("officerBaseProb");
51 public static float OFFICER_PROB_PER_SIZE = Global.getSettings().getFloat("officerProbPerColonySize");
52 public static float OFFICER_ADDITIONAL_BASE_PROB = Global.getSettings().getFloat("officerAdditionalBaseProb");
53 public static float OFFICER_BASE_MERC_PROB = Global.getSettings().getFloat("officerBaseMercProb");
54 public static float ADMIN_BASE_PROB = Global.getSettings().getFloat("adminBaseProb");
55 public static float ADMIN_PROB_PER_SIZE = Global.getSettings().getFloat("adminProbPerColonySize");
56
57
58 //public static float IMPROVE_GROWTH_BONUS = 1f;
59 public static float IMPROVE_STABILITY_BONUS = 1f;
60
61 public static boolean HAZARD_INCREASES_DEFENSE = false;
62
63 public void apply() {
65
66// if (market.getId().equals("chicomoztoc")) {
67// System.out.println("wefwefwe");
68// }
69
70 super.apply(true);
71
72 int size = market.getSize();
73
74 demand(Commodities.FOOD, size);
75
76 if (!market.hasCondition(Conditions.HABITABLE)) {
77 demand(Commodities.ORGANICS, size - 1);
78 }
79
80 int luxuryThreshold = 3;
81
82 demand(Commodities.DOMESTIC_GOODS, size - 1);
83 demand(Commodities.LUXURY_GOODS, size - luxuryThreshold);
84 demand(Commodities.DRUGS, size - 2);
85 demand(Commodities.ORGANS, size - 3);
86
87 demand(Commodities.SUPPLIES, Math.min(size, 3));
88
89 supply(Commodities.CREW, size - 3);
90 supply(Commodities.DRUGS, size - 4);
91 supply(Commodities.ORGANS, size - 5);
92
93
94 Pair<String, Integer> deficit = getMaxDeficit(Commodities.DOMESTIC_GOODS);
95 if (deficit.two <= 0) {
96 market.getStability().modifyFlat(getModId(0), 1, "Domestic goods demand met");
97 } else {
98 market.getStability().unmodifyFlat(getModId(0));
99 }
100
101 deficit = getMaxDeficit(Commodities.LUXURY_GOODS);
102 if (deficit.two <= 0 && size > luxuryThreshold) {
103 market.getStability().modifyFlat(getModId(1), 1, "Luxury goods demand met");
104 } else {
105 market.getStability().unmodifyFlat(getModId(1));
106 }
107
108 deficit = getMaxDeficit(Commodities.FOOD);
109 if (!market.hasCondition(Conditions.HABITABLE)) {
110 deficit = getMaxDeficit(Commodities.FOOD, Commodities.ORGANICS);
111 }
112 if (deficit.two > 0) {
113 market.getStability().modifyFlat(getModId(2), -deficit.two, getDeficitText(deficit.one));
114 } else {
115 market.getStability().unmodifyFlat(getModId(2));
116 }
117
118
119 boolean spaceportFirstInQueue = false;
120 for (ConstructionQueueItem item : market.getConstructionQueue().getItems()) {
121 IndustrySpecAPI spec = Global.getSettings().getIndustrySpec(item.id);
122 if (spec.hasTag(Industries.TAG_SPACEPORT)) {
123 spaceportFirstInQueue = true;
124 }
125 break;
126 }
127 if (spaceportFirstInQueue && Misc.getCurrentlyBeingConstructed(market) != null) {
128 spaceportFirstInQueue = false;
129 }
130 if (!market.hasSpaceport() && !spaceportFirstInQueue) {
131 float accessibilityNoSpaceport = Global.getSettings().getFloat("accessibilityNoSpaceport");
132 market.getAccessibilityMod().modifyFlat(getModId(0), accessibilityNoSpaceport, "No spaceport");
133 }
134
135 float sizeBonus = getAccessibilityBonus(size);
136 if (sizeBonus > 0) {
137 market.getAccessibilityMod().modifyFlat(getModId(1), sizeBonus, "Colony size");
138 }
139
140
141
142
143 float stability = market.getPrevStability();
144 float stabilityQualityMod = FleetFactoryV3.getShipQualityModForStability(stability);
145 float doctrineQualityMod = market.getFaction().getDoctrine().getShipQualityContribution();
146
147 market.getStats().getDynamic().getMod(Stats.FLEET_QUALITY_MOD).modifyFlatAlways(getModId(0), stabilityQualityMod,
148 "Stability");
149
150 market.getStats().getDynamic().getMod(Stats.FLEET_QUALITY_MOD).modifyFlatAlways(getModId(1), doctrineQualityMod,
151 Misc.ucFirst(market.getFaction().getEntityNamePrefix()) + " fleet doctrine");
152
153 //float stabilityDefenseMult = 0.5f + stability / 10f;
154 float stabilityDefenseMult = 0.25f + stability / 10f * 0.75f;
155 market.getStats().getDynamic().getMod(Stats.GROUND_DEFENSES_MOD).modifyMultAlways(getModId(),
156 stabilityDefenseMult, "Stability");
157
158 float baseDef = getBaseGroundDefenses(market.getSize());
159 market.getStats().getDynamic().getMod(Stats.GROUND_DEFENSES_MOD).modifyFlatAlways(getModId(),
160 baseDef, "Base value for a size " + market.getSize() + " colony");
161
162
163 //if (market.getHazardValue() > 1f) {
165 market.getStats().getDynamic().getMod(Stats.GROUND_DEFENSES_MOD).modifyMultAlways(getModId(1),
166 Math.max(market.getHazardValue(), 1f), "Colony hazard rating");
167 }
168 //}
169
170 market.getStats().getDynamic().getMod(Stats.MAX_INDUSTRIES).modifyFlat(getModId(), getMaxIndustries(), null);
171
172// if (market.isPlayerOwned()) {
173// System.out.println("wfwefwef");
174// }
175 FactionDoctrineAPI doctrine = market.getFaction().getDoctrine();
176 float doctrineShipsMult = FleetFactoryV3.getDoctrineNumShipsMult(doctrine.getNumShips());
177 float marketSizeShipsMult = FleetFactoryV3.getNumShipsMultForMarketSize(market.getSize());
178 float deficitShipsMult = FleetFactoryV3.getShipDeficitFleetSizeMult(market);
179 float stabilityShipsMult = FleetFactoryV3.getNumShipsMultForStability(stability);
180
181 market.getStats().getDynamic().getMod(Stats.COMBAT_FLEET_SIZE_MULT).modifyFlatAlways(getModId(0), marketSizeShipsMult,
182 "Colony size");
183
184 market.getStats().getDynamic().getMod(Stats.COMBAT_FLEET_SIZE_MULT).modifyMultAlways(getModId(1), doctrineShipsMult,
185 Misc.ucFirst(market.getFaction().getEntityNamePrefix()) + " fleet doctrine");
186
187 if (deficitShipsMult != 1f) {
188 market.getStats().getDynamic().getMod(Stats.COMBAT_FLEET_SIZE_MULT).modifyMult(getModId(2), deficitShipsMult,
189 getDeficitText(Commodities.SHIPS));
190 } else {
191 market.getStats().getDynamic().getMod(Stats.COMBAT_FLEET_SIZE_MULT).modifyMultAlways(getModId(2), deficitShipsMult,
192 getDeficitText(Commodities.SHIPS).replaceAll("shortage", "demand met"));
193 }
194
195 market.getStats().getDynamic().getMod(Stats.COMBAT_FLEET_SIZE_MULT).modifyMultAlways(getModId(3), stabilityShipsMult,
196 "Stability");
197
198
199 // chance of spawning officers and admins; some industries further modify this
200 market.getStats().getDynamic().getMod(Stats.OFFICER_PROB_MOD).modifyFlat(getModId(0), OFFICER_BASE_PROB);
201 market.getStats().getDynamic().getMod(Stats.OFFICER_PROB_MOD).modifyFlat(getModId(1),
202 OFFICER_PROB_PER_SIZE * Math.max(0, market.getSize() - 3));
203
204 market.getStats().getDynamic().getMod(Stats.OFFICER_ADDITIONAL_PROB_MULT_MOD).modifyFlat(getModId(0), OFFICER_ADDITIONAL_BASE_PROB);
205 market.getStats().getDynamic().getMod(Stats.OFFICER_IS_MERC_PROB_MOD).modifyFlat(getModId(0), OFFICER_BASE_MERC_PROB);
206
207 market.getStats().getDynamic().getMod(Stats.ADMIN_PROB_MOD).modifyFlat(getModId(0), ADMIN_BASE_PROB);
208 market.getStats().getDynamic().getMod(Stats.ADMIN_PROB_MOD).modifyFlat(getModId(1),
209 ADMIN_PROB_PER_SIZE * Math.max(0, market.getSize() - 3));
210
212
213 market.addTransientImmigrationModifier(this);
214
215
216
217// // if there's no queued spaceport, setHasSpaceport() is called by Spaceport (if it's present at the market)
218// boolean spaceportFirstInQueue = false;
219// for (ConstructionQueueItem item : market.getConstructionQueue().getItems()) {
220// IndustrySpecAPI spec = Global.getSettings().getIndustrySpec(item.id);
221// if (spec.hasTag(Industries.TAG_SPACEPORT)) {
222// market.setHasSpaceport(true);
223// market.getMemoryWithoutUpdate().set("$hadQueuedSpaceport", true);
224// spaceportFirstInQueue = true;
225// }
226// break;
227// }
228// if (!spaceportFirstInQueue && market.hasSpaceport() && market.getMemoryWithoutUpdate().is("$hadQueuedSpaceport", true)) {
229// market.getMemoryWithoutUpdate().unset("$hadQueuedSpaceport");
230// boolean hasSpaceport = false;
231// for (Industry ind : market.getIndustries()) {
232// if (ind.getSpec().hasTag(Industries.TAG_SPACEPORT)) {
233// hasSpaceport = true;
234// break;
235// }
236// }
237// if (!hasSpaceport) {
238// market.setHasSpaceport(false);
239// }
240// }
241
242 }
243
244
245 public static float getAccessibilityBonus(int marketSize) {
246 if (marketSize <= 4) return 0f;
247 if (marketSize == 5) return 0.1f;
248 if (marketSize == 6) return 0.15f;
249 if (marketSize == 7) return 0.2f;
250 if (marketSize == 8) return 0.25f;
251 return 0.3f;
252 }
253 public static float getBaseGroundDefenses(int marketSize) {
254 if (marketSize <= 1) return 10;
255 if (marketSize <= 2) return 20;
256 if (marketSize <= 3) return 50;
257
258 return (marketSize - 3) * 100;
259 }
260
261 @Override
262 public void unapply() {
263 super.unapply();
264
265 market.getStability().unmodify(getModId(0));
266 market.getStability().unmodify(getModId(1));
267 market.getStability().unmodify(getModId(2));
268
269 market.getAccessibilityMod().unmodifyFlat(getModId(0));
270 market.getAccessibilityMod().unmodifyFlat(getModId(1));
271
272 market.getStats().getDynamic().getMod(Stats.FLEET_QUALITY_MOD).unmodifyFlat(getModId(0));
273 market.getStats().getDynamic().getMod(Stats.FLEET_QUALITY_MOD).unmodifyFlat(getModId(1));
274
275 market.getStats().getDynamic().getMod(Stats.GROUND_DEFENSES_MOD).unmodifyFlat(getModId());
276 market.getStats().getDynamic().getMod(Stats.GROUND_DEFENSES_MOD).unmodifyMult(getModId());
278 market.getStats().getDynamic().getMod(Stats.GROUND_DEFENSES_MOD).unmodifyMult(getModId(1)); // hazard value modifier
279 }
280
281 market.getStats().getDynamic().getMod(Stats.MAX_INDUSTRIES).unmodifyFlat(getModId());
282
283 market.getStats().getDynamic().getMod(Stats.COMBAT_FLEET_SIZE_MULT).unmodifyFlat(getModId(0));
284 market.getStats().getDynamic().getMod(Stats.COMBAT_FLEET_SIZE_MULT).unmodifyMult(getModId(1));
285 market.getStats().getDynamic().getMod(Stats.COMBAT_FLEET_SIZE_MULT).unmodifyMult(getModId(2));
286 market.getStats().getDynamic().getMod(Stats.COMBAT_FLEET_SIZE_MULT).unmodifyMult(getModId(3));
287
288 market.getStats().getDynamic().getMod(Stats.OFFICER_PROB_MOD).unmodifyFlat(getModId(0));
289 market.getStats().getDynamic().getMod(Stats.OFFICER_PROB_MOD).unmodifyFlat(getModId(1));
290 market.getStats().getDynamic().getMod(Stats.OFFICER_ADDITIONAL_PROB_MULT_MOD).unmodifyFlat(getModId(0));
291 market.getStats().getDynamic().getMod(Stats.OFFICER_IS_MERC_PROB_MOD).unmodifyFlat(getModId(0));
292 market.getStats().getDynamic().getMod(Stats.ADMIN_PROB_MOD).unmodifyFlat(getModId(0));
293 market.getStats().getDynamic().getMod(Stats.ADMIN_PROB_MOD).unmodifyFlat(getModId(1));
294
296
297 market.removeTransientImmigrationModifier(this);
298 }
299
300 protected boolean hasPostDemandSection(boolean hasDemand, IndustryTooltipMode mode) {
301 return true;
302 }
303
304 @Override
305 protected void addPostDemandSection(TooltipMakerAPI tooltip, boolean hasDemand, IndustryTooltipMode mode) {
306 if (mode != IndustryTooltipMode.NORMAL || isFunctional()) {
307
308 MutableStat stabilityMods = new MutableStat(0);
309
310 float total = 0;
311 for (StatMod mod : market.getStability().getFlatMods().values()) {
312 if (mod.source.startsWith(getModId())) {
313 stabilityMods.modifyFlat(mod.source, mod.value, mod.desc);
314 total += mod.value;
315 }
316 }
317
318 String totalStr = "+" + (int)Math.round(total);
319 Color h = Misc.getHighlightColor();
320 if (total < 0) {
321 totalStr = "" + (int)Math.round(total);
322 h = Misc.getNegativeHighlightColor();
323 }
324 float opad = 10f;
325 float pad = 3f;
326 if (total >= 0) {
327 tooltip.addPara("Stability bonus: %s", opad, h, totalStr);
328 } else {
329 tooltip.addPara("Stability penalty: %s", opad, h, totalStr);
330 }
331 tooltip.addStatModGrid(400, 30, opad, pad, stabilityMods, new StatModValueGetter() {
332 public String getPercentValue(StatMod mod) {
333 return null;
334 }
335 public String getMultValue(StatMod mod) {
336 return null;
337 }
338 public Color getModColor(StatMod mod) {
339 if (mod.value < 0) return Misc.getNegativeHighlightColor();
340 return null;
341 }
342 public String getFlatValue(StatMod mod) {
343 return null;
344 }
345 });
346
347 /*
348 MutableStat qualityMods = new MutableStat(0);
349
350 total = 0;
351 for (StatMod mod : market.getStats().getDynamic().getMod(Stats.FLEET_QUALITY_MOD).getFlatBonuses().values()) {
352 if (mod.source.startsWith(getModId())) {
353 qualityMods.modifyFlat(mod.source, mod.value, mod.desc);
354 total += mod.value;
355 }
356 }
357
358 totalStr = "+" + (int)Math.round(total * 100f) + "%";
359 if (total < 0) {
360 totalStr = "" + (int)Math.round(total * 100f) + "%";
361 h = Misc.getNegativeHighlightColor();
362 }
363 if (total >= 0) {
364 tooltip.addPara("Ship quality bonus: %s", opad, h, totalStr);
365 } else {
366 tooltip.addPara("Ship quality penalty: %s", opad, h, totalStr);
367 }
368 tooltip.addStatModGrid(400, 50, opad, pad, qualityMods, new StatModValueGetter() {
369 public String getPercentValue(StatMod mod) {
370 return null;
371 }
372 public String getMultValue(StatMod mod) {
373 return null;
374 }
375 public Color getModColor(StatMod mod) {
376 if (mod.value < 0) return Misc.getNegativeHighlightColor();
377 return null;
378 }
379 public String getFlatValue(StatMod mod) {
380 String prefix = mod.value >= 0 ? "+" : "";
381 return prefix + (int)Math.round(mod.value * 100f) + "%";
382 }
383 });
384 */
385
386 }
387 }
388
389
390
391 @Override
392 public String getCurrentImage() {
393 float size = market.getSize();
394 if (size <= SIZE_FOR_SMALL_IMAGE) {
395 return Global.getSettings().getSpriteName("industry", "pop_low");
396 }
397 if (size >= SIZE_FOR_LARGE_IMAGE) {
398 return Global.getSettings().getSpriteName("industry", "pop_high");
399 }
400
401 return super.getCurrentImage();
402 }
403
404
405 public static float getIncomeStabilityMult(float stability) {
406 if (stability <= 5) {
407 return Math.max(0, stability / 5f);
408 }
409 return 1f;
410 //return 1f + (stability - 5f) * .1f;
411 }
412
413// public static float getUpkeepHazardMult(float hazard) {
414// float hazardMult = hazard;
415// float min = Global.getSettings().getFloat("minUpkeepMult");
416// if (hazardMult < min) hazardMult = min;
417// return hazardMult;
418// }
419 public static float getUpkeepHazardMult(float hazard) {
420 //float hazardMult = 1f + hazard;
421 float hazardMult = hazard;
422 float min = Global.getSettings().getFloat("minUpkeepMult");
423 if (hazardMult < min) hazardMult = min;
424 return hazardMult;
425 }
426
427
428 public static int getMismanagementPenalty() {
429 int outposts = 0;
430 for (MarketAPI curr : Global.getSector().getEconomy().getMarketsCopy()) {
431 if (!curr.isPlayerOwned()) continue;
432
433 if (curr.getAdmin().isPlayer()) {
434 outposts++;
435 }
436 }
437
438 MutableCharacterStatsAPI stats = Global.getSector().getCharacterData().getPerson().getStats();
439
440 int maxOutposts = stats.getOutpostNumber().getModifiedInt();
441
442 int overOutposts = outposts - maxOutposts;
443
444 //if (overOutposts < 0) overOutposts = 0;
445
446 int penaltyOrBonus = (int) (overOutposts * Misc.getOutpostPenalty());
447
448 return penaltyOrBonus;
449 }
450
451 public static void modifyStability2(Industry industry, MarketAPI market, String modId) {
452 if (Misc.getNumIndustries(market) > Misc.getMaxIndustries(market)) {
453 market.getStability().modifyFlat("_" + modId + "_overmax", -Misc.OVER_MAX_INDUSTRIES_PENALTY, "Maximum number of industries exceeded");
454 } else {
455 market.getStability().unmodifyFlat("_" + modId + "_overmax");
456 }
457 }
458
465 public static void modifyUpkeepByHazardRating(MarketAPI market, String modId) {
466 market.getUpkeepMult().modifyMultAlways(modId, getUpkeepHazardMult(market.getHazardValue()), "Hazard rating");
467 }
468
469 public static void modifyStability(Industry industry, MarketAPI market, String modId) {
470 market.getIncomeMult().modifyMultAlways(modId, getIncomeStabilityMult(market.getPrevStability()), "Stability");
471
472 market.getStability().modifyFlat("_" + modId + "_ms", Global.getSettings().getFloat("stabilityBaseValue"), "Base value");
473
474 float inFactionSupply = 0f;
475 float totalDemand = 0f;
476 for (CommodityOnMarketAPI com : market.getCommoditiesCopy()) {
477 if (com.isNonEcon()) continue;
478
479 int d = com.getMaxDemand();
480 if (d <= 0) continue;
481
482 totalDemand += d;
483 CommodityMarketDataAPI cmd = com.getCommodityMarketData();
484 int inFaction = Math.max(Math.min(com.getMaxSupply(), com.getAvailable()),
485 Math.min(cmd.getMaxShipping(market, true), cmd.getMaxExport(market.getFactionId())));
486 if (inFaction > d) inFaction = d;
487 if (inFaction < d) inFaction = Math.max(Math.min(com.getMaxSupply(), com.getAvailable()), 0);
488
489 //CommoditySourceType source = cmd.getMarketShareData(market).getSource();;
490 //if (source != CommoditySourceType.GLOBAL) {
491 // inFactionSupply += Math.min(d - inFaction, com.getAvailable());
492 //}
493 inFactionSupply += Math.max(0, Math.min(inFaction, com.getAvailable()));
494 }
495
496 if (totalDemand > 0) {
497 float max = Global.getSettings().getFloat("upkeepReductionFromInFactionImports");
498 float f = inFactionSupply / totalDemand;
499 if (f < 0) f = 0;
500 if (f > 1) f = 1;
501 if (f > 0) {
502 float mult = Math.round(100f - (f * max * 100f)) / 100f;
503 String desc = "Demand supplied in-faction (" + (int)Math.round(f * 100f) + "%)";
504 if (f == 1f) desc = "All demand supplied in-faction";
505 market.getUpkeepMult().modifyMultAlways(modId + "ifi", mult, desc);
506 } else {
507 market.getUpkeepMult().modifyMultAlways(modId + "ifi", 1f, "All demand supplied out-of-faction; no upkeep reduction");
508 }
509 }
510
511
512 if (market.isPlayerOwned() && market.getAdmin().isPlayer()) {
513 int penalty = getMismanagementPenalty();
514 if (penalty > 0) {
515 market.getStability().modifyFlat("_" + modId + "_mm", -penalty, "Mismanagement penalty");
516 } else if (penalty < 0) {
517 market.getStability().modifyFlat("_" + modId + "_mm", -penalty, "Management bonus");
518 } else {
519 market.getStability().unmodifyFlat("_" + modId + "_mm");
520 }
521 } else {
522 market.getStability().unmodifyFlat(modId + "_mm");
523 }
524
525 if (!market.hasCondition(Conditions.COMM_RELAY)) {
526 market.getStability().modifyFlat(CommRelayCondition.COMM_RELAY_MOD_ID, CommRelayCondition.NO_RELAY_PENALTY, "No active comm relay in-system");
527 }
528 }
529
530
531 public static void unmodifyStability(MarketAPI market, String modId) {
532 market.getIncomeMult().unmodifyMult(modId);
533 market.getUpkeepMult().unmodifyMult(modId);
534 market.getUpkeepMult().unmodifyMult(modId + "ifi");
535
536 market.getStability().unmodifyFlat(modId);
537
538// for (int i = 0; i < 30; i++) {
539// market.getStability().unmodify(modId + i);
540// }
541 market.getStability().unmodifyFlat("_" + modId + "_mm");
542 market.getStability().unmodifyFlat("_" + modId + "_ms");
543 market.getStability().unmodifyFlat("_" + modId + "_overmax");
544
545 if (!market.hasCondition(Conditions.COMM_RELAY)) {
546 market.getStability().unmodifyFlat(CommRelayCondition.COMM_RELAY_MOD_ID);
547 }
548
549 }
550
551
552
553 @Override
554 public boolean showShutDown() {
555 return false;
556 }
557
558 @Override
559 public String getCanNotShutDownReason() {
560 //return "Use \"Abandon Colony\" instead.";
561 return null;
562 }
563
564 @Override
565 public boolean canShutDown() {
566 return false;
567 }
568
569 @Override
570 protected String getDescriptionOverride() {
571 int size = market.getSize();
572 String cid = null;
573 if (size >= 1 && size <= 9) {
574 cid = "population_" + size;
575 MarketConditionSpecAPI mcs = Global.getSettings().getMarketConditionSpec(cid);
576 if (mcs != null) {
577 return spec.getDesc() + "\n\n" + mcs.getDesc().replaceAll("\\$marketName", market.getName());
578 }
579 }
580 return super.getDescriptionOverride();
581 }
582
584// float f = buildProgress / spec.getBuildTime();
585// return "" + (int) Math.round(f * 100f) + "%";
586 if (isUpgrading()) {
587 //return "" + (int) Math.round(Misc.getMarketSizeProgress(market) * 100f) + "%";
588 return "total growth: " + Misc.getRoundedValue(Misc.getMarketSizeProgress(market) * 100f) + "%";
589 }
590
591 return super.getBuildOrUpgradeProgressText();
592 }
593
594 @Override
596 if (!super.isBuilding() && market.getSize() < Misc.MAX_COLONY_SIZE) {
597 return Misc.getMarketSizeProgress(market);
598 }
599 return super.getBuildOrUpgradeProgress();
600 }
601
602 @Override
603 public boolean isBuilding() {
604 if (!super.isBuilding() && market.getSize() < Misc.MAX_COLONY_SIZE && getBuildOrUpgradeProgress() > 0) return true;
605
606 return super.isBuilding();
607 }
608
609 @Override
610 public boolean isUpgrading() {
611 if (!super.isBuilding() && market.getSize() < Misc.MAX_COLONY_SIZE) return true;
612
613 return super.isUpgrading();
614 }
615
616
617
618 public void modifyIncoming(MarketAPI market, PopulationComposition incoming) {
619 float patherLevel = 0;
620 for (Industry curr : market.getIndustries()) {
621 patherLevel += getAICoreImpact(curr.getAICoreId());
622 }
623
624 String adminCoreId = market.getAdmin().getAICoreId();
625 if (adminCoreId != null) {
626 patherLevel += 10f * getAICoreImpact(adminCoreId);
627 }
628
629 List<String> targeted = new ArrayList<String>();
630 targeted.add(Industries.TECHMINING);
631 targeted.add(Industries.HEAVYINDUSTRY);
632 targeted.add(Industries.FUELPROD);
633 targeted.add(Industries.STARFORTRESS);
634
635 for (String curr : targeted) {
636 if (market.hasIndustry(curr)) {
637 patherLevel += 10f;
638 }
639 }
640
641 if (patherLevel > 0) {
642 incoming.add(Factions.LUDDIC_PATH, patherLevel * 0.2f);
643 }
644
645// if (isImproved()) {
646// incoming.getWeight().modifyFlat(getModId(2), (int)Math.round(market.getSize() * IMPROVE_GROWTH_BONUS),
647// getImprovementsDescForModifiers() + " (" + getNameForModifier() + ")");
648// }
649 }
650
651 private float getAICoreImpact(String coreId) {
652 if (Commodities.ALPHA_CORE.equals(coreId)) return 10f;
653 if (Commodities.BETA_CORE.equals(coreId)) return 4f;
654 if (Commodities.GAMMA_CORE.equals(coreId)) return 1f;
655 return 0f;
656 }
657
658 public boolean canBeDisrupted() {
659 return false;
660 }
661
662 public int getMaxIndustries() {
663 return getMaxIndustries(market.getSize());
664 }
665
666 public static int [] MAX_IND = null;
667 public static int getMaxIndustries(int size) {
668 if (MAX_IND == null) {
669 try {
670 MAX_IND = new int [10];
671 JSONArray a = Global.getSettings().getJSONArray("maxIndustries");
672 for (int i = 0; i < MAX_IND.length; i++) {
673 MAX_IND[i] = a.getInt(i);
674 }
675 } catch (JSONException e) {
676 throw new RuntimeException(e);
677 }
678 }
679 size--;
680 if (size < 0) size = 0;
681 if (size > 9) size = 9;
682 return MAX_IND[size];
683// if (size <= 3) return 1;
684// if (size <= 5) return 2;
685// if (size <= 7) return 3;
686// return 4;
687 }
688
689// @Override
690// public boolean canImprove() {
691// return true;
692// }
693//
694// public void addImproveDesc(TooltipMakerAPI info, ImprovementDescriptionMode mode) {
695// float opad = 10f;
696// Color highlight = Misc.getHighlightColor();
697//
698//
699// String str = "" + (int)Math.round(market.getSize() * IMPROVE_GROWTH_BONUS);
700//
701// if (mode == ImprovementDescriptionMode.INDUSTRY_TOOLTIP) {
702// info.addPara("Population growth increased by %s.", 0f, highlight,str);
703// } else {
704// info.addPara("Increases population growth by %s. Bonus is based on colony size.", 0f, highlight,str);
705// }
706//
707// info.addSpacer(opad);
708// super.addImproveDesc(info, mode);
709// }
710
711 @Override
712 public boolean canImprove() {
713 return true;
714 }
715
716 protected void applyImproveModifiers() {
717 if (isImproved()) {
718 market.getStability().modifyFlat("PAI_improve", IMPROVE_STABILITY_BONUS,
720 } else {
721 market.getStability().unmodifyFlat("PAI_improve");
722 }
723 }
724
725 public void addImproveDesc(TooltipMakerAPI info, ImprovementDescriptionMode mode) {
726 float opad = 10f;
727 Color highlight = Misc.getHighlightColor();
728
729
730 if (mode == ImprovementDescriptionMode.INDUSTRY_TOOLTIP) {
731 info.addPara("Stability increased by %s.", 0f, highlight, "" + (int) IMPROVE_STABILITY_BONUS);
732 } else {
733 info.addPara("Increases stability by %s.", 0f, highlight, "" + (int) IMPROVE_STABILITY_BONUS);
734 }
735
736 info.addSpacer(opad);
737 super.addImproveDesc(info, mode);
738 }
739
740
741
742 protected static class LampRemover implements EveryFrameScript {
743 protected SectorEntityToken lamp;
744 protected MarketAPI market;
745 protected PopulationAndInfrastructure industry;
746 public LampRemover(SectorEntityToken lamp, MarketAPI market, PopulationAndInfrastructure industry) {
747 this.lamp = lamp;
748 this.market = market;
749 this.industry = industry;
750 }
751 public void advance(float amount) {
752 Industry ind = market.getIndustry(Industries.POPULATION);
753 SpecialItemData item = ind == null ? null : ind.getSpecialItem();
754 if (item == null || !item.getId().equals(Items.ORBITAL_FUSION_LAMP)) {
755 Misc.fadeAndExpire(lamp);
756 industry.lamp = null;
757 lamp = null;
758 }
759 }
760 public boolean isDone() {
761 return lamp == null;
762 }
763 public boolean runWhilePaused() {
764 return false;
765 }
766 }
767
768 protected String addedHeatCondition = null;
769 protected String removedHeatCondition = null;
770 protected SectorEntityToken lamp;
771 @Override
772 public void setSpecialItem(SpecialItemData special) {
773 super.setSpecialItem(special);
774
775 if (addedHeatCondition != null && (special == null || !special.getId().equals(Items.ORBITAL_FUSION_LAMP))) {
776 market.removeCondition(addedHeatCondition);
777 addedHeatCondition = null;
778 if (removedHeatCondition != null) {
779 market.addCondition(removedHeatCondition);
781 }
782 }
783
784 if (special != null && special.getId().equals(Items.ORBITAL_FUSION_LAMP)) {
785 if (lamp == null) {
786 SectorEntityToken focus = market.getPlanetEntity();
787 if (focus == null) focus = market.getPrimaryEntity();
788 if (focus != null) {
789 EntityLocation loc = new EntityLocation();
790 float radius = focus.getRadius() + 100f;
791 loc.orbit = Global.getFactory().createCircularOrbit(focus, (float) Math.random() * 360f,
792 radius, radius / (10f + 10f * (float) Math.random()));
793 AddedEntity added = BaseThemeGenerator.addNonSalvageEntity(
794 market.getContainingLocation(), loc, Entities.FUSION_LAMP, getMarket().getFactionId());//Factions.NEUTRAL);
795 if (added != null) {
796 lamp = added.entity;
797 market.getContainingLocation().addScript(new LampRemover(lamp, market, this));
798 }
799 }
800 }
801 if (addedHeatCondition == null &&
802 !market.hasCondition(Conditions.COLD) &&
803 !market.hasCondition(Conditions.VERY_COLD) &&
804 !market.hasCondition(Conditions.VERY_HOT)) {
805 if (market.hasCondition(Conditions.HOT)) {
806 addedHeatCondition = Conditions.VERY_HOT;
807 removedHeatCondition = Conditions.HOT;
808 } else {
809 addedHeatCondition = Conditions.HOT;
810 }
811 if (removedHeatCondition != null) market.removeCondition(removedHeatCondition);
812 if (addedHeatCondition != null) market.addCondition(addedHeatCondition);
813 }
814 }
815 }
816
817
818 @Override
819 public boolean wantsToUseSpecialItem(SpecialItemData data) {
820 if (special != null) return false;
821
822 if (Items.ORBITAL_FUSION_LAMP.equals(data.getId())) {
823 for (String mc : ItemEffectsRepo.FUSION_LAMP_CONDITIONS) {
824 if (market.hasCondition(mc)) return true;
825 }
826 return false;
827 }
828 return super.wantsToUseSpecialItem(data);
829 }
830
831
832 public static Pair<SectorEntityToken, Float> getNearestCoronalTap(Vector2f locInHyper, boolean usable) {
833 SectorEntityToken nearest = null;
834 float minDist = Float.MAX_VALUE;
835
836 for (SectorEntityToken entity : Global.getSector().getCustomEntitiesWithTag(Tags.CORONAL_TAP)) {
837 if (!usable || entity.getMemoryWithoutUpdate().contains("$usable")) {
838 float dist = Misc.getDistanceLY(locInHyper, entity.getLocationInHyperspace());
840 Math.round(dist * 10f) <= ItemEffectsRepo.CORONAL_TAP_LIGHT_YEARS * 10f) {
842 }
843 if (dist < minDist) {
844 minDist = dist;
845 nearest = entity;
846 }
847 }
848 }
849
850 if (nearest == null) return null;
851
852 return new Pair<SectorEntityToken, Float>(nearest, minDist);
853 }
854
855 public static class CoronalTapFactor implements ColonyOtherFactorsListener {
856 public boolean isActiveFactorFor(SectorEntityToken entity) {
857 return getNearestCoronalTap(entity.getLocationInHyperspace(), true) != null;
858 }
859
860 public void printOtherFactors(TooltipMakerAPI text, SectorEntityToken entity) {
861 Pair<SectorEntityToken, Float> p = getNearestCoronalTap(entity.getLocationInHyperspace(), true);
862 if (p != null) {
863 Color h = Misc.getHighlightColor();
864 float opad = 10f;
865
866 String dStr = "" + Misc.getRoundedValueMaxOneAfterDecimal(p.two);
867 String lights = "light-years";
868 if (dStr.equals("1")) lights = "light-year";
869
870 if (p.two > ItemEffectsRepo.CORONAL_TAP_LIGHT_YEARS) {
871 text.addPara("The nearest coronal tap is located in the " +
872 p.one.getContainingLocation().getNameWithLowercaseType() + ", %s " + lights + " away. The maximum " +
873 "range at a portal can connect to a tap is %s light-years.",
874 opad, h,
875 "" + Misc.getRoundedValueMaxOneAfterDecimal(p.two),
876 "" + (int)ItemEffectsRepo.CORONAL_TAP_LIGHT_YEARS);
877 } else {
878 text.addPara("The nearest coronal tap is located in the " +
879 p.one.getContainingLocation().getNameWithLowercaseType() + ", %s " + lights + " away, allowing " +
880 "a coronal portal located here to connect to it.",
881 opad, h,
882 "" + Misc.getRoundedValueMaxOneAfterDecimal(p.two));
883 }
884 }
885 }
886 }
887
888}
889
890
891
892
893
894
895
static SettingsAPI getSettings()
Definition Global.java:51
static FactoryAPI getFactory()
Definition Global.java:35
static SectorAPI getSector()
Definition Global.java:59
Map< String, MutableCommodityQuantity > supply
Map< String, MutableCommodityQuantity > demand
Pair< String, Integer > getMaxDeficit(String ... commodityIds)
static Pair< SectorEntityToken, Float > getNearestCoronalTap(Vector2f locInHyper, boolean usable)
void addImproveDesc(TooltipMakerAPI info, ImprovementDescriptionMode mode)
static void modifyStability2(Industry industry, MarketAPI market, String modId)
static void modifyStability(Industry industry, MarketAPI market, String modId)
void addPostDemandSection(TooltipMakerAPI tooltip, boolean hasDemand, IndustryTooltipMode mode)
OrbitAPI createCircularOrbit(SectorEntityToken focus, float angle, float orbitRadius, float orbitDays)
JSONArray getJSONArray(String key)
String getSpriteName(String category, String id)
MarketConditionSpecAPI getMarketConditionSpec(String conditionId)
IndustrySpecAPI getIndustrySpec(String industryId)