1package com.fs.starfarer.api.impl.campaign.missions.hub;
3import java.util.ArrayList;
4import java.util.HashSet;
5import java.util.LinkedHashSet;
8import java.util.Random;
11import org.lwjgl.util.vector.Vector2f;
13import com.fs.starfarer.api.Global;
14import com.fs.starfarer.api.campaign.InteractionDialogAPI;
15import com.fs.starfarer.api.campaign.SectorEntityToken;
16import com.fs.starfarer.api.campaign.StarSystemAPI;
17import com.fs.starfarer.api.campaign.comm.IntelInfoPlugin;
18import com.fs.starfarer.api.campaign.econ.MarketAPI;
19import com.fs.starfarer.api.campaign.rules.MemoryAPI;
20import com.fs.starfarer.api.characters.ImportantPeopleAPI;
21import com.fs.starfarer.api.characters.PersonAPI;
22import com.fs.starfarer.api.impl.campaign.DebugFlags;
23import com.fs.starfarer.api.impl.campaign.DevMenuOptions;
24import com.fs.starfarer.api.impl.campaign.ids.Tags;
25import com.fs.starfarer.api.impl.campaign.intel.bar.events.BarEventManager;
26import com.fs.starfarer.api.impl.campaign.intel.contacts.ContactIntel;
27import com.fs.starfarer.api.impl.campaign.missions.hub.HubMissionWithSearch.StarSystemUnexploredReq;
28import com.fs.starfarer.api.impl.campaign.rulecmd.CallEvent.CallableEvent;
29import com.fs.starfarer.api.impl.campaign.rulecmd.FireAll;
30import com.fs.starfarer.api.impl.campaign.rulecmd.FireBest;
31import com.fs.starfarer.api.loading.PersonMissionSpec;
32import com.fs.starfarer.api.util.Misc;
33import com.fs.starfarer.api.util.Misc.Token;
34import com.fs.starfarer.api.util.TimeoutTracker;
35import com.fs.starfarer.api.util.WeightedRandomPicker;
48 public static String
LAST_OPENED =
"$mHub_lastOpenedTimestamp";
50 public static String
KEY =
"$mHub";
53 person.getMemoryWithoutUpdate().unset(
KEY);
55 person.getMemoryWithoutUpdate().set(
KEY, hub);
59 if (
person ==
null)
return null;
60 if (
person.getMemoryWithoutUpdate().contains(
KEY)) {
75 return Long.MIN_VALUE;
88 protected TimeoutTracker<String>
timeout =
new TimeoutTracker<String>();
90 protected List<HubMissionCreator>
creators =
new ArrayList<HubMissionCreator>();
91 protected transient List<HubMission>
offered =
new ArrayList<HubMission>();
104 Set<String> validMissions =
new HashSet<String>();
105 Set<String> alreadyHaveCreatorsFor =
new HashSet<String>();
106 for (PersonMissionSpec spec : specs) {
107 validMissions.add(spec.getMissionId());
111 if (!curr.wasAutoAdded())
continue;
113 if (!validMissions.contains(curr.getSpecId())) {
114 curr.setActive(
false);
117 curr.setActive(
true);
118 alreadyHaveCreatorsFor.add(curr.getSpecId());
122 for (PersonMissionSpec spec : specs) {
123 if (!alreadyHaveCreatorsFor.contains(spec.getMissionId())) {
141 public boolean callEvent(String ruleId, InteractionDialogAPI dialog,
142 List<Token> params, Map<String, MemoryAPI> memoryMap) {
143 String action = params.get(0).getString(memoryMap);
144 if (action.equals(
"setMHOptionText")) {
146 }
else if (action.equals(
"prepare")) {
148 }
else if (action.equals(
"listMissions")) {
150 }
else if (action.equals(
"returnToList")) {
152 }
else if (action.equals(
"doCleanup")) {
154 }
else if (action.equals(
"accept")) {
155 String missionId = params.get(1).getString(memoryMap);
156 accept(dialog, memoryMap, missionId);
158 throw new RuntimeException(
"Unhandled action [" + action +
"] in " + getClass().getSimpleName() +
159 " for rule [" + ruleId +
"], params:[" + params +
"]");
165 public void accept(InteractionDialogAPI dialog, Map<String, MemoryAPI> memoryMap, String missionId) {
167 if (curr.getMissionId().equals(missionId)) {
168 curr.accept(dialog, memoryMap);
171 float dur = curr.getCreator().getAcceptedTimeoutDuration();
172 timeout.add(curr.getCreator().getSpecId(), dur);
179 public void prepare(InteractionDialogAPI dialog, Map<String, MemoryAPI> memoryMap) {
186 public void doCleanup(InteractionDialogAPI dialog, Map<String, MemoryAPI> memoryMap) {
191 offered =
new ArrayList<HubMission>();
195 MemoryAPI pMem = dialog.getInteractionTarget().getActivePerson().getMemoryWithoutUpdate();
198 String firstInlineBlurb =
null;
201 if (firstInlineBlurb ==
null) firstInlineBlurb = curr.getBlurbText();
204 pMem.set(
"$mh_firstInlineBlurb", firstInlineBlurb, 0);
205 pMem.set(
"$mh_count", count, 0);
208 public void listMissions(InteractionDialogAPI dialog, Map<String, MemoryAPI> memoryMap,
boolean withBlurbs) {
209 if (dialog !=
null && dialog.getVisualPanel() !=
null) {
210 dialog.getVisualPanel().removeMapMarkerFromPersonInfo();
212 MemoryAPI pMem = dialog.getInteractionTarget().getActivePerson().getMemoryWithoutUpdate();
215 if (pMem.getFloat(
"$mh_count") <= 0) {
216 FireAll.fire(
null, dialog, memoryMap,
"PopulateOptions");
220 dialog.getOptionPanel().clearOptions();
223 boolean hasCommonBlurb =
false;
227 if (curr.getBlurbText() !=
null) {
228 blurb += curr.getBlurbText() +
" ";
229 FireBest.fire(
null, dialog, memoryMap, curr.getTriggerPrefix() +
"_option true");
230 hasCommonBlurb =
true;
245 if (curr.getBlurbText() ==
null) {
247 if (!FireBest.fire(
null, dialog, memoryMap, curr.getTriggerPrefix() +
"_blurb true")) {
248 dialog.getTextPanel().addPara(
"No blurb found for " + curr.getTriggerPrefix(), Misc.getNegativeHighlightColor());
251 if (!FireBest.fire(
null, dialog, memoryMap, curr.getTriggerPrefix() +
"_option true")) {
252 dialog.getTextPanel().addPara(
"No option found for " + curr.getTriggerPrefix(), Misc.getNegativeHighlightColor());
257 FireBest.fire(
null, dialog, memoryMap,
"AddMHCloseOption true");
259 if (withBlurbs && hasCommonBlurb && !pMem.getBoolean(
"$mh_doNotPrintBlurbs")) {
260 blurb = blurb.trim();
262 dialog.getTextPanel().addPara(blurb);
266 FireBest.fire(
null, dialog, memoryMap,
"MHPostMissionListText");
276 return "\"Do you have any work for me?\"";
312 creator.setSeed(BarEventManager.getInstance().getSeed(
null,
person,
323 WeightedRandomPicker<HubMissionCreator> picker =
new WeightedRandomPicker<HubMissionCreator>(
missionGenRandom);
324 WeightedRandomPicker<HubMissionCreator> priority =
new WeightedRandomPicker<HubMissionCreator>(
missionGenRandom);
325 float rel =
person.getRelToPlayer().getRel();
327 Set<String> completed =
new LinkedHashSet<String>();
329 if (creator.getNumCompleted() > 0) completed.add(creator.getSpecId());
338 if (
timeout.contains(creator.getSpecId()) &&
341 if (!creator.isActive())
continue;
343 if (creator.getSpec().hasTag(Tags.MISSION_NON_REPEATABLE) &&
344 creator.getNumCompleted() > 0) {
354 if (!creator.matchesRep(rel))
continue;
356 if (
person.getImportance().ordinal() < creator.getSpec().getImportance().ordinal())
continue;
360 float w = creator.getFrequencyWeight();
361 if (creator.isPriority()) {
362 priority.add(creator, w);
364 picker.add(creator, w);
369 int bonusMissions = 0;
372 float rem = bonus - (int) bonus;
373 bonusMissions = (int) bonus;
381 if (num < 1 && MIN_TO_SHOW > 0) num = 1;
389 offered =
new ArrayList<HubMission>();
395 ip.resetExcludeFromGetPerson();
397 for (IntelInfoPlugin intel :
Global.
getSector().getIntelManager().getIntel(ContactIntel.class)) {
398 ip.excludeFromGetPerson(((ContactIntel)intel).getPerson());
401 while ((!picker.isEmpty() || !priority.isEmpty()) &&
offered.size() < num) {
403 if (creator ==
null) {
404 creator = picker.pickAndRemove();
415 if (mission !=
null) {
433 ip.resetExcludeFromGetPerson();
447 List<PersonMissionSpec> result =
new ArrayList<PersonMissionSpec>();
449 Set<String> personTags =
new HashSet<String>(
person.getTags());
450 personTags.add(
person.getFaction().getId());
453 if (spec.getPersonId() !=
null && !spec.getPersonId().equals(
person.getId()))
continue;
454 if (!spec.tagsMatch(personTags))
continue;
456 if (spec.getPersonId() ==
null && spec.getTagsAll().isEmpty() &&
457 spec.getTagsAny().isEmpty() && spec.getTagsNotAny().isEmpty())
continue;
482 if (market !=
null) {
483 mem = market.getMemoryWithoutUpdate();
484 }
else if (
person!=
null) {
485 mem =
person.getMemoryWithoutUpdate();
487 Random random = Misc.getRandom(BarEventManager.getInstance().getSeed(
null,
null,
null), 11);
488 return random.nextFloat() * 360f;
495 StarSystemUnexploredReq unexplored =
new StarSystemUnexploredReq();
496 Vector2f loc =
Global.
getSector().getPlayerFleet().getLocationInHyperspace();
498 SectorEntityToken entity =
null;
499 if (market !=
null) entity = market.getPrimaryEntity();
500 if (entity ==
null &&
person !=
null &&
person.getMarket() !=
null) {
501 entity =
person.getMarket().getPrimaryEntity();
503 Random random = Misc.getRandom(BarEventManager.getInstance().getSeed(entity,
person,
null), 11);
504 WeightedRandomPicker<Float> picker =
new WeightedRandomPicker<Float>(random);
506 float dir = Misc.getAngleInDegrees(loc, system.getLocation());
507 if (unexplored.systemMatchesRequirement(system)) {
510 float days = system.getDaysSinceLastPlayerVisit();
511 float weight = days / 1000f;
512 if (weight < 0.01f) weight = 0.01f;
513 if (weight > 1f) weight = 1f;
514 picker.add(dir, weight * 0.01f);
518 angle = picker.pick();
static SettingsAPI getSettings()
static SectorAPI getSector()
static boolean ALLOW_ALL_CONTACT_MISSIONS
void setWasAutoAdded(boolean wasAutoAdded)
void setActive(boolean isActive)
void prepare(InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap)
void updateCountAndFirstInlineBlurb(InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap)
static String CONTACT_SUSPENDED
static float getMissionAngle(PersonAPI person, MarketAPI market)
void updateOfferedMissions(InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap)
void updateMissionCreatorsFromSpecs()
static long getLastOpenedTimestamp(PersonAPI person)
BaseMissionHub(PersonAPI person)
TimeoutTracker< String > recentlyAcceptedTimeout
static String LAST_OPENED
List< HubMissionCreator > creators
static String MISSION_ANGLE_KEY
static int MAX_TO_SHOW_WITH_BONUS
void setPerson(PersonAPI person)
float daysSinceLastUpdate
static void setDaysSinceLastOpened(PersonAPI person)
transient List< HubMission > offered
void accept(InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap, String missionId)
static List< PersonMissionSpec > getMissionsForPerson(PersonAPI person)
static String MISSION_QUALITY_BONUS
TimeoutTracker< String > timeout
List< HubMission > getOfferedMissions()
float getUpdateInterval()
boolean callEvent(String ruleId, InteractionDialogAPI dialog, List< Token > params, Map< String, MemoryAPI > memoryMap)
static String NUM_BONUS_MISSIONS
static float getDaysSinceLastOpened(PersonAPI person)
void doCleanup(InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap)
static float UPDATE_INTERVAL
transient Random missionGenRandom
void listMissions(InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap, boolean withBlurbs)
String getOpenOptionText()
float getFloat(String key)
List< PersonMissionSpec > getAllMissionSpecs()
float getWasShownTimeoutDuration()
HubMission createHubMission(MissionHub hub)
boolean isMissionCreationAborted()
void setGenRandom(Random random)
void setHub(MissionHub hub)
void setCreator(HubMissionCreator creator)
void updateInteractionData(InteractionDialogAPI dialog, Map< String, MemoryAPI > memoryMap)
void createAndAbortIfFailed(MarketAPI market, boolean barEvent)