Starsector API
Loading...
Searching...
No Matches
HyperspaceTopographyEventIntel.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.intel.events.ht;
2
3import java.awt.Color;
4import java.util.ArrayList;
5import java.util.EnumSet;
6import java.util.List;
7import java.util.Set;
8
9import org.lwjgl.util.vector.Vector2f;
10
11import com.fs.starfarer.api.Global;
12import com.fs.starfarer.api.campaign.BattleAPI;
13import com.fs.starfarer.api.campaign.CampaignEventListener.FleetDespawnReason;
14import com.fs.starfarer.api.campaign.CampaignFleetAPI;
15import com.fs.starfarer.api.campaign.CargoAPI;
16import com.fs.starfarer.api.campaign.InteractionDialogAPI;
17import com.fs.starfarer.api.campaign.LocationAPI;
18import com.fs.starfarer.api.campaign.PersistentUIDataAPI.AbilitySlotAPI;
19import com.fs.starfarer.api.campaign.PersistentUIDataAPI.AbilitySlotsAPI;
20import com.fs.starfarer.api.campaign.SectorEntityToken;
21import com.fs.starfarer.api.campaign.SpecialItemData;
22import com.fs.starfarer.api.campaign.StarSystemAPI;
23import com.fs.starfarer.api.campaign.TextPanelAPI;
24import com.fs.starfarer.api.campaign.econ.Industry;
25import com.fs.starfarer.api.campaign.econ.MarketAPI;
26import com.fs.starfarer.api.campaign.listeners.CharacterStatsRefreshListener;
27import com.fs.starfarer.api.campaign.listeners.CurrentLocationChangedListener;
28import com.fs.starfarer.api.campaign.listeners.FleetEventListener;
29import com.fs.starfarer.api.combat.MutableStat;
30import com.fs.starfarer.api.combat.MutableStat.StatMod;
31import com.fs.starfarer.api.combat.StatBonus;
32import com.fs.starfarer.api.impl.campaign.ids.Abilities;
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.intel.events.BaseEventIntel;
38import com.fs.starfarer.api.impl.campaign.intel.events.BaseFactorTooltip;
39import com.fs.starfarer.api.impl.campaign.intel.events.EventFactor;
40import com.fs.starfarer.api.impl.campaign.rulecmd.AddAbility;
41import com.fs.starfarer.api.impl.campaign.velfield.SlipstreamTerrainPlugin2;
42import com.fs.starfarer.api.ui.SectorMapAPI;
43import com.fs.starfarer.api.ui.TooltipMakerAPI;
44import com.fs.starfarer.api.ui.TooltipMakerAPI.TooltipCreator;
45import com.fs.starfarer.api.util.Misc;
46import com.fs.starfarer.api.util.Misc.Token;
47import com.fs.starfarer.api.util.Misc.TokenType;
48import com.fs.starfarer.api.util.TimeoutTracker;
49
50public class HyperspaceTopographyEventIntel extends BaseEventIntel implements FleetEventListener,
51 CharacterStatsRefreshListener,
52 CurrentLocationChangedListener {
53
54 public static Color BAR_COLOR = Global.getSettings().getColor("progressBarFleetPointsColor");
55
56
57// public static int PROGRESS_MAX = 1000;
58// public static int PROGRESS_1 = 100;
59// public static int PROGRESS_2 = 400;
60// public static int PROGRESS_3 = 700;
61 public static int PROGRESS_MAX = 1000;
62 public static int PROGRESS_1 = 100;
63 public static int PROGRESS_2 = 250;
64 public static int PROGRESS_3 = 400;
65 public static int PROGRESS_4 = 550;
66 public static int PROGRESS_5 = 700;
67
68 public static float BASE_DETECTION_RANGE_LY = 3f;
70 public static float RANGE_PER_DOMAIN_SENSOR_ARRAY = 2f;
71 public static float RANGE_PER_MAKESHIFT_SENSOR_ARRAY = 1f;
72 public static int MAX_SENSOR_ARRAYS = 3;
73 public static float WAYSTATION_BONUS = 2f;
74
75
76 public static float SLIPSTREAM_FUEL_MULT = 0.25f;
77 public static float HYPER_BURN_BONUS = 3f;
78
79 public static String KEY = "$hte_ref";
80
81 public static enum Stage {
82 START,
83 SLIPSTREAM_DETECTION,
84 SLIPSTREAM_NAVIGATION,
85 REVERSE_POLARITY,
86 HYPERFIELD_OPTIMIZATION,
87 GENERATE_SLIPSURGE,
88 TOPOGRAPHIC_DATA,
89 }
90
91
92 public static float RECENT_READINGS_TIMEOUT = 30f;
93 public static float RECENT_READINGS_RANGE_LY = 10f;
94
95 public static class RecentTopographyReadings {
96 public Vector2f loc;
97 public RecentTopographyReadings(Vector2f loc) {
98 this.loc = loc;
99 }
100 }
101
102 public static void addFactorCreateIfNecessary(EventFactor factor, InteractionDialogAPI dialog) {
103 if (get() == null) {
104 //TextPanelAPI text = dialog == null ? null : dialog.getTextPanel();
105 //new HyperspaceTopographyEventIntel(text);
106 // adding a factor anyway, so it'll show a message - don't need to double up
107 new HyperspaceTopographyEventIntel(null, false);
108 }
109 if (get() != null) {
110 get().addFactor(factor, dialog);
111 }
112 }
113
114 public static HyperspaceTopographyEventIntel get() {
115 return (HyperspaceTopographyEventIntel) Global.getSector().getMemoryWithoutUpdate().get(KEY);
116 }
117
118
119 protected TimeoutTracker<RecentTopographyReadings> recent = new TimeoutTracker<RecentTopographyReadings>();
120
121// public static float CHECK_DAYS = 0.1f;
122// protected IntervalUtil interval = new IntervalUtil(CHECK_DAYS * 0.8f, CHECK_DAYS * 1.2f);
123// protected float burnBasedPoints = 0f;
124
125 public HyperspaceTopographyEventIntel(TextPanelAPI text, boolean withIntelNotification) {
126 super();
127
128 Global.getSector().getMemoryWithoutUpdate().set(KEY, this);
129
130
131 setup();
132
133 // now that the event is fully constructed, add it and send notification
134 Global.getSector().getIntelManager().addIntel(this, !withIntelNotification, text);
135 }
136
137 protected void setup() {
138 factors.clear();
139 stages.clear();
140
142
143 addStage(Stage.START, 0);
144 addStage(Stage.SLIPSTREAM_NAVIGATION, PROGRESS_1, StageIconSize.MEDIUM);
145 addStage(Stage.SLIPSTREAM_DETECTION, PROGRESS_2, StageIconSize.MEDIUM);
146 addStage(Stage.REVERSE_POLARITY, PROGRESS_3, StageIconSize.LARGE);
147 addStage(Stage.HYPERFIELD_OPTIMIZATION, PROGRESS_4, StageIconSize.MEDIUM);
148 addStage(Stage.GENERATE_SLIPSURGE, PROGRESS_5, StageIconSize.LARGE);
149 addStage(Stage.TOPOGRAPHIC_DATA, PROGRESS_MAX, true, StageIconSize.SMALL);
150
151 getDataFor(Stage.SLIPSTREAM_NAVIGATION).keepIconBrightWhenLaterStageReached = true;
152 getDataFor(Stage.SLIPSTREAM_DETECTION).keepIconBrightWhenLaterStageReached = true;
153 getDataFor(Stage.REVERSE_POLARITY).keepIconBrightWhenLaterStageReached = true;
154 getDataFor(Stage.HYPERFIELD_OPTIMIZATION).keepIconBrightWhenLaterStageReached = true;
155 getDataFor(Stage.GENERATE_SLIPSURGE).keepIconBrightWhenLaterStageReached = true;
156
157 }
158
159 protected Object readResolve() {
160 if (getDataFor(Stage.GENERATE_SLIPSURGE) == null) {
161 setup();
162 }
163 return this;
164 }
165
166
167 @Override
168 protected void notifyEnding() {
169 super.notifyEnding();
170 }
171
172 @Override
173 protected void notifyEnded() {
174 super.notifyEnded();
175 Global.getSector().getMemoryWithoutUpdate().unset(KEY);
176 }
177
178 protected void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode, boolean isUpdate,
179 Color tc, float initPad) {
180
181 if (addEventFactorBulletPoints(info, mode, isUpdate, tc, initPad)) {
182 return;
183 }
184
185 Color h = Misc.getHighlightColor();
186 if (isUpdate && getListInfoParam() instanceof EventStageData) {
187 EventStageData esd = (EventStageData) getListInfoParam();
188 if (esd.id == Stage.SLIPSTREAM_DETECTION) {
189 info.addPara("Able to detect slipstreams near your spaceports", tc, initPad);
190 }
191 if (esd.id == Stage.SLIPSTREAM_NAVIGATION) {
192// info.addPara("Fuel use while traversing slipstreams multiplied by %s", initPad, tc,
193// h, "" + SLIPSTREAM_FUEL_MULT + Strings.X);
194 info.addPara("Fuel use while traversing slipstreams reduced by %s", initPad, tc,
195 h, "" + (int)Math.round((1f - SLIPSTREAM_FUEL_MULT) * 100f) + "%");
196 }
197 if (esd.id == Stage.HYPERFIELD_OPTIMIZATION) {
198 info.addPara("Maximum burn increased by %s while in hyperspace", initPad, tc,
199 h, "" + (int) HYPER_BURN_BONUS);
200 }
201 if (esd.id == Stage.REVERSE_POLARITY) {
202 info.addPara("%s ability unlocked", initPad, tc, h, "Reverse Polarity");
203 }
204 if (esd.id == Stage.GENERATE_SLIPSURGE) {
205 info.addPara("%s ability unlocked", initPad, tc, h, "Generate Slipsurge");
206 }
207 if (esd.id == Stage.TOPOGRAPHIC_DATA) {
208 info.addPara("Topographic data gained", tc, initPad);
209 }
210 return;
211 }
212
213// EventStageData esd = getLastActiveStage(false);
214// if (esd != null && EnumSet.of(Stage.START, Stage.HA_1, Stage.HA_2, Stage.HA_3, Stage.HA_4).contains(esd.id)) {
215//
216// }
217 }
218
219 public float getImageSizeForStageDesc(Object stageId) {
220// if (stageId == Stage.REVERSE_POLARITY || stageId == Stage.GENERATE_SLIPSURGE) {
221// return 48f;
222// }
223 if (stageId == Stage.START) {
224 return 64f;
225 }
226 return 48f;
227 }
228 public float getImageIndentForStageDesc(Object stageId) {
229// if (stageId == Stage.REVERSE_POLARITY || stageId == Stage.GENERATE_SLIPSURGE) {
230// return 16f;
231// }
232 if (stageId == Stage.START) {
233 return 0f;
234 }
235 return 16f;
236 }
237
238 @Override
239 public void addStageDescriptionText(TooltipMakerAPI info, float width, Object stageId) {
240 float opad = 10f;
241 float small = 0f;
242 Color h = Misc.getHighlightColor();
243
244 //setProgress(0);
245 //setProgress(199);
246 //setProgress(600);
247 //setProgress(899);
248 //setProgress(1000);
249 //setProgress(499);
250 //setProgress(600);
251
252 EventStageData stage = getDataFor(stageId);
253 if (stage == null) return;
254
255// if (isStageActiveAndLast(stageId) && stageId == Stage.START) {
256// addStageDesc(info, stageId, small, false);
257// } else if (isStageActive(stageId) && stageId != Stage.START) {
258// addStageDesc(info, stageId, small, false);
259// }
260
261 if (isStageActive(stageId)) {
262 addStageDesc(info, stageId, small, false);
263 }
264 }
265
266
267 public void addStageDesc(TooltipMakerAPI info, Object stageId, float initPad, boolean forTooltip) {
268 float opad = 10f;
269 Color h = Misc.getHighlightColor();
270 if (stageId == Stage.START) {
271 info.addPara("Detailed sensor readings greatly aid hyperspace navigation. "
272 + "There are many ways of acquiring this data, including using in-system sensor arrays,"
273 + " using an Active Sensor Burst near interesting phenomena, "
274 + "traveling through hyperspace at a very high burn level, or simply buying the data from scavengers.",
275 initPad);
276 } else if (stageId == Stage.SLIPSTREAM_DETECTION) {
277// info.addPara("The facilities and staff at a Spaceport are able to interpret data from various sources "
278// + "to discover the presence of nearby slipstreams. The detection range is increased "
279// + "for larger colonies. Claimed sensor arrays within %s light-years provide an additional "
280// + "bonus - %s ly for Domain-era arrays, and %s ly for makeshift ones. "
281// + "Up to %s sensor arrays can be of use.", initPad,
282// Misc.getHighlightColor(),
283// "" + (int) RANGE_WITHIN_WHICH_SENSOR_ARRAYS_HELP_LY,
284// "+" + (int) RANGE_PER_DOMAIN_SENSOR_ARRAY,
285// "+" + (int) RANGE_PER_MAKESHIFT_SENSOR_ARRAY,
286// "" + (int) MAX_SENSOR_ARRAYS
287// );
288 info.addPara("Allows a Spaceport "
289 + "to detect nearby slipstreams. Detection range increased "
290 + "for %s. Claimed sensor arrays within %s light-years provide extra detection range: "
291 + "%s ly for Domain-era arrays, and %s ly for makeshift ones. "
292 + "Up to %s sensor arrays can be used.", initPad,
293 Misc.getHighlightColor(),
294 "larger colonies",
298 "" + (int) MAX_SENSOR_ARRAYS
299 );
300 } else if (stageId == Stage.SLIPSTREAM_NAVIGATION) {
301 info.addPara("Fuel use while traveling inside slipstreams reduced by %s. This reduction is multiplicative " +
302 "with the baseline fuel use reduction for traveling inside a slipstream.",
303 initPad, h,
304 "" + (int)Math.round((1f - SLIPSTREAM_FUEL_MULT) * 100f) + "%");
305 } else if (stageId == Stage.REVERSE_POLARITY) {
306 info.addPara("Unlocks the %s ability, which allows your fleet to "
307 + "travel against the current of slipstreams.", initPad, h,
308 "Reverse Polarity");
309 } else if (stageId == Stage.GENERATE_SLIPSURGE) {
310 info.addPara("Unlocks the %s ability, which allows your fleet to "
311 + "create powerful, short-lived slipstreams useful for rapid travel.", initPad, h,
312 "Generate Slipsurge");
313 } else if (stageId == Stage.HYPERFIELD_OPTIMIZATION) {
314 info.addPara("Maximum burn increased by %s while in hyperspace.", initPad, h,
315 "" + (int) HYPER_BURN_BONUS);
316 } else if (stageId == Stage.TOPOGRAPHIC_DATA) {
317 int min = getTopoResetMin();
318 int max = getTopoResetMax();
319 info.addPara("A batch of topographic data that can be sold for a"
320 + " considerable number of credits.", initPad);
321 info.addPara("Event progress will be reset to between %s and %s points when this outcome is reached.",
322 opad, h, "" + min, "" + max);
323 }
324 }
325
326 public TooltipCreator getStageTooltipImpl(Object stageId) {
327 final EventStageData esd = getDataFor(stageId);
328
329 if (esd != null && EnumSet.of(Stage.SLIPSTREAM_DETECTION, Stage.SLIPSTREAM_NAVIGATION,
330 Stage.GENERATE_SLIPSURGE, Stage.REVERSE_POLARITY,
331 Stage.HYPERFIELD_OPTIMIZATION, Stage.TOPOGRAPHIC_DATA).contains(esd.id)) {
332 return new BaseFactorTooltip() {
333 @Override
334 public void createTooltip(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) {
335 float opad = 10f;
336
337 if (esd.id == Stage.SLIPSTREAM_DETECTION) {
338 tooltip.addTitle("Slipstream detection");
339 } else if (esd.id == Stage.SLIPSTREAM_NAVIGATION) {
340 tooltip.addTitle("Slipstream navigation");
341 } else if (esd.id == Stage.HYPERFIELD_OPTIMIZATION) {
342 tooltip.addTitle("Hyperfield optimization");
343 } else if (esd.id == Stage.REVERSE_POLARITY) {
344 tooltip.addTitle("Reverse Polarity");
345 } else if (esd.id == Stage.GENERATE_SLIPSURGE) {
346 tooltip.addTitle("Generate Slipsurge");
347 } else if (esd.id == Stage.TOPOGRAPHIC_DATA) {
348 tooltip.addTitle("Topographic data");
349 }
350
351 addStageDesc(tooltip, esd.id, opad, true);
352
353 esd.addProgressReq(tooltip, opad);
354 }
355 };
356 }
357
358 return null;
359 }
360
361
362
363 @Override
364 public String getIcon() {
365 return Global.getSettings().getSpriteName("events", "hyperspace_topography");
366 }
367
368 protected String getStageIconImpl(Object stageId) {
369 EventStageData esd = getDataFor(stageId);
370 if (esd == null) return null;
371
372
373 if (EnumSet.of(Stage.SLIPSTREAM_DETECTION, Stage.SLIPSTREAM_NAVIGATION, Stage.HYPERFIELD_OPTIMIZATION,
374 Stage.TOPOGRAPHIC_DATA, Stage.START).contains(esd.id)) {
375 return Global.getSettings().getSpriteName("events", "hyperspace_topography_" + ((Stage)esd.id).name());
376 }
377 if (stageId == Stage.REVERSE_POLARITY) {
378 return Global.getSettings().getAbilitySpec(Abilities.REVERSE_POLARITY).getIconName();
379 }
380 if (stageId == Stage.GENERATE_SLIPSURGE) {
381 return Global.getSettings().getAbilitySpec(Abilities.GENERATE_SLIPSURGE).getIconName();
382 }
383 // should not happen - the above cases should handle all possibilities - but just in case
384 return Global.getSettings().getSpriteName("events", "hyperspace_topography");
385 }
386
387
388 @Override
389 public Color getBarColor() {
390 Color color = BAR_COLOR;
391 //color = Misc.getBasePlayerColor();
392 color = Misc.interpolateColor(color, Color.black, 0.25f);
393 return color;
394 }
395
396 @Override
398 return super.getBarProgressIndicatorColor();
399 }
400
401 @Override
402 protected int getStageImportance(Object stageId) {
403 return super.getStageImportance(stageId);
404 }
405
406
407 @Override
408 protected String getName() {
409 return "Hyperspace Topography";
410 }
411
412
413 public void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param) {
414
415 }
416 public void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle) {
417// if (isEnded() || isEnding()) return;
418//
419// if (!battle.isPlayerInvolved()) return;
420
421// HAShipsDestroyedFactor factor = new HAShipsDestroyedFactor(-1 * points);
422// sendUpdateIfPlayerHasIntel(factor, false);
423// addFactor(factor);
424 }
425
426
427 public int getTopoResetMin() {
428 EventStageData stage = getDataFor(Stage.GENERATE_SLIPSURGE);
429 return stage.progress;
430 }
431 public int getTopoResetMax() {
432 return getTopoResetMin() + 50;
433 }
434
435 public void resetTopographicData() {
436 int resetProgress = getTopoResetMin() + getRandom().nextInt(getTopoResetMax() - getTopoResetMin() + 1);
437 setProgress(resetProgress);
438 }
439
440 @Override
441 public Set<String> getIntelTags(SectorMapAPI map) {
442 Set<String> tags = super.getIntelTags(map);
443 tags.add(Tags.INTEL_EXPLORATION);
444 //tags.remove(Tags.INTEL_MAJOR_EVENT);
445 return tags;
446 }
447
448 @Override
449 protected void advanceImpl(float amount) {
450 super.advanceImpl(amount);
452
453 float days = Global.getSector().getClock().convertToDays(amount);
454 recent.advance(days);
455
456 //setProgress(getProgress() + 10);
457 }
458
459 public void addAbility(String id) {
460 if (Global.getSector().getPlayerFleet().hasAbility(id)) {
461 return;
462 }
463 List<Token> params = new ArrayList<Token>();
464 Token t = new Token(id, TokenType.LITERAL);
465 params.add(t);
466 t = new Token("-1", TokenType.LITERAL);
467 params.add(t); // don't want to assign it to a slot - will assign as hyper-only alternate later here
468 new AddAbility().execute(null, null, params, null);
469
470
471 AbilitySlotsAPI slots = Global.getSector().getUIData().getAbilitySlotsAPI();
472 int curr = slots.getCurrBarIndex();
473 OUTER: for (int i = 0; i < 5; i++) {
474 slots.setCurrBarIndex(i);
475 for (AbilitySlotAPI slot : slots.getCurrSlotsCopy()) {
476 if (Abilities.REVERSE_POLARITY.equals(id) && Abilities.SCAVENGE.equals(slot.getAbilityId())) {
477 slot.setInHyperAbilityId(Abilities.REVERSE_POLARITY);
478 break OUTER;
479 }
480 if (Abilities.GENERATE_SLIPSURGE.equals(id) && Abilities.DISTRESS_CALL.equals(slot.getAbilityId())) {
481 slot.setInHyperAbilityId(Abilities.GENERATE_SLIPSURGE);
482 break OUTER;
483 }
484 }
485 }
486 slots.setCurrBarIndex(curr);
487 }
488
489
490 @Override
491 protected void notifyStageReached(EventStageData stage) {
492 //applyFleetEffects();
493
494 if (stage.id == Stage.REVERSE_POLARITY) {
495 addAbility(Abilities.REVERSE_POLARITY);
496 }
497 if (stage.id == Stage.GENERATE_SLIPSURGE) {
498 addAbility(Abilities.GENERATE_SLIPSURGE);
499 }
500 if (stage.id == Stage.TOPOGRAPHIC_DATA) {
502
503 CargoAPI cargo = Global.getSector().getPlayerFleet().getCargo();
504 cargo.addSpecial(new SpecialItemData(Items.TOPOGRAPHIC_DATA, null), 1);
505 //sendUpdateIfPlayerHasIntel(stage, getTextPanelForStageChange());
506 }
507 }
508
509 public void reportCurrentLocationChanged(LocationAPI prev, LocationAPI curr) {
510 //applyFleetEffects();
511 }
512
516
518 // called when opening colony screen, so the Spaceport tooltip gets the right values
521 }
522
523 public void applyFleetEffects() {
524 String id1 = "hypertopology1";
525
526 CampaignFleetAPI pf = Global.getSector().getPlayerFleet();
527 pf.getStats().getFleetwideMaxBurnMod().unmodifyFlat(id1);
528
529 MutableStat stat = pf.getStats().getDynamic().getStat(Stats.FUEL_USE_NOT_SHOWN_ON_MAP_MULT);
530 stat.unmodifyMult(id1);
531
532 //if (pf.isInHyperspace()) { // doesn't work; after reportCurrentLocationChanged()
533 // the current location is right but the player fleet hasn't been added to it yet
534 if (Global.getSector().getCurrentLocation().isHyperspace()) {
535 if (isStageActive(Stage.SLIPSTREAM_NAVIGATION)) {
536 for (StatMod mod : stat.getMultMods().values()) {
537 if (SlipstreamTerrainPlugin2.FUEL_USE_MODIFIER_DESC.equals(mod.desc)) {
538 stat.modifyMult(id1, SLIPSTREAM_FUEL_MULT,
539 SlipstreamTerrainPlugin2.FUEL_USE_MODIFIER_DESC + " (hyperspace topography)");
540 break;
541 }
542 }
543 }
544
545 if (isStageActive(Stage.HYPERFIELD_OPTIMIZATION)) {
546 pf.getStats().getFleetwideMaxBurnMod().modifyFlat(id1, HYPER_BURN_BONUS, "Hyperspace topography");
547 }
548
549 }
550 }
551
553 if (isStageActive(Stage.SLIPSTREAM_DETECTION)) {
554 String id1 = "hypertopology1";
555 String id2 = "hypertopology2";
556 String id3 = "hypertopology3";
557 String id4 = "hypertopology4";
558 for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
559 if (market.isHidden()) continue;
560
561 boolean unapplicable = false;
562 Industry spaceport = market.getIndustry(Industries.SPACEPORT);
563 if (spaceport == null) {
564 spaceport = market.getIndustry(Industries.MEGAPORT);
565 }
566 if (spaceport == null || !spaceport.isFunctional()) {
567 unapplicable = true;
568 }
569
570 StatBonus mod = market.getStats().getDynamic().getMod(Stats.SLIPSTREAM_REVEAL_RANGE_LY_MOD);
571 if (!market.isPlayerOwned() || unapplicable) {
572 mod.unmodify(id1);
573 mod.unmodify(id2);
574 mod.unmodify(id3);
575 mod.unmodify(id4);
576 continue;
577 }
578
579 mod.modifyFlat(id1, BASE_DETECTION_RANGE_LY, "Base detection range");
580 mod.modifyFlat(id2, market.getSize(), "Colony size");
581
583
584 mod.modifyFlatAlways(id3, arraysBonus,
585 "Claimed sensor arrays within " + (int) RANGE_WITHIN_WHICH_SENSOR_ARRAYS_HELP_LY +
586 " ly (max: " + (int) MAX_SENSOR_ARRAYS + " arrays)");
587 }
588 }
589 }
590
591 public float gerSensorArrayBonusFor(MarketAPI market, float range) {
592 int countDomain = 0;
593 int countMakeshift= 0;
594 Vector2f locInHyper = market.getLocationInHyperspace();
595 for (StarSystemAPI system : Global.getSector().getStarSystems()) {
596 float dist = Misc.getDistanceLY(locInHyper, system.getLocation());
597 if (dist > range && Math.round(dist * 10f) <= range * 10f) {
598 dist = range;
599 }
600 if (dist <= range) {
601 for (SectorEntityToken entity : system.getEntitiesWithTag(Tags.SENSOR_ARRAY)) {
602 if (entity.getFaction() != null && entity.getFaction().isPlayerFaction()) {
603 if (entity.hasTag(Tags.MAKESHIFT)) {
604 countMakeshift++;
605 } else {
606 countDomain++;
607 }
608 }
609 }
610 }
611 }
612
613 float bonus = Math.min(countDomain, MAX_SENSOR_ARRAYS) * RANGE_PER_DOMAIN_SENSOR_ARRAY;
614 float useMakeshift = Math.min(MAX_SENSOR_ARRAYS - countDomain, countMakeshift);
615 if (useMakeshift < 0) useMakeshift = 0;
616 bonus += useMakeshift * RANGE_PER_MAKESHIFT_SENSOR_ARRAY;
617 //bonus += Math.min(Math.max(0, countMakeshift - countDomain), MAX_SENSOR_ARRAYS) * RANGE_PER_MAKESHIFT_SENSOR_ARRAY;
618
619 return bonus;
620 }
621
622 public boolean withMonthlyFactors() {
623 return false;
624 }
625
626
627 public void addRecentReadings(Vector2f loc) {
628 recent.add(new RecentTopographyReadings(loc), RECENT_READINGS_TIMEOUT);
629 }
630
631 public static boolean hasRecentReadingsNearPlayer() {
632 return get() != null && get().hasRecentReadingsNear(Global.getSector().getPlayerFleet().getLocationInHyperspace());
633 }
634
635 public boolean hasRecentReadingsNear(Vector2f loc) {
636 for (RecentTopographyReadings curr : recent.getItems()) {
637 float distLY = Misc.getDistanceLY(loc, curr.loc);
638 if (distLY <= RECENT_READINGS_RANGE_LY) {
639 return true;
640 }
641 }
642 return false;
643 }
644
645 protected String getSoundForStageReachedUpdate(Object stageId) {
646 if (stageId == Stage.REVERSE_POLARITY || stageId == Stage.GENERATE_SLIPSURGE) {
647 return "ui_learned_ability";
648 }
649 return super.getSoundForStageReachedUpdate(stageId);
650 }
651
652 @Override
654// if (factor instanceof HTAbyssalLightFactor) {
655// return "sound_none";
656// }
657 return null;
658 }
659
660
661
662}
663
664
665
666
667
668
669
670
static SettingsAPI getSettings()
Definition Global.java:51
static SectorAPI getSector()
Definition Global.java:59
boolean addEventFactorBulletPoints(TooltipMakerAPI info, ListInfoMode mode, boolean isUpdate, Color tc, float initPad)
void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode, boolean isUpdate, Color tc, float initPad)
void addStageDesc(TooltipMakerAPI info, Object stageId, float initPad, boolean forTooltip)
static void addFactorCreateIfNecessary(EventFactor factor, InteractionDialogAPI dialog)
void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param)
void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle)
AbilitySpecAPI getAbilitySpec(String abilityId)
String getSpriteName(String category, String id)