Difference between revisions of "Options Menu"
Jump to navigation
Jump to search
m
Reverted edits by Threedee (talk) to last revision by JustinOther
imported>Threedee (→Notes) |
imported>JustinOther m (Reverted edits by Threedee (talk) to last revision by JustinOther) |
||
Line 1: | Line 1: | ||
== Overview == | == Overview == | ||
Using [[Show - Message]], it is possible to make an options menu with any number of buttons and/or levels. This is enabling as one can maintain but a single plugin with an options menu offering multiple configuration setting rather than necessitating multiple versions. In these examples, we'll use apparel items and a book, but a menu can be prompted and managed in a number of ways. First, create a message(s) form(s) and add/fill the buttons with the options you'd like to offer. Note that no more than ten buttons can be in a message box and that the button indices are offset by one such that the first option's index is 0 and not 1. If offering a lot of options, it's best to think ahead regarding how you want to organize your options, making the message forms first, then plugging them into the script | Using [[Show - Message]], it is possible to make an options menu with any number of buttons and/or levels. This is enabling as one can maintain but a single plugin with an options menu offering multiple configuration setting rather than necessitating multiple versions. In these examples, we'll use apparel items and a book, but a menu can be prompted and managed in a number of ways. First, create a message(s) form(s) and add/fill the buttons with the options you'd like to offer. Note that no more than ten buttons can be in a message box and that the button indices are offset by one such that the first option's index is 0 and not 1. If offering a lot of options, it's best to think ahead regarding how you want to organize your options, making the message forms first, then plugging them into the script. | ||
== Examples == | == Examples == | ||
*For the first example, we'll have only three options: "Mage", "Thief", and "Warrior". When the | *For the first example, we'll have only three options: "Mage", "Thief", and "Warrior". The token should be unplayable in this case. When the item is added to the player, the menu will be prompted and will exit as soon as a button is selected, executing the appropriate code right after the token is silently removed. | ||
<source lang="papyrus">ScriptName OptionsMenuScript extends ObjectReference | <source lang="papyrus">ScriptName OptionsMenuScript extends ObjectReference | ||
Message Property OptionsMESG Auto | Actor Property PlayerREF Auto | ||
Armor Property MenuARMO Auto | |||
Message Property OptionsMESG Auto | |||
Event OnContainerChanged(ObjectReference akNewContainer, ObjectReference akOldContainer) | Event OnContainerChanged(ObjectReference akNewContainer, ObjectReference akOldContainer) | ||
If akNewContainer == | If akNewContainer == PlayerREF ; Only the player | ||
Int iButton = OptionsMESG.Show() ; Shows your menu | Int iButton = OptionsMESG.Show() ; Shows your menu. | ||
PlayerREF.RemoveItem(MenuARMO, 1, True) ; Silently remove token | |||
If iButton == 0 ; Mage | If iButton == 0 ; Mage | ||
Debug.Notification("Mage selected") | Debug.Notification("Mage selected") | ||
Line 21: | Line 22: | ||
Debug.Notification("Warrior selected") | Debug.Notification("Warrior selected") | ||
EndIf | EndIf | ||
EndIf | EndIf | ||
EndEvent</source> | EndEvent</source> | ||
*For the next example, we'll offer sub-options for each main selection. For a multilevel menu, a function works well. Keep in mind each button can have conditions, so you could hide "Lunch" and "Dinner" if it's time for breakfast or hide "Lobster" if it's not currently available. In this case, to make it repeatable, we'll use a book so the menu will show each time it is read. A book cannot be favorited or hotkeyed, unlike an apparel item. A potion can be hotkeyed, but it will be consumed when used and not remain hotkeyed even if immediately replaced. This example will let the user choose breakfast, lunch, or dinner, then close after one meal is selected. | |||
<source lang="papyrus">ScriptName OptionsMenuScript extends ObjectReference | |||
Armor Property MenuBook Auto | |||
Message Property MainMenuMESG Auto | Message Property MainMenuMESG Auto | ||
Message Property BreakfastMESG Auto | Message Property BreakfastMESG Auto | ||
Message Property LunchMESG Auto | Message Property LunchMESG Auto | ||
Message Property DinnerMESG Auto | Message Property DinnerMESG Auto | ||
Event OnRead() | Event OnRead() | ||
Game.DisablePlayerControls(False, False, False, False, False, True) ; | Game.DisablePlayerControls(False, False, False, False, False, True) ; Momentarily disable other menus | ||
Game.EnablePlayerControls(False, False, False, False, False, True) ; Undo DisablePlayerControls | |||
Menu() | Menu() | ||
EndEvent | EndEvent | ||
Function Menu(Bool abMenu = True, Int aiButton = 0) | |||
While abMenu | |||
If aiButton != -1 ; Wait for input (this can prevent problems if recycling the aiButton argument in submenus) | |||
aiButton = MainMenuMESG.Show() ; Main Menu | |||
abMenu = False ; End the function | |||
If aiButton == 0 ; Breakfast | |||
aiButton = BreakfastMESG.Show() | |||
If aiButton == 0 ; Sweet Roll & Coffee | |||
ElseIf aiButton == 1 ; Pancakes, Bacon & Eggs | |||
ElseIf aiButton == 2 ; Chicken Fried Pony Steak | |||
EndIf | |||
ElseIf aiButton == 1 ; Lunch | |||
aiButton = LunchMESG.Show() | |||
If aiButton == 0 ; Glazed Turkey Sandwich | |||
ElseIf aiButton == 1 ; Grilled Ham Sandwich | |||
ElseIf aiButton == 2 ; Shredded Pony Sandwich | |||
EndIf | |||
ElseIf aiButton == 2 ; Dinner | |||
aiButton = DinnerMESG.Show() | |||
If aiButton == 0 ; Filet Mignon | |||
ElseIf aiButton == 1 ; Pony Fajitas | |||
ElseIf aiButton == 2 ; Lobster | |||
EndIf | |||
EndIf | |||
EndIf | |||
EndWhile | |||
EndFunction</source> | |||
*To make a multilevel, looping menu with thirty buttons that will not close until a "Done" button is pressed, use the above method but with an altered Menu() function. Note that you can jump to a given message by specifying the aiMessage argument when calling the function. Sub-options as described in the previous example can be added to the below in the same manner. Theoretically, any number of options can be added with the below structure. | |||
<source lang="papyrus">ScriptName OptionsMenuScript extends ObjectReference | <source lang="papyrus">ScriptName OptionsMenuScript extends ObjectReference | ||
Actor Property PlayerREF Auto | |||
Message Property OptionsMenu00MESG Auto | Armor Property MenuARMO Auto ; Playable apparel item | ||
Message Property OptionsMenu01MESG Auto | Message Property OptionsMenu00MESG Auto | ||
Message Property OptionsMenu02MESG Auto | Message Property OptionsMenu01MESG Auto | ||
Message Property OptionsMenu02MESG Auto | |||
Event OnEquipped(Actor akActor) | Event OnEquipped(Actor akActor) | ||
If akActor == Game. | If akActor == PlayerREF | ||
Game.DisablePlayerControls(False, False, False, False, False, True) ; Momentarily disable other menus | |||
PlayerREF.EquipItem(MenuARMO, True, True) ; Prevent unequip/reequip in favorites until the current menu is resolved | |||
Utility.Wait(0.01) ; This ensures equipping the token from the favorites menu works | |||
Game. | PlayerREF.UnequipItem(MenuARMO, False, True) ; Silently unequip item | ||
Game.EnablePlayerControls(False, False, False, False, False, True) ; Undo DisablePlayerControls | |||
Menu() | Menu() | ||
EndIf | EndIf | ||
EndEvent | EndEvent | ||
Function Menu(Int aiMessage = 0, Int aiButton = 0, Bool abMenu = True) | |||
While abMenu | While abMenu | ||
If aiButton == -1 ; Wait for input | |||
ElseIf aiMessage == 0 | |||
aiButton = OptionsMenu00MESG.Show() | |||
If aiButton == 0 | |||
ElseIf | ElseIf aiButton == 1 | ||
ElseIf aiButton == 2 | |||
ElseIf | ElseIf aiButton == 3 | ||
ElseIf aiButton == 4 | |||
ElseIf aiButton == 5 | |||
ElseIf aiButton == 6 | |||
ElseIf aiButton == 7 | |||
ElseIf aiButton == 8 ; More | |||
aiMessage = 1 | |||
ElseIf aiButton == 9 ; Done | |||
abMenu = False | |||
EndIf | |||
ElseIf aiMessage == 1 | |||
aiButton = OptionsMenu01MESG.Show() | |||
If aiButton == 0 | |||
ElseIf aiButton == 1 | |||
ElseIf aiButton == 2 | |||
ElseIf aiButton == 3 | |||
ElseIf aiButton == 4 | |||
ElseIf aiButton == 5 | |||
ElseIf aiButton == 6 | |||
ElseIf aiButton == 7 ; Back | |||
aiMessage = 0 | |||
ElseIf aiButton == 8 ; More | |||
aiMessage = 2 | |||
ElseIf aiButton == 9 ; Done | |||
abMenu = False | |||
EndIf | |||
ElseIf aiMessage == 2 | |||
aiButton = OptionsMenu02MESG.Show() | |||
If aiButton == 0 | |||
ElseIf aiButton == 1 | |||
ElseIf aiButton == 2 | |||
ElseIf aiButton == 3 | |||
ElseIf aiButton == 4 | |||
ElseIf aiButton == 5 | |||
ElseIf aiButton == 6 | |||
ElseIf aiButton == 7 | |||
ElseIf aiButton == 8 ; Back | |||
aiMessage = 1 | |||
ElseIf aiButton == 9 ; Done | |||
abMenu = False | |||
EndIf | |||
EndIf | EndIf | ||
EndWhile | EndWhile | ||
EndFunction</source> | |||
EndFunction | |||
</source> | |||
== Notes == | == Notes == | ||
*Given the buttons in Skyrim are listed from side to side, it is easy to spill over the edges of the user's monitor, particularly if it's a 4:3, in the event either the options are too verbose or there are too many options presented by a single message form. Currently, there's no way to list them from top to bottom as they were in previous Bethesda games. To mitigate this, keep the button text to a minimum and/or make sure to always set up conditions on mutually exclusive buttons to ensure only applicable options are presented. | *Given the buttons in Skyrim are listed from side to side, it is easy to spill over the edges of the user's monitor, particularly if it's a 4:3, in the event either the options are too verbose or there are too many options presented by a single message form. Currently, there's no way to list them from top to bottom as they were in previous Bethesda games. To mitigate this, keep the button text to a minimum and/or make sure to always set up conditions on mutually exclusive buttons to ensure only applicable options are presented. | ||
*To conditionalize buttons | *To conditionalize buttons upon script/quest variables, use [[GetVMScriptVariable]] and [[GetVMQuestVariable]]. | ||
*To hide buttons you wish to fill in later, add an impossible condition like 'IsXBox == -1'. | *To hide buttons you wish to fill in later, add an impossible condition like 'IsXBox == -1'. | ||
* Conditionalizing MessageBox buttons will not change their indices such that, for instance, button 9 will still execute the "Done" code in the last example even if buttons 0-8 are hidden. | |||
*Conditionalizing MessageBox buttons will not change their indices such that, for instance, button 9 will still execute the "Done" code in the | * To learn how to assign user-created messageboxes as values to the message box properties defined in the above scripts, see [[Bethesda_Tutorial_Papyrus_Introduction_to_Properties_and_Functions#Hooking_up_the_message_boxes_to_the_properties_in_the_script|the Papyrus tutorial's page on Properties and Functions]] | ||
*To learn how to assign user-created messageboxes as values to the message box | *If the Message property isn't filled in the CK the Show() will always return a 0. | ||
*If the Message | *If the Message is a Notification (without buttons) instead of a Message Box the Show() will return a -1. | ||
*If the Message is a Notification (without buttons) instead of a Message Box the Show() will return a -1 | |||
== See Also == | == See Also == | ||
[[Show - Message]] | [[Show - Message]] |