Skip to content

Conversation

@Khundiann
Copy link

Add Opt-In Dialogue Choice Paging (>8 Choices)

Summary

This PR introduces an opt-in UI utility that enables dialogue choice paging when a dialogue node contains more than 8 choices (vanilla prefab limit). It keeps compatibility with both Mono and IL2CPP by avoiding transpilers and only patches the dialogue UI (DialogueCanvas).

Paging behavior:

  • Show up to 7 real choices per page + a final “More (x/y)” entry.
  • Selecting More cycles to the next page (wraps back to page 1).

Motivation / Problem

Schedule I’s dialogue UI prefab provides a fixed list of 8 choice entries. Mods that inject additional choices (e.g., adding more hire locations, quest options, etc.) can exceed this limit and either:

  • lose choices, or
  • require custom UI/prefab work.

An API-level, opt-in solution helps modders safely expose more than 8 choices without rebuilding UI prefabs.

Design Goals

  • Opt-in: no behavior changes unless a mod enables it.
  • Targeted: patch only DialogueCanvas methods; do not patch dialogue handlers/controllers.
  • IL2CPP-safe: avoid transpilers and avoid patching coroutine bodies.
  • Minimal coupling: work with existing dialogue systems and injected choices.

Public API (S1API)

public override void OnInitializeMelon()
{
    S1API.Dialogues.DialogueChoicePaging.Enable(new S1API.Dialogues.DialogueChoicePagingOptions
    {
        // Defaults match the "7 + More" paging behavior
        ChoicesPerPage = 7,
        WrapPages = true,
        MoreTextFormat = "More ({0}/{1})",

        // Optional: override the vanilla visible-cap (default 8)
        MaxVisibleChoices = 8
    });
}

Implementation Notes

Patch only DialogueCanvas:

  • DisplayDialogueNode(...) (prefix): if choices.Count > MaxVisibleChoices, cache the full list and replace the passed-in list with the current page slice + “More (x/y)”.
  • DisplayDialogueNode(...) (postfix): restore DialogueHandler.CurrentChoices to the full list (ensures downstream logic sees the real list).
  • ChoiceSelected(int) (prefix): if the selected index is “More”, advance page and re-render the same node; otherwise remap visible index → real index.
  • IsChoiceValid(int, out string) (prefix): when paging is active, validate using the real index (pageStart + visibleIndex); “More” always valid.
  • EndDialogue() (postfix): clear cached paging state.

Behavior Details

  • Paging activates only when choices.Count > MaxVisibleChoices (default 8).
  • “More (x/y)” is always clickable and does not advance the dialogue tree; it only re-renders the same node with the next page.
  • Page count is ceil(totalChoices / ChoicesPerPage).

Notes / Bug Avoidance

Vanilla DialogueCanvas.IsChoiceValid indexes into DialogueHandler.CurrentChoices[choiceIndex]. When paging, the visible index is no longer the same as the real index, so the patch remaps visible index → real index for validity checks. This avoids showing incorrect validity reasons (e.g. mismatch between the displayed option and the “invalid reason” text).

Compatibility / Risk

  • Scope is limited to the dialogue UI surface (DialogueCanvas).
  • Should be compatible with mods that:
    • inject choices by modifying lists at runtime, and/or
    • build/attach dialogue containers.

Testing

  • Manual verification:
    • dialogue with <= MaxVisibleChoices remains unchanged
    • dialogue with 9–20 choices pages correctly and selection/validity maps to the correct underlying option

Docs: S1API/docs/dialogue-system.md (Advanced Features → Large Choice Lists (Paging))

Copy link
Owner

@ifBars ifBars left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very well done, thanks for the PR :)

@ifBars ifBars merged commit 208b280 into ifBars:stable Jan 19, 2026
4 checks passed
@Khundiann Khundiann deleted the feature/optin-dialogue-choice-paging branch January 26, 2026 04:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants