1package com.fs.starfarer.api.impl.campaign.missions;
3import java.util.ArrayList;
4import java.util.Arrays;
7import java.util.Random;
9import org.lwjgl.util.vector.Vector2f;
11import com.fs.starfarer.api.Global;
12import com.fs.starfarer.api.campaign.CampaignFleetAPI;
13import com.fs.starfarer.api.campaign.FactionAPI;
14import com.fs.starfarer.api.campaign.FactionAPI.ShipPickMode;
15import com.fs.starfarer.api.campaign.InteractionDialogAPI;
16import com.fs.starfarer.api.campaign.JumpPointAPI;
17import com.fs.starfarer.api.campaign.JumpPointAPI.JumpDestination;
18import com.fs.starfarer.api.campaign.LocationAPI;
19import com.fs.starfarer.api.campaign.PlanetAPI;
20import com.fs.starfarer.api.campaign.SectorEntityToken;
21import com.fs.starfarer.api.campaign.StarSystemAPI;
22import com.fs.starfarer.api.campaign.ai.FleetAIFlags;
23import com.fs.starfarer.api.campaign.econ.MarketAPI;
24import com.fs.starfarer.api.campaign.listeners.GateTransitListener;
25import com.fs.starfarer.api.campaign.rules.MemoryAPI;
26import com.fs.starfarer.api.characters.PersonAPI;
27import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.CustomRepImpact;
28import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActionEnvelope;
29import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActions;
30import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepRewards;
31import com.fs.starfarer.api.impl.campaign.ids.Factions;
32import com.fs.starfarer.api.impl.campaign.ids.Tags;
33import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithSearch;
34import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithSearch.RequiredSystemTags;
35import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers;
36import com.fs.starfarer.api.impl.campaign.missions.hub.MissionTrigger.TriggerAction;
37import com.fs.starfarer.api.impl.campaign.missions.hub.MissionTrigger.TriggerActionContext;
38import com.fs.starfarer.api.impl.campaign.missions.hub.ReqMode;
39import com.fs.starfarer.api.impl.campaign.procgen.StarSystemGenerator;
40import com.fs.starfarer.api.util.Misc;
41import com.fs.starfarer.api.util.Misc.Token;
42import com.fs.starfarer.api.util.WeightedRandomPicker;
50 public static enum EncounterType {
54 FROM_SOMEWHERE_IN_SYSTEM,
57 public static enum EncounterLocation {
84 return StarSystemGenerator.getNormalRandom(Misc.random, base * 0.75f, base * 1.25f);
119 StarSystemAPI curr = playerFleet.getStarSystem();
140 playerFleet.getLocationInHyperspace()) > 2f) {
144 boolean onlyCheckInSystem =
true;
145 StageData stage = getData(currentStage);
147 onlyCheckInSystem =
false;
152 if (
allowedTypes.contains(EncounterType.IN_HYPER_EN_ROUTE) && !onlyCheckInSystem) {
153 if (playerFleet.isInHyperspace()) {
154 float maxSpeed = Misc.getSpeedForBurnLevel(playerFleet.getFleetData().getBurnLevel());
156 float currSpeed = playerFleet.getVelocity().length();
157 if (currSpeed >= maxSpeed * 0.9f) {
160 float dir = Misc.getAngleInDegrees(playerFleet.getVelocity());
161 dir += 75f - 150f * genRandom.nextFloat();
162 location = Misc.getUnitVectorAtDegreeAngle(dir);
172 if (
allowedTypes.contains(EncounterType.OUTSIDE_SYSTEM)) {
174 float dist = Misc.getDistance(
lastSystemPlayerWasIn.getLocation(), playerFleet.getLocationInHyperspace());
182 if (
allowedTypes.contains(EncounterType.FROM_SOMEWHERE_IN_SYSTEM)) {
186 typePicked = EncounterType.FROM_SOMEWHERE_IN_SYSTEM;
190 if (
allowedTypes.contains(EncounterType.JUMP_IN_NEAR_PLAYER)) {
198 SectorEntityToken entity = Misc.findNearestJumpPointTo(playerFleet);
199 if (entity !=
null) {
200 float dist = Misc.getDistance(playerFleet, entity);
206 entity = Misc.findNearestPlanetTo(playerFleet,
true,
false);
207 if (entity !=
null) {
208 float dist = Misc.getDistance(playerFleet, entity);
237 typePicked = EncounterType.JUMP_IN_NEAR_PLAYER;
249 if (system instanceof StarSystemAPI && system == playerFleet.getContainingLocation()) {
252 if (!req.systemMatchesRequirement((StarSystemAPI) system)) {
258 List<MarketAPI> markets = Misc.getMarketsInLocation(system);
260 MarketAPI largest =
null;
261 MarketAPI largestHostile =
null;
263 int maxHostileSize = 0;
264 for (MarketAPI market : markets) {
265 if (market.getSize() > maxSize) {
267 maxSize = market.getSize();
270 if (market.getSize() > maxHostileSize) {
271 largestHostile = market;
272 maxHostileSize = market.getSize();
276 if (largestHostile !=
null && maxHostileSize > maxSize) {
281 boolean found =
false;
282 for (MarketAPI market : markets) {
294 Vector2f coreCenter =
new Vector2f();
296 float fringeRange = 46000;
298 float nearMarketRange = 5000f;
299 boolean nearCoreMarket =
false;
300 boolean nearAnyMarket =
false;
301 MarketAPI nearest =
null;
302 float minDist = Float.MAX_VALUE;
305 for (MarketAPI market :
Global.
getSector().getEconomy().getMarketsCopy()) {
306 if (market.isHidden())
continue;
307 if (market.getContainingLocation().hasTag(Tags.THEME_CORE_POPULATED)) {
308 Vector2f.add(coreCenter, market.getLocationInHyperspace(), coreCenter);
311 if (!nearCoreMarket) {
312 float dist = Misc.getDistance(market.getLocation(), playerFleet.getLocationInHyperspace());
313 nearCoreMarket = dist < nearMarketRange;
314 if (dist < minDist) {
319 }
else if (!nearAnyMarket) {
320 float dist = Misc.getDistance(market.getLocation(), playerFleet.getLocationInHyperspace());
321 nearAnyMarket = dist < nearMarketRange;
322 if (dist < minDist) {
331 system == nearest.getStarSystem()) {
338 coreCenter.scale(1f / count);
341 if (nearCoreMarket &&
allowedLocations.contains(EncounterLocation.NEAR_CORE)) {
344 if (nearAnyMarket &&
allowedLocations.contains(EncounterLocation.POPULATED_SYSTEM)) {
349 if (
location == EncounterLocation.NEAR_CORE)
continue;
350 if (
location == EncounterLocation.POPULATED_SYSTEM)
continue;
354 float distFromCore = Misc.getDistance(coreCenter, playerFleet.getLocationInHyperspace());
356 if (
location == EncounterLocation.MIDRANGE) {
357 if (distFromCore > fringeRange || nearCoreMarket) {
362 if (
location == EncounterLocation.FRINGE) {
363 if (distFromCore < fringeRange || nearCoreMarket) {
378 public void doAction(TriggerActionContext context) {
385 playerFleet.getContainingLocation().addEntity(context.fleet);
388 Vector2f loc = Misc.getPointAtRadius(playerFleet.getLocationInHyperspace(), 1000f);
389 context.fleet.setLocation(loc.x, loc.y);
391 WeightedRandomPicker<MarketAPI> from =
new WeightedRandomPicker<MarketAPI>(genRandom);
392 for (MarketAPI curr :
Global.
getSector().getEconomy().getMarkets(playerFleet.getContainingLocation())) {
394 if (curr.getFaction() == context.fleet.getFaction()) {
395 w = curr.getSize() * 10000f;
396 }
else if (!curr.getFaction().isHostileTo(context.fleet.getFaction())) {
403 MarketAPI market = from.pick();
404 if (market !=
null) {
405 float dir = Misc.getAngleInDegrees(playerFleet.getLocation(), market.getPrimaryEntity().getLocation());
406 Vector2f loc = HubMissionWithTriggers.pickLocationWithinArc(genRandom, playerFleet,
407 dir, 30f, 3000f, 3000f, 3000f);
408 context.fleet.setLocation(loc.x, loc.y);
410 Vector2f loc = Misc.getPointAtRadius(playerFleet.getLocation(), 3000f);
411 context.fleet.setLocation(loc.x, loc.y);
418 context.fleet.setLocation(jp.getLocation().x, jp.getLocation().y);
423 context.fleet.updateFleetView();
424 context.fleet.getContainingLocation().removeEntity(context.fleet);
426 context.fleet.setLocation(1000000000, 0);
435 float radius = 2000f * (0.5f + 0.5f * genRandom.nextFloat());
436 Vector2f approximatePlayerLoc = Misc.getPointAtRadius(playerFleet.getLocation(), radius);
437 context.fleet.getMemoryWithoutUpdate().set(FleetAIFlags.PLACE_TO_LOOK_FOR_TARGET, approximatePlayerLoc, 2f);
447 protected List<EncounterType>
allowedTypes =
new ArrayList<EncounterType>();
461 if (random ==
null) random =
new Random(Misc.genRandomSeed());
462 setGenRandom(random);
464 globalEndFlag =
"$" +
"dfe"+
"_" + missionId +
"_" + Misc.genUID();
465 setMissionId(missionId);
467 setTypes(EncounterType.OUTSIDE_SYSTEM, EncounterType.JUMP_IN_NEAR_PLAYER, EncounterType.IN_HYPER_EN_ROUTE);
481 if (!fleet.isPlayerFleet() || gateFrom ==
null)
return;
484 getElapsedInCurrentStage() <
waitDays * 0.9f) {
488 float dist = Misc.getDistanceLY(gateFrom, gateTo);
499 super.notifyEnding();
510 if (factions ==
null || factions.length <= 0) {
523 requiredTags =
new ArrayList<HubMissionWithSearch.RequiredSystemTags>();
525 RequiredSystemTags req =
new RequiredSystemTags(mode, tags);
530 setTypes(EncounterType.OUTSIDE_SYSTEM, EncounterType.IN_HYPER_EN_ROUTE);
533 setTypes(EncounterType.OUTSIDE_SYSTEM);
536 setTypes(EncounterType.JUMP_IN_NEAR_PLAYER);
539 setTypes(EncounterType.FROM_SOMEWHERE_IN_SYSTEM);
542 setTypes(EncounterType.IN_HYPER_EN_ROUTE);
550 EncounterLocation ... locations) {
557 public void setDelay(
float minDays,
float maxDays) {
558 this.minDelay = minDays;
559 this.maxDelay = maxDays;
563 this.minDelay = base * 0.5f;
564 this.maxDelay = base * 1.5f;
569 EncounterLocation.POPULATED_SYSTEM);
574 EncounterLocation.NEAR_CORE);
579 EncounterLocation.FRINGE, EncounterLocation.MIDRANGE);
584 EncounterLocation.ANYWHERE);
589 EncounterLocation.FRINGE);
594 EncounterLocation.NEAR_CORE, EncounterLocation.MIDRANGE);
619 triggerMakeHostileAndAggressive();
620 triggerFleetAllowLongPursuit();
621 triggerSetFleetAlwaysPursue();
622 triggerOrderFleetInterceptPlayer();
623 triggerOrderFleetMaybeEBurn();
629 super.advanceImpl(amount);
649 checker.daysBeforeInHyper = (0.5f + (0.5f + genRandom.nextFloat())) * 2f;
650 checker.daysBeforeInSystem = (0.5f + (0.5f + genRandom.nextFloat())) * 3f;
660 setStageOnCustomCondition(
Stage.
ENDED,
new ConditionChecker() {
661 public boolean conditionsMet() {
666 getElapsedInCurrentStage() >
waitDays * 0.9f) ||
678 playerFleet.getLocationInHyperspace()) > 2f) {
686 triggerMakeAllFleetFlagsPermanent();
699 triggerRandomizeFleetProperties();
702 setUseQualityInsteadOfQualityFraction(
true);
703 triggerAutoAdjustFleetStrengthMajor();
704 setUseQualityInsteadOfQualityFraction(
false);
710 String thingItOrThey,
713 boolean aggressiveIfDeclined,
714 ComplicationRepImpact repImpact,
720 triggerSetFleetMissionRef(
"$" + getMissionId() +
"_ref");
721 triggerSetFleetMissionRef(
"$fwt_ref");
723 if (aggressiveIfDeclined) {
724 triggerSetPirateFleet();
725 triggerMakeHostileAndAggressive();
728 if (repImpact == ComplicationRepImpact.LOW) {
729 triggerMakeLowRepImpact();
730 }
else if (repImpact == ComplicationRepImpact.NONE) {
731 triggerMakeNoRepImpact();
734 triggerFleetAllowLongPursuit();
735 triggerSetFleetAlwaysPursue();
738 if (faction.getCustomBoolean(Factions.CUSTOM_SPAWNS_AS_INDEPENDENT)) {
739 triggerSetFleetFaction(Factions.INDEPENDENT);
740 triggerSetFleetMemoryValue(
"$fwt_originalFaction", originalFactionId);
743 triggerSetFleetMemoryValue(
"$fwt_wantsThing",
true);
744 triggerSetFleetMemoryValue(
"$fwt_aggressive", aggressiveIfDeclined);
745 triggerSetFleetMemoryValue(
"$fwt_thing", getWithoutArticle(thing));
746 triggerSetFleetMemoryValue(
"$fwt_Thing", Misc.ucFirst(getWithoutArticle(thing)));
747 triggerSetFleetMemoryValue(
"$fwt_theThing", thing);
748 triggerSetFleetMemoryValue(
"$fwt_TheThing", Misc.ucFirst(thing));
749 triggerSetFleetMemoryValue(
"$fwt_payment", Misc.getWithDGS(paymentOffered));
750 triggerSetFleetMemoryValue(
"$fwt_itOrThey", thingItOrThey);
751 triggerSetFleetMemoryValue(
"$fwt_ItOrThey", Misc.ucFirst(thingItOrThey));
753 String thingItOrThem =
"them";
754 if (
"it".equals(thingItOrThey)) thingItOrThem =
"it";
755 triggerSetFleetMemoryValue(
"$fwt_itOrThem", thingItOrThem);
756 triggerSetFleetMemoryValue(
"$fwt_ItOrThem", Misc.ucFirst(thingItOrThem));
758 triggerSetFleetMemoryValue(
"$fwt_thingDesc", thingDesc);
759 triggerSetFleetMemoryValue(
"$fwt_ThingDesc", Misc.ucFirst(thingDesc));
761 if (failTrigger ==
null) {
762 failTrigger =
"FWTDefaultFailTrigger";
764 triggerSetFleetMemoryValue(
"$fwt_missionFailTrigger", failTrigger);
788 float maxPoints = faction.getApproximateMaxFPPerFleet(ShipPickMode.PRIORITY_THEN_ALL);
794 super.triggerSetFleetFaction(factionId);
798 public void triggerCreateFleet(FleetSize size, FleetQuality quality, String factionId, String type, SectorEntityToken roughlyWhere) {
801 super.triggerCreateFleet(size, quality, factionId, type, roughlyWhere);
804 public void triggerCreateFleet(FleetSize size, FleetQuality quality, String factionId, String type, StarSystemAPI roughlyWhere) {
807 super.triggerCreateFleet(size, quality, factionId, type, roughlyWhere);
810 public void triggerCreateFleet(FleetSize size, FleetQuality quality, String factionId, String type, Vector2f locInHyper) {
813 super.triggerCreateFleet(size, quality, factionId, type, locInHyper);
817 protected boolean create(MarketAPI createdAt,
boolean barEvent) {
832 protected boolean callAction(String action, String ruleId, InteractionDialogAPI dialog, List<Token> params, Map<String, MemoryAPI> memoryMap) {
833 float repLossPerson = 0f;
834 float repLossFaction = 0f;
835 if (
"repLossMinor".equals(action)) {
836 repLossPerson = -RepRewards.SMALL;
837 repLossFaction = -RepRewards.TINY;
838 }
else if (
"repLossMedium".equals(action)) {
839 repLossPerson = -RepRewards.HIGH;
840 repLossFaction = -RepRewards.SMALL;
841 }
else if (
"repLossHigh".equals(action)) {
842 repLossPerson = -RepRewards.EXTREME;
843 repLossFaction = -RepRewards.HIGH;
847 CustomRepImpact impact =
new CustomRepImpact();
848 impact.delta = repLossPerson;
850 new RepActionEnvelope(RepActions.CUSTOM, impact,
853 impact.delta = repLossFaction;
855 new RepActionEnvelope(RepActions.CUSTOM, impact,
860 return super.callAction(action, ruleId, dialog, params, memoryMap);
static SectorAPI getSector()
StarSystemAPI lastSystemPlayerWasIn
void advance(float amount)
SectorEntityToken foundEntity
boolean isPlayerInRightRangeBand(LocationAPI system)
void doAction(TriggerActionContext context)
float estimatedFleetPoints
static float RADIUS_FROM_CORE
static String TIMEOUT_KEY
void setFleetWantsThing(String originalFactionId, String thing, String thingItOrThey, String thingDesc, int paymentOffered, boolean aggressiveIfDeclined, ComplicationRepImpact repImpact, String failTrigger, PersonAPI personForRepLoss)
void setLocationAnywhere(boolean allowInsidePopulatedSystems, String requireLargestMarketNotHostileToFaction)
void setRequireLargestMarketNotHostileToFaction(String requireLargestMarketNotHostileToFaction)
void setEncounterOutsideSystem()
void setLocationAnyPopulated(boolean allowInsidePopulatedSystems, String requireLargestMarketNotHostileToFaction)
void setEncounterInSystemFromJumpPoint()
boolean canBeAvoidedByGateTransit
void setAllowInsidePopulatedSystems(boolean allowInsidePopulatedSystems)
void setLocations(boolean allowInsidePopulatedSystems, String requireLargestMarketNotHostileToFaction, EncounterLocation ... locations)
void setCanNotBeAvoidedByGateTransit()
void triggerCreateFleet(FleetSize size, FleetQuality quality, String factionId, String type, SectorEntityToken roughlyWhere)
static float BASE_ONLY_CHECK_IN_SYSTEM_DAYS
static float BASE_DELAY_SHORT
void triggerSetStandardAggroInterceptFlags()
List< EncounterLocation > allowedLocations
boolean create(MarketAPI createdAt, boolean barEvent)
List< RequiredSystemTags > requiredTags
static String TRIGGER_REP_LOSS_MINOR
static String TRIGGER_REP_LOSS_HIGH
CanSpawnFleetConditionChecker checker
boolean callAction(String action, String ruleId, InteractionDialogAPI dialog, List< Token > params, Map< String, MemoryAPI > memoryMap)
void reportFleetTransitingGate(CampaignFleetAPI fleet, SectorEntityToken gateFrom, SectorEntityToken gateTo)
void setDelay(float base)
void setTypes(EncounterType ... types)
PersonAPI personForRepLoss
static float BASE_DELAY_MEDIUM
void triggerCreateFleet(FleetSize size, FleetQuality quality, String factionId, String type, Vector2f locInHyper)
void setDoNotAbortWhenPlayerFleetTooStrong()
void requireDFESystemTags(ReqMode mode, String ... tags)
void setLocationOuterSector(boolean allowInsidePopulatedSystems, String requireLargestMarketNotHostileToFaction)
void advanceImpl(float amount)
static float BASE_DAYS_IN_SYSTEM_BEFORE_IN_SYSTEM_ATTACK
float onlyCheckForSpawnInSystemDays
static float BASE_DELAY_VERY_SHORT
void setDelay(float minDays, float maxDays)
void setRequireFactionPresence(String ... factions)
static boolean isInTimeout()
void setLocationFringeOnly(boolean allowInsidePopulatedSystems, String requireLargestMarketNotHostileToFaction)
void triggerCreateFleet(FleetSize size, FleetQuality quality, String factionId, String type, StarSystemAPI roughlyWhere)
float playerFleetSizeAbortMult
String requireLargestMarketNotHostileToFaction
void setLocationCoreOnly(boolean allowInsidePopulatedSystems, String requireLargestMarketNotHostileToFaction)
static String TRIGGER_REP_LOSS_MEDIUM
List< EncounterType > allowedTypes
void clearDFESystemTagRequirements()
static float getRandomValue(float base)
void setPlayerFleetSizeAbortMult(float playerFleetSizeAbortMult)
void triggerSetAdjustStrengthBasedOnQuality(boolean randomize, float quality)
boolean allowInsidePopulatedSystems
static float BASE_DAYS_IN_SYSTEM_BEFORE_AMBUSH_IN_HYPER
void triggerFleetSetFaction(String factionId)
static float BASE_DELAY_LONG
void setEncounterFromSomewhereInSystem()
void setLocationInnerSector(boolean allowInsidePopulatedSystems, String requireLargestMarketNotHostileToFaction)
List< String > requiredFactionPresence
void setEncounterInHyperEnRoute()
static float BASE_TIMEOUT
LocationAPI initialTransitFrom
void computeThresholdPoints(String factionId)
void setEncounterInHyper()
DelayedFleetEncounter(Random random, String missionId)