1package com.fs.starfarer.api.impl.campaign.events.nearby;
3import java.text.DecimalFormat;
4import java.text.ParseException;
5import java.util.HashSet;
7import java.util.Locale;
9import java.util.Random;
14import org.lwjgl.util.vector.Vector2f;
16import com.fs.starfarer.api.Global;
17import com.fs.starfarer.api.campaign.CampaignFleetAPI;
18import com.fs.starfarer.api.campaign.CargoAPI;
19import com.fs.starfarer.api.campaign.CustomCampaignEntityAPI;
20import com.fs.starfarer.api.campaign.FactionAPI;
21import com.fs.starfarer.api.campaign.InteractionDialogAPI;
22import com.fs.starfarer.api.campaign.LocationAPI;
23import com.fs.starfarer.api.campaign.RepLevel;
24import com.fs.starfarer.api.campaign.SectorEntityToken;
25import com.fs.starfarer.api.campaign.StarSystemAPI;
26import com.fs.starfarer.api.campaign.TextPanelAPI;
27import com.fs.starfarer.api.campaign.econ.MarketAPI;
28import com.fs.starfarer.api.campaign.events.CampaignEventTarget;
29import com.fs.starfarer.api.campaign.rules.MemoryAPI;
30import com.fs.starfarer.api.characters.PersonAPI;
31import com.fs.starfarer.api.combat.ShipVariantAPI;
32import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.CustomRepImpact;
33import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActionEnvelope;
34import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActions;
35import com.fs.starfarer.api.impl.campaign.DerelictShipEntityPlugin;
36import com.fs.starfarer.api.impl.campaign.DerelictShipEntityPlugin.DerelictShipData;
37import com.fs.starfarer.api.impl.campaign.events.BaseEventPlugin;
38import com.fs.starfarer.api.impl.campaign.fleets.PirateFleetManager;
39import com.fs.starfarer.api.impl.campaign.fleets.RouteManager;
40import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.OptionalFleetData;
41import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteData;
42import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteFleetSpawner;
43import com.fs.starfarer.api.impl.campaign.fleets.RouteManager.RouteSegment;
44import com.fs.starfarer.api.impl.campaign.ids.Abilities;
45import com.fs.starfarer.api.impl.campaign.ids.Commodities;
46import com.fs.starfarer.api.impl.campaign.ids.Entities;
47import com.fs.starfarer.api.impl.campaign.ids.Factions;
48import com.fs.starfarer.api.impl.campaign.ids.FleetTypes;
49import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
50import com.fs.starfarer.api.impl.campaign.ids.Tags;
51import com.fs.starfarer.api.impl.campaign.intel.bases.PirateBaseManager;
52import com.fs.starfarer.api.impl.campaign.intel.misc.DistressCallIntel;
53import com.fs.starfarer.api.impl.campaign.procgen.themes.BaseThemeGenerator;
54import com.fs.starfarer.api.impl.campaign.procgen.themes.RuinsFleetRouteManager;
55import com.fs.starfarer.api.impl.campaign.procgen.themes.SalvageSpecialAssigner;
56import com.fs.starfarer.api.impl.campaign.rulecmd.AddRemoveCommodity;
57import com.fs.starfarer.api.impl.campaign.rulecmd.BaseCommandPlugin;
58import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.special.TransmitterTrapSpecial.TransmitterTrapSpecialData;
59import com.fs.starfarer.api.util.IntervalUtil;
60import com.fs.starfarer.api.util.Misc;
61import com.fs.starfarer.api.util.Misc.Token;
62import com.fs.starfarer.api.util.TimeoutTracker;
63import com.fs.starfarer.api.util.WeightedRandomPicker;
73 public static enum DistressEventType {
102 Object readResolve() {
151 if ((
float) Math.random() < skipProb)
return;
157 if (params !=
null) {
169 float distFromPlayer = 3000f + (float) Math.random() * 2000f;
178 angle = angle - arc /2f + arc * (float) Math.random();
179 float speed = 10f + 10f * (float) Math.random();
182 speed *= (0.5f + 0.5f * (1f - depth));
203 public static class NESpawnData {
204 public DistressEventType type;
219 if (system.hasPulsar())
continue;
224 float sincePlayerVisit = system.getDaysSinceLastPlayerVisit();
229 boolean validTheme =
false;
230 for (String tag : system.getTags()) {
236 if (!validTheme)
continue;
250 if ((
float) Math.random() >= p && !
TEST_MODE)
return;
254 if (system ==
null)
return;
260 picker.
add(DistressEventType.NORMAL, 10f);
261 picker.
add(DistressEventType.PIRATE_AMBUSH, 10f);
262 picker.
add(DistressEventType.PIRATE_AMBUSH_TRAP, 10f);
263 picker.
add(DistressEventType.DERELICT_SHIP, 10f);
265 DistressEventType type = picker.
pick();
267 if (
TEST_MODE) type = DistressEventType.DERELICT_SHIP;
269 if (type == DistressEventType.NORMAL) {
271 }
else if (type == DistressEventType.PIRATE_AMBUSH) {
273 }
else if (type == DistressEventType.PIRATE_AMBUSH_TRAP) {
275 }
else if (type == DistressEventType.DERELICT_SHIP) {
291 if (jumpPoint ==
null)
return;
297 if (params ==
null)
return;
299 params.durationDays = 60f;
304 float radius = 400f + 400f * (float) Math.random();
306 if (radius > maxRadius) radius = maxRadius;
308 float orbitDays = radius / (5f +
Misc.
random.nextFloat() * 20f);
309 float angle = (float) Math.random() * 360f;
317 if (jumpPoint ==
null)
return;
323 if (params ==
null)
return;
325 params.durationDays = 60f;
330 float radius = 400f + 400f * (float) Math.random();
332 if (radius > maxRadius) radius = maxRadius;
334 float orbitDays = radius / (5f +
Misc.
random.nextFloat() * 20f);
335 float angle = (float) Math.random() * 360f;
339 TransmitterTrapSpecialData data =
new TransmitterTrapSpecialData();
341 data.maxRange = 20000f;
343 data.useAllFleetsInRange =
true;
346 int numPirates =
new Random().nextInt(3) + 1;
347 for (
int i = 0; i < numPirates; i++) {
349 NESpawnData dcd =
new NESpawnData();
350 dcd.type = DistressEventType.PIRATE_AMBUSH_TRAP;
351 dcd.location = system;
352 dcd.jumpPoint = jumpPoint;
354 OptionalFleetData extra =
new OptionalFleetData();
359 float waitDays = 30f + (float) Math.random() * 10f;
360 route.addSegment(
new RouteSegment(waitDays, jumpPoint));
379 if (jumpPoint ==
null)
return;
381 int numPirates =
new Random().nextInt(3) + 1;
384 for (
int i = 0; i < numPirates; i++) {
385 NESpawnData dcd =
new NESpawnData();
386 dcd.type = DistressEventType.PIRATE_AMBUSH;
387 dcd.location = system;
388 dcd.jumpPoint = jumpPoint;
390 OptionalFleetData extra =
new OptionalFleetData();
395 float waitDays = 30f + (float) Math.random() * 10f;
396 route.addSegment(
new RouteSegment(waitDays, jumpPoint));
414 if (jumpPoint ==
null)
return;
416 NESpawnData dcd =
new NESpawnData();
417 dcd.type = DistressEventType.NORMAL;
418 dcd.location = system;
419 dcd.jumpPoint = jumpPoint;
421 OptionalFleetData extra =
new OptionalFleetData();
426 float waitDays = 30f + (float) Math.random() * 10f;
427 route.addSegment(
new RouteSegment(waitDays, jumpPoint));
482 NESpawnData data = (NESpawnData) route.getCustom();
484 if (data.type == DistressEventType.PIRATE_AMBUSH_TRAP) {
486 int points = (int) (10 +
new Random().nextInt(20) * tf);
498 }
else if (data.type == DistressEventType.PIRATE_AMBUSH) {
500 int points = (int) (10 +
new Random().nextInt(20) * tf);
512 }
else if (data.type == DistressEventType.NORMAL) {
518 String type = typePicker.
pick();
520 boolean pirate = (float) Math.random() < 0.5f;
525 if (fleet ==
null)
return null;
536 "distress",
true, 1000f);
559 String action = params.get(0).getString(memoryMap);
565 Color color = playerFaction.
getColor();
574 if (action.equals(
"initDistress")) {
579 float returnDistLY = 0;
580 if (source !=
null) {
588 if (fuel < 10) fuel = 10;
589 fuel = (int) (Math.ceil(fuel / 10f) * 10);
600 memory.
set(
"$distressCrewTakeOn", takeOnCrew, 0f);
604 memory.
set(
"$distressFuelHostileThreshold", fuel, 0f);
607 }
else if (action.equals(
"takeDistressCrew")) {
611 boolean enough = crew >= needed;
616 float repChange = (int) (crew / 20);
617 if (repChange < 1) repChange = 1;
618 if (repChange > 5) repChange = 5;
630 }
else if (action.equals(
"sellDistressFuel")) {
644 float repChange = (int) (crew / 20);
645 if (repChange < 1) repChange = 1;
646 if (repChange > 5) repChange = 5;
651 }
else if (action.equals(
"scaredDistressFuel")) {
663 }
else if (action.equals(
"giveDistressFuel")) {
674 float repChange = (int) (credits / 1000);
675 if (repChange > 10) repChange = 10;
702 if (repChangePercent != 0) {
703 CustomRepImpact impact =
new CustomRepImpact();
704 impact.delta = repChangePercent * 0.01f;
705 impact.limit = limit;
707 new RepActionEnvelope(RepActions.CUSTOM, impact,
711 if (person !=
null) {
714 new RepActionEnvelope(RepActions.CUSTOM, impact,
715 null, text,
true), person);
722 Map<String, String> map = super.getTokenReplacements();
733 return super.getHighlightColors(stageId);
739 return super.getEventTarget();
748 return CampaignEventCategory.DO_NOT_SHOW_IN_MESSAGE_FILTER;
755 public static void main(String[] args)
throws ParseException {
756 Locale.setDefault(Locale.GERMAN);
762 DecimalFormat format =
new DecimalFormat(
"###,###,###,###,###");
763 System.out.println(format.parse(
"25,000").floatValue());
static SettingsAPI getSettings()
static SectorAPI getSector()
static float getDefaultSModProb()
static DerelictShipData createRandom(String factionId, DerelictType type, Random random)
static float getBaseDuration(HullSize size)
CampaignEventTarget eventTarget
static void undistress(SectorEntityToken fleet)
static void scuttleShips(CampaignFleetAPI fleet, int crewFreed)
IntervalUtil distressCallInterval
static float DISTRESS_MAX_PROB
void maybeSpawnDerelictShip()
TimeoutTracker< String > skipForDistressCalls
void maybeSpawnDistressCall()
boolean shouldRepeat(RouteData route)
void generateDistressCallAmbush(StarSystemAPI system)
static void main(String[] args)
void reportAboutToBeDespawnedByRouteManager(RouteData route)
static float DISTRESS_REPEAT_TIMEOUT
CampaignEventCategory getEventCategory()
void adjustRep(float repChangePercent, RepLevel limit, FactionAPI faction, PersonAPI person, TextPanelAPI text)
Color[] getHighlightColors(String stageId)
boolean shouldCancelRouteAfterDelayCheck(RouteData route)
static float DERELICT_SKIP_PROB
boolean showAllMessagesIfOngoing()
static Set< String > distressCallAllowedThemes
void init(String type, CampaignEventTarget eventTarget)
void advance(float amount)
static float DISTRESS_PROB_PER_SYSTEM
IntervalUtil derelictShipInterval
CampaignFleetAPI spawnFleet(RouteData route)
void generateDistressCallAmbushTrap(StarSystemAPI system)
static float DISTRESS_MIN_CHECK_INTERVAL
Map< String, String > getTokenReplacements()
static float DISTRESS_ALREADY_WAS_NEARBY_TIMEOUT
CampaignEventTarget getEventTarget()
static float DISTRESS_MIN_SINCE_PLAYER_IN_SYSTEM
String[] getHighlights(String stageId)
void generateDistressDerelictShip(StarSystemAPI system)
static float DERELICT_SKIP_PROB_ABYSS
static float DISTRESS_MAX_CHECK_INTERVAL
boolean callEvent(String ruleId, InteractionDialogAPI dialog, List< Token > params, Map< String, MemoryAPI > memoryMap)
void generateDistressCallNormal(StarSystemAPI system)
static CampaignFleetAPI createPirateFleet(int combatPoints, RouteData route, Vector2f locInHyper)
RouteData addRoute(String source, MarketAPI market, Long seed, OptionalFleetData extra, RouteFleetSpawner spawner)
static RouteManager getInstance()
static final String EMERGENCY_BURN
static final String WRECK
static final String NEUTRAL
static final String PIRATES
static final String INDEPENDENT
static final String SCAVENGER_MEDIUM
static final String SCAVENGER_LARGE
static final String SCAVENGER_SMALL
static final String ENTITY_MISSION_IMPORTANT
static final String MEMORY_KEY_NO_JUMP
static final String MEMORY_KEY_LOW_REP_IMPACT
static PirateBaseManager getInstance()
float getStandardTimeFactor()
static SectorEntityToken addSalvageEntity(LocationAPI location, String id, String faction)
static CampaignFleetAPI createScavenger(String type, Vector2f locInHyper, MarketAPI source, boolean pirate, Random random)
static void assignSpecials(SectorEntityToken entity)
static WeightedRandomPicker< String > getNearbyFactions(Random random, SectorEntityToken entity)
static void assignSpecialForDistressDerelict(SectorEntityToken entity)
static void addCommodityLossText(String commodityId, int quantity, TextPanelAPI text)
static void addCreditsGainText(int credits, TextPanelAPI text)
static void addCommodityGainText(String commodityId, int quantity, TextPanelAPI text)
static MemoryAPI getEntityMemory(Map< String, MemoryAPI > memoryMap)
void advance(float amount)
static MarketAPI getSourceMarket(CampaignFleetAPI fleet)
static String getWithDGS(float num)
static float getDistanceLY(SectorEntityToken from, SectorEntityToken to)
static Vector2f getUnitVectorAtDegreeAngle(float degrees)
static boolean isInAbyss(Vector2f loc)
static List< MarketAPI > getMarketsInLocation(LocationAPI location, String factionId)
static Color getNegativeHighlightColor()
static JumpPointAPI getDistressJumpPoint(StarSystemAPI system)
static List< StarSystemAPI > getNearbyStarSystems(SectorEntityToken token, float maxRangeLY)
static long genRandomSeed()
static void setSalvageSpecial(SectorEntityToken entity, Object data)
static Color getHighlightColor()
static boolean setFlagWithReason(MemoryAPI memory, String flagKey, String reason, boolean value, float expire)
static Vector2f getPointAtRadius(Vector2f from, float r)
static float getAbyssalDepth(Vector2f loc)
static void makeHostile(CampaignFleetAPI fleet)
static float getAngleInDegrees(Vector2f v)
ShipVariantAPI getVariant(String variantId)
float getFloat(String key)
float convertToDays(float realSeconds)
FleetDataAPI getFleetData()
FleetLogisticsAPI getLogistics()
void setLocation(float x, float y)
boolean isInHyperspaceTransition()
void removeFuel(float quantity)
void addCrew(int quantity)
MutableValue getCredits()
TextPanelAPI getTextPanel()
SectorEntityToken getInteractionTarget()
void addEntity(SectorEntityToken entity)
CampaignFleetAPI getPlayerFleet()
ReputationAdjustmentResult adjustPlayerReputation(Object action, String factionId)
CampaignClockAPI getClock()
boolean isInFastAdvance()
IntelManagerAPI getIntelManager()
LocationAPI getHyperspace()
void setCircularOrbit(SectorEntityToken focus, float angle, float orbitRadius, float orbitDays)
void removeAbility(String id)
void addScript(EveryFrameScript script)
void setDiscoverable(Boolean discoverable)
PersonAPI getActivePerson()
Vector2f getLocationInHyperspace()
float getCircularOrbitRadius()
MemoryAPI getMemoryWithoutUpdate()
void addIntel(IntelInfoPlugin plugin)
Vector2f getLocationInHyperspace()
float getFloat(String key)
void set(String key, Object value)
boolean getBoolean(String key)
ShipAPI.HullSize getHullSize()
float getFuelCostPerLightYear()