1package com.fs.starfarer.api.impl.campaign.rulecmd;
6import java.util.Random;
8import org.lwjgl.util.vector.Vector2f;
10import com.fs.starfarer.api.EveryFrameScript;
11import com.fs.starfarer.api.Global;
12import com.fs.starfarer.api.campaign.CampaignFleetAPI;
13import com.fs.starfarer.api.campaign.CargoAPI;
14import com.fs.starfarer.api.campaign.CargoAPI.CargoItemType;
15import com.fs.starfarer.api.campaign.CargoStackAPI;
16import com.fs.starfarer.api.campaign.CustomCampaignEntityAPI;
17import com.fs.starfarer.api.campaign.FactionAPI;
18import com.fs.starfarer.api.campaign.InteractionDialogAPI;
19import com.fs.starfarer.api.campaign.OptionPanelAPI;
20import com.fs.starfarer.api.campaign.PersonImportance;
21import com.fs.starfarer.api.campaign.SpecialItemData;
22import com.fs.starfarer.api.campaign.TextPanelAPI;
23import com.fs.starfarer.api.campaign.comm.IntelInfoPlugin;
24import com.fs.starfarer.api.campaign.econ.Industry;
25import com.fs.starfarer.api.campaign.econ.MarketAPI;
26import com.fs.starfarer.api.campaign.listeners.ColonyPlayerHostileActListener;
27import com.fs.starfarer.api.campaign.rules.MemKeys;
28import com.fs.starfarer.api.campaign.rules.MemoryAPI;
29import com.fs.starfarer.api.characters.PersonAPI;
30import com.fs.starfarer.api.combat.ShipAPI.HullSize;
31import com.fs.starfarer.api.combat.ShipHullSpecAPI;
32import com.fs.starfarer.api.combat.WeaponAPI.WeaponSize;
33import com.fs.starfarer.api.fleet.FleetMemberAPI;
34import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.CustomRepImpact;
35import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActionEnvelope;
36import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActions;
37import com.fs.starfarer.api.impl.campaign.DelayedBlueprintLearnScript;
38import com.fs.starfarer.api.impl.campaign.FusionLampEntityPlugin;
39import com.fs.starfarer.api.impl.campaign.econ.impl.InstallableItemEffect;
40import com.fs.starfarer.api.impl.campaign.econ.impl.ItemEffectsRepo;
41import com.fs.starfarer.api.impl.campaign.ids.Conditions;
42import com.fs.starfarer.api.impl.campaign.ids.Entities;
43import com.fs.starfarer.api.impl.campaign.ids.Factions;
44import com.fs.starfarer.api.impl.campaign.ids.FleetTypes;
45import com.fs.starfarer.api.impl.campaign.ids.Industries;
46import com.fs.starfarer.api.impl.campaign.ids.Items;
47import com.fs.starfarer.api.impl.campaign.ids.People;
48import com.fs.starfarer.api.impl.campaign.ids.Tags;
49import com.fs.starfarer.api.impl.campaign.intel.contacts.ContactIntel;
50import com.fs.starfarer.api.impl.campaign.intel.contacts.ContactIntel.ContactState;
51import com.fs.starfarer.api.impl.campaign.intel.events.HostileActivityEventIntel;
52import com.fs.starfarer.api.impl.campaign.intel.events.KantasProtectionOneTimeFactor;
53import com.fs.starfarer.api.impl.campaign.intel.events.PiracyRespiteScript;
54import com.fs.starfarer.api.impl.campaign.intel.events.PirateHostileActivityFactor;
55import com.fs.starfarer.api.impl.campaign.missions.DelayedFleetEncounter;
56import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers.FleetQuality;
57import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithTriggers.FleetSize;
58import com.fs.starfarer.api.impl.campaign.rulecmd.salvage.MarketCMD.TempData;
59import com.fs.starfarer.api.loading.IndustrySpecAPI;
60import com.fs.starfarer.api.loading.WeaponSpecAPI;
61import com.fs.starfarer.api.util.DelayedActionScript;
62import com.fs.starfarer.api.util.IntervalUtil;
63import com.fs.starfarer.api.util.Misc;
64import com.fs.starfarer.api.util.Misc.Token;
65import com.fs.starfarer.api.util.Pair;
66import com.fs.starfarer.api.util.WeightedRandomPicker;
86 public static float MIN_ELAPSED = 720f;
90 public static float PROB_PER_MONTH = 0.01f;
92 public static float MIN_DELAY_BETWEEN_COURIERS = 60f;
93 public static float MAX_DELAY_BETWEEN_COURIERS = 90f;
94 public static int MAX_ATTEMPTS = 5;
98 protected float elapsed = 0f;
99 protected float resendTimeout = 0f;
100 protected int attempts = 0;
101 protected Random random =
new Random();
102 protected boolean done =
false;
104 public void advance(
float amount) {
115 boolean send =
false;
118 if (interval.intervalElapsed()) {
119 if (random.nextFloat() < PROB_PER_MONTH) {
132 if (attempts <= 0 && elapsed < MIN_ELAPSED) {
135 if (attempts > 0 && elapsed < resendTimeout) {
137 }
else if (attempts > 0) {
138 if (attempts >= MAX_ATTEMPTS) {
140 Global.getSector().getCampaignUI().addMessage(
"Kanta's Protection lost", Misc.getNegativeHighlightColor());
154 resendTimeout = MIN_DELAY_BETWEEN_COURIERS +
155 (MAX_DELAY_BETWEEN_COURIERS - MIN_DELAY_BETWEEN_COURIERS) * random.nextFloat();
159 public boolean isDone() {
163 public boolean runWhilePaused() {
167 public void sendCourier() {
168 DelayedFleetEncounter e =
new DelayedFleetEncounter(random,
"kantaFavorCourier");
170 e.setLocationInnerSector(
false,
null);
171 e.setEncounterFromSomewhereInSystem();
172 e.setDoNotAbortWhenPlayerFleetTooStrong();
174 e.triggerCreateFleet(FleetSize.VERY_SMALL, FleetQuality.HIGHER,
175 Factions.PIRATES, FleetTypes.PATROL_SMALL,
new Vector2f());
176 e.triggerFleetSetName(
"Courier");
177 e.triggerMakeNonHostile();
178 e.triggerFleetMakeImportantPermanent(
null);
179 e.triggerFleetMakeFaster(
true, 0,
true);
180 e.triggerOrderFleetInterceptPlayer();
181 e.triggerOrderFleetEBurn(1f);
182 e.triggerSetFleetGenericHailPermanent(
"KantaFavorCourierHail");
189 public static class TakingBackTheNanoforgeChecker
implements ColonyPlayerHostileActListener {
190 protected MarketAPI market;
191 public TakingBackTheNanoforgeChecker(MarketAPI market) {
192 this.market = market;
195 public void reportRaidForValuablesFinishedBeforeCargoShown(InteractionDialogAPI dialog, MarketAPI market,
196 TempData actionData, CargoAPI cargo) {
197 if (this.market.hasCondition(Conditions.DECIVILIZED)) {
198 Global.getSector().getListenerManager().removeListener(
this);
200 if (actionData.secret) {
203 if (market == this.market) {
204 if (cargo.getQuantity(CargoItemType.SPECIAL,
new SpecialItemData(Items.PRISTINE_NANOFORGE,
null)) > 0) {
205 PersonAPI kanta = People.getPerson(People.KANTA);
207 TextPanelAPI text = dialog.getTextPanel();
208 text.addPara(
"Word of this is bound to get back to Kanta. "
209 +
"You can't imagine she would react well to being made a fool of.");
212 Global.getSector().getListenerManager().removeListener(
this);
217 public void reportRaidToDisruptFinished(InteractionDialogAPI dialog, MarketAPI market, TempData actionData, Industry industry) {
220 public void reportTacticalBombardmentFinished(InteractionDialogAPI dialog, MarketAPI market, TempData actionData) {
223 public void reportSaturationBombardmentFinished(InteractionDialogAPI dialog, MarketAPI market, TempData actionData) {
228 public static class FusionLampColorChanger
implements EveryFrameScript {
229 public boolean isDone() {
230 return market.getContainingLocation() ==
null;
233 public boolean runWhilePaused() {
237 protected MarketAPI market;
238 protected IntervalUtil interval =
new IntervalUtil(0.5f, 1f);
239 public FusionLampColorChanger(MarketAPI market) {
240 this.market = market;
243 public void advance(
float amount) {
244 float days = Global.getSector().getClock().convertToDays(amount);
245 if (Global.getSector().getClock().getMonth() == 11 &&
246 Global.getSector().getClock().getDay() == 28) {
250 interval.advance(days);
251 if (interval.intervalElapsed()) {
252 for (CustomCampaignEntityAPI curr : market.getContainingLocation().getCustomEntities()) {
253 if (curr.getCustomEntityType().equals(Entities.FUSION_LAMP) &&
254 curr.getOrbitFocus() == market.getPrimaryEntity()) {
256 WeightedRandomPicker<Pair<Color, Color>> picker =
new WeightedRandomPicker<Pair<Color, Color>>();
259 picker.add(
new Pair<Color, Color>(FusionLampEntityPlugin.GLOW_COLOR, FusionLampEntityPlugin.LIGHT_COLOR));
262 picker.add(
new Pair<Color, Color>(
new Color(255,50,50,255),
new Color(255,50,50,255)));
265 picker.add(
new Pair<Color, Color>(
new Color(210,230,255,255),
new Color(210,230,255,255)));
268 picker.add(
new Pair<Color, Color>(
new Color(245,250,255,255),
new Color(245,250,255,255)));
271 picker.add(
new Pair<Color, Color>(
new Color(255,225,125,255),
new Color(255,225,125,255)));
274 picker.add(
new Pair<Color, Color>(
new Color(100,255,100,255),
new Color(100,255,100,255)));
276 Pair<Color, Color> pick = picker.pick();
278 FusionLampEntityPlugin plugin = (FusionLampEntityPlugin) curr.getCustomPlugin();
279 plugin.setGlowColor(pick.one);
280 plugin.setLightColor(pick.two);
290 public static class DelayedInstallItemScript
extends DelayedActionScript {
291 protected MarketAPI market;
292 protected String industryId;
293 protected String itemId;
295 public DelayedInstallItemScript(
float daysLeft, MarketAPI market, String industryId, String itemId) {
297 this.market = market;
298 this.industryId = industryId;
299 this.itemId = itemId;
303 public void doAction() {
304 InstallableItemEffect effect = ItemEffectsRepo.ITEM_EFFECTS.get(itemId);
305 Industry ind = market.getIndustry(industryId);
306 if (ind !=
null && effect !=
null && !market.hasCondition(Conditions.DECIVILIZED)) {
307 List<String> unmet = effect.getUnmetRequirements(ind);
308 if (unmet ==
null || unmet.isEmpty()) {
309 ind.setSpecialItem(
new SpecialItemData(itemId,
null));
317 if (dialog ==
null)
return false;
324 String action = params.get(0).getString(memoryMap);
327 if (memory ==
null)
return false;
331 if (
"findLargeOmega".equals(action)) {
333 if (!stack.isWeaponStack())
continue;
336 if (spec.
getSize() != WeaponSize.LARGE)
continue;
342 memory.
set(
"$foundWeaponQuantity", (
int) Math.round(stack.getSize()));
345 }
else if (
"findContactToBetray".equals(action)) {
347 int bestImportance = 0;
359 if (importance > bestImportance || (importance >= bestImportance && rel > bestRel)) {
361 bestImportance = importance;
366 if (best ==
null)
return false;
370 memory.
set(
"$foundContactRank", contact.
getRank().toLowerCase());
371 memory.
set(
"$foundContactPost", contact.
getPost().toLowerCase());
373 memory.
set(
"$foundContactIntel", best);
376 }
else if (
"betrayContact".equals(action)) {
378 CustomRepImpact impact =
new CustomRepImpact();
379 impact.delta = -0.75f;
381 new RepActionEnvelope(RepActions.CUSTOM,
382 impact,
null, text,
true,
true),
385 }
else if (
"gaveHamatsu".equals(action)) {
387 if (ibrahim !=
null) {
388 CustomRepImpact impact =
new CustomRepImpact();
391 new RepActionEnvelope(RepActions.CUSTOM,
392 impact,
null, text,
true,
true),
399 }
else if (
"findRemnantCapital".equals(action)) {
402 memory.
set(
"$foundShipId", member.getId());
403 memory.
set(
"$foundShipClass", member.getHullSpec().getNameWithDesignationWithDashClass());
404 memory.
set(
"$foundShipName", member.getShipName());
408 }
else if (
"findShieldBlueprint".equals(action)) {
410 if (!stack.isSpecialStack())
continue;
413 if (data.
getData() ==
null)
continue;
420 memory.
set(
"$foundIndustryId", spec.
getId());
421 String firstWord = stack.getDisplayName().split(
" ")[0];
422 memory.
set(
"$foundIndustryName",
Misc.
ucFirst(
Misc.
getAOrAnFor(firstWord)) +
" " + stack.getDisplayName().replace(
"Blueprint",
"blueprint"));
426 }
else if (
"findShipBlueprint".equals(action)) {
429 if (!stack.isSpecialStack())
continue;
432 if (data.
getData() ==
null)
continue;
445 String firstWord = stack.getDisplayName().split(
" ")[0];
450 }
else if (
"learnShipBP".equals(action)) {
451 String hullId = params.get(1).getString(memoryMap);
452 float daysDelay = params.get(2).getFloat(memoryMap);
457 }
else if (
"oweKantaAFavor".equals(action)) {
459 }
else if (
"abortFavor".equals(action)) {
461 }
else if (
"alreadyDidFavor".equals(action)) {
464 }
else if (
"installFusionLamp".equals(action)) {
468 if (ind !=
null && effect !=
null) {
470 if (unmet ==
null || unmet.isEmpty()) {
476 }
else if (
"buildPlanetaryShield".equals(action)) {
490 }
else if (
"gavePristineNanoforge".equals(action)) {
491 float daysDelay = params.get(1).getFloat(memoryMap);
494 if (kapteyn !=
null) {
496 new DelayedInstallItemScript(daysDelay,
501 }
else if (
"kapteynHasForge".equals(action)) {
506 if (ind ==
null)
return false;
509 }
else if (
"gainProtection".equals(action)) {
527 }
else if (
"loseProtection".equals(action)) {
544 CustomRepImpact impact =
new CustomRepImpact();
545 impact.delta = -0.5f;
547 new RepActionEnvelope(RepActions.CUSTOM,
548 impact,
null, text,
true,
true),
static SettingsAPI getSettings()
static SoundPlayerAPI getSoundPlayer()
static SectorAPI getSector()
static final String LOCAL
List< String > getShips()
static Map< String, InstallableItemEffect > ITEM_EFFECTS
static final String DECIVILIZED
static final String PIRATES
static final String POPULATION
static final String ORBITALWORKS
static final String PLANETARYSHIELD
static final String ORBITAL_FUSION_LAMP
static final String SHIP_BP
static final String PRISTINE_NANOFORGE
static final String INDUSTRY_BP
static PersonAPI getPerson(String id)
void addFactor(EventFactor factor)
static HostileActivityEventIntel get()
static void avertOrAbortRaid()
static final String EVER_HAD_KANTA_PROTECTION
static boolean playerHasProtection()
static final String KANTA_PROTECTION
static void loseProtection(InteractionDialogAPI dialog)
boolean execute(String ruleId, InteractionDialogAPI dialog, List< Token > params, Map< String, MemoryAPI > memoryMap)
static boolean playerEverHadProtection()
void advance(float amount)
static String ucFirst(String str)
static Color getNegativeHighlightColor()
static void incrUntrustwortyCount()
static String getAOrAnFor(String word)
static Color getPositiveHighlightColor()
ShipHullSpecAPI getHullSpec(String hullId)
IndustrySpecAPI getIndustrySpec(String industryId)
SoundAPI playUISound(String id, float pitch, float volume)
float convertToDays(float realSeconds)
FleetDataAPI getFleetData()
List< CargoStackAPI > getStacksCopy()
MemoryAPI getMemoryWithoutUpdate()
String getPersonNamePrefixAOrAn()
String getPersonNamePrefix()
boolean knowsShip(String hullId)
List< FleetMemberAPI > getMembersListCopy()
TextPanelAPI getTextPanel()
SectorEntityToken getInteractionTarget()
OptionPanelAPI getOptionPanel()
CampaignFleetAPI getPlayerFleet()
void addScript(EveryFrameScript script)
boolean hasScript(Class<?> clazz)
void removeScriptsOfClass(Class c)
ReputationAdjustmentResult adjustPlayerReputation(Object action, String factionId)
CampaignClockAPI getClock()
IntelManagerAPI getIntelManager()
FactionAPI getFaction(String factionId)
MemoryAPI getMemoryWithoutUpdate()
ListenerManagerAPI getListenerManager()
CharacterDataAPI getCharacterData()
void addScript(EveryFrameScript script)
LabelAPI addPara(String text)
void setFontSmallInsignia()
List< IntelInfoPlugin > getIntel()
MarketAPI getMarket(String id)
void setSpecialItem(SpecialItemData special)
SpecialItemData getSpecialItem()
Industry getIndustry(String id)
boolean hasCondition(String id)
SectorEntityToken getPrimaryEntity()
void addIndustry(String id)
void addListener(Object listener)
void set(String key, Object value)
boolean getBoolean(String key)
RelationshipAPI getRelToPlayer()
PersonImportance getImportance()
boolean hasTag(String tag)
boolean isCivilianNonCarrier()
List< String > getUnmetRequirements(Industry industry)
boolean hasTag(String tag)