Starsector API
Loading...
Searching...
No Matches
CheapCommodityMission.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.missions;
2
3import java.awt.Color;
4import java.util.Map;
5
6import com.fs.starfarer.api.Global;
7import com.fs.starfarer.api.campaign.InteractionDialogAPI;
8import com.fs.starfarer.api.campaign.PersonImportance;
9import com.fs.starfarer.api.campaign.econ.CommodityOnMarketAPI;
10import com.fs.starfarer.api.campaign.econ.CommoditySpecAPI;
11import com.fs.starfarer.api.campaign.econ.MarketAPI;
12import com.fs.starfarer.api.campaign.rules.MemoryAPI;
13import com.fs.starfarer.api.characters.PersonAPI;
14import com.fs.starfarer.api.impl.campaign.ids.Commodities;
15import com.fs.starfarer.api.impl.campaign.ids.Factions;
16import com.fs.starfarer.api.impl.campaign.ids.Ranks;
17import com.fs.starfarer.api.impl.campaign.ids.Tags;
18import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithBarEvent;
19import com.fs.starfarer.api.impl.campaign.missions.hub.ReqMode;
20import com.fs.starfarer.api.ui.TooltipMakerAPI;
21import com.fs.starfarer.api.util.Misc;
22
23public class CheapCommodityMission extends HubMissionWithBarEvent {
24
25 public static boolean SAME_CONTACT_DEBUG = false;
26
27 public static float MISSION_DAYS = 60f;
28
29 public static float MIN_BASE_VALUE = 10000;
30 public static float MAX_BASE_VALUE = 100000;
31 public static float BASE_PRICE_MULT = 0.75f;
32
33 public static float PROB_REMOTE = 0.5f;
34
35 public static float PROB_BAR_UNDERWORLD = 0.25f;
36 public static float PROB_ILLEGAL_IF_UNDERWORLD = 0.75f;
37 public static float ILLEGAL_QUANTITY_MULT = 0.5f;
38
39
40 public static enum Stage {
41 TALK_TO_PERSON,
42 COMPLETED,
43 FAILED,
44 }
45 public static enum Variation {
46 LOCAL,
47 REMOTE,
48 }
49
50 protected String commodityId;
51 protected int quantity;
52 protected int pricePerUnit;
53
54 protected Variation variation;
55 protected MarketAPI remoteMarket;
56 protected PersonAPI remoteContact;
57
58
59 @Override
60 protected boolean create(MarketAPI createdAt, boolean barEvent) {
61 if (barEvent) {
62 if (rollProbability(PROB_BAR_UNDERWORLD)) {
63 setGiverRank(Ranks.CITIZEN);
64 setGiverPost(pickOne(Ranks.POST_SMUGGLER, Ranks.POST_GANGSTER,
65 Ranks.POST_FENCE, Ranks.POST_CRIMINAL));
66 setGiverImportance(pickImportance());
67 setGiverFaction(Factions.PIRATES);
68 setGiverTags(Tags.CONTACT_UNDERWORLD);
69 } else {
70 setGiverRank(Ranks.CITIZEN);
71 setGiverPost(pickOne(Ranks.POST_TRADER, Ranks.POST_COMMODITIES_AGENT,
72 Ranks.POST_MERCHANT, Ranks.POST_INVESTOR, Ranks.POST_PORTMASTER));
73 setGiverImportance(pickImportance());
74 setGiverTags(Tags.CONTACT_TRADE);
75 }
76 findOrCreateGiver(createdAt, false, false);
77 }
78
79 PersonAPI person = getPerson();
80 if (person == null) return false;
81 MarketAPI market = person.getMarket();
82 if (market == null) return false;
83
84 if (!setPersonMissionRef(person, "$cheapCom_ref")) {
85 return false;
86 }
87
88 if (barEvent) {
89 setGiverIsPotentialContactOnSuccess();
90 }
91
92 PersonImportance importance = person.getImportance();
93 boolean canOfferRemote = importance.ordinal() >= PersonImportance.MEDIUM.ordinal();
94 boolean preferExpensive = getQuality() >= PersonImportance.HIGH.getValue();
95 variation = Variation.LOCAL;
96 if (canOfferRemote && rollProbability(PROB_REMOTE)) {
97 variation = Variation.REMOTE;
98 }
99 if (SAME_CONTACT_DEBUG) variation = Variation.REMOTE;
100
101 CommodityOnMarketAPI com = null;
102 if (variation == Variation.LOCAL) {
103 requireMarketIs(market);
104 requireCommodityIsNotPersonnel();
105 requireCommodityDeficitAtMost(0);
106 requireCommodityAvailableAtLeast(1);
107 requireCommoditySurplusAtLeast(1);
108 if (person.hasTag(Tags.CONTACT_UNDERWORLD) && rollProbability(PROB_ILLEGAL_IF_UNDERWORLD)) {
109 preferCommodityIllegal();
110 } else {
111 requireCommodityLegal();
112 }
113 if (preferExpensive) {
114 preferCommodityTags(ReqMode.ALL, Commodities.TAG_EXPENSIVE);
115 }
116 com = pickCommodity();
117 }
118
119 if (com == null && canOfferRemote) {
120 variation = Variation.REMOTE;
121 }
122
123
124 if (variation == Variation.REMOTE) {
125 requireMarketIsNot(market);
126 requireMarketFaction(market.getFactionId());
127 if (SAME_CONTACT_DEBUG) {
128 requireMarketIs("jangala");
129 }
130 requireCommodityIsNotPersonnel();
131 requireCommodityDeficitAtMost(0);
132 requireCommodityAvailableAtLeast(1);
133 requireCommoditySurplusAtLeast(1);
134 preferMarketInDirectionOfOtherMissions();
135 if (person.hasTag(Tags.CONTACT_UNDERWORLD) && rollProbability(PROB_ILLEGAL_IF_UNDERWORLD)) {
136 preferCommodityIllegal();
137 } else {
138 requireMarketFactionNotHostileTo(Factions.PLAYER);
139 requireCommodityLegal();
140 }
141 if (preferExpensive) {
142 preferCommodityTags(ReqMode.ALL, Commodities.TAG_EXPENSIVE);
143 }
144 com = pickCommodity();
145 if (com != null) remoteMarket = com.getMarket();
146 }
147
148 if (SAME_CONTACT_DEBUG) {
149 com = Global.getSector().getEconomy().getMarket("jangala").getCommodityData(Commodities.ORGANICS);
150 remoteMarket = com.getMarket();
151 }
152
153 if (com == null) return false;
154
155 commodityId = com.getId();
156
157 float value = MIN_BASE_VALUE + (MAX_BASE_VALUE - MIN_BASE_VALUE) * getQuality();
158 quantity = getRoundNumber(value / com.getCommodity().getBasePrice());
159 if (com.isIllegal()) {
161 }
162
163 if (quantity < 10) quantity = 10;
164 pricePerUnit = (int) (com.getMarket().getSupplyPrice(com.getId(), quantity, true) / (float) quantity *
165 BASE_PRICE_MULT / getRewardMult());
166 pricePerUnit = getRoundNumber(pricePerUnit);
167 if (pricePerUnit < 2) pricePerUnit = 2;
168
169
170 if (variation == Variation.REMOTE) {
171 remoteContact = findOrCreateTrader(remoteMarket.getFactionId(), remoteMarket, true);
172 //person = findOrCreateCriminal(market, true);
173 if (remoteContact == null || !setPersonMissionRef(remoteContact, "$cheapCom_ref")) {
174 return false;
175 }
176 setPersonDoGenericPortAuthorityCheck(remoteContact);
177 makeImportant(remoteContact, "$cheapCom_hasCommodity", Stage.TALK_TO_PERSON);
178
179 setStartingStage(Stage.TALK_TO_PERSON);
180 setSuccessStage(Stage.COMPLETED);
181 setFailureStage(Stage.FAILED);
182
183 setStageOnMemoryFlag(Stage.COMPLETED, remoteContact, "$cheapCom_completed");
184 setTimeLimit(Stage.FAILED, MISSION_DAYS, null);
185
186 }
187
188 if (getQuality() < 0.5f) {
189 setRepFactionChangesVeryLow();
190 } else {
191 setRepFactionChangesLow();
192 }
193 setRepPersonChangesMedium();
194
195 return true;
196 }
197
198 protected void updateInteractionDataImpl() {
199 set("$cheapCom_ref2", this);
200
201 set("$cheapCom_barEvent", isBarEvent());
202 set("$cheapCom_underworld", getPerson().hasTag(Tags.CONTACT_UNDERWORLD));
203
204 set("$cheapCom_commodityId", commodityId);
205 set("$cheapCom_commodityName", getSpec().getLowerCaseName());
206 set("$cheapCom_quantity", Misc.getWithDGS(quantity));
207 set("$cheapCom_pricePerUnit", Misc.getDGSCredits(pricePerUnit));
208 set("$cheapCom_totalPrice", Misc.getDGSCredits(pricePerUnit * quantity));
209 set("$cheapCom_variation", variation);
210 set("$cheapCom_manOrWoman", getPerson().getManOrWoman());
211
212 //set("$cheapCom_heOrShe", getPerson().getHeOrShe());
213 //set("$cheapCom_HeOrShe", getPerson().getHeOrShe().substring(0, 1).toUpperCase() + getPerson().getHeOrShe().substring(1));
214
215 //set("$cheapCom_manOrWoman", getPerson().getManOrWoman());
216
217 if (variation == Variation.REMOTE) {
218 set("$cheapCom_personName", remoteContact.getNameString());
219 set("$cheapCom_personPost", remoteContact.getPost().toLowerCase());
220 set("$cheapCom_marketName", remoteMarket.getName());
221 set("$cheapCom_marketOnOrAt", remoteMarket.getOnOrAt());
222 set("$cheapCom_dist", getDistanceLY(remoteMarket));
223 }
224 }
225
226 @Override
227 public void addDescriptionForNonEndStage(TooltipMakerAPI info, float width, float height) {
228 float opad = 10f;
229 Color h = Misc.getHighlightColor();
230 if (currentStage == Stage.TALK_TO_PERSON) {
231 TooltipMakerAPI text = info.beginImageWithText(remoteContact.getPortraitSprite(), 48f);
232 text.addPara("Go to " + remoteMarket.getName() + " and contact " + remoteContact.getNameString() + " to pick up %s units of " +
233 getSpec().getLowerCaseName() + " " +
234 "for %s per unit, or %s total.",
235 0f, h,
236 Misc.getWithDGS(quantity),
237 Misc.getDGSCredits(pricePerUnit),
238 Misc.getDGSCredits(pricePerUnit * quantity));
239 info.addImageWithText(opad);
240 }
241 }
242
243 @Override
244 public boolean addNextStepText(TooltipMakerAPI info, Color tc, float pad) {
245 Color h = Misc.getHighlightColor();
246 if (currentStage == Stage.TALK_TO_PERSON) {
247 info.addPara("Go to " + remoteMarket.getName() + " and contact " + remoteContact.getNameString() + " to arrange pickup", tc, pad);
248 return true;
249 }
250 return false;
251 }
252
253// protected String getMissionTypeNoun() {
254// return "mission";
255// }
256
257 @Override
258 public String getBaseName() {
259 return getSpec().getName() + " Pickup";
260 }
261
262 @Override
263 public void accept(InteractionDialogAPI dialog, Map<String, MemoryAPI> memoryMap) {
264 if (variation == Variation.REMOTE) {
265 super.accept(dialog, memoryMap);
266
267 // papering over a bug for a hotfix - apparently it's possible
268 // for the remote contact to be removed from the comm directory
269 // should be fixed by -RC9, though; possibly save is from RC8
270 if (remoteMarket != null && remoteMarket.getCommDirectory() != null &&
271 remoteMarket.getCommDirectory().getEntryForPerson(remoteContact) == null) {
272 remoteMarket.getCommDirectory().addPerson(remoteContact);
273 }
274 } else {
275 // if it's the local variation, there's no intel item and the commodity/credits etc is handled
276 // in the rules csv. Need to abort here, though, so that mission ref is unset from person memory
277
278 currentStage = new Object(); // so that the abort() assumes the mission was successful
279 abort();
280 }
281 }
282
283 protected transient CommoditySpecAPI spec;
284 protected CommoditySpecAPI getSpec() {
285 if (spec == null) {
287 }
288 return spec;
289 }
290
291 @Override
292 public String getBlurbText() {
293 return null;
294 }
295
296
297
298// if (variation == Variation.REMOTE) {
299// return "There's a surplus of " + getSpec().getLowerCaseName() +
300// " at " + remoteMarket.getName() + " that I can let you have for a good price.";
301// }
302// return "There's a surplus of " + getSpec().getLowerCaseName() + " I can let you have for a good price.";
303}
304
static SettingsAPI getSettings()
Definition Global.java:51
static SectorAPI getSector()
Definition Global.java:59
void accept(InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap)
void addDescriptionForNonEndStage(TooltipMakerAPI info, float width, float height)
boolean addNextStepText(TooltipMakerAPI info, Color tc, float pad)
CommoditySpecAPI getCommoditySpec(String commodityId)