1package com.fs.starfarer.api.impl.campaign.intel.events;
3import java.util.ArrayList;
4import java.util.Collections;
5import java.util.Comparator;
6import java.util.Iterator;
7import java.util.LinkedHashMap;
14import com.fs.starfarer.api.Global;
15import com.fs.starfarer.api.campaign.BattleAPI;
16import com.fs.starfarer.api.campaign.CampaignEventListener.FleetDespawnReason;
17import com.fs.starfarer.api.campaign.CampaignFleetAPI;
18import com.fs.starfarer.api.campaign.StarSystemAPI;
19import com.fs.starfarer.api.campaign.StoryPointActionDelegate;
20import com.fs.starfarer.api.campaign.econ.EconomyAPI.EconomyUpdateListener;
21import com.fs.starfarer.api.campaign.econ.MarketAPI;
22import com.fs.starfarer.api.campaign.listeners.FleetEventListener;
23import com.fs.starfarer.api.campaign.listeners.ListenerUtil;
24import com.fs.starfarer.api.combat.MutableStatWithTempMods;
25import com.fs.starfarer.api.fleet.FleetMemberAPI;
26import com.fs.starfarer.api.impl.campaign.command.WarSimScript.LocationDanger;
27import com.fs.starfarer.api.impl.campaign.ids.Conditions;
28import com.fs.starfarer.api.impl.campaign.ids.Factions;
29import com.fs.starfarer.api.impl.campaign.ids.Sounds;
30import com.fs.starfarer.api.impl.campaign.ids.Tags;
31import com.fs.starfarer.api.impl.campaign.intel.bases.LuddicPathBaseIntel;
32import com.fs.starfarer.api.impl.campaign.intel.bases.PirateBaseIntel;
33import com.fs.starfarer.api.impl.campaign.rulecmd.HA_CMD;
34import com.fs.starfarer.api.impl.campaign.rulecmd.SetStoryOption.BaseOptionStoryPointActionDelegate;
35import com.fs.starfarer.api.impl.campaign.rulecmd.SetStoryOption.StoryOptionParams;
36import com.fs.starfarer.api.ui.Alignment;
37import com.fs.starfarer.api.ui.ButtonAPI;
38import com.fs.starfarer.api.ui.IntelUIAPI;
39import com.fs.starfarer.api.ui.LabelAPI;
40import com.fs.starfarer.api.ui.SectorMapAPI;
41import com.fs.starfarer.api.ui.TooltipMakerAPI;
42import com.fs.starfarer.api.ui.TooltipMakerAPI.TooltipCreator;
43import com.fs.starfarer.api.ui.TooltipMakerAPI.TooltipLocation;
44import com.fs.starfarer.api.util.Misc;
45import com.fs.starfarer.api.util.WeightedRandomPicker;
49 public static enum Stage {
57 @Deprecated INCREASED_DEFENSES,
61 public static String
KEY =
"$hae_ref";
74 public static class HAERandomEventData {
76 public EventStageData stage;
77 public boolean isReset =
false;
86 public static class HAEFactorDangerData {
90 public static class HAEStarSystemDangerData {
93 public float totalMag;
95 public List<HAEFactorDangerData> factorData =
new ArrayList<HAEFactorDangerData>();
104 protected Map<String, MutableStatWithTempMods>
systemSpawnMults =
new LinkedHashMap<String, MutableStatWithTempMods>();
121 boolean minorCompleted =
false;
122 EventStageData minor =
getDataFor(Stage.MINOR_EVENT);
123 if (minor !=
null) minorCompleted = minor.wasEverReached;
130 addStage(Stage.MINOR_EVENT, 300, StageIconSize.MEDIUM);
131 addStage(Stage.HA_EVENT, 600,
true, StageIconSize.LARGE);
133 setRandomized(Stage.MINOR_EVENT, RandomizedStageType.BAD, 200, 250,
false,
false);
134 setRandomized(Stage.HA_EVENT, RandomizedStageType.BAD, 425, 500,
false);
138 minor.wasEverReached = minorCompleted;
193 super.notifyEnding();
206 Color tc,
float initPad) {
222 for (EventStageData stage :
stages) {
223 if (stage.rollData instanceof HAERandomEventData) {
224 HAERandomEventData data = (HAERandomEventData) stage.rollData;
246 EventStageData stage =
getDataFor(Stage.HA_EVENT);
247 if (stage ==
null)
return null;;
249 if (stage.rollData instanceof HAERandomEventData) {
250 HAERandomEventData data = (HAERandomEventData) stage.rollData;
277 if (stage ==
null)
return;
279 if (stage.rollData instanceof HAERandomEventData) {
280 HAERandomEventData data = (HAERandomEventData) stage.rollData;
286 if (stageId == Stage.START) {
290 info.
addPara(
"Low-level pirate activity continues, but aside from that, there are "
291 +
"no major crises on the horizon.", small);
293 info.
addPara(
"A crisis is virtually inevitable at some point, "
294 +
"and hostile fleets continually probe your defenses, but where there is "
295 +
"danger, there is often opportunity.", small);
304 float systemW = 230f;
305 float threatW = 300f;
307 "Star system", systemW,
309 "Primary threats", threatW
313 int maxSystemsToList = 4;
315 info.
addTableHeaderTooltip(0,
"Star system with hostile activity, and the name (or number) of your colonies found there.\n\nUp to four of the hardest-hit systems are listed here.");
316 info.
addTableHeaderTooltip(1,
"Danger level of the stronger fleets likely to be found in the system. "
317 +
"Approximate, there may be exceptions. Does not include hostile fleets that may be present there for other reasons.");
318 info.
addTableHeaderTooltip(2,
"The most dangerous types of threats likely to be found in the system. "
319 +
"Not comprehensive, and does not include hostile fleets that may be present there for other reasons.");
323 for (
final HAEStarSystemDangerData sys : systemData) {
324 if (sys.sortMag <= 0)
continue;
326 float mag = sys.sortMag;
331 List<String> threats =
new ArrayList<String>();
332 List<Color> colors =
new ArrayList<Color>();
333 for (HAEFactorDangerData data : sys.factorData) {
334 if (data.mag <= 0)
continue;
335 threats.add(data.factor.getNameForThreatList(count == 0));
336 colors.add(data.factor.getNameColorForThreatList());
338 if (count >= maxThreats) {
348 String systemName = sys.system.getNameWithNoType();
352 if (colonies.size() == 1) {
353 colStr = colonies.get(0).getName();
355 colStr =
"" + colonies.size() +
" colonies";
357 systemName +=
" - " + colStr +
"";
364 public void createTooltip(
TooltipMakerAPI tooltip,
boolean expanded, Object tooltipParam) {
366 float h = Math.round(w / 1.6f);
371 }, TooltipLocation.LEFT,
false);
376 if (numListed >= maxSystemsToList) {
396 float inset = width - bw;
404 public boolean isTooltipExpandable(Object tooltipParam) {
408 public float getTooltipWidth(Object tooltipParam) {
412 public void createTooltip(
TooltipMakerAPI tooltip,
boolean expanded, Object tooltipParam) {
413 tooltip.
addPara(
"Only available when event progress is below %s points.", 0f,
416 }, button, TooltipLocation.BELOW);
422 if (data.rowId instanceof HAEStarSystemDangerData) {
423 HAEStarSystemDangerData d = (HAEStarSystemDangerData) data.rowId;
426 ui.
showOnMap(m.get(0).getPrimaryEntity());
428 ui.
showOnMap(d.system.getHyperspaceAnchor());
435 final EventStageData esd =
getDataFor(stageId);
437 if (esd !=
null && esd.rollData instanceof HAERandomEventData) {
438 HAERandomEventData data = (HAERandomEventData) esd.rollData;
457 if (esd !=
null && esd.id == Stage.HA_EVENT && esd.rollData !=
null &&
RANDOM_EVENT_NONE.equals(esd.rollData)) {
460 return super.getStageIcon(stageId);
465 final EventStageData esd =
getDataFor(stageId);
466 if (esd !=
null && esd.id == Stage.HA_EVENT && esd.rollData !=
null &&
RANDOM_EVENT_NONE.equals(esd.rollData)) {
468 public boolean isTooltipExpandable(Object tooltipParam) {
471 public float getTooltipWidth(Object tooltipParam) {
475 public void createTooltip(
TooltipMakerAPI tooltip,
boolean expanded, Object tooltipParam) {
477 tooltip.
addPara(
"There's no crisis on the horizon right now. When this stage is reached, "
478 +
"event progress will be reset to a lower value.",
483 return super.getStageTooltip(stageId);
489 if (esd ==
null)
return null;
498 if (esd.rollData instanceof HAERandomEventData) {
499 HAERandomEventData data = (HAERandomEventData) esd.rollData;
507 if (esd.id == Stage.START) {
525 return super.getBarProgressIndicatorColor();
537 return super.getStageImportance(stageId);
545 return "Colony Crises";
566 if (curr ==
null)
return;
569 if (cause ==
null)
return;
580 if (curr ==
null)
return null;
583 if (cause ==
null)
return null;
593 Iterator<EventFactor> iter =
factors.iterator();
594 while (iter.hasNext()) {
596 if (curr.getClass() == c) {
603 Iterator<EventFactor> iter =
factors.iterator();
604 while (iter.hasNext()) {
606 if (curr.getClass() == c) {
614 List<HAEStarSystemDangerData> systemData =
new ArrayList<HAEStarSystemDangerData>();
617 systemData.add(data);
619 Collections.sort(systemData,
new Comparator<HAEStarSystemDangerData>() {
620 public int compare(HAEStarSystemDangerData o1, HAEStarSystemDangerData o2) {
621 int result = (int) Math.signum(o2.sortMag - o1.sortMag);
623 result = (int) Math.signum(o2.totalMag - o1.totalMag);
626 result = (int) Math.signum(o2.system.getId().hashCode() - o1.system.getId().hashCode());
635 HAEStarSystemDangerData data =
new HAEStarSystemDangerData();
636 data.system = system;
642 HAEFactorDangerData curr =
new HAEFactorDangerData();
645 data.factorData.add(curr);
646 maxMag = Math.max(maxMag, curr.mag);
650 data.maxMag = maxMag;
651 data.totalMag = total;
652 data.sortMag = data.maxMag * 0.75f + data.totalMag * 0.25f;
654 Collections.sort(data.factorData,
new Comparator<HAEFactorDangerData>() {
655 public int compare(HAEFactorDangerData o1, HAEFactorDangerData o2) {
656 return (int) Math.signum(o2.mag - o1.mag);
664 if (mag <= 0f)
return LocationDanger.NONE;
665 if (mag < 0.25f)
return LocationDanger.MINIMAL;
666 if (mag < 0.5f)
return LocationDanger.LOW;
667 if (mag < 0.75f)
return LocationDanger.MEDIUM;
668 if (mag < 1f)
return LocationDanger.HIGH;
669 return LocationDanger.EXTREME;
673 return getDangerString(getDanger(mag));
677 case EXTREME:
return "Extreme";
678 case HIGH:
return "High";
679 case MEDIUM:
return "Medium";
680 case LOW:
return "Low";
681 case MINIMAL:
return "Minimal";
682 case NONE:
return "None";
688 LocationDanger d = getDanger(mag);
689 if (d == LocationDanger.NONE || d == LocationDanger.MINIMAL) {
692 if (d == LocationDanger.EXTREME || d == LocationDanger.HIGH) {
699 float mag = getTotalActivityMagnitude(system,
true);
701 mag *= 0.2f + getMarketPresenceFactor(system) * 0.8f;
715 maxSize = Math.max(market.getSize(), maxSize);
719 float f = (maxSize - 3f + count - 1f) / 3f;
722 if (maxSize <= 4f) cap = 0.55f;
723 else if (maxSize <= 5f) cap = 0.75f;
727 if (f > cap) f = cap;
733 return getTotalActivityMagnitude(system,
true);
744 if (capped && total > 1f) total = 1f;
746 total = Math.round(total * 100f) / 100f;
753 super.advanceImpl(amount);
755 if (systemSpawnMults !=
null) {
764 if (system ==
null) {
767 if (systemSpawnMults ==
null) {
768 systemSpawnMults =
new LinkedHashMap<String, MutableStatWithTempMods>();
771 String
id = system.
getId();
775 systemSpawnMults.put(
id, stat);
781 return getNumFleetsStat(system).getModifiedValue();
785 cleanUpHostileActivityConditions();
798 return isEnding() || isEnded();
809 if (isEnded() || isEnding())
return;
817 if (otherFleet.isStationMode() && otherFleet.getFleetData().getMembersListCopy().isEmpty()) {
822 int tier = intel.
getTier().ordinal();
823 if (tier < 0) tier = 0;
824 if (tier > 4) tier = 4;
834 float totalInterest = 0f;
835 float activeCells = 0f;
841 if (totalInterest > 0) {
846 int points = -1 * Math.min(max, (flat + perCell * (
int) Math.round(activeCells)));
858 boolean nearAny =
false;
863 if (!nearAny)
return;
865 float fpDestroyed = 0;
870 fpDestroyed += loss.getFleetPointCost();
877 int points = computeProgressPoints(fpDestroyed);
887 if (fleetPointsDestroyed <= 0)
return 0;
889 int points = Math.round(fleetPointsDestroyed / FP_PER_POINT);
890 if (points < 1) points = 1;
897 if (stage.rollData instanceof HAERandomEventData) {
898 HAERandomEventData data = (HAERandomEventData) stage.rollData;
899 boolean fired = data.factor.
fireEvent(
this, stage);
900 stage.rollData =
null;
902 if (stage.id == Stage.HA_EVENT) {
903 int resetProgress = getResetProgress(fired);
904 setProgress(resetProgress);
906 }
else if (stage.id == Stage.HA_EVENT &&
907 (stage.rollData ==
null || RANDOM_EVENT_NONE.equals(stage.rollData))) {
908 stage.rollData =
null;
909 int resetProgress = getResetProgress(
false);
910 setProgress(resetProgress);
919 if (!fired) min = RESET_MAX - 200;
921 int resetAdd = random.nextInt(RESET_MAX - min + 1);
922 resetAdd = Math.min(resetAdd, random.nextInt(RESET_MAX - min + 1));
923 int resetProgress = min + resetAdd;
925 int add = Math.min(blowback, (
int)((RESET_MAX - resetProgress) * 0.5f));
927 resetProgress += add;
930 return resetProgress;
934 EventStageData stage = getDataFor(Stage.HA_EVENT);
936 int resetProgress = getResetProgress(
false);
937 resetRandomizedStage(stage);
938 setProgress(resetProgress);
942 EventStageData stage = getDataFor(Stage.HA_EVENT);
943 if (stage !=
null && stage.rollData instanceof HAERandomEventData &&
944 ((HAERandomEventData)stage.rollData).factor == factor) {
951 if (stage.rollData instanceof HAERandomEventData) {
952 HAERandomEventData data = (HAERandomEventData) stage.rollData;
956 super.resetRandomizedStage(stage);
963 if (stage.id == Stage.HA_EVENT || stage.id == Stage.MINOR_EVENT) {
967 total += factor.getProgress(
this);
970 if (total < 1f) total = 1f;
978 float w = factor.getProgress(
this) / total;
982 picker.
add(curr, f * w);
987 if (stage.id == Stage.HA_EVENT) {
988 if (prevMajorEventPick == pick && !picker.
isEmpty()) {
991 prevMajorEventPick = pick;
994 if (pick ==
null)
return;
996 stage.rollData =
null;
1003 Set<String> tags = super.getIntelTags(map);
1016 p = Math.min(p, getProgress());
1022 super.addFactor(factor);
1027 super.reportEconomyMonthEnd();
1034 if (factor.isOneTime())
continue;
1035 mult *= factor.getAllProgressMult(
this);
1038 amt = Math.round(amt * mult);
1040 if (amt < 1) amt = 1;
1042 if (blowback < 0) blowback = 0;
1059 this.blowback = blowback;
1063 if (param instanceof HAERandomEventData) {
1064 HAERandomEventData data = (HAERandomEventData) param;
1065 if (data.isReset)
return null;
1066 if (data.factor ==
null)
return null;
1082 if (buttonId == BUTTON_ESCALATE) {
1088 if (buttonId == BUTTON_ESCALATE) {
1089 StoryOptionParams params =
new StoryOptionParams(
null, 1,
"escalateCrisis",
1091 "Escalated colony crisis");
1092 return new BaseOptionStoryPointActionDelegate(
null, params) {
1094 public void confirm() {
1095 setProgress(ESCALATE_PROGRESS);
1099 public String getTitle() {
1106 info.
addPara(
"Take certain actions to precipitate a crisis more quickly. Sets event progress "
1109 super.createDescription(info);
static SettingsAPI getSettings()
static SectorAPI getSector()
static void finishedAddingCrisisFactors(HostileActivityEventIntel intel)
static final String HOSTILE_ACTIVITY
static final String PLAYER
static String STORY_POINT_SPEND_INDUSTRY
ButtonAPI addGenericButton(TooltipMakerAPI info, float width, String text, Object data)
Object getListInfoParam()
FactionAPI getFactionForUIColors()
static LuddicPathBaseIntel getIntelFor(StarSystemAPI system)
static PirateBaseIntel getIntelFor(StarSystemAPI system)
static float TOOLTIP_WIDTH
static final String RANDOM_EVENT_NONE
void addStage(Object id, int progress)
void setRandomized(Object stageId, RandomizedStageType type, int resetAt, int rollAt, boolean sendUpdateWhenReached)
void setMaxProgress(int maxProgress)
EventStageData getDataFor(Object stageId)
boolean addEventFactorBulletPoints(TooltipMakerAPI info, ListInfoMode mode, boolean isUpdate, Color tc, float initPad)
List< EventStageData > stages
List< EventFactor > factors
boolean isStageActiveAndLast(Object stageId)
List< HostileActivityCause2 > getCauses()
void setRandomizedStageSeed(long seed)
float getEventFrequency(HostileActivityEventIntel intel, EventStageData stage)
void addCause(HostileActivityCause2 cause)
HostileActivityCause2 getCauseOfClass(Class c)
String getDangerString(LocationDanger d)
boolean isEventProgressANegativeThingForThePlayer()
static int computeProgressPoints(float fleetPointsDestroyed)
float getVeryApproximateFPStrength(StarSystemAPI system)
void addFactor(EventFactor factor)
void notifyStageReached(EventStageData stage)
void storyActionConfirmed(Object buttonId, IntelUIAPI ui)
int getMaxMonthlyProgress()
HAERandomEventData getRollDataForEvent()
void tableRowClicked(IntelUIAPI ui, TableRowClickData data)
HostileActivityCause2 getActivityCause(Class activityClass, Class causeClass)
float getNumFleetsMultiplier(StarSystemAPI system)
void cleanUpHostileActivityConditions()
void rollRandomizedStage(EventStageData stage)
void addActivity(BaseHostileActivityFactor factor, HostileActivityCause2 cause)
void afterStageDescriptions(TooltipMakerAPI main)
static String BUTTON_ESCALATE
void commodityUpdated(String commodityId)
void addStageDescriptionText(TooltipMakerAPI info, float width, Object stageId)
List< HAEStarSystemDangerData > computePlayerSystemDangerData()
boolean isEconomyListenerExpired()
static int ESCALATE_PROGRESS
Color getBarProgressIndicatorColor()
void removeActivity(BaseHostileActivityFactor plugin)
BaseHostileActivityFactor getActivityOfClass(Class c)
Map< String, MutableStatWithTempMods > systemSpawnMults
String getStageIconImpl(Object stageId)
int getResetProgress(boolean fired)
MutableStatWithTempMods getNumFleetsStat(StarSystemAPI system)
StoryPointActionDelegate getButtonStoryPointActionDelegate(Object buttonId)
TooltipCreator getStageTooltip(Object stageId)
Set< String > getIntelTags(SectorMapAPI map)
int getStageImportance(Object stageId)
void advanceImpl(float amount)
HostileActivityEventIntel()
String getStageIcon(Object stageId)
float getTotalActivityMagnitude(StarSystemAPI system, boolean capped)
String getDangerString(float mag)
void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode, boolean isUpdate, Color tc, float initPad)
void resetRandomizedStage(EventStageData stage)
void removeActivityOfClass(Class c)
LocationDanger getDanger(float mag)
void resetHA_EVENTIfFromFactor(HostileActivityFactor factor)
static float FP_PER_POINT
TooltipCreator getStageTooltipImpl(Object stageId)
void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle)
void setBlowback(int blowback)
float getMarketPresenceFactor(StarSystemAPI system)
void addBlowback(int points)
void reportEconomyMonthEnd()
Color getDangerColor(float mag)
void removeActivityCause(Class activityClass, Class causeClass)
String getSoundForOtherUpdate(Object param)
float getTotalActivityMagnitude(StarSystemAPI system)
HAEStarSystemDangerData computeDangerData(StarSystemAPI system)
void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param)
static float getPatherInterest(StarSystemAPI system, float multIfNoCells, float multIfSleeper, float multIfActive)
static boolean baseInvolved(StarSystemAPI system, PirateBaseIntel base)
static Color getStoryOptionColor()
static Color getTextColor()
static Color getStoryDarkColor()
static List< FleetMemberAPI > getSnapshotMembersLost(CampaignFleetAPI fleet)
static List< MarketAPI > getMarketsInLocation(LocationAPI location, String factionId)
static Color getNegativeHighlightColor()
static String getJoined(String joiner, List< String > strings)
static List< StarSystemAPI > getPlayerSystems(boolean includeNonPlayerFaction)
static Color getBasePlayerColor()
static Color getGrayColor()
static float getDays(float amount)
static boolean isNear(SectorEntityToken entity, Vector2f hyperLoc)
static Color getHighlightColor()
static CampaignFleetAPI getStationFleet(MarketAPI market)
static List< MarketAPI > getPlayerMarkets(boolean includeNonPlayerFaction)
static Color interpolateColor(Color from, Color to, float progress)
static Color getPositiveHighlightColor()
int getIntFromArray(String key, int index)
String getSpriteName(String category, String id)
float getFloat(String key)
List< CampaignFleetAPI > getNonPlayerSideSnapshot()
boolean isPlayerInvolved()
List< CampaignFleetAPI > getPlayerSide()
LocationAPI getCurrentLocation()
IntelManagerAPI getIntelManager()
MemoryAPI getMemoryWithoutUpdate()
ListenerManagerAPI getListenerManager()
void addIntel(IntelInfoPlugin plugin)
void removeUpdateListener(EconomyUpdateListener listener)
void removeListenerOfClass(Class<?> c)
void set(String key, Object value)
int getProgress(BaseEventIntel intel)
String getEventStageIcon(HostileActivityEventIntel intel, EventStageData stage)
boolean fireEvent(HostileActivityEventIntel intel, EventStageData stage)
void addStageDescriptionForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info)
void addBulletPointForEvent(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info, ListInfoMode mode, boolean isUpdate, Color tc, float initPad)
void addBulletPointForEventReset(HostileActivityEventIntel intel, EventStageData stage, TooltipMakerAPI info, ListInfoMode mode, boolean isUpdate, Color tc, float initPad)
TooltipCreator getStageTooltipImpl(HostileActivityEventIntel intel, EventStageData stage)
void rollEvent(HostileActivityEventIntel intel, EventStageData stage)
void resetEvent(HostileActivityEventIntel intel, EventStageData stage)
String getEventStageSound(HAERandomEventData data)
void showOnMap(SectorEntityToken token)
void setHighlight(int start, int end)
void setHighlightColors(Color ... colors)
PositionAPI setXAlignOffset(float xAlignOffset)
PositionAPI getPosition()