1package com.fs.starfarer.api.impl.campaign.intel.events.ht;
4import java.util.ArrayList;
5import java.util.EnumSet;
9import org.lwjgl.util.vector.Vector2f;
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;
51 CharacterStatsRefreshListener,
52 CurrentLocationChangedListener {
79 public static String
KEY =
"$hte_ref";
81 public static enum Stage {
84 SLIPSTREAM_NAVIGATION,
86 HYPERFIELD_OPTIMIZATION,
95 public static class RecentTopographyReadings {
97 public RecentTopographyReadings(Vector2f loc) {
119 protected TimeoutTracker<RecentTopographyReadings>
recent =
new TimeoutTracker<RecentTopographyReadings>();
134 Global.
getSector().getIntelManager().addIntel(
this, !withIntelNotification, text);
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;
160 if (
getDataFor(Stage.GENERATE_SLIPSURGE) ==
null) {
169 super.notifyEnding();
178 protected void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode,
boolean isUpdate,
179 Color tc,
float initPad) {
185 Color h = Misc.getHighlightColor();
188 if (esd.id == Stage.SLIPSTREAM_DETECTION) {
189 info.addPara(
"Able to detect slipstreams near your spaceports", tc, initPad);
191 if (esd.id == Stage.SLIPSTREAM_NAVIGATION) {
194 info.addPara(
"Fuel use while traversing slipstreams reduced by %s", initPad, tc,
197 if (esd.id == Stage.HYPERFIELD_OPTIMIZATION) {
198 info.addPara(
"Maximum burn increased by %s while in hyperspace", initPad, tc,
201 if (esd.id == Stage.REVERSE_POLARITY) {
202 info.addPara(
"%s ability unlocked", initPad, tc, h,
"Reverse Polarity");
204 if (esd.id == Stage.GENERATE_SLIPSURGE) {
205 info.addPara(
"%s ability unlocked", initPad, tc, h,
"Generate Slipsurge");
207 if (esd.id == Stage.TOPOGRAPHIC_DATA) {
208 info.addPara(
"Topographic data gained", tc, initPad);
223 if (stageId == Stage.START) {
232 if (stageId == Stage.START) {
242 Color h = Misc.getHighlightColor();
253 if (stage ==
null)
return;
267 public void addStageDesc(TooltipMakerAPI info, Object stageId,
float initPad,
boolean forTooltip) {
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.",
276 }
else if (stageId == Stage.SLIPSTREAM_DETECTION) {
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(),
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.",
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,
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,
316 }
else if (stageId == Stage.TOPOGRAPHIC_DATA) {
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);
327 final EventStageData esd =
getDataFor(stageId);
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)) {
334 public void createTooltip(TooltipMakerAPI tooltip,
boolean expanded, Object tooltipParam) {
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");
353 esd.addProgressReq(tooltip, opad);
370 if (esd ==
null)
return null;
373 if (EnumSet.of(Stage.SLIPSTREAM_DETECTION, Stage.SLIPSTREAM_NAVIGATION, Stage.HYPERFIELD_OPTIMIZATION,
374 Stage.TOPOGRAPHIC_DATA, Stage.START).contains(esd.id)) {
377 if (stageId == Stage.REVERSE_POLARITY) {
380 if (stageId == Stage.GENERATE_SLIPSURGE) {
392 color = Misc.interpolateColor(color, Color.black, 0.25f);
398 return super.getBarProgressIndicatorColor();
403 return super.getStageImportance(stageId);
409 return "Hyperspace Topography";
428 EventStageData stage =
getDataFor(Stage.GENERATE_SLIPSURGE);
429 return stage.progress;
442 Set<String> tags = super.getIntelTags(map);
443 tags.add(Tags.INTEL_EXPLORATION);
450 super.advanceImpl(amount);
463 List<Token> params =
new ArrayList<Token>();
464 Token t =
new Token(
id, TokenType.LITERAL);
466 t =
new Token(
"-1", TokenType.LITERAL);
468 new AddAbility().execute(
null,
null, params,
null);
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);
480 if (Abilities.GENERATE_SLIPSURGE.equals(
id) && Abilities.DISTRESS_CALL.equals(slot.getAbilityId())) {
481 slot.setInHyperAbilityId(Abilities.GENERATE_SLIPSURGE);
486 slots.setCurrBarIndex(curr);
494 if (stage.id == Stage.REVERSE_POLARITY) {
497 if (stage.id == Stage.GENERATE_SLIPSURGE) {
500 if (stage.id == Stage.TOPOGRAPHIC_DATA) {
504 cargo.addSpecial(
new SpecialItemData(Items.TOPOGRAPHIC_DATA,
null), 1);
524 String id1 =
"hypertopology1";
527 pf.getStats().getFleetwideMaxBurnMod().unmodifyFlat(id1);
529 MutableStat stat = pf.getStats().getDynamic().getStat(Stats.FUEL_USE_NOT_SHOWN_ON_MAP_MULT);
530 stat.unmodifyMult(id1);
536 for (StatMod mod : stat.getMultMods().values()) {
537 if (SlipstreamTerrainPlugin2.FUEL_USE_MODIFIER_DESC.equals(mod.desc)) {
539 SlipstreamTerrainPlugin2.FUEL_USE_MODIFIER_DESC +
" (hyperspace topography)");
546 pf.getStats().getFleetwideMaxBurnMod().modifyFlat(id1,
HYPER_BURN_BONUS,
"Hyperspace topography");
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;
561 boolean unapplicable =
false;
562 Industry spaceport = market.getIndustry(Industries.SPACEPORT);
563 if (spaceport ==
null) {
564 spaceport = market.getIndustry(Industries.MEGAPORT);
566 if (spaceport ==
null || !spaceport.isFunctional()) {
570 StatBonus mod = market.getStats().getDynamic().getMod(Stats.SLIPSTREAM_REVEAL_RANGE_LY_MOD);
571 if (!market.isPlayerOwned() || unapplicable) {
580 mod.modifyFlat(id2, market.getSize(),
"Colony size");
584 mod.modifyFlatAlways(id3, arraysBonus,
593 int countMakeshift= 0;
594 Vector2f locInHyper = market.getLocationInHyperspace();
596 float dist = Misc.getDistanceLY(locInHyper, system.getLocation());
597 if (dist > range && Math.round(dist * 10f) <= range * 10f) {
601 for (SectorEntityToken entity : system.getEntitiesWithTag(Tags.SENSOR_ARRAY)) {
602 if (entity.getFaction() !=
null && entity.getFaction().isPlayerFaction()) {
603 if (entity.hasTag(Tags.MAKESHIFT)) {
615 if (useMakeshift < 0) useMakeshift = 0;
632 return get() !=
null &&
get().hasRecentReadingsNear(
Global.
getSector().getPlayerFleet().getLocationInHyperspace());
636 for (RecentTopographyReadings curr :
recent.getItems()) {
637 float distLY = Misc.getDistanceLY(loc, curr.loc);
646 if (stageId == Stage.REVERSE_POLARITY || stageId == Stage.GENERATE_SLIPSURGE) {
647 return "ui_learned_ability";
649 return super.getSoundForStageReachedUpdate(stageId);
static SettingsAPI getSettings()
static SectorAPI getSector()
Object getListInfoParam()
void addFactor(EventFactor factor)
void addStage(Object id, int progress)
boolean isStageActive(Object stageId)
void setMaxProgress(int maxProgress)
EventStageData getDataFor(Object stageId)
void setProgress(int progress)
boolean addEventFactorBulletPoints(TooltipMakerAPI info, ListInfoMode mode, boolean isUpdate, Color tc, float initPad)
List< EventStageData > stages
List< EventFactor > factors
void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode, boolean isUpdate, Color tc, float initPad)
void resetTopographicData()
boolean withMonthlyFactors()
static boolean hasRecentReadingsNearPlayer()
static float RANGE_PER_MAKESHIFT_SENSOR_ARRAY
void addStageDesc(TooltipMakerAPI info, Object stageId, float initPad, boolean forTooltip)
void addStageDescriptionText(TooltipMakerAPI info, float width, Object stageId)
void notifyStageReached(EventStageData stage)
TooltipCreator getStageTooltipImpl(Object stageId)
static float SLIPSTREAM_FUEL_MULT
String getSoundForOneTimeFactorUpdate(EventFactor factor)
void updateMarketDetectionRanges()
static float RECENT_READINGS_TIMEOUT
static float RECENT_READINGS_RANGE_LY
String getSoundForStageReachedUpdate(Object stageId)
Set< String > getIntelTags(SectorMapAPI map)
static float BASE_DETECTION_RANGE_LY
void reportCurrentLocationChanged(LocationAPI prev, LocationAPI curr)
static float HYPER_BURN_BONUS
float gerSensorArrayBonusFor(MarketAPI market, float range)
static void addFactorCreateIfNecessary(EventFactor factor, InteractionDialogAPI dialog)
static float WAYSTATION_BONUS
void reportRefreshedCharacterStatEffects()
int getStageImportance(Object stageId)
String getStageIconImpl(Object stageId)
void addRecentReadings(Vector2f loc)
static int MAX_SENSOR_ARRAYS
TimeoutTracker< RecentTopographyReadings > recent
float getImageIndentForStageDesc(Object stageId)
boolean hasRecentReadingsNear(Vector2f loc)
void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param)
void advanceImpl(float amount)
void reportAboutToRefreshCharacterStatEffects()
HyperspaceTopographyEventIntel(TextPanelAPI text, boolean withIntelNotification)
Color getBarProgressIndicatorColor()
void addAbility(String id)
void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle)
float getImageSizeForStageDesc(Object stageId)
static float RANGE_WITHIN_WHICH_SENSOR_ARRAYS_HELP_LY
static float RANGE_PER_DOMAIN_SENSOR_ARRAY
AbilitySpecAPI getAbilitySpec(String abilityId)
String getSpriteName(String category, String id)
Color getColor(String id)