1package com.fs.starfarer.api.impl.campaign.events;
4import java.util.ArrayList;
8import org.apache.log4j.Logger;
10import com.fs.starfarer.api.Global;
11import com.fs.starfarer.api.Script;
12import com.fs.starfarer.api.campaign.BaseOnMessageDeliveryScript;
13import com.fs.starfarer.api.campaign.CampaignFleetAPI;
14import com.fs.starfarer.api.campaign.FleetAssignment;
15import com.fs.starfarer.api.campaign.InteractionDialogAPI;
16import com.fs.starfarer.api.campaign.LocationAPI;
17import com.fs.starfarer.api.campaign.PlayerMarketTransaction;
18import com.fs.starfarer.api.campaign.SectorEntityToken;
19import com.fs.starfarer.api.campaign.StarSystemAPI;
20import com.fs.starfarer.api.campaign.SubmarketPlugin;
21import com.fs.starfarer.api.campaign.CargoAPI.CargoItemType;
22import com.fs.starfarer.api.campaign.comm.CommMessageAPI;
23import com.fs.starfarer.api.campaign.comm.MessagePriority;
24import com.fs.starfarer.api.campaign.econ.CommodityOnMarketAPI;
25import com.fs.starfarer.api.campaign.econ.MarketAPI;
26import com.fs.starfarer.api.campaign.econ.SubmarketAPI;
27import com.fs.starfarer.api.campaign.events.CampaignEventManagerAPI;
28import com.fs.starfarer.api.campaign.events.CampaignEventTarget;
29import com.fs.starfarer.api.campaign.events.EventProbabilityAPI;
30import com.fs.starfarer.api.campaign.rules.MemKeys;
31import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActionEnvelope;
32import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.RepActions;
33import com.fs.starfarer.api.impl.campaign.fleets.FleetFactory;
34import com.fs.starfarer.api.impl.campaign.fleets.FleetFactoryV3;
35import com.fs.starfarer.api.impl.campaign.fleets.FleetParamsV3;
36import com.fs.starfarer.api.impl.campaign.ids.Commodities;
37import com.fs.starfarer.api.impl.campaign.ids.Conditions;
38import com.fs.starfarer.api.impl.campaign.ids.Events;
39import com.fs.starfarer.api.impl.campaign.ids.FleetTypes;
40import com.fs.starfarer.api.impl.campaign.rulecmd.FireBest;
41import com.fs.starfarer.api.impl.campaign.shared.SharedData;
42import com.fs.starfarer.api.util.Misc;
57 public static enum Ending {
64 public static class PlayerFoodTransaction {
65 public long timestamp;
70 public float quantity;
73 private boolean ended =
false;
75 private float maxDurationDays;
76 private float daysBeforeReliefCheck;
77 private float daysBeforeReliefSend;
78 private float elapsedDays = 0f;
79 private int stage = 0;
82 private float preEventFoodLevel;
85 private float baseFoodToMeetShortage = 0;
87 private float netDeliveredByPlayerBlack = 0;
88 private float netDeliveredByPlayerOther = 0;
91 private float originalReliefFleetPoints = 0;
94 private MessagePriority messagePriority = MessagePriority.CLUSTER;
95 private String foodShortageConditionToken =
null;
105 super.startEvent(
true);
106 if (
market ==
null)
return;
130 baseFoodToMeetShortage = getBaseShortageAmount();
133 maxDurationDays = 20f + (float) Math.random() * 20f;
135 daysBeforeReliefCheck = 7f + (float) Math.random() * 7f;
136 daysBeforeReliefSend = daysBeforeReliefCheck + (float) Math.random() * 7f;
157 (
int)Math.max(1, baseFoodToMeetShortage * (0.1f + (
float) Math.random() * 0.05f)));
163 ", food needed: " + (
int) baseFoodToMeetShortage +
164 ", stockpile mult: " + getStockpileMult() +
165 ", max duration: " + (
int) maxDurationDays +
" days");
169 private float getBaseShortageAmount() {
170 float stockpileMult = getStockpileMult();
172 float amount = com.
getStockpile() * (1f - stockpileMult);
173 if (amount < 50) amount = 50;
178 private float getStockpileMult() {
251 float mult = Math.min(1f, netDeliveredByPlayerBlack / baseFoodToMeetShortage);
252 return Math.round(base * mult);
269 if (elapsedDays > daysBeforeReliefCheck && stage == 0) {
307 if (reliefMarket !=
null) {
312 applyReliefFleetDidNotMakeItConsequences();
317 if (elapsedDays > daysBeforeReliefSend && stage == 1) {
319 if (reliefMarket !=
null) {
321 if (reliefFleet ==
null) {
323 applyReliefFleetDidNotMakeItConsequences();
333 "loading food from " + reliefMarket.
getName(),
new Script() {
344 endEvent(Ending.RELIEF_ARRIVED);
348 "returning to " + reliefMarket.
getName() +
" after delivering food relief to " +
market.
getName());
356 if (reliefFleet !=
null) {
358 if (currPoints < originalReliefFleetPoints * 0.5f) {
364 applyReliefFleetDidNotMakeItConsequences();
370 endEvent(Ending.DURATION_EXPIRED);
376 private void applyReliefFleetDidNotMakeItConsequences() {
382 private void createReliefFleet() {
387 float freighter = size * 1.5f;
388 float transport = size * 0.25f;
407 private void endEvent(Ending ending) {
413 com.
setStockpile(com.getStockpile() / getStockpileMult());
414 com.getPlayerSupplyPriceMod().unmodifyMult(
PRICE_MOD_ID);
415 com.getPlayerSupplyPriceMod().unmodifyFlat(
PRICE_MOD_ID);
426 case DURATION_EXPIRED:
433 if (dialog !=
null && dialog.getPlugin().getMemoryMap() !=
null && dialog.getTextPanel() !=
null) {
436 if (elapsedDays < 7) {
437 ongoingStabilityImpact = 0;
438 Global.getSector().reportEventStage(
this,
"end_player_fast",
null, MessagePriority.DELIVER_IMMEDIATELY,
439 new BaseOnMessageDeliveryScript() {
440 public void beforeDelivery(CommMessageAPI message) {
441 Global.getSector().adjustPlayerReputation(
442 new RepActionEnvelope(RepActions.FOOD_SHORTAGE_PLAYER_ENDED_FAST,
market, message,
443 dialog.getTextPanel(),
true),
455 Global.getSector().reportEventStage(
this,
"end_player",
null, MessagePriority.DELIVER_IMMEDIATELY,
456 new BaseOnMessageDeliveryScript() {
457 public void beforeDelivery(CommMessageAPI message) {
458 Global.getSector().adjustPlayerReputation(
459 new RepActionEnvelope(RepActions.FOOD_SHORTAGE_PLAYER_ENDED_NORMAL,
market, message,
460 dialog.getTextPanel(),
true),
467 if (dialog !=
null && dialog.getPlugin().getMemoryMap() !=
null) {
468 dialog.getVisualPanel().hideCore();
469 FireBest.fire(
null, dialog, dialog.getPlugin().getMemoryMap(),
"FoodShortageEndedByPlayerSale");
472 case PLAYER_ENDED_BLACK:
473 if (dialog !=
null && dialog.getPlugin().getMemoryMap() !=
null && dialog.getTextPanel() !=
null) {
474 dialog.getTextPanel().addParagraph(
"Financial transaction confirmed", Global.getSettings().getColor(
"buttonText"));
477 Global.getSector().reportEventStage(
this,
"end_player_black",
null, MessagePriority.DELIVER_IMMEDIATELY,
478 new BaseOnMessageDeliveryScript() {
479 public void beforeDelivery(CommMessageAPI message) {
488 if (dialog !=
null && dialog.getPlugin().getMemoryMap() !=
null) {
489 dialog.getVisualPanel().hideCore();
490 FireBest.fire(
null, dialog, dialog.getPlugin().getMemoryMap(),
"FoodShortageEndedByPlayerSale");
494 Global.getSector().reportEventStage(
this,
"end_relief_arrived",
null, messagePriority);
502 if (sub.getPlugin().isFreeTransfer())
continue;
504 float food = sub.getCargo().getQuantity(CargoItemType.RESOURCES, Commodities.FOOD);
505 sub.getCargo().removeItems(CargoItemType.RESOURCES, Commodities.FOOD, food);
518 return messagePriority;
522 return messagePriority;
556 if (
market ==
null)
return;
569 float netBought = bought - sold;
571 if (netBought == 0)
return;
581 netDeliveredByPlayerBlack -= bought;
582 netDeliveredByPlayerBlack += sold;
584 netDeliveredByPlayerOther -= bought;
585 netDeliveredByPlayerOther += sold;
588 if (postTransactionLevel >= preEventFoodLevel &&
591 endEvent(Ending.PLAYER_ENDED_BLACK);
593 endEvent(Ending.PLAYER_ENDED);
608 if (fleet == reliefFleet) {
610 applyReliefFleetDidNotMakeItConsequences();
616 return Math.max(0, baseFoodToMeetShortage - netDeliveredByPlayerBlack - netDeliveredByPlayerOther);
620 Map<String, String> map = super.getTokenReplacements();
630 if (reliefMarket !=
null) {
635 map.put(
"$reliefSystem", ((
StarSystemAPI)loc).getBaseName());
637 map.put(
"$reliefSystem",
"hyperspace");
640 map.put(
"$reliefMarket", primary.
getName());
643 if (reliefFleet !=
null) {
652 s =
"within a few days";
653 }
else if (eta <= 7) {
655 }
else if (eta <= 14) {
656 s =
"within a couple of weeks";
657 }
else if (eta <= 30) {
658 s =
"within a month";
660 s =
"in the coming months";
667 map.put(
"$neededFood",
"" + needed);
679 List<String> result =
new ArrayList<String>();
680 if (
"start".equals(stageId)) {
683 if (
"relief_unavailable".equals(stageId)) {
686 if (
"relief_aborted".equals(stageId)) {
689 if (
"relief_lost".equals(stageId)) {
692 if (
"end_relief_arrived".equals(stageId)) {
695 if (
"end_expired".equals(stageId)) {
698 if (
"end_player".equals(stageId)) {
701 if (
"end_player_black".equals(stageId)) {
704 if (
"end_player_fast".equals(stageId)) {
706 return result.toArray(
new String[0]);
711 return super.getHighlightColors(stageId);
725 List<String> commodities =
new ArrayList<String>();
732 List<PriceUpdatePlugin> updates =
new ArrayList<PriceUpdatePlugin>();
static SettingsAPI getSettings()
static Logger getLogger(Class c)
static SectorAPI getSector()
SubmarketAPI getSubmarket()
float getQuantityBought(String commodityId)
float getQuantitySold(String commodityId)
SectorEntityToken getEntity()
void modifyMult(String source, float value)
void modifyFlat(String source, float value)
void increaseRecentUnrest(float stabilityChange)
void addTokensToList(List< String > list, String ... keys)
static MarketAPI findNearestMarket(MarketAPI from, MarketFilter filter)
CampaignEventTarget eventTarget
String getStageIdForPossible()
static float MAX_POSSIBLE_DURATION
void reportFleetDespawned(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param)
float getEndBlackUnrest()
MessagePriority getWarningWhenLikelyPriority()
float getRemainingFoodToMeetShortage()
float getStabilityImpact()
void advance(float amount)
static float FOOD_PRICE_MULT
Color[] getHighlightColors(String stageId)
float getAddedExpiredUnrest()
float getReducedEndedUnrest()
String[] getHighlights(String stageId)
static float MIN_FRACTION_FOR_PLAYER_ENDING_EVENT
static float FOOD_PRICE_FLAT
List< String > getRelatedCommodities()
void init(String type, CampaignEventTarget eventTarget)
Map< String, String > getTokenReplacements()
void reportPlayerMarketTransaction(PlayerMarketTransaction transaction)
float getReliefAbortUnrest()
MessagePriority getWarningWhenPossiblePriority()
String getStageIdForLikely()
List< PriceUpdatePlugin > getPriceUpdates()
static String PRICE_MOD_ID
static CampaignFleetAPI createFleet(FleetParamsV3 params)
static final float SUPPLIES_FRACTION
static final String EVENT_FOOD_SHORTAGE
static final String FOOD_SHORTAGE
static final String FOOD_RELIEF_FLEET
TimeoutTracker< String > getMarketsThatSentRelief()
static SharedData getData()
static float getDistance(SectorEntityToken from, SectorEntityToken to)
static float getRounded(float in)
GO_TO_LOCATION_AND_DESPAWN
Color getColor(String id)
float convertToDays(float realSeconds)
FleetDataAPI getFleetData()
void addAssignment(FleetAssignment assignment, SectorEntityToken target, float maxDurationInDays)
void setLocation(float x, float y)
InteractionDialogAPI getCurrentInteractionDialog()
float getQuantity(CargoAPI.CargoItemType type, Object data)
boolean removeItems(CargoAPI.CargoItemType itemType, Object data, float quantity)
void addItems(CargoAPI.CargoItemType itemType, Object data, float quantity)
boolean isHostileTo(FactionAPI other)
void addEntity(SectorEntityToken entity)
CampaignClockAPI getClock()
CampaignEventManagerAPI getEventManager()
void reportEventStage(CampaignEventPlugin event, String stage, MessagePriority priority)
CampaignUIAPI getCampaignUI()
LocationAPI getContainingLocation()
Vector2f getLocationInHyperspace()
void updateCargoPrePlayerInteraction()
boolean isParticipatesInEconomy()
StatBonus getPlayerSupplyPriceMod()
void setStockpile(float stockpile)
float getStabilityValue()
CommodityOnMarketAPI getCommodityData(String commodityId)
MemoryAPI getMemoryWithoutUpdate()
SubmarketAPI getSubmarket(String specId)
String addCondition(String id)
List< SubmarketAPI > getSubmarketsCopy()
void removeCondition(String id)
SectorEntityToken getPrimaryEntity()
SubmarketPlugin getPlugin()
EventProbabilityAPI getProbability(String eventType, SectorEntityToken eventTargetEntity)
boolean isOngoing(EventProbabilityAPI ep)
void set(String key, Object value)