1package com.fs.starfarer.api.impl.campaign.intel.events;
4import java.util.ArrayList;
5import java.util.Collections;
6import java.util.Comparator;
7import java.util.Iterator;
8import java.util.LinkedHashMap;
13import com.fs.starfarer.api.Global;
14import com.fs.starfarer.api.campaign.BattleAPI;
15import com.fs.starfarer.api.campaign.CampaignEventListener.FleetDespawnReason;
16import com.fs.starfarer.api.campaign.CampaignFleetAPI;
17import com.fs.starfarer.api.campaign.StarSystemAPI;
18import com.fs.starfarer.api.campaign.econ.EconomyAPI.EconomyUpdateListener;
19import com.fs.starfarer.api.campaign.econ.MarketAPI;
20import com.fs.starfarer.api.campaign.listeners.FleetEventListener;
21import com.fs.starfarer.api.combat.MutableStatWithTempMods;
22import com.fs.starfarer.api.fleet.FleetMemberAPI;
23import com.fs.starfarer.api.impl.campaign.command.WarSimScript.LocationDanger;
24import com.fs.starfarer.api.impl.campaign.ids.Conditions;
25import com.fs.starfarer.api.impl.campaign.ids.Factions;
26import com.fs.starfarer.api.impl.campaign.ids.Tags;
27import com.fs.starfarer.api.impl.campaign.intel.bases.LuddicPathBaseIntel;
28import com.fs.starfarer.api.impl.campaign.intel.bases.PirateBaseIntel;
29import com.fs.starfarer.api.impl.campaign.rulecmd.HA_CMD;
30import com.fs.starfarer.api.ui.Alignment;
31import com.fs.starfarer.api.ui.IntelUIAPI;
32import com.fs.starfarer.api.ui.LabelAPI;
33import com.fs.starfarer.api.ui.SectorMapAPI;
34import com.fs.starfarer.api.ui.TooltipMakerAPI;
35import com.fs.starfarer.api.ui.TooltipMakerAPI.TooltipCreator;
36import com.fs.starfarer.api.ui.TooltipMakerAPI.TooltipLocation;
37import com.fs.starfarer.api.util.Misc;
38import com.fs.starfarer.api.util.WeightedRandomPicker;
42 public static enum Stage {
50 @Deprecated INCREASED_DEFENSES,
54 public static String
KEY =
"$hae_ref";
64 public static class HAERandomEventData {
66 public EventStageData stage;
67 public boolean isReset =
false;
76 public static class HAEFactorDangerData {
80 public static class HAEStarSystemDangerData {
81 public StarSystemAPI system;
83 public float totalMag;
85 public List<HAEFactorDangerData> factorData =
new ArrayList<HAEFactorDangerData>();
94 protected Map<String, MutableStatWithTempMods>
systemSpawnMults =
new LinkedHashMap<String, MutableStatWithTempMods>();
111 boolean minorCompleted =
false;
112 EventStageData minor =
getDataFor(Stage.MINOR_EVENT);
113 if (minor !=
null) minorCompleted = minor.wasEverReached;
120 addStage(Stage.MINOR_EVENT, 300, StageIconSize.MEDIUM);
121 addStage(Stage.HA_EVENT, 600,
true, StageIconSize.LARGE);
123 setRandomized(Stage.MINOR_EVENT, RandomizedStageType.BAD, 200, 250,
false,
false);
124 setRandomized(Stage.HA_EVENT, RandomizedStageType.BAD, 425, 500,
false);
128 minor.wasEverReached = minorCompleted;
180 super.notifyEnding();
192 protected void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode,
boolean isUpdate,
193 Color tc,
float initPad) {
202 data.factor.addBulletPointForEventReset(
this, data.stage, info, mode, isUpdate, tc, initPad);
204 data.factor.addBulletPointForEvent(
this, data.stage, info, mode, isUpdate, tc, initPad);
209 for (EventStageData stage :
stages) {
210 if (stage.rollData instanceof HAERandomEventData) {
211 HAERandomEventData data = (HAERandomEventData) stage.rollData;
212 data.factor.addBulletPointForEvent(
this, stage, info, mode, isUpdate, tc, initPad);
233 EventStageData stage =
getDataFor(Stage.HA_EVENT);
234 if (stage ==
null)
return null;;
236 if (stage.rollData instanceof HAERandomEventData) {
237 HAERandomEventData data = (HAERandomEventData) stage.rollData;
247 Color h = Misc.getHighlightColor();
264 if (stage ==
null)
return;
266 if (stage.rollData instanceof HAERandomEventData) {
267 HAERandomEventData data = (HAERandomEventData) stage.rollData;
268 data.factor.addStageDescriptionForEvent(
this, stage, info);
273 if (stageId == Stage.START) {
277 info.addPara(
"Low-level pirate activity continues, but aside from that, there are "
278 +
"no major crises on the horizon.", small);
280 info.addPara(
"A crisis is virtually inevitable at some point, "
281 +
"and hostile fleets continually probe your defenses, but where there is "
282 +
"danger, there is often opportunity.", small);
291 float systemW = 230f;
292 float threatW = 300f;
294 "Star system", systemW,
296 "Primary threats", threatW
298 info.makeTableItemsClickable();
300 int maxSystemsToList = 4;
302 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.");
303 info.addTableHeaderTooltip(1,
"Danger level of the stronger fleets likely to be found in the system. "
304 +
"Approximate, there may be exceptions. Does not include hostile fleets that may be present there for other reasons.");
305 info.addTableHeaderTooltip(2,
"The most dangerous types of threats likely to be found in the system. "
306 +
"Not comprehensive, and does not include hostile fleets that may be present there for other reasons.");
310 for (
final HAEStarSystemDangerData sys : systemData) {
311 if (sys.sortMag <= 0)
continue;
313 float mag = sys.sortMag;
318 List<String> threats =
new ArrayList<String>();
319 List<Color> colors =
new ArrayList<Color>();
320 for (HAEFactorDangerData data : sys.factorData) {
321 if (data.mag <= 0)
continue;
322 threats.add(data.factor.getNameForThreatList(count == 0));
323 colors.add(data.factor.getNameColorForThreatList());
325 if (count >= maxThreats) {
329 String threatStr = Misc.getJoined(
"", threats);
331 LabelAPI label = info.createLabel(threatStr, Misc.getTextColor(), threatW);
332 label.setHighlightColors(colors.toArray(
new Color[0]));
333 label.setHighlight(threats.toArray(
new String[0]));
335 String systemName = sys.system.getNameWithNoType();
337 List<MarketAPI> colonies = Misc.getMarketsInLocation(sys.system, Factions.PLAYER);
339 if (colonies.size() == 1) {
340 colStr = colonies.get(0).getName();
342 colStr =
"" + colonies.size() +
" colonies";
344 systemName +=
" - " + colStr +
"";
346 info.addRowWithGlow(Alignment.LMID, Misc.getBasePlayerColor(), systemName,
348 Alignment.MID,
null, label);
351 public void createTooltip(TooltipMakerAPI tooltip,
boolean expanded, Object tooltipParam) {
352 float w = tooltip.getWidthSoFar();
353 float h = Math.round(w / 1.6f);
354 tooltip.addSectorMap(w, h, sys.system, 0f);
355 tooltip.addPara(
"Click to open map", Misc.getGrayColor(), 5f);
358 }, TooltipLocation.LEFT,
false);
360 info.setIdForAddedRow(sys);
363 if (numListed >= maxSystemsToList) {
367 info.addTable(
"None", -1, opad);
374 if (data.rowId instanceof HAEStarSystemDangerData) {
375 HAEStarSystemDangerData d = (HAEStarSystemDangerData) data.rowId;
376 List<MarketAPI> m = Misc.getMarketsInLocation(d.system, Factions.PLAYER);
378 ui.showOnMap(m.get(0).getPrimaryEntity());
380 ui.showOnMap(d.system.getHyperspaceAnchor());
387 final EventStageData esd =
getDataFor(stageId);
389 if (esd !=
null && esd.rollData instanceof HAERandomEventData) {
390 HAERandomEventData data = (HAERandomEventData) esd.rollData;
391 return data.factor.getStageTooltipImpl(
this, esd);
409 if (esd !=
null && esd.id == Stage.HA_EVENT && esd.rollData !=
null &&
RANDOM_EVENT_NONE.equals(esd.rollData)) {
412 return super.getStageIcon(stageId);
417 final EventStageData esd =
getDataFor(stageId);
418 if (esd !=
null && esd.id == Stage.HA_EVENT && esd.rollData !=
null &&
RANDOM_EVENT_NONE.equals(esd.rollData)) {
419 return new TooltipCreator() {
420 public boolean isTooltipExpandable(Object tooltipParam) {
423 public float getTooltipWidth(Object tooltipParam) {
427 public void createTooltip(TooltipMakerAPI tooltip,
boolean expanded, Object tooltipParam) {
428 Color h = Misc.getHighlightColor();
429 tooltip.addPara(
"There's no crisis on the horizon right now. When this stage is reached, "
430 +
"event progress will be reset to a lower value.",
435 return super.getStageTooltip(stageId);
441 if (esd ==
null)
return null;
450 if (esd.rollData instanceof HAERandomEventData) {
451 HAERandomEventData data = (HAERandomEventData) esd.rollData;
452 return data.factor.getEventStageIcon(
this, esd);
459 if (esd.id == Stage.START) {
469 Color color = Misc.getNegativeHighlightColor();
471 color = Misc.interpolateColor(color, Color.black, 0.25f);
477 return super.getBarProgressIndicatorColor();
489 return super.getStageImportance(stageId);
497 return "Colony Crises";
518 if (curr ==
null)
return;
521 if (cause ==
null)
return;
532 if (curr ==
null)
return null;
535 if (cause ==
null)
return null;
545 Iterator<EventFactor> iter =
factors.iterator();
546 while (iter.hasNext()) {
548 if (curr.getClass() == c) {
555 Iterator<EventFactor> iter =
factors.iterator();
556 while (iter.hasNext()) {
558 if (curr.getClass() == c) {
566 List<HAEStarSystemDangerData> systemData =
new ArrayList<HAEStarSystemDangerData>();
567 for (StarSystemAPI system : Misc.getPlayerSystems(
false)) {
569 systemData.add(data);
571 Collections.sort(systemData,
new Comparator<HAEStarSystemDangerData>() {
572 public int compare(HAEStarSystemDangerData o1, HAEStarSystemDangerData o2) {
573 int result = (int) Math.signum(o2.sortMag - o1.sortMag);
575 result = (int) Math.signum(o2.totalMag - o1.totalMag);
578 result = (int) Math.signum(o2.system.getId().hashCode() - o1.system.getId().hashCode());
587 HAEStarSystemDangerData data =
new HAEStarSystemDangerData();
588 data.system = system;
594 HAEFactorDangerData curr =
new HAEFactorDangerData();
597 data.factorData.add(curr);
598 maxMag = Math.max(maxMag, curr.mag);
602 data.maxMag = maxMag;
603 data.totalMag = total;
604 data.sortMag = data.maxMag * 0.75f + data.totalMag * 0.25f;
606 Collections.sort(data.factorData,
new Comparator<HAEFactorDangerData>() {
607 public int compare(HAEFactorDangerData o1, HAEFactorDangerData o2) {
608 return (
int) Math.signum(o2.mag - o1.mag);
616 if (mag <= 0f)
return LocationDanger.NONE;
617 if (mag < 0.25f)
return LocationDanger.MINIMAL;
618 if (mag < 0.5f)
return LocationDanger.LOW;
619 if (mag < 0.75f)
return LocationDanger.MEDIUM;
620 if (mag < 1f)
return LocationDanger.HIGH;
621 return LocationDanger.EXTREME;
629 case EXTREME:
return "Extreme";
630 case HIGH:
return "High";
631 case MEDIUM:
return "Medium";
632 case LOW:
return "Low";
633 case MINIMAL:
return "Minimal";
634 case NONE:
return "None";
641 if (d == LocationDanger.NONE || d == LocationDanger.MINIMAL) {
642 return Misc.getPositiveHighlightColor();
644 if (d == LocationDanger.EXTREME || d == LocationDanger.HIGH) {
645 return Misc.getNegativeHighlightColor();
647 return Misc.getHighlightColor();
666 for (MarketAPI market : Misc.getMarketsInLocation(system, Factions.PLAYER)) {
667 maxSize = Math.max(market.getSize(), maxSize);
671 float f = (maxSize - 3f + count - 1f) / 3f;
674 if (maxSize <= 4f) cap = 0.55f;
675 else if (maxSize <= 5f) cap = 0.75f;
679 if (f > cap) f = cap;
696 if (capped && total > 1f) total = 1f;
698 total = Math.round(total * 100f) / 100f;
705 super.advanceImpl(amount);
708 float days = Misc.getDays(amount);
716 if (system ==
null) {
717 return new MutableStatWithTempMods(1f);
723 String
id = system.getId();
726 stat =
new MutableStatWithTempMods(1f);
742 for (MarketAPI curr : Misc.getPlayerMarkets(
false)) {
743 if (curr.hasCondition(Conditions.HOSTILE_ACTIVITY)) {
744 curr.removeCondition(Conditions.HOSTILE_ACTIVITY);
763 if (!battle.isPlayerInvolved())
return;
765 if (
Global.
getSector().getCurrentLocation() instanceof StarSystemAPI &&
766 battle.getPlayerSide().contains(primaryWinner)) {
767 StarSystemAPI system = (StarSystemAPI)
Global.
getSector().getCurrentLocation();
768 for (CampaignFleetAPI otherFleet : battle.getNonPlayerSideSnapshot()) {
769 if (otherFleet.isStationMode()) {
771 PirateBaseIntel intel = PirateBaseIntel.getIntelFor(system);
772 if (intel !=
null && Misc.getStationFleet(intel.getMarket()) == otherFleet &&
773 HA_CMD.baseInvolved(system, intel)) {
774 int tier = intel.getTier().ordinal();
775 if (tier < 0) tier = 0;
776 if (tier > 4) tier = 4;
784 LuddicPathBaseIntel intel = LuddicPathBaseIntel.getIntelFor(system);
785 if (intel !=
null && Misc.getStationFleet(intel.getMarket()) == otherFleet) {
786 float totalInterest = 0f;
787 float activeCells = 0f;
788 for (StarSystemAPI curr : Misc.getPlayerSystems(
false)) {
793 if (totalInterest > 0) {
798 int points = -1 * Math.min(max, (flat + perCell * (
int) Math.round(activeCells)));
810 boolean nearAny =
false;
811 for (StarSystemAPI system : Misc.getPlayerSystems(
false)) {
812 nearAny |= Misc.isNear(primaryWinner, system.getLocation());
815 if (!nearAny)
return;
817 float fpDestroyed = 0;
818 CampaignFleetAPI first =
null;
819 for (CampaignFleetAPI otherFleet : battle.getNonPlayerSideSnapshot()) {
821 for (FleetMemberAPI loss : Misc.getSnapshotMembersLost(otherFleet)) {
822 fpDestroyed += loss.getFleetPointCost();
839 if (fleetPointsDestroyed <= 0)
return 0;
841 int points = Math.round(fleetPointsDestroyed /
FP_PER_POINT);
842 if (points < 1) points = 1;
849 if (stage.rollData instanceof HAERandomEventData) {
850 HAERandomEventData data = (HAERandomEventData) stage.rollData;
851 boolean fired = data.factor.fireEvent(
this, stage);
852 stage.rollData =
null;
854 if (stage.id == Stage.HA_EVENT) {
858 }
else if (stage.id == Stage.HA_EVENT &&
860 stage.rollData =
null;
875 int resetProgress = min + resetAdd;
879 resetProgress += add;
882 return resetProgress;
886 EventStageData stage =
getDataFor(Stage.HA_EVENT);
894 EventStageData stage =
getDataFor(Stage.HA_EVENT);
895 if (stage !=
null && stage.rollData instanceof HAERandomEventData &&
896 ((HAERandomEventData)stage.rollData).factor == factor) {
903 if (stage.rollData instanceof HAERandomEventData) {
904 HAERandomEventData data = (HAERandomEventData) stage.rollData;
906 data.factor.resetEvent(
this, stage);
908 super.resetRandomizedStage(stage);
915 if (stage.id == Stage.HA_EVENT || stage.id == Stage.MINOR_EVENT) {
919 total += factor.getProgress(
this);
922 if (total < 1f) total = 1f;
924 WeightedRandomPicker<HostileActivityFactor> picker =
new WeightedRandomPicker<HostileActivityFactor>(
random);
930 float w = factor.getProgress(
this) / total;
934 picker.add(curr, f * w);
939 if (stage.id == Stage.HA_EVENT) {
941 pick = picker.pickAndRemove();
946 if (pick ==
null)
return;
948 stage.rollData =
null;
955 Set<String> tags = super.getIntelTags(map);
956 tags.add(Tags.INTEL_COLONIES);
974 super.addFactor(factor);
979 super.reportEconomyMonthEnd();
986 if (factor.isOneTime())
continue;
987 mult *= factor.getAllProgressMult(
this);
990 amt = Math.round(amt * mult);
992 if (amt < 1) amt = 1;
1015 if (param instanceof HAERandomEventData) {
1016 HAERandomEventData data = (HAERandomEventData) param;
1017 if (data.isReset)
return null;
1018 if (data.factor ==
null)
return null;
1019 return data.factor.getEventStageSound(data);
1027 if (Misc.isEasy()) {
static SettingsAPI getSettings()
static SectorAPI getSector()
Object getListInfoParam()
FactionAPI getFactionForUIColors()
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)
void setProgress(int progress)
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)
int getMaxMonthlyProgress()
HAERandomEventData getRollDataForEvent()
void tableRowClicked(IntelUIAPI ui, TableRowClickData data)
HostileActivityCause2 getActivityCause(Class activityClass, Class causeClass)
HostileActivityFactor prevMajorEventPick
float getNumFleetsMultiplier(StarSystemAPI system)
void cleanUpHostileActivityConditions()
void rollRandomizedStage(EventStageData stage)
void addActivity(BaseHostileActivityFactor factor, HostileActivityCause2 cause)
void commodityUpdated(String commodityId)
void addStageDescriptionText(TooltipMakerAPI info, float width, Object stageId)
List< HAEStarSystemDangerData > computePlayerSystemDangerData()
boolean isEconomyListenerExpired()
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)
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)
int getIntFromArray(String key, int index)
String getSpriteName(String category, String id)
float getFloat(String key)
int getProgress(BaseEventIntel intel)
void rollEvent(HostileActivityEventIntel intel, EventStageData stage)