- 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.
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", ...)
- 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: