1package com.fs.starfarer.api.impl.campaign.intel;
8import org.apache.log4j.Logger;
10import com.fs.starfarer.api.Global;
11import com.fs.starfarer.api.campaign.CampaignFleetAPI;
12import com.fs.starfarer.api.campaign.CargoAPI;
13import com.fs.starfarer.api.campaign.CargoStackAPI;
14import com.fs.starfarer.api.campaign.FactionAPI;
15import com.fs.starfarer.api.campaign.InteractionDialogAPI;
16import com.fs.starfarer.api.campaign.RepLevel;
17import com.fs.starfarer.api.campaign.SectorEntityToken;
18import com.fs.starfarer.api.campaign.CargoAPI.CargoItemType;
19import com.fs.starfarer.api.campaign.ReputationActionResponsePlugin.ReputationAdjustmentResult;
20import com.fs.starfarer.api.campaign.econ.CommodityOnMarketAPI;
21import com.fs.starfarer.api.campaign.econ.CommoditySpecAPI;
22import com.fs.starfarer.api.campaign.econ.EconomyAPI;
23import com.fs.starfarer.api.campaign.econ.MarketAPI;
24import com.fs.starfarer.api.campaign.econ.SubmarketAPI;
25import com.fs.starfarer.api.campaign.rules.MemoryAPI;
26import com.fs.starfarer.api.characters.ImportantPeopleAPI;
27import com.fs.starfarer.api.characters.PersonAPI;
28import com.fs.starfarer.api.characters.ImportantPeopleAPI.PersonDataAPI;
29import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin;
30import com.fs.starfarer.api.impl.campaign.CoreReputationPlugin.MissionCompletionRep;
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.econ.impl.BaseIndustry;
34import com.fs.starfarer.api.impl.campaign.ids.Commodities;
35import com.fs.starfarer.api.impl.campaign.ids.Factions;
36import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
37import com.fs.starfarer.api.impl.campaign.ids.Ranks;
38import com.fs.starfarer.api.impl.campaign.ids.Tags;
39import com.fs.starfarer.api.impl.campaign.rulecmd.AddRemoveCommodity;
40import com.fs.starfarer.api.impl.campaign.shared.PlayerTradeDataForSubmarket;
41import com.fs.starfarer.api.impl.campaign.shared.SharedData;
42import com.fs.starfarer.api.ui.ButtonAPI;
43import com.fs.starfarer.api.ui.IntelUIAPI;
44import com.fs.starfarer.api.ui.LabelAPI;
45import com.fs.starfarer.api.ui.SectorMapAPI;
46import com.fs.starfarer.api.ui.TooltipMakerAPI;
47import com.fs.starfarer.api.util.Misc;
48import com.fs.starfarer.api.util.WeightedRandomPicker;
49import com.fs.starfarer.api.util.Misc.Token;
72 if (commodityId ==
null) {
79 float illegalMult = 0.2f;
100 WeightedRandomPicker<Float> durationPicker =
new WeightedRandomPicker<Float>();
101 durationPicker.add(20f);
102 durationPicker.add(30f);
103 durationPicker.add(40f);
104 durationPicker.add(60f);
110 float minReward = 7500 + (float) Math.random() * 5000f;
123 float basePerUnit =
market.getCommodityData(commodityId).getCommodity().getBasePrice();
126 float maxQuantity = 10000f;
127 float maxDuration = 60f;
131 if (durationBonus < 10) durationBonus = 10;
132 if (quantityBonus < 10) quantityBonus = 10;
140 boolean illegal =
contact.getFaction().isHostileTo(
market.getFaction());
157 log.info(
"Created ProcurementMissionIntel: " + commodityId +
" to " +
market.getName());
168 contact.getMemoryWithoutUpdate().set(
"$mpm_isPlayerContact",
true,
duration);
170 contact.getMemoryWithoutUpdate().set(
"$mpm_commodityName",
commodity.getCommodity().getName().toLowerCase(),
duration);
172 Misc.setFlagWithReason(
contact.getMemoryWithoutUpdate(),
173 MemFlags.MEMORY_KEY_REQUIRES_DISCRETION,
"mpm_" +
commodity.getId(),
176 Misc.setFlagWithReason(
contact.getMemoryWithoutUpdate(),
177 MemFlags.MEMORY_KEY_MISSION_IMPORTANT,
182 boolean illegal =
contact.getFaction().isHostileTo(
market.getFaction());
188 contact.incrWantsToContactReasons();
199 String comId = com.getId();
201 if (
market.getFaction().isPlayerFaction()) {
205 if (
contact ==
null && com.getCommodity().hasTag(Commodities.TAG_MILITARY)) {
206 if ((
float) Math.random() > 0.1f) {
209 Ranks.POST_SUPPLY_OFFICER,
210 Ranks.POST_BASE_COMMANDER,
211 Ranks.POST_OUTPOST_COMMANDER,
212 Ranks.POST_PORTMASTER).getPerson();
218 if (
contact ==
null && com.getCommodity().hasTag(Commodities.TAG_MEDICAL)) {
219 if ((
float) Math.random() > 0.25f) {
220 contact = ip.getPerson((
float) Math.random() > 0.5f ? Factions.INDEPENDENT :
market.getFactionId(),
223 Ranks.POST_MEDICAL_SUPPLIER).getPerson();
229 if (
contact ==
null && com.getCommodity().hasTag(Commodities.TAG_LUXURY)) {
230 if ((
float) Math.random() > 0.1f && !
market.isIllegal(comId)) {
238 if ((
float) Math.random() > 0.05f && !
market.isIllegal(comId)) {
248 contact.setPostId(Ranks.POST_CITIZEN);
261 return ip.getPerson(factionId,
263 checkoutReason, Ranks.CITIZEN,
265 Ranks.POST_COMMODITIES_AGENT,
270 public static PersonDataAPI
getCriminal(MarketAPI
market, String checkoutReason, String factionId) {
272 return ip.getPerson(factionId,
274 checkoutReason, Ranks.CITIZEN,
286 WeightedRandomPicker<String> picker =
new WeightedRandomPicker<String>();
288 for (String curr : economy.getAllCommodityIds()) {
289 CommoditySpecAPI spec = economy.getCommoditySpec(curr);
290 if (spec.isMeta())
continue;
291 if (spec.hasTag(Commodities.TAG_CREW))
continue;
292 if (spec.hasTag(Commodities.TAG_MARINES))
continue;
293 if (spec.hasTag(Commodities.TAG_NON_ECONOMIC))
continue;
299 picker.add(curr, weight);
302 return picker.pick();
307 float cargoCapacity = 30;
309 if (player !=
null) {
310 if (Commodities.FUEL.equals(commodityId)) {
311 cargoCapacity = Math.max(cargoCapacity, cargoCapacity = player.getCargo().getMaxFuel());
313 cargoCapacity = Math.max(cargoCapacity, player.getCargo().getMaxCapacity());
319 float targetValue = cargoCapacity * Math.max(5f, fuel.getBasePrice());
321 float units = targetValue / Math.max(5f, spec.getBasePrice());
323 units *= 0.5f + (float) Math.random();
326 return (
int) units / 10 * 10;
330 if (
market.getSize() <= 4) {
332 }
else if (
market.getSize() == 5) {
334 }
else if (
market.getSize() == 6) {
336 }
else if (
market.getSize() == 7) {
338 }
else if (
market.getSize() >= 8) {
341 CommodityOnMarketAPI com =
market.getCommodityData(commodityId);
342 if (com.getUtilityOnMarket() > 0) {
343 quantity /= com.getUtilityOnMarket();
345 boolean illegal =
market.isIllegal(commodityId);
360 WeightedRandomPicker<MarketAPI> picker =
new WeightedRandomPicker<MarketAPI>();
362 for (MarketAPI
market : economy.getMarketsCopy()) {
363 if (
market.isHidden())
continue;
364 if (
market.isPlayerOwned())
continue;
368 boolean illegal =
market.isIllegal(commodityId);
372 if (test < min) test = min;
380 float weight =
market.getSize();
382 if (
market.getFaction().isPlayerFaction()) {
386 picker.add(
market, weight);
389 return picker.pick();
393 if (from.getContainingLocation() ==
null)
return false;
397 for (MarketAPI curr : Misc.getMarketsInLocation(from.getContainingLocation())) {
399 if (curr.getPrimaryEntity() !=
null && from.getPrimaryEntity() !=
null) {
400 float dist = Misc.getDistance(curr.getPrimaryEntity().getLocation(), from.getPrimaryEntity().getLocation());
401 if (dist > 10000)
continue;
404 CommodityOnMarketAPI com = curr.getCommodityData(commodityId);
407 int a = com.getAvailable();
408 if (a <= 0)
continue;
410 float limit = BaseIndustry.getSizeMult(a);
411 limit *= com.getCommodity().getEconUnit();
413 if (limit * 0.5f >= minQty)
return true;
421 for (SubmarketAPI submarket : curr.getSubmarketsCopy()) {
422 if (!submarket.getPlugin().isParticipatesInEconomy())
continue;
423 CargoAPI cargo = submarket.getCargoNullOk();
424 if (cargo ==
null)
continue;
425 if (cargo.getQuantity(CargoItemType.RESOURCES, commodityId) >= minQty * 0.5f)
return true;
438 if (!
market.isInEconomy()) {
447 public boolean callEvent(String ruleId,
final InteractionDialogAPI dialog, List<Token> params, Map<String, MemoryAPI> memoryMap) {
448 String action = params.get(0).getString(memoryMap);
451 CargoAPI cargo = playerFleet.getCargo();
454 if (action.equals(
"performDelivery")) {
455 cargo.removeItems(CargoItemType.RESOURCES, commodityId,
quantity);
457 cargo.getCredits().add(reward);
459 AddRemoveCommodity.addCommodityLossText(commodityId, (
int)
quantity, dialog.getTextPanel());
460 AddRemoveCommodity.addCreditsGainText(reward, dialog.getTextPanel());
464 float repAmount = 0.01f *
baseReward / 100000f;
465 if (repAmount < 0.01f) repAmount = 0.01f;
466 if (repAmount > 0.05f) repAmount = 0.05f;
468 MissionCompletionRep completionRep =
new MissionCompletionRep(repAmount, RepLevel.WELCOMING, -repAmount, RepLevel.INHOSPITABLE);
470 ReputationAdjustmentResult repF =
Global.
getSector().adjustPlayerReputation(
471 new RepActionEnvelope(RepActions.MISSION_SUCCESS, completionRep,
472 null, dialog.getTextPanel(),
true,
true),
474 ReputationAdjustmentResult repC =
Global.
getSector().adjustPlayerReputation(
475 new RepActionEnvelope(RepActions.MISSION_SUCCESS, completionRep,
476 null, dialog.getTextPanel(),
true,
true),
482 }
else if (action.equals(
"hasEnough")) {
483 return cargo.getCommodityQuantity(commodityId) >=
quantity;
484 }
else if (action.equals(
"endEvent")) {
497 }
else if (action.equals(
"hasBonus")) {
510 boolean illegal =
contact.getFaction().isHostileTo(
market.getFaction());
512 SubmarketAPI submarket =
null;
513 for (SubmarketAPI curr :
market.getSubmarketsCopy()) {
514 if (!curr.getPlugin().isParticipatesInEconomy())
continue;
515 if (
contact.getFaction() == curr.getFaction()) {
521 if (submarket ==
null) {
522 for (SubmarketAPI curr :
market.getSubmarketsCopy()) {
523 if (!curr.getPlugin().isParticipatesInEconomy())
continue;
525 if (illegal && curr.getPlugin().isBlackMarket()) {
529 if (!illegal && curr.getPlugin().isOpenMarket()) {
536 if (submarket ==
null)
return;
538 PlayerTradeDataForSubmarket tradeData = SharedData.getData().getPlayerActivityTracker().getPlayerTradeData(submarket);
541 tradeData.addToTrackedPlayerSold(stack, totalReward);
549 contact.getMemoryWithoutUpdate().unset(
"$mpm_isPlayerContact");
550 contact.getMemoryWithoutUpdate().unset(
"$mpm_eventRef");
551 contact.getMemoryWithoutUpdate().unset(
"$mpm_commodityName");
552 contact.getMemoryWithoutUpdate().unset(
"$mpm_quantity");
553 Misc.setFlagWithReason(
contact.getMemoryWithoutUpdate(),
554 MemFlags.MEMORY_KEY_REQUIRES_DISCRETION,
"mpm_" +
commodity.getId(),
556 Misc.setFlagWithReason(
contact.getMemoryWithoutUpdate(),
557 MemFlags.MEMORY_KEY_MISSION_IMPORTANT,
561 contact.decrWantsToContactReasons();
580 Color h = Misc.getHighlightColor();
581 Color g = Misc.getGrayColor();
586 if (mode == ListInfoMode.IN_DESC) initPad = opad;
599 info.addPara(
"%s received", initPad, tc, h, Misc.getDGSCredits(
missionResult.payment));
602 null,
null, info, tc, isUpdate, 0f);
604 null,
null, info, tc, isUpdate, 0f);
610 info.addPara(
"%s received", initPad, tc, h, Misc.getDGSCredits(
missionResult.payment));
616 null,
null, info, tc, isUpdate, initPad);
621 null,
null, info, tc, isUpdate, initPad);
625 if (mode != ListInfoMode.IN_DESC) {
626 FactionAPI faction =
contact.getFaction();
627 info.addPara(
"Faction: " + faction.getDisplayName(), initPad, tc,
628 faction.getBaseUIColor(),
629 faction.getDisplayName());
633 LabelAPI label = info.addPara(
"%s units required at " +
market.getName(),
634 initPad, tc, h,
"" + (
int)
quantity);
636 label.setHighlightColors(h,
market.getFaction().getBaseUIColor());
637 info.addPara(
"%s reward", 0f, tc, h, Misc.getDGSCredits(
baseReward));
647 Color h = Misc.getHighlightColor();
648 Color g = Misc.getGrayColor();
653 info.addPara(
getName(), c, 0f);
659 return "Procurement";
664 return "Procurement - " +
commodity.getCommodity().getName();
682 Color h = Misc.getHighlightColor();
683 Color g = Misc.getGrayColor();
684 Color tc = Misc.getTextColor();
688 FactionAPI faction =
contact.getFaction();
689 boolean illegal =
contact.getFaction().isHostileTo(
market.getFaction());
693 info.addImages(width, 80, opad, opad * 2f,
698 String prefix = faction.getPersonNamePrefix();
699 if (Factions.PIRATES.equals(faction.getId())) {
700 prefix +=
"-affiliated";
703 String desc =
contact.getPost();
704 if (desc ==
null) desc =
contact.getRank();
705 if (desc ==
null) desc =
"supplier";
706 desc = desc.toLowerCase();
709 info.addPara(Misc.ucFirst(faction.getPersonNamePrefixAOrAn()) +
" " + prefix +
" " + desc +
" at " +
711 "has posted a procurement contract for a quantity of " +
712 commodity.getCommodity().getLowerCaseName() +
".",
713 opad, tc, faction.getBaseUIColor(), prefix);
721 info.addPara(
"Contact " +
contact.getNameString() +
722 " at " +
market.getName() +
" to complete the delivery.", opad);
725 info.addPara(
contact.getNameString() +
726 " is affiliated with the local underworld and will require clandestine delivery, " +
727 "which may attract the interest of local authorities.", opad);
729 if (
market.getFaction().isHostileTo(Factions.PLAYER)) {
730 info.addPara(
contact.getNameString() +
" is " +
731 "operating with the knowledge of the local authorities. " +
732 "However, " + faction.getDisplayNameWithArticle() +
" is hostile towards you, and you'll need " +
733 "to sneak into port without attracting notice in order to complete the delivery.", opad);
735 info.addPara(
contact.getNameString() +
" is " +
736 "operating with the knowledge of the local authorities and the delivery may be made openly.", opad);
746 (
int)(width), 20f, opad * 3f);
747 if (!
Global.
getSector().getIntelManager().isPlayerInRangeOfCommRelay()) {
748 button.setEnabled(
false);
749 info.addPara(
"Seeing remote price data requires being within range of a functional comm relay.", g, opad);
755 info.addPara(
"You have failed this contract because " +
market.getName() +
756 " no longer exists as a functional polity.", opad);
767 return commodity.getCommodity().getIconName();
771 Set<String> tags = super.getIntelTags(map);
772 tags.add(Tags.INTEL_TRADE);
773 tags.add(
contact.getFaction().getId());
780 return market.getPrimaryEntity();
794 float repAmount = 0.01f *
baseReward / 100000f;
795 if (repAmount < 0.01f) repAmount = 0.01f;
796 if (repAmount > 0.05f) repAmount = 0.05f;
798 MissionCompletionRep completionRep =
new MissionCompletionRep(repAmount, RepLevel.WELCOMING, -repAmount, RepLevel.INHOSPITABLE);
800 ReputationAdjustmentResult repF =
Global.
getSector().adjustPlayerReputation(
801 new RepActionEnvelope(RepActions.MISSION_FAILURE, completionRep,
802 null,
null,
true,
false),
804 ReputationAdjustmentResult repC =
Global.
getSector().adjustPlayerReputation(
805 new RepActionEnvelope(RepActions.MISSION_FAILURE, completionRep,
806 null,
null,
true,
false),
809 return new MissionResult(0, repF, repC);
812 return new MissionResult();
826 super.buttonPressConfirmed(buttonId, ui);
833 super.createConfirmationPrompt(buttonId, prompt);
837 prompt.setParaFontDefault();
839 prompt.addPara(
"This procurement contract offers a price of %s per unit of " +
commodity.getCommodity().getName() +
".",
840 0f, Misc.getHighlightColor(), Misc.getDGSCredits(
pricePerUnit));
850 return super.doesButtonHaveConfirmDialog(buttonId);
855 return 664f + 43f + 10f;
857 return super.getConfirmationPromptWidth(buttonId);
864 return super.getConfirmText(buttonId);
871 return super.getCancelText(buttonId);
static SettingsAPI getSettings()
static FactoryAPI getFactory()
static Logger getLogger(Class c)
static SectorAPI getSector()
static void addAdjustmentMessage(float delta, FactionAPI faction, PersonAPI person, TextPanelAPI panel, TooltipMakerAPI info, Color tc, boolean withCurrent, float pad)
void setPostingLocation(SectorEntityToken postingLocation)
void unindent(TooltipMakerAPI info)
void addDays(TooltipMakerAPI info, String after, float days)
Object getListInfoParam()
Color getBulletColorForMode(ListInfoMode mode)
void bullet(TooltipMakerAPI info)
Color getTitleColor(ListInfoMode mode)
void addAcceptOrAbandonButton(TooltipMakerAPI info, float width)
String getPostfixForState()
void setMissionState(MissionState missionState)
MissionResult missionResult
void setDuration(Float duration)
void addGenericMissionState(TooltipMakerAPI info)
void setMissionResult(MissionResult missionResult)
CommodityOnMarketAPI commodity
boolean doNearbyMarketsHave(MarketAPI from, String commodityId, float minQty)
void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode)
boolean contactWillInitiateComms
SectorEntityToken getMapLocation(SectorMapAPI map)
void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode)
void advanceMission(float amount)
String getMissionTypeNoun()
void createSmallDescription(TooltipMakerAPI info, float width, float height)
void applyTradeValueImpact(float totalReward)
String getConfirmText(Object buttonId)
void buttonPressConfirmed(Object buttonId, IntelUIAPI ui)
static String BUTTON_COMMODITY_INFO
float getQuantityAdjustedForMarket(String commodityId, float quantity, float illegalMult, float min, MarketAPI market)
void createConfirmationPrompt(Object buttonId, TooltipMakerAPI prompt)
static PersonDataAPI getLegitTrader(MarketAPI market, String checkoutReason, String factionId)
FactionAPI getFactionForUIColors()
ProcurementMissionIntel()
static final String PERSON_CHECKOUT_REASON
boolean callEvent(String ruleId, final InteractionDialogAPI dialog, List< Token > params, Map< String, MemoryAPI > memoryMap)
MarketAPI pickMarket(String commodityId, float quantity, float illegalMult, float min)
boolean doesButtonHaveConfirmDialog(Object buttonId)
float getConfirmationPromptWidth(Object buttonId)
PersonAPI pickContact(MarketAPI market, CommodityOnMarketAPI com)
static PersonDataAPI getCriminal(MarketAPI market, String checkoutReason, String factionId)
String getSmallDescriptionTitle()
int getQuantity(String commodityId)
Set< String > getIntelTags(SectorMapAPI map)
MissionResult createAbandonedResult(boolean withPenalty)
MissionResult createTimeRanOutFailedResult()
String getCancelText(Object buttonId)
CargoStackAPI createCargoStack(CargoItemType type, Object data, CargoAPI cargo)
void addCommodityInfoToTooltip(TooltipMakerAPI tooltip, float initPad, CommoditySpecAPI spec, int max, boolean withText, boolean withSell, boolean withBuy)
CommoditySpecAPI getCommoditySpec(String commodityId)
void profilerBegin(String id)