Starsector API
Loading...
Searching...
No Matches
ProcurementMission.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 org.lwjgl.util.vector.Vector2f;
7
8import com.fs.starfarer.api.Global;
9import com.fs.starfarer.api.campaign.InteractionDialogAPI;
10import com.fs.starfarer.api.campaign.PersonImportance;
11import com.fs.starfarer.api.campaign.econ.CommodityOnMarketAPI;
12import com.fs.starfarer.api.campaign.econ.CommoditySpecAPI;
13import com.fs.starfarer.api.campaign.econ.MarketAPI;
14import com.fs.starfarer.api.campaign.rules.MemoryAPI;
15import com.fs.starfarer.api.characters.PersonAPI;
16import com.fs.starfarer.api.impl.campaign.ids.Commodities;
17import com.fs.starfarer.api.impl.campaign.ids.Factions;
18import com.fs.starfarer.api.impl.campaign.ids.FleetTypes;
19import com.fs.starfarer.api.impl.campaign.ids.Ranks;
20import com.fs.starfarer.api.impl.campaign.ids.Tags;
21import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithBarEvent;
22import com.fs.starfarer.api.impl.campaign.missions.hub.ReqMode;
23import com.fs.starfarer.api.ui.TooltipMakerAPI;
24import com.fs.starfarer.api.util.Misc;
25
26public class ProcurementMission extends HubMissionWithBarEvent {
27
28 public static float PROB_COMPLICATIONS = 0.5f;
29
30 public static float MISSION_DAYS = 60f;
31
32 public static float MIN_BASE_VALUE = 10000;
33 public static float MAX_BASE_VALUE = 100000;
34 public static float BASE_PRICE_MULT = 1.5f;
35
36 public static float PROB_REMOTE = 0.5f;
37
38 public static float PROB_BAR_UNDERWORLD = 0.25f;
39 public static float PROB_ILLEGAL_IF_UNDERWORLD = 0.5f;
40 public static float ILLEGAL_QUANTITY_MULT = 0.5f;
41
42
43 public static enum Stage {
44 TALK_TO_PERSON,
45 COMPLETED,
46 FAILED,
47 }
48 public static enum Variation {
49 LOCAL,
50 REMOTE,
51 }
52
53 protected String commodityId;
54 protected int quantity;
55 protected int pricePerUnit;
56
57 protected Variation variation;
58 protected MarketAPI deliveryMarket;
59 protected PersonAPI deliveryContact;
60
61
62 @Override
63 protected boolean create(MarketAPI createdAt, boolean barEvent) {
64 //genRandom = Misc.random;
65 if (barEvent) {
66 if (rollProbability(PROB_BAR_UNDERWORLD)) {
67 setGiverRank(Ranks.CITIZEN);
68 setGiverPost(pickOne(Ranks.POST_SMUGGLER, Ranks.POST_GANGSTER,
69 Ranks.POST_FENCE, Ranks.POST_CRIMINAL));
70 setGiverImportance(pickImportance());
71 setGiverTags(Tags.CONTACT_UNDERWORLD);
72 setGiverFaction(Factions.PIRATES);
73 } else {
74 setGiverRank(Ranks.CITIZEN);
75 String post = pickOne(Ranks.POST_TRADER, Ranks.POST_COMMODITIES_AGENT,
76 Ranks.POST_MERCHANT, Ranks.POST_INVESTOR,
77 Ranks.POST_EXECUTIVE, Ranks.POST_SENIOR_EXECUTIVE,
78 Ranks.POST_PORTMASTER);
79 setGiverPost(post);
80 if (post.equals(Ranks.POST_SENIOR_EXECUTIVE)) {
81 setGiverImportance(pickHighImportance());
82 } else {
83 setGiverImportance(pickImportance());
84 }
85 setGiverTags(Tags.CONTACT_TRADE);
86 }
87 findOrCreateGiver(createdAt, false, false);
88 }
89
90
91 PersonAPI person = getPerson();
92 if (person == null) return false;
93 MarketAPI market = person.getMarket();
94 if (market == null) return false;
95
96 if (!setPersonMissionRef(person, "$proCom_ref")) {
97 return false;
98 }
99
100 if (barEvent) {
101 setGiverIsPotentialContactOnSuccess();
102 }
103
104 PersonImportance importance = person.getImportance();
105 boolean canOfferRemote = importance.ordinal() >= PersonImportance.MEDIUM.ordinal();
106 boolean preferExpensive = getQuality() >= PersonImportance.HIGH.getValue();
107 variation = Variation.LOCAL;
108 if (canOfferRemote && rollProbability(PROB_REMOTE)) {
109 variation = Variation.REMOTE;
110 }
112 variation = Variation.REMOTE;
113 }
114
115 CommodityOnMarketAPI com = null;
116 if (variation == Variation.LOCAL) {
117 requireMarketIs(market);
118 requireCommodityIsNotPersonnel();
119 if (person.hasTag(Tags.CONTACT_UNDERWORLD) && rollProbability(PROB_ILLEGAL_IF_UNDERWORLD)) {
120 preferCommodityIllegal();
121 } else {
122 requireCommodityLegal();
123 requireCommodityDemandAtLeast(1);
124 }
125 requireCommoditySurplusAtMost(0);
126 requireCommodityDeficitAtLeast(1);
127 if (preferExpensive) {
128 preferCommodityTags(ReqMode.ALL, Commodities.TAG_EXPENSIVE);
129 }
130 com = pickCommodity();
131 }
132
133 if (com == null && canOfferRemote) {
134 variation = Variation.REMOTE;
135 }
136
137 if (variation == Variation.REMOTE) {
139 requireMarketIs("jangala");
140 } else {
141 requireMarketIsNot(market);
142 }
143 requireMarketFaction(market.getFactionId());
144 requireMarketNotHidden();
145 requireMarketLocationNot(createdAt.getContainingLocation());
146 requireCommodityIsNotPersonnel();
147 if (person.hasTag(Tags.CONTACT_UNDERWORLD) && rollProbability(PROB_ILLEGAL_IF_UNDERWORLD)) {
148 preferCommodityIllegal();
149 } else {
150 requireMarketFactionNotHostileTo(Factions.PLAYER);
151 requireCommodityLegal();
152 requireCommodityDemandAtLeast(1);
153 }
154 requireCommoditySurplusAtMost(0);
155 requireCommodityDeficitAtLeast(1);
156 if (preferExpensive) {
157 preferCommodityTags(ReqMode.ALL, Commodities.TAG_EXPENSIVE);
158 }
159 com = pickCommodity();
160 }
161
162 if (com == null) return false;
163
164 deliveryMarket = com.getMarket();
165
166 commodityId = com.getId();
167
168 float value = MIN_BASE_VALUE + (MAX_BASE_VALUE - MIN_BASE_VALUE) * getQuality();
169 quantity = getRoundNumber(value / com.getCommodity().getBasePrice());
170 if (com.isIllegal()) {
172 }
173
174 if (quantity < 10) quantity = 10;
175 pricePerUnit = (int) (com.getMarket().getSupplyPrice(com.getId(), quantity, true) / (float) quantity *
176 BASE_PRICE_MULT / getRewardMult());
177 pricePerUnit = getRoundNumber(pricePerUnit);
178 if (pricePerUnit < 2) pricePerUnit = 2;
179
180
181 if (variation == Variation.REMOTE) {
182 if (com.isIllegal()) {
183 deliveryContact = findOrCreateCriminal(deliveryMarket, true);
184 } else {
185 deliveryContact = findOrCreateTrader(deliveryMarket.getFactionId(), deliveryMarket, true);
186 }
187 } else {
188 deliveryContact = person;
189 }
190 ensurePersonIsInCommDirectory(deliveryMarket, deliveryContact);
191 //setPersonIsPotentialContactOnSuccess(deliveryContact);
192
193 if (deliveryContact == null ||
194 (variation == Variation.REMOTE && !setPersonMissionRef(deliveryContact, "$proCom_ref"))) {
195 return false;
196 }
197 setPersonDoGenericPortAuthorityCheck(deliveryContact);
198 makeImportant(deliveryContact, "$proCom_needsCommodity", Stage.TALK_TO_PERSON);
199
200 setStartingStage(Stage.TALK_TO_PERSON);
201 setSuccessStage(Stage.COMPLETED);
202 setFailureStage(Stage.FAILED);
203
204 setStageOnMemoryFlag(Stage.COMPLETED, deliveryContact, "$proCom_completed");
205 setTimeLimit(Stage.FAILED, MISSION_DAYS, null);
206
207
208 if (getQuality() < 0.5f) {
209 setRepFactionChangesVeryLow();
210 } else {
211 setRepFactionChangesLow();
212 }
213 setRepPersonChangesMedium();
214
215 return true;
216 }
217
218 protected void updateInteractionDataImpl() {
219 set("$proCom_barEvent", isBarEvent());
220
221 set("$proCom_commodityId", commodityId);
222 set("$proCom_underworld", getPerson().hasTag(Tags.CONTACT_UNDERWORLD));
223 set("$proCom_playerHasEnough", playerHasEnough(commodityId, quantity));
224 set("$proCom_commodityName", getSpec().getLowerCaseName());
225 set("$proCom_quantity", Misc.getWithDGS(quantity));
226 set("$proCom_pricePerUnit", Misc.getDGSCredits(pricePerUnit));
227 set("$proCom_totalPrice", Misc.getDGSCredits(pricePerUnit * quantity));
228 set("$proCom_variation", variation);
229 set("$proCom_manOrWoman", getPerson().getManOrWoman());
230 //set("$proCom_heOrShe", getPerson().getHeOrShe());
231 //set("$proCom_HeOrShe", getPerson().getHeOrShe().substring(0, 1).toUpperCase() + getPerson().getHeOrShe().substring(1));
232
233
234 if (variation == Variation.REMOTE) {
235 set("$proCom_personName", deliveryContact.getNameString());
236 set("$proCom_personPost", deliveryContact.getPost().toLowerCase());
237 set("$proCom_PersonPost", Misc.ucFirst(deliveryContact.getPost()));
238 set("$proCom_marketName", deliveryMarket.getName());
239 set("$proCom_marketOnOrAt", deliveryMarket.getOnOrAt());
240 set("$proCom_dist", getDistanceLY(deliveryMarket));
241 }
242 }
243
244 @Override
245 public void addDescriptionForNonEndStage(TooltipMakerAPI info, float width, float height) {
246 float opad = 10f;
247 Color h = Misc.getHighlightColor();
248 if (currentStage == Stage.TALK_TO_PERSON) {
249 TooltipMakerAPI text = info.beginImageWithText(deliveryContact.getPortraitSprite(), 48f);
250 text.addPara("Deliver %s units of " + getSpec().getLowerCaseName() + " to " + deliveryContact.getNameString() + " " +
251 deliveryMarket.getOnOrAt() + " " + deliveryMarket.getName() + ". You will be paid %s per unit, or " +
252 "%s total.", 0f, h,
253 Misc.getWithDGS(quantity),
254 Misc.getDGSCredits(pricePerUnit),
255 Misc.getDGSCredits(pricePerUnit * quantity));
256 info.addImageWithText(opad);
257 if (playerHasEnough(commodityId, quantity)) {
258 info.addPara("You have enough " + getSpec().getLowerCaseName() + " in your cargo holds to complete " +
259 "the delivery.", opad);
260 } else {
261 info.addPara("You do not have enough " + getSpec().getLowerCaseName() + " in your cargo holds to complete " +
262 "the delivery.", opad);
263 }
264 }
265 }
266
267// need to mention that need to acquire the item
268// check whether player has enough and chance desc/bullet point depending?
269
270 @Override
271 public boolean addNextStepText(TooltipMakerAPI info, Color tc, float pad) {
272 Color h = Misc.getHighlightColor();
273 if (currentStage == Stage.TALK_TO_PERSON) {
274 if (playerHasEnough(commodityId, quantity)) {
275 info.addPara("Go to " + deliveryMarket.getName() + " and contact " + deliveryContact.getNameString() + " to arrange delivery", tc, pad);
276 } else {
277 String name = getSpec().getLowerCaseName();
278 info.addPara("Acquire %s units of " + name, pad, tc, h, "" + (int) quantity);
279 }
280 return true;
281 }
282 return false;
283 }
284
285 @Override
286 public String getBaseName() {
287 return getSpec().getName() + " Procurement";
288 }
289
290 @Override
291 public void accept(InteractionDialogAPI dialog, Map<String, MemoryAPI> memoryMap) {
292 super.accept(dialog, memoryMap);
293
294 if (variation == Variation.REMOTE && rollProbability(PROB_COMPLICATIONS)) {
295 DelayedFleetEncounter e = new DelayedFleetEncounter(genRandom, getMissionId());
296 e.setDelay(10f);
297 e.setLocationCoreOnly(true, Factions.PIRATES);
299 e.beginCreate();
300 e.triggerCreateFleet(FleetSize.MEDIUM, FleetQuality.DEFAULT, Factions.PIRATES, FleetTypes.PATROL_MEDIUM, new Vector2f());
301 e.triggerSetAdjustStrengthBasedOnQuality(true, getQuality());
302 e.triggerSetStandardAggroPirateFlags();
304 e.triggerSetFleetMemoryValue("$proCom_commodityName", getSpec().getLowerCaseName());
305 e.triggerSetFleetGenericHailPermanent("PROCOMPirateHail");
306 e.endCreate();
307 }
308 }
309
310
311
312 protected transient CommoditySpecAPI spec;
313 protected CommoditySpecAPI getSpec() {
314 if (spec == null) {
316 }
317 return spec;
318 }
319}
320
static SettingsAPI getSettings()
Definition Global.java:51
void triggerCreateFleet(FleetSize size, FleetQuality quality, String factionId, String type, SectorEntityToken roughlyWhere)
void setLocationCoreOnly(boolean allowInsidePopulatedSystems, String requireLargestMarketNotHostileToFaction)
boolean addNextStepText(TooltipMakerAPI info, Color tc, float pad)
void addDescriptionForNonEndStage(TooltipMakerAPI info, float width, float height)
void accept(InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap)
boolean create(MarketAPI createdAt, boolean barEvent)
CommoditySpecAPI getCommoditySpec(String commodityId)