Hmm - that's actually kind of a pain, since options expect a number key shortcut to be available (thus limiting them to 1-9, at least if we want a shortcut or nice visual alignment), and I think a scrollbar would look pretty odd there - it'd have to be rather far to the right since option text could be long - or it'd have to be resized based on the option text width, I suppose.
Generally, my feeling is that reducing the number of options the player has to pick from at a time might be the better option, anyway, in terms of the player experience. E.G. in your example, it seems fairly clear that these options are of increasing difficulty, so having a choice of "hard/medium/easy" or whatever might be more clear.
That said, I can take a look at it at some point, since the above is just my opinion, and circumstances vary anyway. In the meantime, though, I cooked up something quick.
https://gfycat.com/SatisfiedOccasionalGermanpinscherBasically, it's a rule command - that'll be in the API, but that you could also (most likely, unless it's using stuff that's not exposed on 0.8a? though it shouldn't be) use now. It creates a paginated set of options, handles previous/next commands, and then fires a DialogOptionSelected when the player selects an option.
There are two ways to use it, either:
PaginatedOptions "Option 1" optionId1 "Option 2" optionId2 "Option 3" optionId3 <and so on>
Or creating a derived class that adds the options in code, see: PaginatedOptionsExample.
Hopefully this is useful; if not, no biggie. Seems like something that should be provided by the API anyway.
PaginatedOptions.java:
Spoiler
package com.fs.starfarer.api.impl.campaign.rulecmd;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.fs.starfarer.api.Global;
import com.fs.starfarer.api.campaign.InteractionDialogAPI;
import com.fs.starfarer.api.campaign.InteractionDialogPlugin;
import com.fs.starfarer.api.campaign.rules.MemoryAPI;
import com.fs.starfarer.api.combat.EngagementResultAPI;
import com.fs.starfarer.api.impl.campaign.DevMenuOptions;
import com.fs.starfarer.api.util.Misc.Token;
public class PaginatedOptions extends BaseCommandPlugin implements InteractionDialogPlugin {
public static String OPTION_NEXT_PAGE = "core_option_next_page";
public static String OPTION_PREV_PAGE = "core_option_prev_page";
public static class PaginatedOption {
public String text;
public String id;
public PaginatedOption(String text, String id) {
this.text = text;
this.id = id;
}
}
protected InteractionDialogPlugin originalPlugin;
protected InteractionDialogAPI dialog;
protected Map<String, MemoryAPI> memoryMap;
protected List<PaginatedOption> options = new ArrayList<PaginatedOption>();
protected int optionsPerPage = 5;
protected int currPage = 0;
public boolean execute(String ruleId, InteractionDialogAPI dialog, List<Token> params, final Map<String, MemoryAPI> memoryMap) {
this.dialog = dialog;
this.memoryMap = memoryMap;
originalPlugin = dialog.getPlugin();
//FireBest.fire(null, dialog, memoryMap, "SalvageSpecialFinishedNoContinue");
dialog.setPlugin(this);
init(dialog);
for (int i = 0; i < params.size(); i += 2) {
String text = params.get(i).getString(memoryMap);
String id = params.get(i + 1).getString(memoryMap);
addOption(text, id);
}
if (params.size() > 0) {
showOptions();
}
return true;
}
public void addOption(String text, String id) {
options.add(new PaginatedOption(text, id));
}
public void showOptions() {
dialog.getOptionPanel().clearOptions();
int maxPages = (int) Math.ceil((float)options.size() / (float)optionsPerPage);
if (currPage > maxPages - 1) currPage = maxPages - 1;
if (currPage < 0) currPage = 0;
int start = currPage * optionsPerPage;
for (int i = start; i < start + optionsPerPage; i++) {
if (i >= options.size()) {
if (maxPages > 1) {
dialog.getOptionPanel().addOption("", "spacer" + i);
dialog.getOptionPanel().setEnabled("spacer" + i, false);
}
} else {
PaginatedOption option = options.get(i);
dialog.getOptionPanel().addOption(option.text, option.id);
}
}
if (maxPages > 1) {
dialog.getOptionPanel().addOption(getPreviousPageText(), OPTION_PREV_PAGE);
dialog.getOptionPanel().addOption(getNextPageText(), OPTION_NEXT_PAGE);
if (currPage >= maxPages - 1) {
dialog.getOptionPanel().setEnabled(OPTION_NEXT_PAGE, false);
}
if (currPage <= 0) {
dialog.getOptionPanel().setEnabled(OPTION_PREV_PAGE, false);
}
}
if (Global.getSettings().isDevMode()) {
DevMenuOptions.addOptions(dialog);
}
}
public String getPreviousPageText() {
return "Previous page";
}
public String getNextPageText() {
return "Next page";
}
public void optionSelected(String optionText, Object optionData) {
if (optionData == OPTION_PREV_PAGE) {
currPage--;
showOptions();
return;
}
if (optionData == OPTION_NEXT_PAGE) {
currPage++;
showOptions();
return;
}
if (optionText != null) {
dialog.getTextPanel().addParagraph(optionText, Global.getSettings().getColor("buttonText"));
}
if (optionData == DumpMemory.OPTION_ID) {
new DumpMemory().execute(null, dialog, null, getMemoryMap());
return;
} else if (DevMenuOptions.isDevOption(optionData)) {
DevMenuOptions.execute(dialog, (String) optionData);
return;
}
dialog.setPlugin(originalPlugin);
MemoryAPI memory = dialog.getInteractionTarget().getMemory();
memory.set("$option", optionData);
memory.expire("$option", 0);
boolean fired = FireBest.fire(null, dialog, memoryMap, "DialogOptionSelected");
if (!fired) {
dialog.setPlugin(this); // failsafe for selecting an option with no matching rule
}
}
public void advance(float amount) {
}
public void backFromEngagement(EngagementResultAPI battleResult) {
}
public Object getContext() {
return null;
}
public Map<String, MemoryAPI> getMemoryMap() {
return memoryMap;
}
public void optionMousedOver(String optionText, Object optionData) {
}
public void init(InteractionDialogAPI dialog) {
}
}
PaginatedOptionsExample.java:
Spoiler
package com.fs.starfarer.api.impl.campaign.rulecmd;
import java.util.List;
import java.util.Map;
import com.fs.starfarer.api.campaign.InteractionDialogAPI;
import com.fs.starfarer.api.campaign.rules.MemoryAPI;
import com.fs.starfarer.api.util.Misc.Token;
public class PaginatedOptionsExample extends PaginatedOptions {
public boolean execute(String ruleId, InteractionDialogAPI dialog, List<Token> params, final Map<String, MemoryAPI> memoryMap) {
super.execute(ruleId, dialog, params, memoryMap);
optionsPerPage = 5;
for (int i = 0; i < 14; i++) {
addOption("Option " + i, "o" + i);
}
showOptions();
return true;
}
@Override
public String getNextPageText() {
return super.getNextPageText();
}
@Override
public String getPreviousPageText() {
return super.getPreviousPageText();
}
}