1package com.fs.starfarer.api.impl.campaign.intel.bases;
4import java.util.ArrayList;
5import java.util.Collections;
6import java.util.Comparator;
7import java.util.Iterator;
9import java.util.Random;
12import com.fs.starfarer.api.Global;
13import com.fs.starfarer.api.campaign.BattleAPI;
14import com.fs.starfarer.api.campaign.CampaignEventListener.FleetDespawnReason;
15import com.fs.starfarer.api.campaign.CampaignFleetAPI;
16import com.fs.starfarer.api.campaign.FactionAPI;
17import com.fs.starfarer.api.campaign.SectorEntityToken;
18import com.fs.starfarer.api.campaign.comm.IntelInfoPlugin;
19import com.fs.starfarer.api.campaign.econ.Industry;
20import com.fs.starfarer.api.campaign.econ.MarketAPI;
21import com.fs.starfarer.api.campaign.listeners.FleetEventListener;
22import com.fs.starfarer.api.impl.campaign.DebugFlags;
23import com.fs.starfarer.api.impl.campaign.econ.RecentUnrest;
24import com.fs.starfarer.api.impl.campaign.fleets.EconomyFleetAssignmentAI;
25import com.fs.starfarer.api.impl.campaign.fleets.EconomyFleetAssignmentAI.EconomyRouteData;
26import com.fs.starfarer.api.impl.campaign.fleets.EconomyFleetRouteManager;
27import com.fs.starfarer.api.impl.campaign.fleets.RouteLocationCalculator;
28import com.fs.starfarer.api.impl.campaign.fleets.RouteManager;
29import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.OptionalFleetData;
30import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData;
31import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteFleetSpawner;
32import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteSegment;
33import com.fs.starfarer.api.impl.campaign.ids.Conditions;
34import com.fs.starfarer.api.impl.campaign.ids.Factions;
35import com.fs.starfarer.api.impl.campaign.ids.FleetTypes;
36import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
37import com.fs.starfarer.api.impl.campaign.ids.Tags;
38import com.fs.starfarer.api.impl.campaign.intel.BaseIntelPlugin;
39import com.fs.starfarer.api.impl.campaign.rulecmd.HA_CMD;
40import com.fs.starfarer.api.ui.Alignment;
41import com.fs.starfarer.api.ui.SectorMapAPI;
42import com.fs.starfarer.api.ui.TooltipMakerAPI;
43import com.fs.starfarer.api.util.IntervalUtil;
44import com.fs.starfarer.api.util.Misc;
45import com.fs.starfarer.api.util.WeightedRandomPicker;
69 public static enum IncidentType {
81 protected Random
random =
new Random();
101 if (!
market.isPlayerOwned()) {
105 if (!
market.hasCondition(Conditions.PATHER_CELLS)) {
106 market.addCondition(Conditions.PATHER_CELLS,
this);
120 float minDist = Float.MAX_VALUE;
122 for (IntelInfoPlugin curr : bases) {
124 float dist = Misc.getDistance(intel.
getMarket().getLocationInHyperspace(),
market.getLocationInHyperspace());
125 if (dist < minDist) {
134 List<LuddicPathCellsIntel> result =
new ArrayList<LuddicPathCellsIntel>();
137 for (IntelInfoPlugin curr : cells) {
139 if (!includeSleeper && intel.
isSleeper())
continue;
148 if (
market ==
null)
return null;
150 for (IntelInfoPlugin curr : cells) {
164 return super.canMakeVisibleToPlayer(playerInRelayRange);
176 super.notifyEnding();
178 if (
market.hasCondition(Conditions.PATHER_CELLS)) {
179 market.removeCondition(Conditions.PATHER_CELLS);
202 super.advanceImpl(amount);
204 float days = Misc.getDays(amount);
215 if (!
market.isInEconomy()) {
266 RouteSegment segment =
smuggler.getCurrent();
267 if (segment !=
null && segment.getId() == EconomyFleetRouteManager.ROUTE_TRAVEL_SRC) {
280 Color h = Misc.getHighlightColor();
281 Color g = Misc.getGrayColor();
286 if (mode == ListInfoMode.IN_DESC) initPad = opad;
293 if (mode != ListInfoMode.IN_DESC) {
302 info.addPara(
"Incident averted by local security forces", initPad);
305 case INDUSTRY_SABOTAGE:
307 String days =
getDays(ind.getDisruptedDays());
309 info.addPara(ind.getCurrentName() +
" operations disrupted for %s " + daysStr, initPad, tc, h, days);
311 case REDUCED_STABILITY:
312 info.addPara(
"Stability reduced by %s", initPad, tc, h,
"" + (Integer)
prevIncidentData);
315 info.addPara(
"Colony destroyed by planetbuster", initPad, tc);
328 info.addPara(
getName(), c, 0f);
333 Color h = Misc.getHighlightColor();
339 info.addPara(
"The following activity is attracting Pather interest, whether due to AI core use or the inherent nature of the industry:", opad);
341 List<Industry> industries =
new ArrayList<Industry>(
market.getIndustries());
342 Iterator<Industry> iter = industries.iterator();
343 while (iter.hasNext()) {
344 if (iter.next().isHidden()) {
348 Collections.sort(industries,
new Comparator<Industry>() {
349 public int compare(Industry o1, Industry o2) {
350 float s1 = o1.getPatherInterest();
351 float s2 = o2.getPatherInterest();
352 return (
int) Math.signum(s2 - s1);
357 boolean added =
false;
359 String aiCoreId =
market.getAdmin().getAICoreId();
360 if (aiCoreId !=
null) {
362 if (
market.getAdmin().getMemoryWithoutUpdate().getBoolean(MemFlags.SUSPECTED_AI)) {
363 info.addPara(
indent +
"Suspected AI core administrator (%s)", initPad, h,
"" + s);
365 info.addPara(
indent +
"AI core administrator (%s)", initPad, h,
"" + s);
371 for (Industry ind : industries) {
373 float score = ind.getPatherInterest();
375 int s = (int) Math.round(score);
376 info.addPara(
indent + ind.getCurrentName() +
" (%s)", initPad, h,
"" + s);
385 info.addPara(
indent +
"None", initPad);
394 Color h = Misc.getHighlightColor();
395 Color g = Misc.getGrayColor();
396 Color tc = Misc.getTextColor();
405 info.addPara(
"The Pather cells " +
406 market.getOnOrAt() +
" " +
market.getName() +
" have been dissolved.", opad);
408 info.addPara(
"There are indications that sleeper Luddic Path cells are being organized " +
409 market.getOnOrAt() +
" " +
market.getName() +
".", opad);
410 info.addPara(
"The Pathers have not made any significant moves, but are apparently preparing " +
411 "to do so if whatever activity they object to - industrial development, or the suspected " +
412 "use of AI cores, and other such - continues.", opad);
414 info.addPara(
"There are active Luddic Path cells " +
415 market.getOnOrAt() +
" " +
market.getName() +
".", opad);
419 info.addPara(
"They are engaged in planning acts of terror and industrial sabotage, but " +
420 "are unlikely to carry them off unless the overal level of hostile activity in the system "
421 +
"provides sufficient cover."
422 +
" The cells also provide intel to Pather fleets operating in-system.", opad);
426 if (daysNum < 1) daysNum = 1;
428 info.addPara(
"However, the base supporting these cells is no longer operational. " +
429 "It is projected that establishing a new support network will take at least " +
430 "%s " + days +
", provided another base exists.", opad,
437 info.addPara(
"The Pather base at the " + base.
getMarket().getStarSystem().getNameWithLowercaseType() +
438 " is providing support to these cells.", opad);
440 info.addPara(
"You do not know the location of the Pather base providing support to these cells.", opad);
443 info.addPara(
"If the base is destroyed, it will take some time to organize " +
444 "support from another base, and both ground and fleet operations will be disrupted.", opad);
459 info.addPara(
"%s stability.",
461 "-" + (
int)stability);
464 info.addPara(
"No perceptible impact on operations as of yet.", opad);
466 info.addPara(
"No impact on operations due to lack of material support.", opad);
479 info.addPara(
"There are indications that the Pather cells are preparing to sneak " +
480 "a planetbuster onto " +
market.getName() +
". " +
481 "If they succeed, the colony will effectively be destroyed.", opad);
484 case INDUSTRY_SABOTAGE:
487 if (ind.getDisruptedDays() > 2) {
488 String days =
getDays(ind.getDisruptedDays());
490 info.addPara(
"The Pather cells have conducted a successful act of sabotage, " +
491 "disrupting " + ind.getCurrentName() +
" operations for %s " + daysStr +
".",
496 case REDUCED_STABILITY:
497 info.addPara(
"The Pather cells have conducted low-level attacks on various " +
498 "industrial, military, and civilian targets, reducing stability by %s.",
502 info.addPara(
"The Pather cells have smuggled a planetbuster onto " +
market.getName() +
503 " and detonated it. The colony has been effectively destroyed.", opad);
510 case INDUSTRY_SABOTAGE:
513 info.addPara(
"An attempted act of sabotage against " +
514 ind.getCurrentName() +
" operations was averted by the local security forces.",
518 case REDUCED_STABILITY:
519 info.addPara(
"Multiple planned attacks against various industrial, " +
520 "military, and civilian targets " +
521 " were averted by the local security forces.",
525 info.addPara(
"The Pather cells have smuggled a planetbuster onto " +
market.getName() +
526 ", but the local security forces were able to locate and disarm it, thereby " +
527 "saving the colony.", opad);
547 List<ArrowData> result =
new ArrayList<ArrowData>();
552 SectorEntityToken iconEntity = map.getIntelIconEntity(base);
553 if (iconEntity !=
null) {
554 entityFrom = iconEntity;
558 ArrowData arrow =
new ArrowData(entityFrom,
market.getPrimaryEntity());
575 Set<String> tags = super.getIntelTags(map);
576 tags.add(Factions.LUDDIC_PATH);
579 tags.add(Tags.INTEL_COLONIES);
594 String base =
"Luddic Path Cells";
599 return base +
" - Incident";
601 return base +
" - Incident Averted";
607 return base +
" - Dissolved";
610 return base +
" - Disrupted";
613 return base +
" - Sleeper";
615 return base +
" - Active";
630 return market.getPrimaryEntity();
636 return super.getCommMessageSound();
640 if (Factions.PLAYER.equals(
market.getFactionId())) {
641 if (HA_CMD.playerHasPatherAgreement()) {
662 return EconomyFleetRouteManager.SOURCE_ID;
671 if (base ==
null)
return;
673 WeightedRandomPicker<IncidentType> types =
new WeightedRandomPicker<IncidentType>(
random);
675 types.add(IncidentType.REDUCED_STABILITY, 10f);
677 types.add(IncidentType.INDUSTRY_SABOTAGE, 10f);
714 smuggler.getActiveFleet().removeEventListener(
this);
720 float pSuccess = 1f -
market.getStabilityValue() * 0.075f;
721 return random.nextFloat() < pSuccess;
733 RecentUnrest.get(
market).add(3,
734 Misc.ucFirst(
Global.
getSector().getFaction(Factions.LUDDIC_PATH).getPersonNamePrefix()) +
" sabotage");
737 }
else if (
incidentType == IncidentType.INDUSTRY_SABOTAGE) {
738 WeightedRandomPicker<Industry> picker =
new WeightedRandomPicker<Industry>(
random);
739 for (Industry ind :
market.getIndustries()) {
740 if (!ind.canBeDisrupted())
continue;
741 picker.add(ind, ind.getPatherInterest());
743 Industry target = picker.pick();
744 if (target ==
null) {
752 target.setDisrupted(disruptionDur,
true);
764 ||
market.isPlayerOwned()) {
765 if (
market.isPlayerOwned() ||
779 SectorEntityToken from = base.
getMarket().getPrimaryEntity();
780 SectorEntityToken to =
getMarket().getPrimaryEntity();
782 EconomyRouteData data =
new EconomyRouteData();
785 data.smuggling =
true;
789 OptionalFleetData extra =
new OptionalFleetData(data.from);
790 extra.fleetType = FleetTypes.TRADE_SMUGGLER;
792 RouteData route = RouteManager.getInstance().addRoute(sid, base.
getMarket(), Misc.genRandomSeed(), extra,
this, data);
793 extra.strength = 50f;
794 extra.strength = Misc.getAdjustedStrength(extra.strength, base.
getMarket());
797 float orbitDays = 3f +
random.nextFloat() * 3f;
798 float travelDays = RouteLocationCalculator.getTravelDays(from, to);
801 route.addSegment(
new RouteSegment(EconomyFleetRouteManager.ROUTE_SRC_LOAD, orbitDays, from));
802 route.addSegment(
new RouteSegment(EconomyFleetRouteManager.ROUTE_TRAVEL_DST, travelDays, from, to));
803 route.addSegment(
new RouteSegment(EconomyFleetRouteManager.ROUTE_DST_UNLOAD, orbitDays * 0.5f, to));
804 route.addSegment(
new RouteSegment(EconomyFleetRouteManager.ROUTE_DST_LOAD, orbitDays * 0.5f, to));
805 route.addSegment(
new RouteSegment(EconomyFleetRouteManager.ROUTE_TRAVEL_SRC, travelDays, to, from));
806 route.addSegment(
new RouteSegment(EconomyFleetRouteManager.ROUTE_SRC_UNLOAD, orbitDays, from));
824 Random
random =
new Random();
825 if (route.getSeed() !=
null) {
826 random =
new Random(route.getSeed());
829 CampaignFleetAPI fleet = EconomyFleetRouteManager.createTradeRouteFleet(route,
random);
830 if (fleet ==
null)
return null;;
832 fleet.getMemoryWithoutUpdate().set(MemFlags.FLEET_DO_NOT_IGNORE_PLAYER,
true);
833 fleet.getMemoryWithoutUpdate().set(MemFlags.FLEET_IGNORES_OTHER_FLEETS,
true);
834 fleet.addEventListener(
this);
835 fleet.addScript(
new EconomyFleetAssignmentAI(fleet, route));
842 CampaignFleetAPI active =
smuggler.getActiveFleet();
843 if (!battle.isInvolved(active))
return;
845 if (battle.getSideFor(active) != battle.getSideFor(primaryWinner)) {
static SettingsAPI getSettings()
static SectorAPI getSector()
static boolean SEND_UPDATES_WHEN_NO_COMM
static boolean PATHER_BASE_DEBUG
boolean isSendingUpdate()
void indent(TooltipMakerAPI info)
String getDays(float days)
void setPostingLocation(SectorEntityToken postingLocation)
void unindent(TooltipMakerAPI info)
boolean isPlayerVisible()
void sendUpdateIfPlayerHasIntel(Object listInfoParam, TextPanelAPI textPanel)
Object getListInfoParam()
Color getBulletColorForMode(ListInfoMode mode)
static String getDaysString(float days)
void bullet(TooltipMakerAPI info)
Color getTitleColor(ListInfoMode mode)
static void addMarketToList(TooltipMakerAPI info, MarketAPI market, float pad)
SectorEntityToken getMapLocation(SectorMapAPI map)
static float AI_CORE_ADMIN_INTEREST
List< ArrowData > getArrowData(SectorMapAPI map)
FactionAPI getFactionForUIColors()
static Object INCIDENT_PREVENTED
boolean shouldCancelRouteAfterDelayCheck(RouteData route)
void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode)
CampaignFleetAPI spawnFleet(RouteData route)
static Object UPDATE_DISSOLVED
static Object INCIDENT_PREP
void setInertiaTime(float inertiaTime)
String getCommMessageSound()
IncidentType incidentType
void createSmallDescription(TooltipMakerAPI info, float width, float height)
static float INCIDENT_PROB
void addInterestInfo(TooltipMakerAPI info, float width, float height)
SectorEntityToken getMapLocation(SectorMapAPI map)
void advanceImpl(float amount)
static float MIN_SABOTAGE
void reportBattleOccurred(CampaignFleetAPI fleet, CampaignFleetAPI primaryWinner, BattleAPI battle)
void reportFleetDespawnedToListener(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param)
void setSleeper(boolean sleeper)
String getSmallDescriptionTitle()
static Object INCIDENT_HAPPENED
static float MAX_SABOTAGE
void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode)
Set< String > getIntelTags(SectorMapAPI map)
void reportAboutToBeDespawnedByRouteManager(RouteData route)
float getSleeperTimeout()
static List< LuddicPathCellsIntel > getCellsForBase(LuddicPathBaseIntel base, boolean includeSleeper)
void sendSmuggler(LuddicPathBaseIntel base)
LuddicPathCellsIntel(MarketAPI market, boolean sleeper)
static LuddicPathBaseIntel getClosestBase(MarketAPI market)
static Object UPDATE_DISRUPTED
IntervalUtil incidentTracker
void setSleeperTimeout(float sleeperTimeout)
IncidentType prevIncident
String getRouteSourceId()
boolean prevIncidentSucceeded
static float MIN_WARNING_DAYS
void makeSleeper(float sleeperTimeout)
void makeActiveIfPossible()
static String USED_PLANETBUSTER_KEY
boolean canMakeVisibleToPlayer(boolean playerInRelayRange)
boolean shouldRepeat(RouteData route)
static LuddicPathCellsIntel getCellsForMarket(MarketAPI market)
static int STABLITY_PENALTY
String getSpriteName(String category, String id)
float getFloatFromArray(String key, int index)
float getFloat(String key)