Starsector API
Loading...
Searching...
No Matches
ContactIntel.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.intel.contacts;
2
3import java.awt.Color;
4import java.util.Random;
5import java.util.Set;
6
7import org.lwjgl.input.Keyboard;
8
9import com.fs.starfarer.api.Global;
10import com.fs.starfarer.api.campaign.FactionAPI;
11import com.fs.starfarer.api.campaign.InteractionDialogAPI;
12import com.fs.starfarer.api.campaign.PersonImportance;
13import com.fs.starfarer.api.campaign.SectorEntityToken;
14import com.fs.starfarer.api.campaign.StoryPointActionDelegate;
15import com.fs.starfarer.api.campaign.TextPanelAPI;
16import com.fs.starfarer.api.campaign.comm.IntelInfoPlugin;
17import com.fs.starfarer.api.campaign.econ.MarketAPI;
18import com.fs.starfarer.api.campaign.rules.MemoryAPI;
19import com.fs.starfarer.api.characters.PersonAPI;
20import com.fs.starfarer.api.impl.campaign.DebugFlags;
21import com.fs.starfarer.api.impl.campaign.ids.Conditions;
22import com.fs.starfarer.api.impl.campaign.ids.Factions;
23import com.fs.starfarer.api.impl.campaign.ids.Sounds;
24import com.fs.starfarer.api.impl.campaign.ids.Stats;
25import com.fs.starfarer.api.impl.campaign.ids.Tags;
26import com.fs.starfarer.api.impl.campaign.intel.BaseIntelPlugin;
27import com.fs.starfarer.api.impl.campaign.missions.hub.BaseMissionHub;
28import com.fs.starfarer.api.impl.campaign.rulecmd.SetStoryOption.BaseOptionStoryPointActionDelegate;
29import com.fs.starfarer.api.impl.campaign.rulecmd.SetStoryOption.StoryOptionParams;
30import com.fs.starfarer.api.ui.ButtonAPI;
31import com.fs.starfarer.api.ui.IntelUIAPI;
32import com.fs.starfarer.api.ui.LabelAPI;
33import com.fs.starfarer.api.ui.SectorMapAPI;
34import com.fs.starfarer.api.ui.TooltipMakerAPI;
35import com.fs.starfarer.api.ui.TooltipMakerAPI.TooltipCreator;
36import com.fs.starfarer.api.ui.TooltipMakerAPI.TooltipLocation;
37import com.fs.starfarer.api.ui.UIComponentAPI;
38import com.fs.starfarer.api.util.IntervalUtil;
39import com.fs.starfarer.api.util.Misc;
40import com.fs.starfarer.api.util.WeightedRandomPicker;
41
42public class ContactIntel extends BaseIntelPlugin {
43
44 public static enum ContactState {
45 POTENTIAL,
46 NON_PRIORITY,
47 PRIORITY,
48 SUSPENDED,
49 LOST_CONTACT_DECIV,
50 LOST_CONTACT,
51 }
52
53
54 public static String NO_CONTACTS_ON_MARKET = "$core_noContactsOnMarket";
55
56 public static float MAX_NUM_MISSIONS_BONUS = Global.getSettings().getFloat("priorityContactMaxNumMissionsBonus");
57 public static float MAX_MISSION_QUALITY_BONUS = Global.getSettings().getFloat("priorityContactMaxMissionQualityBonus");
58 public static float DEFAULT_POTENTIAL_CONTACT_PROB = Global.getSettings().getFloat("defaultPotentialContactProbability");
59 public static float ADD_PER_FAIL = Global.getSettings().getFloat("potentialContactProbabilityAddPerFail");
60 public static float DAYS_AT_PRIORITY_FOR_FULL_EFFECT = 30;
61
62 public static String UPDATE_RELOCATED_CONTACT = "update_relocated_contact";
63 public static String UPDATE_LOST_CONTACT = "update_lost_contact";
64
65 public static String BUTTON_DEVELOP = "button_develop";
66 public static String BUTTON_SUSPEND = "button_suspend";
67 public static String BUTTON_DELETE = "button_delete";
68
69 public static String BUTTON_PRIORITY = "button_priority";
70
71 public static float DURATION = 30f;
72 public static boolean POTENTIAL_EXPIRES = false;
73
74 protected ContactState state = ContactState.POTENTIAL;
75 protected PersonAPI person;
76 protected MarketAPI market;
77 protected FactionAPI marketFaction;
78 //protected CampaignFleetAPI fleet;
79
80 protected Boolean wasAddedToCommDirectory = null;
81 protected Boolean wasAddedToMarket = null;
82
83 protected boolean hadMissionHub;
84 protected boolean marketWasDeciv;
85
86 protected IntervalUtil tracker = new IntervalUtil(0.75f, 1.25f);
87 protected int numPriorityInARow = 0;
88
89 public ContactIntel(PersonAPI person, MarketAPI market) {
90 this.person = person;
91 this.market = market;
92 marketFaction = market.getFaction();
93 //person.setMarket(market); // if set here, it can get unset in BaseHubMission.endSuccess()->abort()
94 marketWasDeciv = market.hasCondition(Conditions.DECIVILIZED);
95 if (!Global.getSector().getScripts().contains(this)) {
96 Global.getSector().addScript(this);
97 }
98
99 setImportant(true);
100 }
101
102// public ContactIntel(PersonAPI person, CampaignFleetAPI fleet) {
103// this.person = person;
104// this.fleet = fleet;
105// if (!Global.getSector().getScripts().contains(this)) {
106// Global.getSector().addScript(this);
107// }
108// }
109
110 protected void ensureHasMissionHub() {
111 hadMissionHub = BaseMissionHub.get(person) != null;
112 if (BaseMissionHub.get(person) == null) {
113 BaseMissionHub.set(person, new BaseMissionHub(person));
114 }
115 }
116 protected void ensureIsInCommDirectory() {
117 if (market == null) return;
118 if (market.getCommDirectory() == null) return;
119 if (market.getCommDirectory().getEntryForPerson(person) != null) return;
120
121 market.getCommDirectory().addPerson(person);
123 }
124
125 public void advanceImpl(float amount) {
126 float days = Global.getSector().getClock().convertToDays(amount);
127 tracker.advance(days);
128 if (tracker.intervalElapsed()) {
130 }
131 }
132
136
137 protected MarketAPI findMarketToRelocateTo() {
138 if (market == null) return null;
139
140 if (person.getImportance() == PersonImportance.VERY_LOW) return null;
141 Random random = new Random(Misc.getSalvageSeed(market.getPrimaryEntity()));
142 WeightedRandomPicker<MarketAPI> picker = new WeightedRandomPicker<MarketAPI>(random);
143 for (MarketAPI curr : Global.getSector().getEconomy().getMarketsInGroup(market.getEconGroup())) {
144 if (curr == market) continue;
145 if (!curr.getFactionId().equals(market.getFactionId())) continue;
146 if (curr.hasCondition(Conditions.DECIVILIZED)) continue;
147 picker.add(curr, market.getSize());
148 }
149 return picker.pick();
150 }
151
152 protected void unsetFlags() {
153 MemoryAPI memory = person.getMemoryWithoutUpdate();
154 memory.unset(BaseMissionHub.NUM_BONUS_MISSIONS);
155 memory.unset(BaseMissionHub.MISSION_QUALITY_BONUS);
156 memory.unset(BaseMissionHub.CONTACT_SUSPENDED);
157 }
158
159 public void loseContact(InteractionDialogAPI dialog) {
160 //endAfterDelay();
161 state = ContactState.LOST_CONTACT;
162 if (dialog != null) {
163 sendUpdate(UPDATE_LOST_CONTACT, dialog.getTextPanel());
164 } else {
166 }
168 }
169
170 public void doPeriodicCheck() {
171 if (isEnded() || isEnding()) return;
172
173
174 MemoryAPI memory = person.getMemoryWithoutUpdate();
175 unsetFlags();
176
177 if (state != ContactState.LOST_CONTACT_DECIV && state != ContactState.LOST_CONTACT && market != null) {
178 if (!marketWasDeciv && (market.hasCondition(Conditions.DECIVILIZED) || !market.isInEconomy())) {
179 MarketAPI other = findMarketToRelocateTo();
180 if (other == null) {
182 state = ContactState.LOST_CONTACT_DECIV;
184 } else {
185 relocateToMarket(other, true);
186 }
187 return;
188 }
189 }
190 if (state == ContactState.LOST_CONTACT) return;
191 if (state == ContactState.POTENTIAL) return;
192 if (state == ContactState.SUSPENDED) {
193 memory.set(BaseMissionHub.CONTACT_SUSPENDED, true);
194 return;
195 }
196
197 if (state == ContactState.PRIORITY) {
199 } else {
201 }
202 if (numPriorityInARow < 0) {
206 }
207
208
209 float bonusMissions = getPriorityMult() * MAX_NUM_MISSIONS_BONUS;
210 if (bonusMissions > 0) {
211 memory.set(BaseMissionHub.NUM_BONUS_MISSIONS, bonusMissions);
212 }
213
214 float bonusQuality = getPriorityMult() * MAX_MISSION_QUALITY_BONUS;
215 if (bonusQuality > 0) {
216 memory.set(BaseMissionHub.MISSION_QUALITY_BONUS, bonusMissions);
217 }
218 }
219
220 public void relocateToMarket(MarketAPI other, boolean withIntelUpdate) {
221 if (wasAddedToCommDirectory != null && wasAddedToCommDirectory && market != null && market.getCommDirectory() != null) {
222 market.getCommDirectory().removePerson(person);
224 }
225 market = other;
226 person.setMarket(other);
227 marketWasDeciv = other.hasCondition(Conditions.DECIVILIZED);
230 person.setImportance(person.getImportance().prev());
231 if (withIntelUpdate) {
233 }
234 }
235
236
237 public float getPriorityMult() {
238 float priority = getPriorityContacts();
239 if (priority < 1f) priority = 1f;
240 return ((float) numPriorityInARow / (float) DAYS_AT_PRIORITY_FOR_FULL_EFFECT) / priority;
241 }
242
243
244 @Override
245 public void reportPlayerClickedOn() {
246 super.reportPlayerClickedOn();
247 }
248
249
250 @Override
251 protected void notifyEnding() {
252 super.notifyEnding();
253 if (wasAddedToCommDirectory != null && wasAddedToCommDirectory && market != null && market.getCommDirectory() != null) {
254 market.getCommDirectory().removePerson(person);
256 }
257 if (wasAddedToMarket != null && wasAddedToMarket) {
258 market.removePerson(person);
259 }
260
261 if (!hadMissionHub) {
262 BaseMissionHub.set(person, null);
263 }
264
265 unsetFlags();
266 }
267
268 @Override
269 public void reportRemovedIntel() {
270 super.reportRemovedIntel();
271 Global.getSector().removeScript(this);
272 }
273
274 public boolean shouldRemoveIntel() {
275 if (isEnded()) return true;
276 if (state != ContactState.POTENTIAL) return false;
277 float days = getDaysSincePlayerVisible();
278 if (days >= DURATION && POTENTIAL_EXPIRES) {
279 ended = true;
280 return true;
281 }
282 return false;
283 }
284
285 public String getName() {
286 if (state == ContactState.LOST_CONTACT_DECIV) {
287 return "Lost Contact: " + person.getNameString();
288 } else if (state == ContactState.LOST_CONTACT) {
289 return "Lost Contact: " + person.getNameString();
290 } else if (state == ContactState.POTENTIAL) {
291 return "Potential Contact: " + person.getNameString();
292 } else if (state == ContactState.SUSPENDED) {
293 return "Suspended Contact: " + person.getNameString();
294 } else if (state == ContactState.PRIORITY) {
295 return "Priority Contact: " + person.getNameString();
296 }
297 return "Contact: " + person.getNameString();
298 }
299
300 @Override
301 public String getSortString() {
302 if (state == ContactState.POTENTIAL) {
303 return "Contact2";
304 } else if (state == ContactState.SUSPENDED) {
305 return "Contact3";
306 } else if (state == ContactState.PRIORITY) {
307 return "Contact0";
308 }
309 return "Contact1";
310 }
311
312 public String getSmallDescriptionTitle() {
313 return getName();
314 }
315
316 @Override
317 public void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode) {
318 Color c = getTitleColor(mode);
319 info.addPara(getName(), c, 0f);
320 addBulletPoints(info, mode);
321 }
322
323 protected void addTypePara(TooltipMakerAPI info, Color tc, float pad) {
324 Color h = Misc.getHighlightColor();
325 String [] tags = person.getSortedContactTagStrings().toArray(new String [0]);
326 if (tags.length <= 0) return;
327 String str = "Type: ";
328 for (String tag : tags) {
329 str += tag + ", ";
330 }
331 if (tags.length > 0) {
332 str = str.substring(0, str.length() - 2);
333 }
334 info.addPara(str, pad, tc, h, tags);
335 }
336
337 protected void addFactionPara(TooltipMakerAPI info, Color tc, float pad) {
338 //String faction = Misc.ucFirst(person.getFaction().getDisplayName());
339 String faction = person.getFaction().getDisplayName();
340 String str = "Faction: " + faction;
341
342 info.addPara(str, pad, tc, person.getFaction().getBaseUIColor(), faction);
343 }
344
345 protected void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode) {
346 Color h = Misc.getHighlightColor();
347 Color g = Misc.getGrayColor();
348 Color tc = getBulletColorForMode(mode);
349
350 float pad = 3f;
351 float opad = 10f;
352
353 float initPad = pad;
354 if (mode == ListInfoMode.IN_DESC) initPad = opad;
355
356 bullet(info);
357
359 info.addPara("Relocated to " + market.getName(), tc, initPad);
360 initPad = 0f;
361 info.addPara("Importance reduced to: %s", initPad, tc, h, person.getImportance().getDisplayName());
362 initPad = 0f;
363 unindent(info);
364 return;
365 }
366 if (state == ContactState.LOST_CONTACT_DECIV) {
367 if (mode != ListInfoMode.IN_DESC) {
368 info.addPara(market.getName() + " decivilized", tc, initPad);
369 initPad = 0f;
370 }
371 unindent(info);
372 return;
373 }
374
375 if (state == ContactState.LOST_CONTACT) {
376 unindent(info);
377 return;
378 }
379
380 addFactionPara(info, tc, initPad);
381 initPad = 0f;
382
383 addTypePara(info, tc, initPad);
384 initPad = 0f;
385
386 if (mode != ListInfoMode.IN_DESC) {
387 info.addPara("Importance: %s", initPad, tc, h, person.getImportance().getDisplayName());
388 initPad = 0f;
389
390 if (state == ContactState.PRIORITY || state == ContactState.NON_PRIORITY || state == ContactState.SUSPENDED) {
391 long ts = BaseMissionHub.getLastOpenedTimestamp(person);
392 if (ts <= Long.MIN_VALUE) {
393 //info.addPara("Never visited.", opad);
394 } else {
395 info.addPara("Last visited: %s.", initPad, tc, h, Misc.getDetailedAgoString(ts));
396 initPad = 0f;
397 }
398 }
399 }
400
401// info.addPara("Rank: %s", initPad, tc, h, person.getRank());
402// initPad = 0f;
403
404// info.addPara("Post: %s", initPad, tc, h, person.getPost());
405// initPad = 0f;
406
407 if (state == ContactState.POTENTIAL && POTENTIAL_EXPIRES) {
408 if (mode != ListInfoMode.IN_DESC) {
409 float days = DURATION - getDaysSincePlayerVisible();
410 info.addPara("%s " + getDaysString(days) + " left to develop",
411 initPad, tc, h, getDays(days));
412 initPad = 0f;
413 }
414 }
415
416 //info.addPara("Personality: %s", initPad, tc, h, pName);
417 unindent(info);
418 }
419
420 @Override
421 public void createSmallDescription(TooltipMakerAPI info, float width, float height) {
422 String pName = Misc.getPersonalityName(person);
423
424 Color h = Misc.getHighlightColor();
425 Color g = Misc.getGrayColor();
426 Color tc = Misc.getTextColor();
427 float pad = 3f;
428 float opad = 10f;
429
430 //info.addImage(person.getPortraitSprite(), width, 128, opad);
431
432 FactionAPI faction = person.getFaction();
433 info.addImages(width, 128, opad, opad, person.getPortraitSprite(), faction.getCrest());
434
435 float relBarWidth = 128f * 2f + 10f;
436 float importanceBarWidth = relBarWidth;
437
438 float indent = 25;
439 info.addSpacer(0).getPosition().setXAlignOffset(indent);
440
441 //info.addRelationshipBar(person, relBarWidth, opad);
442
443 relBarWidth = (relBarWidth - 10f) / 2f;
444 info.addRelationshipBar(person, relBarWidth, opad);
445 float barHeight = info.getPrev().getPosition().getHeight();
446 info.addRelationshipBar(person.getFaction(), relBarWidth, 0f);
447 UIComponentAPI prev = info.getPrev();
448 prev.getPosition().setYAlignOffset(barHeight);
449 prev.getPosition().setXAlignOffset(relBarWidth + 10f);
450 info.addSpacer(0f);
451 info.getPrev().getPosition().setXAlignOffset(-(relBarWidth + 10f));
452
453 info.addImportanceIndicator(person.getImportance(), importanceBarWidth, opad);
455// faction = Global.getSector().getPlayerFaction();
456// ButtonAPI button = info.addAreaCheckbox("Priority contact", BUTTON_PRIORITY, faction.getBaseUIColor(),
457// faction.getDarkUIColor(), faction.getBrightUIColor(), relBarWidth, 25f, opad);
458// button.setChecked(state == ContactState.PRIORITY);
459// faction = person.getFaction();
460 info.addSpacer(0).getPosition().setXAlignOffset(-indent);
461
462 if (state == ContactState.NON_PRIORITY || state == ContactState.PRIORITY) {
463 //info.addSpacer(0).getPosition().setXAlignOffset(indent);
464 faction = Global.getSector().getPlayerFaction();
465 ButtonAPI button = info.addAreaCheckbox("Priority contact", BUTTON_PRIORITY, faction.getBaseUIColor(),
466 faction.getDarkUIColor(), faction.getBrightUIColor(), width, 25f, opad);
467 button.setChecked(state == ContactState.PRIORITY);
468 addPriorityTooltip(info);
469 faction = person.getFaction();
470 //info.addSpacer(0).getPosition().setXAlignOffset(-indent);
471 }
472
473 if (market != null && state == ContactState.LOST_CONTACT_DECIV) {
474 info.addPara(person.getNameString() + " was " +
475 person.getPostArticle() + " " + person.getPost().toLowerCase() +
476 " " + market.getOnOrAt() + " " + market.getName() +
477 ", a colony controlled by " + marketFaction.getDisplayNameWithArticle() + ".",
478 opad, marketFaction.getBaseUIColor(),
479 Misc.ucFirst(marketFaction.getDisplayNameWithArticleWithoutArticle()));
480 info.addPara("This colony has decivilized, and you've since lost contact with " + person.getHimOrHer() + ".", opad);
481 } else if (state == ContactState.LOST_CONTACT) {
482 info.addPara("You've lost this contact.", opad);
483 } else {
484 if (market != null) {
485 LabelAPI label = info.addPara(person.getNameString() + " is " +
486 person.getPostArticle() + " " + person.getPost().toLowerCase() +
487 " and can be found " + market.getOnOrAt() + " " + market.getName() +
488 ", a size %s colony controlled by " + market.getFaction().getDisplayNameWithArticle() + ".",
489 opad, market.getFaction().getBaseUIColor(),
490 "" + (int)market.getSize(), market.getFaction().getDisplayNameWithArticleWithoutArticle());
491 label.setHighlightColors(h, market.getFaction().getBaseUIColor());
492// LabelAPI label = info.addPara(Misc.ucFirst(person.getPost().toLowerCase()) +
493// ", found " + market.getOnOrAt() + " " + market.getName() +
494// ", a size %s colony controlled by " + market.getFaction().getDisplayNameWithArticle() + ".",
495// opad, market.getFaction().getBaseUIColor(),
496// "" + (int)market.getSize(), Misc.ucFirst(market.getFaction().getPersonNamePrefix()));
497// label.setHighlightColors(h, market.getFaction().getBaseUIColor());
498 }
499 }
500
501 if (state == ContactState.POTENTIAL){
502 info.addPara("If this contact is developed, " + person.getHeOrShe() + " will periodically " +
503 "have work for you. As the relationship improves, you may gain " +
504 "access to better opportunities.", opad);
505 } else if (state == ContactState.SUSPENDED) {
506 info.addPara("Your contact with " + person.getNameString() + " is currently suspended.", Misc.getNegativeHighlightColor(), opad);
507 }
508
509 addBulletPoints(info, ListInfoMode.IN_DESC);
510
511
512 if (state == ContactState.PRIORITY || state == ContactState.NON_PRIORITY || state == ContactState.SUSPENDED) {
513
514
515 long ts = BaseMissionHub.getLastOpenedTimestamp(person);
516 if (ts <= Long.MIN_VALUE) {
517 //info.addPara("Never visited.", opad);
518 } else {
519 info.addPara("Last visited: %s.", opad, h, Misc.getDetailedAgoString(ts));
520 }
521
522// Color color = faction.getBaseUIColor();
523// Color dark = faction.getDarkUIColor();
524// info.addSectionHeading("Personality traits", color, dark, Alignment.MID, opad);
525// info.addPara("Suspicous Ambitious", opad, h, "Suspicous", "Ambitious");
526// info.addPara("Ambitious: will offer missions that further their advancement more frequently. Refusing " +
527// "these missions will damage the relationship.", opad, h, "Ambitious:");
528// info.addPara("Suspicous: reduced reputation gains.", opad, h, "Suspicous:");
529
530 }
531
532
533 Color color = Misc.getStoryOptionColor();
534 Color dark = Misc.getStoryDarkColor();
535
536 TooltipCreator noDeleteTooltip = new TooltipCreator() {
537 public boolean isTooltipExpandable(Object tooltipParam) {
538 return false;
539 }
540 public float getTooltipWidth(Object tooltipParam) {
541 return TOOLTIP_WIDTH;
542 }
543
544 public void createTooltip(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) {
545 tooltip.addPara("Can not delete or suspend contact at this time.", 0f);
546 }
547 };
548
549 if (state == ContactState.POTENTIAL || state == ContactState.SUSPENDED){
550 if (state == ContactState.POTENTIAL && POTENTIAL_EXPIRES) {
551 float days = DURATION - getDaysSincePlayerVisible();
552 info.addPara("The opportunity to develop this contact will be available for %s more " + getDaysString(days) + ".",
553 opad, tc, h, getDays(days));
554 }
555
556
557 int max = getMaxContacts();
558 int curr = getCurrentContacts();
559
560 info.addPara("Active contacts: %s %s %s", opad,
561 h, "" + curr, "/", "" + max);
562
563 ButtonAPI develop = null;
564 String developText = "Develop contact";
565 if (state == ContactState.SUSPENDED) developText = "Resume contact";
566 if (curr >= max) {
567// info.addPara("Developing contacts above the maximum will " +
568// "require a story point per additional contact.", opad,
569// Misc.getStoryOptionColor(), "story point");
570 develop = addGenericButton(info, width, color, dark, developText, BUTTON_DEVELOP);
571 addDevelopTooltip(info);
572 } else {
573 develop = addGenericButton(info, width, developText, BUTTON_DEVELOP);
574 }
575 develop.setShortcut(Keyboard.KEY_T, true);
576 } else if (state == ContactState.NON_PRIORITY || state == ContactState.PRIORITY) {
577 ButtonAPI suspend = addGenericButton(info, width, color, dark, "Suspend contact", BUTTON_SUSPEND);
578 suspend.setShortcut(Keyboard.KEY_U, true);
579 if (Global.getSector().getIntel().isInShowMap()) {
580 suspend.setEnabled(false);
581 info.addTooltipToPrevious(noDeleteTooltip, TooltipLocation.LEFT);
582 }
583 }
584
585 info.addSpacer(-10f);
586 ButtonAPI delete = addGenericButton(info, width, "Delete contact", BUTTON_DELETE);
587 if (Global.getSector().getIntel().isInShowMap()) {
588 delete.setEnabled(false);
589 info.addTooltipToPrevious(noDeleteTooltip, TooltipLocation.LEFT);
590 }
591 delete.setShortcut(Keyboard.KEY_G, true);
592 }
593
594
595 @Override
596 public void buttonPressConfirmed(Object buttonId, IntelUIAPI ui) {
597 if (buttonId == BUTTON_DEVELOP) {
598 develop(ui);
599 Global.getSoundPlayer().playUISound("ui_contact_developed", 1f, 1f);
600 } else if (buttonId == BUTTON_PRIORITY) {
601 if (state == ContactState.NON_PRIORITY) {
602 state = ContactState.PRIORITY;
603 } else if (state == ContactState.PRIORITY) {
604 state = ContactState.NON_PRIORITY;
605 }
606 ui.updateUIForItem(this);
607 } else if (buttonId == BUTTON_DELETE) {
609 ui.recreateIntelUI();
610 //Global.getSector().getCampaignUI().showCoreUITab(CoreUITabId.CARGO);
611 }
612 }
613
614 public void storyActionConfirmed(Object buttonId, IntelUIAPI ui) {
615 if (buttonId == BUTTON_DEVELOP) {
616 develop(ui);
617 } else if (buttonId == BUTTON_SUSPEND) {
618 state = ContactState.SUSPENDED;
619 person.getMemoryWithoutUpdate().set(BaseMissionHub.CONTACT_SUSPENDED, true);
620 ui.updateUIForItem(this);
621 }
622 }
623
624 public void ensureIsAddedToMarket() {
625 if (market == null) return;
626
627 boolean hadPerson = market.getPeopleCopy().contains(person) || market == person.getMarket();
628
629 if (person.getMarket() != null) {
630 person.getMarket().removePerson(person);
631 }
632
633 if (market.getPeopleCopy().contains(person)) return;
634 market.addPerson(person);
635 if (!hadPerson) wasAddedToMarket = true;
636 }
637 public void develop(IntelUIAPI ui) {
641
642 state = ContactState.NON_PRIORITY;
643 if (ui != null) {
644 ui.updateUIForItem(this);
645 }
646 person.getMemoryWithoutUpdate().unset(BaseMissionHub.CONTACT_SUSPENDED);
647 }
648
649 @Override
650 public void createConfirmationPrompt(Object buttonId, TooltipMakerAPI prompt) {
651 prompt.setParaInsigniaLarge();
652 if (buttonId == BUTTON_DELETE) {
653 if (state == ContactState.POTENTIAL) {
654 prompt.addPara("Are you sure? Deleting a potential contact can not be undone.", 0f);
655 } else if (state == ContactState.SUSPENDED) {
656 prompt.addPara("Are you sure? Deleting a contact can not be undone.", 0f);
657 } else {
658 prompt.addPara("Are you sure? Deleting a contact can not be undone. " +
659 "To stop receiving missions from a contact, but not lose them permanently, you can \"suspend\" the contact instead.", 0f);
660 }
661 return;
662 } else if (buttonId == BUTTON_DEVELOP) {
663 prompt.addPara("Develop a relationship with this contact?", 0f);
664 return;
665 }
666 super.createConfirmationPrompt(buttonId, prompt);
667 return;
668 }
669
670 @Override
671 public boolean doesButtonHaveConfirmDialog(Object buttonId) {
672 if (buttonId == BUTTON_DELETE) return true;
673 if (buttonId == BUTTON_DEVELOP) return true;
674 return super.doesButtonHaveConfirmDialog(buttonId);
675 }
676
677 public StoryPointActionDelegate getButtonStoryPointActionDelegate(Object buttonId) {
678 if (buttonId == BUTTON_DEVELOP && developRequiresStoryPoint()) {
679 StoryOptionParams params = new StoryOptionParams(null, 1, "developContactOverMax",
680 Sounds.STORY_POINT_SPEND,
681 "Developed additional contact (" + person.getNameString() + ")");
682 return new BaseOptionStoryPointActionDelegate(null, params) {
683 @Override
684 public void confirm() {
685 }
686
687 @Override
688 public String getTitle() {
689 return null;
690 }
691 @Override
692 public void createDescription(TooltipMakerAPI info) {
693 //info.setParaInsigniaLarge();
694 super.createDescription(info);
695 }
696 };
697 }
698 if (buttonId == BUTTON_SUSPEND) {
699 StoryOptionParams params = new StoryOptionParams(null, 1, "suspendContact",
700 Sounds.STORY_POINT_SPEND,
701 "Suspended contact (" + person.getNameString() + ")");
702 return new BaseOptionStoryPointActionDelegate(null, params) {
703 @Override
704 public void confirm() {
705 }
706
707 @Override
708 public String getTitle() {
709 return null;
710 }
711 @Override
712 public void createDescription(TooltipMakerAPI info) {
713 info.setParaInsigniaLarge();
714 info.addPara("If suspended, this contact will not offer you missions and will not " +
715 "count against the maximum number of contacts. You will be able to re-develop this " +
716 "contact at any time.", -10f);
717 info.addSpacer(20f);
718 super.createDescription(info);
719 }
720 };
721 }
722 return null;
723 }
724
725
726 @Override
727 public String getIcon() {
728 return person.getPortraitSprite();
729 }
730
731 @Override
732 public Set<String> getIntelTags(SectorMapAPI map) {
733 Set<String> tags = super.getIntelTags(map);
734 tags.add(Tags.INTEL_CONTACTS);
735 return tags;
736 }
737
738 @Override
739 public String getCommMessageSound() {
740 return super.getCommMessageSound();
741 //return getSoundMajorPosting();
742 }
743
744 @Override
745 public FactionAPI getFactionForUIColors() {
746 return person.getFaction();
747 //return super.getFactionForUIColors();
748 }
749
750 public PersonAPI getPerson() {
751 return person;
752 }
753
754 public void setPerson(PersonAPI person) {
755 this.person = person;
756 }
757
758 public ContactState getState() {
759 return state;
760 }
761
762 public void setState(ContactState state) {
763 this.state = state;
764 }
765
766 protected boolean developRequiresStoryPoint() {
768 }
769
770 @Override
771 public SectorEntityToken getMapLocation(SectorMapAPI map) {
772 if (market != null) {
773 return market.getPrimaryEntity();
774 }
775 return null;
776 }
777
778 public static float TOOLTIP_WIDTH = 400f;
779 protected void addImportanceTooltip(TooltipMakerAPI info) {
780 info.addTooltipToPrevious(new TooltipCreator() {
781 public boolean isTooltipExpandable(Object tooltipParam) {
782 return false;
783 }
784 public float getTooltipWidth(Object tooltipParam) {
785 return TOOLTIP_WIDTH;
786 }
787 public void createTooltip(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) {
788 tooltip.addPara("The importance of this person in whatever hierarchy or social structure they " +
789 "belong to. A more highly placed or connected individual will have more difficult - " +
790 "and more profitable - missions and opportunities to offer.", 0f);
791 }
792 }, TooltipLocation.LEFT);
793 }
794 protected void addPriorityTooltip(TooltipMakerAPI info) {
795 info.addTooltipToPrevious(new TooltipCreator() {
796 public boolean isTooltipExpandable(Object tooltipParam) {
797 return false;
798 }
799 public float getTooltipWidth(Object tooltipParam) {
800 return TOOLTIP_WIDTH;
801 } public void createTooltip(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) {
802 float opad = 10f;
803 tooltip.addPara("Whether cultivating a relationship with this contact is a priority for you. " +
804 "Priority contacts will have more missions available, and the missions will be of a " +
805 "higher quality.", 0f);
806 tooltip.addPara("The more priority contacts you have, the less the impact there is on each individual contact.", opad);
807 tooltip.addPara("It takes about a month for changes in priority status to take full effect.", opad);
808 }
809 }, TooltipLocation.LEFT);
810 }
811 protected void addDevelopTooltip(TooltipMakerAPI info) {
812 info.addTooltipToPrevious(new TooltipCreator() {
813 public boolean isTooltipExpandable(Object tooltipParam) {
814 return false;
815 }
816 public float getTooltipWidth(Object tooltipParam) {
817 return TOOLTIP_WIDTH;
818 }
819 public void createTooltip(TooltipMakerAPI tooltip, boolean expanded, Object tooltipParam) {
820 tooltip.addPara("Developing contacts above the maximum " +
821 "requires a story point for each additional contact.", 0f,
822 Misc.getStoryOptionColor(), "story point");
823 }
824 }, TooltipLocation.LEFT);
825 }
826
827
828 public static int getMaxContacts() {
829 int base = Global.getSettings().getInt("maxContacts");
830 int max = (int) Global.getSector().getPlayerStats().getDynamic().getMod(Stats.NUM_MAX_CONTACTS_MOD).computeEffective(base);
831 return max;
832 }
833
834 public static int getCurrentContacts() {
835 int count = 0;
836 for (IntelInfoPlugin intel : Global.getSector().getIntelManager().getIntel(ContactIntel.class)) {
837 if (intel.isEnding() || intel.isEnded()) continue;
838 if (((ContactIntel)intel).getState() == ContactState.POTENTIAL) continue;
839 if (((ContactIntel)intel).getState() == ContactState.SUSPENDED) continue;
840 if (((ContactIntel)intel).getState() == ContactState.LOST_CONTACT_DECIV) continue;
841 if (((ContactIntel)intel).getState() == ContactState.LOST_CONTACT) continue;
842 count++;
843 }
844 return count;
845 }
846
847 public static int getPriorityContacts() {
848 int count = 0;
849 for (IntelInfoPlugin intel : Global.getSector().getIntelManager().getIntel(ContactIntel.class)) {
850 if (intel.isEnding() || intel.isEnded()) continue;
851 if (((ContactIntel)intel).getState() != ContactState.PRIORITY) continue;
852 count++;
853 }
854 return count;
855 }
856
857 public static boolean playerHasIntelItemForContact(PersonAPI person) {
858 for (IntelInfoPlugin intel : Global.getSector().getIntelManager().getIntel(ContactIntel.class)) {
859 if (((ContactIntel)intel).getPerson() == person) {
860 return true;
861 }
862 }
863 return false;
864 }
865
866 public static boolean playerHasContact(PersonAPI person, boolean includePotential) {
867 for (IntelInfoPlugin intel : Global.getSector().getIntelManager().getIntel(ContactIntel.class)) {
868 if (((ContactIntel)intel).getPerson() == person) {
869 ContactState state = ((ContactIntel)intel).getState();
870 if (state == ContactState.POTENTIAL && !includePotential) {
871 continue;
872 }
873 if (state == ContactState.LOST_CONTACT || state == ContactState.LOST_CONTACT_DECIV) {
874 continue;
875 }
876 return true;
877 }
878 }
879 return false;
880 }
881
882 public static ContactIntel getContactIntel(PersonAPI person) {
883 for (IntelInfoPlugin intel : Global.getSector().getIntelManager().getIntel(ContactIntel.class)) {
884 if (((ContactIntel)intel).getPerson() == person) return (ContactIntel)intel;
885 }
886 return null;
887 }
888
889 public static void removeContact(PersonAPI person, InteractionDialogAPI dialog) {
890 if (person == null) return;
892 if (intel != null) {
893 intel.loseContact(dialog);
894 }
895 }
896
897 public static void addPotentialContact(PersonAPI contact, MarketAPI market, TextPanelAPI text) {
899 }
900 public static void addPotentialContact(float probability, PersonAPI contact, MarketAPI market, TextPanelAPI text) {
901 if (playerHasIntelItemForContact(contact)) return;
902 if (contact.getFaction().isPlayerFaction()) return;
903 if (market == null) return;
904 if (market != null && market.getMemoryWithoutUpdate().getBoolean(NO_CONTACTS_ON_MARKET)) return;
905 if (contact != null && contact.getFaction().getCustomBoolean(Factions.CUSTOM_NO_CONTACTS)) return;
906
907 Random random = new Random(getContactRandomSeed(contact));
908 // if the player already has some existing relationship with the person, use it to
909 // modify the probability they'll be available as a potential contact
910 probability += contact.getRelToPlayer().getRel();
911
912
913 String key = "$potentialContactRollFails";
914 MemoryAPI mem = Global.getSector().getMemoryWithoutUpdate();
915 float fails = mem.getInt(key);
916 probability += ADD_PER_FAIL * fails;
917
918 if (random.nextFloat() >= probability && !DebugFlags.ALWAYS_ADD_POTENTIAL_CONTACT) {
919 fails++;
920 mem.set(key, fails);
921 return;
922 }
923
924 mem.set(key, 0);
925
926
927 ContactIntel intel = new ContactIntel(contact, market);
928 Global.getSector().getIntelManager().addIntel(intel, false, text);
929 }
930
931
932 public static long getContactRandomSeed(PersonAPI person) {
933 String id = person.getId();
934 if (id == null) id = Misc.genUID();
935 long seed = Misc.seedUniquifier() ^ (person.getId().hashCode() * 17000);
936 Random r = new Random(seed);
937 for (int i = 0; i < 5; i++) {
938 r.nextLong();
939 }
940 return r.nextLong();
941 }
942}
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
static SettingsAPI getSettings()
Definition Global.java:51
static SoundPlayerAPI getSoundPlayer()
Definition Global.java:43
static SectorAPI getSector()
Definition Global.java:59
void sendUpdate(Object listInfoParam, TextPanelAPI textPanel)
ButtonAPI addGenericButton(TooltipMakerAPI info, float width, String text, Object data)
void sendUpdateIfPlayerHasIntel(Object listInfoParam, TextPanelAPI textPanel)
static void addPotentialContact(float probability, PersonAPI contact, MarketAPI market, TextPanelAPI text)
void relocateToMarket(MarketAPI other, boolean withIntelUpdate)
static void removeContact(PersonAPI person, InteractionDialogAPI dialog)
static boolean playerHasContact(PersonAPI person, boolean includePotential)
StoryPointActionDelegate getButtonStoryPointActionDelegate(Object buttonId)
void createSmallDescription(TooltipMakerAPI info, float width, float height)
void addFactionPara(TooltipMakerAPI info, Color tc, float pad)
static void addPotentialContact(PersonAPI contact, MarketAPI market, TextPanelAPI text)
void addBulletPoints(TooltipMakerAPI info, ListInfoMode mode)
void addTypePara(TooltipMakerAPI info, Color tc, float pad)
void createConfirmationPrompt(Object buttonId, TooltipMakerAPI prompt)
void createIntelInfo(TooltipMakerAPI info, ListInfoMode mode)
SoundAPI playUISound(String id, float pitch, float volume)