Starsector API
Loading...
Searching...
No Matches
FoodShortageEvent.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.events;
2
3import java.awt.Color;
4import java.util.ArrayList;
5import java.util.List;
6import java.util.Map;
7
8import org.apache.log4j.Logger;
9
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;
43
44public class FoodShortageEvent extends BaseEventPlugin {
45
46 public static Logger log = Global.getLogger(FoodShortageEvent.class);
47
48 public static String PRICE_MOD_ID = "fse_priceMod";
49
50 public static float FOOD_PRICE_MULT = 1.5f;
51 public static float FOOD_PRICE_FLAT = 50f;
52
53 public static float MAX_POSSIBLE_DURATION = 60f;
54 public static float MIN_FRACTION_FOR_PLAYER_ENDING_EVENT = 0.5f;
55
56
57 public static enum Ending {
58 DURATION_EXPIRED,
59 RELIEF_ARRIVED,
60 PLAYER_ENDED,
61 PLAYER_ENDED_BLACK,
62 }
63
64 public static class PlayerFoodTransaction {
65 public long timestamp;
66
70 public float quantity;
71 }
72
73 private boolean ended = false;
74
75 private float maxDurationDays;
76 private float daysBeforeReliefCheck;
77 private float daysBeforeReliefSend;
78 private float elapsedDays = 0f;
79 private int stage = 0;
80
81 //private List<PlayerFoodTransaction> preEventTransactions = new ArrayList<PlayerFoodTransaction>();
82 private float preEventFoodLevel;
83
84 //private float foodToMeetShortage = 0;
85 private float baseFoodToMeetShortage = 0;
86 //private float playerBlameAmount = 0;
87 private float netDeliveredByPlayerBlack = 0;
88 private float netDeliveredByPlayerOther = 0;
89
90 //private float originalReliefFleetCargoCapacity = 0;
91 private float originalReliefFleetPoints = 0;
92 private CampaignFleetAPI reliefFleet;
93
94 private MessagePriority messagePriority = MessagePriority.CLUSTER;
95 private String foodShortageConditionToken = null;
96
97 private MarketAPI reliefMarket;
98
99
100 public void init(String type, CampaignEventTarget eventTarget) {
101 super.init(type, eventTarget, false);
102 }
103
104 public void startEvent() {
105 super.startEvent(true);
106 if (market == null) return;
107
108 switch (market.getSize()) {
109 case 1:
110 case 2:
111 case 3:
112 messagePriority = MessagePriority.SYSTEM;
113 break;
114 case 4:
115 case 5:
116 messagePriority = MessagePriority.CLUSTER;
117 break;
118 case 6:
119 case 7:
120 case 8:
121 case 9:
122 messagePriority = MessagePriority.SECTOR;
123 break;
124 }
125
126 // moved to FoodShortage condition
127// String sellId = Stats.getPlayerSellImpactMultId(Commodities.FOOD);
128// market.getStats().getDynamic().getStat(sellId).modifyFlat(getId() + "_mod", getStabilityImpact());
129
130 baseFoodToMeetShortage = getBaseShortageAmount();
131 //foodToMeetShortage = baseFoodToMeetShortage;
132
133 maxDurationDays = 20f + (float) Math.random() * 20f;
134
135 daysBeforeReliefCheck = 7f + (float) Math.random() * 7f;
136 daysBeforeReliefSend = daysBeforeReliefCheck + (float) Math.random() * 7f;
137
138 foodShortageConditionToken = market.addCondition(Conditions.EVENT_FOOD_SHORTAGE, this);
139 CommodityOnMarketAPI com = market.getCommodityData(Commodities.FOOD);
140
141 preEventFoodLevel = com.getStockpile();
142 com.setStockpile(com.getStockpile() * getStockpileMult());
143 com.getPlayerSupplyPriceMod().modifyMult(PRICE_MOD_ID, FOOD_PRICE_MULT);
144 com.getPlayerSupplyPriceMod().modifyFlat(PRICE_MOD_ID, FOOD_PRICE_FLAT);
145
146
147 SubmarketAPI open = market.getSubmarket("open_market");
148 if (open != null) {
149 float food = open.getCargo().getQuantity(CargoItemType.RESOURCES, Commodities.FOOD);
150 open.getCargo().removeItems(CargoItemType.RESOURCES, Commodities.FOOD, food);
151 }
152
153 SubmarketAPI black = market.getSubmarket("black_market");
154 if (black != null) {
155 black.getPlugin().updateCargoPrePlayerInteraction();
156 black.getCargo().addItems(CargoItemType.RESOURCES, Commodities.FOOD,
157 (int)Math.max(1, baseFoodToMeetShortage * (0.1f + (float) Math.random() * 0.05f)));
158 }
159
160 Global.getSector().reportEventStage(this, "start", messagePriority);
161
162 log.info(getLoggingId() + " Starting food shortage" +
163 ", food needed: " + (int) baseFoodToMeetShortage +
164 ", stockpile mult: " + getStockpileMult() +
165 ", max duration: " + (int) maxDurationDays + " days");
166 }
167
168
169 private float getBaseShortageAmount() {
170 float stockpileMult = getStockpileMult();
171 CommodityOnMarketAPI com = market.getCommodityData(Commodities.FOOD);
172 float amount = com.getStockpile() * (1f - stockpileMult);
173 if (amount < 50) amount = 50;
174 return Misc.getRounded(amount);
175 }
176
177
178 private float getStockpileMult() {
179 switch ((int) market.getSize()) {
180 case 0:
181 case 1:
182 return 0f;
183 case 2:
184 case 3:
185 return 0.2f;
186 case 4:
187 case 5:
188 return 0.3f;
189 case 6:
190 case 7:
191 return 0.5f;
192 case 8:
193 case 9:
194 return 0.9f;
195 }
196 return 1f;
197// switch ((int) market.getSize()) {
198// case 0:
199// case 1:
200// return 0f;
201// case 2:
202// case 3:
203// return 0.25f;
204// case 4:
205// case 5:
206// return 0.5f;
207// case 6:
208// case 7:
209// case 8:
210// case 9:
211// return 0.9f;
212// }
213// return 1f;
214 }
215
216
217 public float getStabilityImpact() {
218 switch ((int) market.getSize()) {
219 case 0:
220 case 1:
221 return 4;
222 case 2:
223 case 3:
224 return 3;
225 case 4:
226 case 5:
227 return 2;
228 case 6:
229 case 7:
230 case 8:
231 case 9:
232 return 1;
233 }
234 return 1f;
235 }
236
237 public float getReliefAbortUnrest() {
238 return 2;
239 }
240
241 public float getAddedExpiredUnrest() {
242 return 1;
243 }
244
245 public float getReducedEndedUnrest() {
246 return 1;
247 }
248
249 public float getEndBlackUnrest() {
250 float base = getStabilityImpact();
251 float mult = Math.min(1f, netDeliveredByPlayerBlack / baseFoodToMeetShortage);
252 return Math.round(base * mult);
253 }
254
255 public void advance(float amount) {
256 if (Global.getSector().isPaused()) return;
257
258 //float econInterval = Global.getSettings().getFloat("economyIntervalnGameDays");
259 float days = Global.getSector().getClock().convertToDays(amount);
260
261 if (!isEventStarted()) {
262 return;
263 }
264
265 if (isDone()) return;
266
267 elapsedDays += days;
268
269 if (elapsedDays > daysBeforeReliefCheck && stage == 0) {
270 stage++;
271
272 reliefMarket = findNearestMarket(market, new MarketFilter() {
273 public boolean acceptMarket(MarketAPI market) {
274 if (market == FoodShortageEvent.this.market) {
275 return false;
276 }
277 if (market.getFaction().isHostileTo(FoodShortageEvent.this.market.getFaction())) {
278 return false;
279 }
280 if (SharedData.getData().getMarketsThatSentRelief().contains(market.getId())) {
281 return false;
282 }
283 if (market.getCommodityData(Commodities.FOOD).getStockpile() < baseFoodToMeetShortage) {
284 return false;
285 }
286
287 CampaignEventManagerAPI manager = Global.getSector().getEventManager();
288 EventProbabilityAPI ep = manager.getProbability(Events.FOOD_SHORTAGE, market);
289 if (ep.getProbability() > 0.1) {
290 return false;
291 }
292 if (manager.isOngoing(ep)) {
293 return false;
294 }
295 if ((float) Math.random() * 10f > market.getStabilityValue()) return false;
296
297 return market.getSize() >= FoodShortageEvent.this.market.getSize();
298 }
299 });
300 //reliefMarket = Global.getSector().getEconomy().getMarket("sindria");
301
302 //if ((float) Math.random() > 0.67f || market.getFaction().getId().equals("pirates")) {
303 if (market.getFaction().getId().equals("pirates")) {
304 reliefMarket = null;
305 }
306
307 if (reliefMarket != null) {
308 SharedData.getData().getMarketsThatSentRelief().add(reliefMarket.getId(), 14f + (float) Math.random() * 14f);
309 Global.getSector().reportEventStage(this, "warning_relief", reliefMarket.getPrimaryEntity(), messagePriority);
310 } else {
311 log.info(getLoggingId() + " No relief market found");
312 applyReliefFleetDidNotMakeItConsequences();
313 Global.getSector().reportEventStage(this, "relief_unavailable", messagePriority);
314 }
315 }
316
317 if (elapsedDays > daysBeforeReliefSend && stage == 1) {
318 stage++;
319 if (reliefMarket != null) {
320 createReliefFleet();
321 if (reliefFleet == null) {
322 log.info(getLoggingId() + " Failed to spawn relief fleet");
323 applyReliefFleetDidNotMakeItConsequences();
324 Global.getSector().reportEventStage(this, "relief_unavailable", messagePriority);
325 } else {
326 originalReliefFleetPoints = reliefFleet.getFleetPoints();
327
328 SectorEntityToken entity = reliefMarket.getPrimaryEntity();
329 reliefMarket.getPrimaryEntity().getContainingLocation().addEntity(reliefFleet);
330 reliefFleet.setLocation(entity.getLocation().x, entity.getLocation().y);
331
332 reliefFleet.addAssignment(FleetAssignment.ORBIT_PASSIVE, reliefMarket.getPrimaryEntity(), 2,
333 "loading food from " + reliefMarket.getName(), new Script() {
334 public void run() {
335 reliefFleet.getCargo().addItems(CargoItemType.RESOURCES, Commodities.FOOD,
336 reliefFleet.getCargo().getMaxCapacity() * (1f - FleetFactory.SUPPLIES_FRACTION));
337 }
338 });
339 reliefFleet.addAssignment(FleetAssignment.DELIVER_RESOURCES, market.getPrimaryEntity(), 1000,
340 "delivering food relief from " + reliefMarket.getName() + " to " + market.getName());
341 reliefFleet.addAssignment(FleetAssignment.ORBIT_PASSIVE, market.getPrimaryEntity(), 2,
342 "offloading food at " + market.getName(), new Script() {
343 public void run() {
344 endEvent(Ending.RELIEF_ARRIVED);
345 }
346 });
347 reliefFleet.addAssignment(FleetAssignment.GO_TO_LOCATION_AND_DESPAWN, reliefMarket.getPrimaryEntity(), 1000,
348 "returning to " + reliefMarket.getName() + " after delivering food relief to " + market.getName());
349
350 Global.getSector().reportEventStage(this, "relief_sent", reliefMarket.getPrimaryEntity(), messagePriority);
351 log.info(getLoggingId() + " Sending relief fleet from " + reliefMarket.getName());
352 }
353 }
354 }
355
356 if (reliefFleet != null) {
357 float currPoints = reliefFleet.getFleetPoints();
358 if (currPoints < originalReliefFleetPoints * 0.5f) {
359 Global.getSector().reportEventStage(this, "relief_aborted", reliefMarket.getPrimaryEntity(), messagePriority);
360 log.info(getLoggingId() + " Relief aborted, fleet returning to " + reliefMarket.getName());
361
362 reliefFleet.clearAssignments();
363 reliefFleet.addAssignment(FleetAssignment.GO_TO_LOCATION_AND_DESPAWN, reliefMarket.getPrimaryEntity(), 1000);
364 applyReliefFleetDidNotMakeItConsequences();
365 reliefFleet = null;
366 }
367 }
368
369 if ((elapsedDays > maxDurationDays || elapsedDays > MAX_POSSIBLE_DURATION) && stage == 2) {
370 endEvent(Ending.DURATION_EXPIRED);
371 stage++;
372 }
373 }
374
375
376 private void applyReliefFleetDidNotMakeItConsequences() {
377 float abortUnrest = getReliefAbortUnrest();
378 increaseRecentUnrest((int) abortUnrest);
379 log.info(" +" + abortUnrest + " unrest at " + market.getName());
380 }
381
382 private void createReliefFleet() {
383 reliefFleet = FleetFactory.createEmptyFleet(reliefMarket.getFactionId(), FleetTypes.FOOD_RELIEF_FLEET, reliefMarket);
384
385 int size = market.getSize();
386 float combat = size;
387 float freighter = size * 1.5f;
388 float transport = size * 0.25f;
389 combat *= 5;
390 freighter *= 3;
391 transport *= 3;
392 reliefFleet = FleetFactoryV3.createFleet(new FleetParamsV3(
393 reliefMarket,
394 FleetTypes.FOOD_RELIEF_FLEET,
395 combat, // combatPts
396 freighter, // freighterPts
397 0f, // tankerPts
398 transport, // transportPts
399 0f, // linerPts
400 0f, // utilityPts
401 0f // qualityMod
402 ));
403 }
404
405
406
407 private void endEvent(Ending ending) {
408 if (market != null) {
409 market.removeCondition(Conditions.EVENT_FOOD_SHORTAGE);
410 }
411 ended = true;
412 CommodityOnMarketAPI com = market.getCommodityData(Commodities.FOOD);
413 com.setStockpile(com.getStockpile() / getStockpileMult());
414 com.getPlayerSupplyPriceMod().unmodifyMult(PRICE_MOD_ID);
415 com.getPlayerSupplyPriceMod().unmodifyFlat(PRICE_MOD_ID);
416
417 // moved to FoodShortage condition
418// String sellId = Stats.getPlayerSellImpactMultId(Commodities.FOOD);
419// market.getStats().getDynamic().getStat(sellId).unmodify(getId() + "_mod");
420
421 float ongoingStabilityImpact = getStabilityImpact();
422
423 Misc.unsetAll("$market.foodShortage", MemKeys.MARKET, market.getMemoryWithoutUpdate());
424 final InteractionDialogAPI dialog = Global.getSector().getCampaignUI().getCurrentInteractionDialog();
425 switch (ending) {
426 case DURATION_EXPIRED:
427 Global.getSector().reportEventStage(this, "end_expired", messagePriority);
428 log.info(getLoggingId() + " Expired");
429 ongoingStabilityImpact += getAddedExpiredUnrest();
430 market.getMemoryWithoutUpdate().set("$foodShortageExpired", true, 10);
431 break;
432 case PLAYER_ENDED:
433 if (dialog != null && dialog.getPlugin().getMemoryMap() != null && dialog.getTextPanel() != null) {
434 dialog.getTextPanel().addParagraph("Financial transaction confirmed", Global.getSettings().getColor("buttonText"));
435 }
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),
444 market.getFaction().getId());
445 }
446 });
447 log.info(getLoggingId() + " Ended by player within 7 days");
448 market.getMemoryWithoutUpdate().set("$foodShortageEndedByPlayerFast", true, 10);
449 //market.getFaction().adjustRelationship(Factions.PLAYER, RepRewards.HIGH);
450// Global.getSector().adjustPlayerReputation(
451// new RepActionEnvelope(RepActions.FOOD_SHORTAGE_PLAYER_ENDED_FAST, market),
452// market.getFaction().getId());
453 } else {
454 ongoingStabilityImpact = Math.max(0, ongoingStabilityImpact - getReducedEndedUnrest());
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),
461 market.getFaction().getId());
462 }
463 });
464 log.info(getLoggingId() + " Ended by player");
465 market.getMemoryWithoutUpdate().set("$foodShortageEndedByPlayer", true, 10);
466 }
467 if (dialog != null && dialog.getPlugin().getMemoryMap() != null) {
468 dialog.getVisualPanel().hideCore();
469 FireBest.fire(null, dialog, dialog.getPlugin().getMemoryMap(), "FoodShortageEndedByPlayerSale");
470 }
471 break;
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"));
475 }
476 ongoingStabilityImpact = ongoingStabilityImpact + getEndBlackUnrest();
477 Global.getSector().reportEventStage(this, "end_player_black", null, MessagePriority.DELIVER_IMMEDIATELY,
478 new BaseOnMessageDeliveryScript() {
479 public void beforeDelivery(CommMessageAPI message) {
480// Global.getSector().adjustPlayerReputation(
481// new RepActionEnvelope(RepActions.FOOD_SHORTAGE_PLAYER_ENDED_MEDIUM_CONTRIB, market, message,
482// dialog.getTextPanel(), true),
483// market.getFaction().getId());
484 }
485 });
486 log.info(getLoggingId() + " Ended by player black market trade");
487 market.getMemoryWithoutUpdate().set("$foodShortageEndedByPlayerBlack", true, 10);
488 if (dialog != null && dialog.getPlugin().getMemoryMap() != null) {
489 dialog.getVisualPanel().hideCore();
490 FireBest.fire(null, dialog, dialog.getPlugin().getMemoryMap(), "FoodShortageEndedByPlayerSale");
491 }
492 break;
493 case RELIEF_ARRIVED:
494 Global.getSector().reportEventStage(this, "end_relief_arrived", null, messagePriority);
495 ongoingStabilityImpact = Math.max(0, ongoingStabilityImpact - getReducedEndedUnrest());
496 log.info(getLoggingId() + " Ended by relief fleet arrival");
497 market.getMemoryWithoutUpdate().set("$foodShortageEndedByNPC", true, 10);
498 break;
499 }
500
501 for (SubmarketAPI sub : market.getSubmarketsCopy()) {
502 if (sub.getPlugin().isFreeTransfer()) continue;
503
504 float food = sub.getCargo().getQuantity(CargoItemType.RESOURCES, Commodities.FOOD);
505 sub.getCargo().removeItems(CargoItemType.RESOURCES, Commodities.FOOD, food);
506 }
507
508 increaseRecentUnrest((int) ongoingStabilityImpact);
509 log.info(getLoggingId() + " Unrest +" + (int)ongoingStabilityImpact);
510
511 }
512
513 public boolean isDone() {
514 return ended;
515 }
516
517 public MessagePriority getWarningWhenPossiblePriority() {
518 return messagePriority;
519 }
520
521 public MessagePriority getWarningWhenLikelyPriority() {
522 return messagePriority;
523 }
524
525 public String getStageIdForLikely() {
526 return "likely";
527 }
528
529 public String getStageIdForPossible() {
530 return "possible";
531 }
532
533
534// private float updatePurchaseListAndReturnTotalBought() {
535// CampaignClockAPI clock = Global.getSector().getClock();
536// float maxDays = 30f;
537// float total = 0f;
538// List<PlayerFoodTransaction> remove = new ArrayList<PlayerFoodTransaction>();
539// for (PlayerFoodTransaction p : preEventTransactions) {
540// float elapsed = clock.getElapsedDaysSince(p.timestamp);
541// if (elapsed > maxDays) {
542// remove.add(p);
543// } else {
544// total += p.quantity;
545// }
546// }
547// preEventTransactions.removeAll(remove);
548//
549// return total;
550// }
551
552 @Override
553 public void reportPlayerMarketTransaction(PlayerMarketTransaction transaction) {
554 if (!isEventStarted()) return;
555
556 if (market == null) return;
557 if (transaction.getMarket() != market) return;
558 if (isDone()) return;
559
560// if (market.getId().equals("jangala")) {
561// System.out.println("123sfe");
562// }
563
564 SubmarketPlugin plugin = transaction.getSubmarket().getPlugin();
565 if (!plugin.isParticipatesInEconomy()) return;
566
567 float bought = transaction.getQuantityBought(Commodities.FOOD);
568 float sold = transaction.getQuantitySold(Commodities.FOOD);
569 float netBought = bought - sold;
570
571 if (netBought == 0) return;
572
573// CampaignEventManagerAPI manager = Global.getSector().getEventManager();
574// EventProbabilityAPI ep = manager.getProbability(getEventType(), getEventTarget());
575
576
577 CommodityOnMarketAPI com = market.getCommodityData(Commodities.FOOD);
578 float postTransactionLevel = com.getStockpile();
579
580 if (plugin.isBlackMarket()) {
581 netDeliveredByPlayerBlack -= bought;
582 netDeliveredByPlayerBlack += sold;
583 } else {
584 netDeliveredByPlayerOther -= bought;
585 netDeliveredByPlayerOther += sold;
586 }
587
588 if (postTransactionLevel >= preEventFoodLevel &&
589 netDeliveredByPlayerOther + netDeliveredByPlayerBlack >= MIN_FRACTION_FOR_PLAYER_ENDING_EVENT * baseFoodToMeetShortage) {
590 if (netDeliveredByPlayerBlack >= MIN_FRACTION_FOR_PLAYER_ENDING_EVENT * baseFoodToMeetShortage) {
591 endEvent(Ending.PLAYER_ENDED_BLACK);
592 } else {
593 endEvent(Ending.PLAYER_ENDED);
594 }
595 // added in endEvent() before rep gain
596// InteractionDialogAPI dialog = Global.getSector().getCampaignUI().getCurrentInteractionDialog();
597// if (dialog != null && dialog.getPlugin().getMemoryMap() != null) {
598// //dialog.getTextPanel().clear();
599// //dialog.getTextPanel().addParagraph("Financial transaction confirmed", Global.getSettings().getColor("buttonText"));
600// dialog.getVisualPanel().hideCore();
601// FireBest.fire(null, dialog, dialog.getPlugin().getMemoryMap(), "FoodShortageEndedByPlayerSale");
602// }
603 }
604 }
605
606 @Override
607 public void reportFleetDespawned(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param) {
608 if (fleet == reliefFleet) {
609 Global.getSector().reportEventStage(this, "relief_lost", reliefMarket.getPrimaryEntity(), messagePriority);
610 applyReliefFleetDidNotMakeItConsequences();
611 reliefFleet = null;
612 }
613 }
614
616 return Math.max(0, baseFoodToMeetShortage - netDeliveredByPlayerBlack - netDeliveredByPlayerOther);
617 }
618
619 public Map<String, String> getTokenReplacements() {
620 Map<String, String> map = super.getTokenReplacements();
621
622 /*
623 $targetFaction
624 $reliefSystem
625 $reliefEntity
626 $playerName
627 */
628 map.put("$targetFaction", eventTarget.getEntity().getFaction().getDisplayName());
629
630 if (reliefMarket != null) {
631 SectorEntityToken primary = reliefMarket.getPrimaryEntity();
632 LocationAPI loc = primary.getContainingLocation();
633 if (loc instanceof StarSystemAPI) {
634 //map.put("$reliefSystem", ((StarSystemAPI)loc).getBaseName() + " star system");
635 map.put("$reliefSystem", ((StarSystemAPI)loc).getBaseName());
636 } else {
637 map.put("$reliefSystem", "hyperspace");
638 }
639
640 map.put("$reliefMarket", primary.getName());
641// map.put("$reliefSystem", "Askonia");
642// map.put("$reliefEntity", "Volturn");
643 if (reliefFleet != null) {
644 float dist = Misc.getDistance(primary.getLocationInHyperspace(), market.getPrimaryEntity().getLocationInHyperspace());
645 float eta = dist / reliefFleet.getFleetData().getTravelSpeed();
646 // since travel speed is units/second, not per day
647 eta /= Global.getSector().getClock().getSecondsPerDay();
648 eta += 2f;
649
650 String s = null;
651 if (eta <= 3f) {
652 s = "within a few days";
653 } else if (eta <= 7) {
654 s = "within a week";
655 } else if (eta <= 14) {
656 s = "within a couple of weeks";
657 } else if (eta <= 30) {
658 s = "within a month";
659 } else {
660 s = "in the coming months";
661 }
662 map.put("$eta", s);
663 }
664 }
665
666 int needed = (int) Misc.getRounded(getRemainingFoodToMeetShortage());
667 map.put("$neededFood", "" + needed);
668
669 map.put("$stabilityPenalty", "" + (int) getStabilityImpact());
670 map.put("$stabilityPenaltyRelief", "" + (int) getReliefAbortUnrest());
671 map.put("$stabilityPenaltyExpire", "" + (int) (getAddedExpiredUnrest() + getStabilityImpact()));
672 map.put("$stabilityPenaltyEnd", "" + (int) Math.max(0, getStabilityImpact() - getReducedEndedUnrest()));
673 map.put("$stabilityPenaltyEndBlack", "" + (int) (getStabilityImpact() + getEndBlackUnrest()));
674 return map;
675 }
676
677 @Override
678 public String[] getHighlights(String stageId) {
679 List<String> result = new ArrayList<String>();
680 if ("start".equals(stageId)) {
681 addTokensToList(result, "$stabilityPenalty", "$neededFood");
682 }
683 if ("relief_unavailable".equals(stageId)) {
684 addTokensToList(result, "$stabilityPenaltyRelief");
685 }
686 if ("relief_aborted".equals(stageId)) {
687 addTokensToList(result, "$stabilityPenaltyRelief");
688 }
689 if ("relief_lost".equals(stageId)) {
690 addTokensToList(result, "$stabilityPenaltyRelief");
691 }
692 if ("end_relief_arrived".equals(stageId)) {
693 addTokensToList(result, "$stabilityPenaltyEnd");
694 }
695 if ("end_expired".equals(stageId)) {
696 addTokensToList(result, "$stabilityPenaltyExpire");
697 }
698 if ("end_player".equals(stageId)) {
699 addTokensToList(result, "$stabilityPenaltyEnd");
700 }
701 if ("end_player_black".equals(stageId)) {
702 addTokensToList(result, "$stabilityPenaltyEndBlack");
703 }
704 if ("end_player_fast".equals(stageId)) {
705 }
706 return result.toArray(new String[0]);
707 }
708
709 @Override
710 public Color[] getHighlightColors(String stageId) {
711 return super.getHighlightColors(stageId);
712// String [] highlights = getHighlights(stageId);
713// if (highlights != null) {
714// Color c = Global.getSettings().getColor("buttonShortcut");
715// Color [] colors = new Color[highlights.length];
716// Arrays.fill(colors, c);
717// return colors;
718// }
719// //return null;
720// return null;
721 }
722
723 @Override
724 public List<String> getRelatedCommodities() {
725 List<String> commodities = new ArrayList<String>();
726 commodities.add(Commodities.FOOD);
727 return commodities;
728 }
729
730 @Override
731 public List<PriceUpdatePlugin> getPriceUpdates() {
732 List<PriceUpdatePlugin> updates = new ArrayList<PriceUpdatePlugin>();
733 updates.add(new PriceUpdate(market.getCommodityData(Commodities.FOOD)));
734 return updates;
735 }
736
737 public String getEventName() {
738 if (!isEventStarted()) {
739 return "Possible food shortage - " + market.getName() + "";
740 }
741 if (isDone()) {
742 return "Food shortage - " + market.getName() + " (over)";
743 }
744 return "Food shortage - " + market.getName() + "";
745 }
746}
747
748
749
750
static SettingsAPI getSettings()
Definition Global.java:51
static Logger getLogger(Class c)
Definition Global.java:26
static SectorAPI getSector()
Definition Global.java:59
void addTokensToList(List< String > list, String ... keys)
static MarketAPI findNearestMarket(MarketAPI from, MarketFilter filter)
void reportFleetDespawned(CampaignFleetAPI fleet, FleetDespawnReason reason, Object param)
void init(String type, CampaignEventTarget eventTarget)
void reportPlayerMarketTransaction(PlayerMarketTransaction transaction)