Easy way of creating a question dialogue

From The Stardew Modding Wiki
Jump to navigation Jump to search
    //Instead of using this class one could also use a tuple, but that might cause issues with your mod
    //on Linux and macOS
    /// <summary>A possible answer for a question dialogue.</summary>
    internal class QuestionAnswer
    {
        /// <summary>The answer key provided to the game.</summary>
        public string sKey { get; }

        /// <summary>Handles the answer when the player chooses it.</summary>
        public Action fuHandler { get; }

        /// <summary>Construct an instance.</summary>
        /// <param name="sKey">The answer key provided to the game.</param>
        /// <param name="fuHandler">Handles the answer when the player chooses it.</param>
        public QuestionAnswer(string sKey, Action fuHandler)
        {
            this.sKey = sKey;
            this.fuHandler = fuHandler;
        }
    }
    //A class to handle the question dialogue more easily
    internal class QuestionDialogue
    {
        //List of answers
        List<QuestionAnswer> ltAnswers;
        //The message that should be displayed
        private string sMessage;
        //The actual list of responses the DialogueBox needs. Is being build automatically by this class
        List<Response> ltResponses;

        //Basic constructor. Just calling this makes the question dialogue pop up
        public QuestionDialogue(string sMessage, List<QuestionAnswer> ltAnswers, int iDelay = 100)
        {
            //Setup
            this.ltAnswers = ltAnswers;
            this.sMessage = sMessage;

            //Builds the responses for the dialogue
            ltResponses = new List<Response>();
            for (int iCounter = 0; iCounter < ltAnswers.Count; iCounter++)
            {
                //Responses are made up out of the string to be displayed and the string the after-dialogue function gets
                ltResponses.Add(new Response(iCounter.ToString(), ltAnswers[iCounter].sKey));
            }

            //After a set moment the question dialogue is being displayed
            DelayedAction.functionAfterDelay(DisplayDialogue, iDelay);
        }

        //The function that actually draws the dialogue
        public void DisplayDialogue()
        {
            //Parameters used here are as following:
            //the question to be displayed, the possible answers, the function that will be called once an answer is being selected
            Game1.player.currentLocation.createQuestionDialogue(sMessage, ltResponses.ToArray(), EvaluateAnswer);
        }

        //The function that is being called after the dialogue ends. Acts as a shell here to just call the function assigned to the answer in ltAnswers
        public void EvaluateAnswer(Farmer csFarmer, string sAnswer)
        {
            //Gets the corresponding function in ltAnswers
            Action fuAction = ltAnswers[Convert.ToInt32(sAnswer)].fuHandler;

            //If the function isnt null:
            if(fuAction != null)
            {
                //Call it
                fuAction();
            }
        }
    }
    //Example on how to use the class
    //Creating the list of possible answers with the functions that should be called when the answer left of them is being selected
    //Instead of a function null can be given. This results in nothing happening when the corresponding answer is selected
    List<QuestionAnswer> ltAnswers = new List<QuestionAnswer>()
    {
        //The answers will be displayed in the order they are given here
        new QuestionAnswer("Answer 1", Function1),
        new QuestionAnswer("Answer 2", Function2),
        new QuestionAnswer("Answer 3", null)
    };

    //Calls the QuestionDialogue and thus displays the question dialogue, with the given answers
    new QuestionDialogue("Question?", ltAnswers);

    //displays the same question dialogue, but after a longer delay
    new QuestionDialogue("Question?", ltAnswers, 1000);