• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

[Pokeemerald] [Event Scripts] Dynamic Multichoice

  • 91
    Posts
    15
    Years
    • Seen Feb 22, 2023
    Dynamic Multichoice

    Hey there. Over the last couple days I've been working on a take on the multichoice script command that allows you to create arbitrary menus from the scripting system. I was mostly not fully satisfied with the implementations of list menus / other forms of dynamic multichoice versions, so I decided to overengineer one. The idea is to have a "satisfies all needs" solution that can do all of these things:

    • Implement simple menus in one line without needing to adjust a global list.
    • Implement "conditions" (see below) to create menus based on certain game states.
    • Make drawing the list customizable, if you are willing to put in a little more coding effort.

    Examples

    [PokeCommunity.com] [Event Scripts] Dynamic Multichoice[PokeCommunity.com] [Event Scripts] Dynamic Multichoice[PokeCommunity.com] [Event Scripts] Dynamic Multichoice

    How to implement

    All the code for this system is available on my pokeemerald fork: https://github.com/SBird1337/pokeemerald/tree/feature/dynmulti
    If you want to use it you can choose to implement it however you want. (Yes, you can also use git to merge it.)
    I would really recommend looking at the changes I made and try to follow along by implementing them yourself on your fork.

    Basic Usage

    The most simple menus you can build as seen in the examples above just consist of a list of elements, you can use the following syntax in poryscript:
    Code:
    dynmultichoice(left, top, ignoreBPress, maxBeforeScroll, initialSelected, callbacks, "Option 1", "Option 2", "Option 3", ...)
    with the following arguments:
    • left: The x offset of the menu (in tiles / units of 8 pixels)
    • top (the y offset of the menu, in tiles / units of 8 pixels)
    • ignoreBPress: Whether the menu should stay open if the user presses the B Button
    • maxBeforeScroll: The maximum amount of items shown before the menu scrolls
    • initialSelected: Variable or static value that determines the initially selected item
    • callbacks: The event callbacks of the menu. For a simple menu supply DYN_MULTICHOICE_CB_NONE
    • ...: Any number of menu options can follow after these arguments

    The menu will automatically convert to a scrolling list (and indicate that with UI Arrows) if the amount of elements is larger than maxBeforeScroll.

    When the menu is closed by player interaction, it will return the selected option index in VAR_RESULT. If the user aborted the menu by pressing the B Button, it will return 127.

    Conditional Menus

    Ever thought you only wanted to enable certain options if the player aquired a specific item, or progressed the game to a certain point? You can use this pattern to fully customize the options of your menu:
    Code:
    dynmultipush("First option", 0)
    if (flag(FLAG_SYS_GAME_CLEAR)) {
       dynmultipush("Secret option", 1)
    }
    dynmultistack(left, top, ignoreBPress, maxBeforeScroll, shouldSort, initialSelected, callbacks)

    dynmultistack behaves just like dynmultichoice with the addition of a shouldSort argument, that determines whether the list should be sorted according to the IDs you pass to dynmultipush. The latter also accepts variables as its second argument.

    Callbacks

    The callbacks argument chooses from a set of event listeners. If that does not make any sense to you, you may notice in the example I already use one such set of events, which will display an icon corresponding to the item id which the menu is built from. But you do not need to use the callbacks, you can always pass DYN_MULTICHOICE_CB_NONE. Those callbacks are written in C and allow you to have a very powerful extensions for those menus that really need it. You might also want to look at examples over at https://github.com/SBird1337/pokeemerald/blob/feature/dynmulti/src/script_menu.c#L71-L85.

    Script Example

    The example images from above where created by using the following script in poryscript syntax:
    Code:
    script EventScript_MultichoiceTests {
        lock 
        faceplayer
        msgbox (LittlerootTown_Text_CanUsePCToStoreItems, MSGBOX_DEFAULT)
    
        // random items with visualization example
    
        random(ITEMS_COUNT)
        bufferitemname(STR_VAR_1, VAR_RESULT)
        dynmultipush("{STR_VAR_1}", VAR_RESULT)
        random(ITEMS_COUNT)
        bufferitemname(STR_VAR_2, VAR_RESULT)
        dynmultipush("{STR_VAR_2}", VAR_RESULT)
        random(ITEMS_COUNT)
        bufferitemname(STR_VAR_3, VAR_RESULT)
        dynmultipush("{STR_VAR_3}", VAR_RESULT)
        dynmultistack(0, 0, TRUE, 6, FALSE, VAR_0x800A, DYN_MULTICHOICE_CB_SHOW_ITEM)
    
        // inline example without scrolling
    
        dynmultichoice(0,0, TRUE, 6, 0, DYN_MULTICHOICE_CB_NONE, "Option 1", "Option 2", "Option 3")
    
        // inline example with scrolling
    
        dynmultichoice(0,0, TRUE, 3, 0, DYN_MULTICHOICE_CB_NONE, "Option 1", "Option 2", "Option 3", "Option 4")
    
        buffernumberstring(STR_VAR_1, VAR_RESULT)
        msgbox("{STR_VAR_1}", MSGBOX_DEFAULT)
        closemessage
        release
        end
    }

    For an example of how this would translate to regular scripting visit https://www.huderlem.com/poryscript-playground/

    I hope this is helpful to some people, at least I had a blast coding it. If you have questions about it, feel free to contact me on the usual suspects of discord servers, or leave a comment (Though bear in mind I'm not very active on this forum, and I might take a while to respond)

    If you want to credit me for this (Which you should not feel obligated to do) I would appreciate if you used the name SBird instead of any other aliases you might know me under.

    Good luck on your scripting adventures!

    ~SBird
     
    Last edited:
    THIS LOOKS PHENOMENAL!!
    I'LL DEFINETLY BE USING THIS ON MY PROJECT!
    This not only is really easy to use, customise and display, but it's also really professional-looking and flexible! I look foward to see what I can create thanks to this!
     
    Dynamic Multichoice
    I think you know what I think of this beautiful piece of work, but I'll say it again; it's absolutely phenomenal and it was sorely needed too.
    It's super flexible and allows the user to do so. many. things with the multichoices system it's ridiculous.
    Completely foolproof and futureproof, surely something that would have made the lives of the workers at Game Freak much, much easier imo.
    One could easily go as far as to replace every multichoice in the code with one of these and get rid of all the multichoice arrays.

    When you first linked the branch before it was ready for public use, I decided to use it to remake the start menu of the game on a whim, thinking back about MapleFang's flawed implementation.
    Since I just finished getting it to a point in which I think it's good enough to distribute, I think that I may as well link it here to display one of the many possibilities this system opens
    [PokeCommunity.com] [Event Scripts] Dynamic Multichoice


    It's functionally equivalent to the original start menu as far as I tested, but naturally, it has the advantages that this system brings, like faster transition from one option to the next, being able to hold the arrow keys to move between options constantly, being easier to read and easier to expand too!
    EDIT: And scrolling options, of course.

    https://github.com/LOuroboros/pokeemerald/commits/dynamicMultiTest2
    [PokeCommunity.com] [Event Scripts] Dynamic Multichoice

    Note: I didn't bother trying to keep absolute accuracy on the visuals department; that's a fool's errand imo. I just left it in a state that I personally like.
    Note2: I intended to delete the code that composes the original and now unused start menu too, but it's too ingrained in the codebase which makes the task a big pita. I'll leave that up to the user.


    EDIT2 (03/12/2023): I pushed a few new commits fixing some issues with the Battle Pyramid's start menu and tweaking the speed of the arrow in the start menu. Thanks to Ardorin for reaching out to me on Discord.
     
    Last edited:
    Dynamic Multichoice

    Hey there. Over the last couple days I've been working on a take on the multichoice script command that allows you to create arbitrary menus from the scripting system. I was mostly not fully satisfied with the implementations of list menus / other forms of dynamic multichoice versions, so I decided to overengineer one. The idea is to have a "satisfies all needs" solution that can do all of these things:

    • Implement simple menus in one line without needing to adjust a global list.
    • Implement "conditions" (see below) to create menus based on certain game states.
    • Make drawing the list customizable, if you are willing to put in a little more coding effort.


    All the code for this system is available on my pokeemerald fork: https://github.com/SBird1337/pokeemerald/tree/feature/dynmulti
    If you want to use it you can choose to implement it however you want. (Yes, you can also use git to merge it.)
    I would really recommend looking at the changes I made and try to follow along by implementing them yourself on your fork.

    Basic Usage

    The most simple menus you can build as seen in the examples above just consist of a list of elements, you can use the following syntax in poryscript:
    Code:
    dynmultichoice(left, top, ignoreBPress, maxBeforeScroll, initialSelected, callbacks, "Option 1", "Option 2", "Option 3", ...)
    with the following arguments:
    • left: The x offset of the menu (in tiles / units of 8 pixels)
    • top (the y offset of the menu, in tiles / units of 8 pixels)
    • ignoreBPress: Whether the menu should stay open if the user presses the B Button
    • maxBeforeScroll: The maximum amount of items shown before the menu scrolls
    • initialSelected: Variable or static value that determines the initially selected item
    • callbacks: The event callbacks of the menu. For a simple menu supply DYN_MULTICHOICE_CB_NONE
    • ...: Any number of menu options can follow after these arguments

    The menu will automatically convert to a scrolling list (and indicate that with UI Arrows) if the amount of elements is larger than maxBeforeScroll.

    When the menu is closed by player interaction, it will return the selected option index in VAR_RESULT. If the user aborted the menu by pressing the B Button, it will return 127.

    Conditional Menus

    Ever thought you only wanted to enable certain options if the player aquired a specific item, or progressed the game to a certain point? You can use this pattern to fully customize the options of your menu:
    Code:
    dynmultipush("First option", 0)
    if (flag(FLAG_SYS_GAME_CLEAR)) {
       dynmultipush("Secret option", 1)
    }
    dynmultistack(left, top, ignoreBPress, maxBeforeScroll, shouldSort, initialSelected, callbacks)

    dynmultistack behaves just like dynmultichoice with the addition of a shouldSort argument, that determines whether the list should be sorted according to the IDs you pass to dynmultipush. The latter also accepts variables as its second argument.

    Callbacks

    The callbacks argument chooses from a set of event listeners. If that does not make any sense to you, you may notice in the example I already use one such set of events, which will display an icon corresponding to the item id which the menu is built from. But you do not need to use the callbacks, you can always pass DYN_MULTICHOICE_CB_NONE. Those callbacks are written in C and allow you to have a very powerful extensions for those menus that really need it. You might also want to look at examples over at https://github.com/SBird1337/pokeemerald/blob/feature/dynmulti/src/script_menu.c#L71-L85.

    Script Example

    The example images from above where created by using the following script in poryscript syntax:
    Code:
    script EventScript_MultichoiceTests {
        lock
        faceplayer
        msgbox (LittlerootTown_Text_CanUsePCToStoreItems, MSGBOX_DEFAULT)
    
        // random items with visualization example
    
        random(ITEMS_COUNT)
        bufferitemname(STR_VAR_1, VAR_RESULT)
        dynmultipush("{STR_VAR_1}", VAR_RESULT)
        random(ITEMS_COUNT)
        bufferitemname(STR_VAR_2, VAR_RESULT)
        dynmultipush("{STR_VAR_2}", VAR_RESULT)
        random(ITEMS_COUNT)
        bufferitemname(STR_VAR_3, VAR_RESULT)
        dynmultipush("{STR_VAR_3}", VAR_RESULT)
        dynmultistack(0, 0, TRUE, 6, FALSE, VAR_0x800A, DYN_MULTICHOICE_CB_SHOW_ITEM)
    
        // inline example without scrolling
    
        dynmultichoice(0,0, TRUE, 6, 0, DYN_MULTICHOICE_CB_NONE, "Option 1", "Option 2", "Option 3")
    
        // inline example with scrolling
    
        dynmultichoice(0,0, TRUE, 3, 0, DYN_MULTICHOICE_CB_NONE, "Option 1", "Option 2", "Option 3", "Option 4")
    
        buffernumberstring(STR_VAR_1, VAR_RESULT)
        msgbox("{STR_VAR_1}", MSGBOX_DEFAULT)
        closemessage
        release
        end
    }

    For an example of how this would translate to regular scripting visit https://www.huderlem.com/poryscript-playground/

    I hope this is helpful to some people, at least I had a blast coding it. If you have questions about it, feel free to contact me on the usual suspects of discord servers, or leave a comment (Though bear in mind I'm not very active on this forum, and I might take a while to respond)

    If you want to credit me for this (Which you should not feel obligated to do) I would appreciate if you used the name SBird instead of any other aliases you might know me under.

    Good luck on your scripting adventures!

    ~SBird
    I really like this but I dont see your git pull. Please provide your git pull. Thanks
     
    I really like this but I dont see your git pull. Please provide your git pull. Thanks
    There isn't "a" git pull.
    git pull is a command that lets you incorporate the commits pushed to X or Y branch of a Git repository into your project.
    You can see in the main post that the branch in which SBird hosts the commits to implement this feature is called "dynmulti" and that it's located in his Pokeemerald repository.
    https://github.com/SBird1337/pokeemerald/tree/feature/dynmulti
    ^ You don't need anything other than that to work with.
    git remote add sbird https://github.com/SBird1337/pokeemerald
    git pull sbird dynmulti
     
    There isn't "a" git pull.
    git pull is a command that lets you incorporate the commits pushed to X or Y branch of a Git repository into your project.
    You can see in the main post that the branch in which SBird hosts the commits to implement this feature is called "dynmulti" and that it's located in his Pokeemerald repository.
    https://github.com/SBird1337/pokeemerald/tree/feature/dynmulti
    ^ You don't need anything other than that to work with.
    i added all the changes and I got many errors but I wont bother u with them. I just hope it gets added to the expansion in the next update. Thank you lunos
     
    Back
    Top