Difference between revisions of "MessageBox Tutorial"
Jump to navigation
Jump to search
→Avoiding Common Mistakes for More Complex Menus: Rewrite
imported>ShadowDancer m (→Multiple Menus in a Spell Script: typed the wrong thing) |
imported>Haama |
||
|
==Avoiding Common Mistakes for More Complex Menus==
===Starting, stopping, and the first menu===
You won't want your menu script to run all the time, so it needs a clear beginning and a clear ending. On activators you can use the onActivate block and Activate it to start the menu:
<pre>begin onActivate
messagebox "What would you like to do?" "Button 0" ... "Button 9"
set Choosing to 1
end
begin GameMode
if (Choosing == 1)
set Choice to GetButtonPressed
...</pre>
This works, but you will never be able to return to the first menu. To fix this, place the menu in the GameMode block, and start it up like this:
<pre>
set Choosing to -1
end
begin GameMode
if (Choosing == -1)
messagebox "What would you like to do?" "Button 0" ... "Button 9"
elseif (Choosing == 1)
set Choice to GetButtonPressed
...</pre>
For the ending, you can set '''''Choosing''''' back to 0. However, note that the GameMode block continues to run. To reduce the number of '''if''' tests run each frame, [[Return]] if '''''Choosing''''' is 0:
<pre>begin onActivate
set Choosing to -1
end
begin GameMode
if (Choosing == 0)
return
elseif (Choosing == -1)
...
===Keeping multiple menus separated===
Multiple menus require careful use of a governing variable to keep the menus separate. The most common error is to place the second menu within a button response, like this:
<pre>begin onActivate
messagebox "What would you like to repair?" "Armor" ... "Weapons"
end
begin GameMode
set Choice to GetButtonPressed
if (Choice == -1)
...
elseif (Choice == 0) ;Armor
messagebox "Which armor would you like to repair?" "Helmet" ... "Boots"
set Choice2 to GetButtonPressed
if Choice2 == -1
...
elseif (Choice2 == 0) ;Helmet
...
elseif (Choice2 == 9) ;Boots
...
endif
elseif (Choice == 9) ;Weapons
messagebox "Which weapon would you like to repair?" "Blade" ... "Bow"
...</pre>
If the player selects "Armor" from the first menu, the second menu ("Which armor would you like to repair") will be displayed, but any choice the player makes will really be based on the first menu. For instance, if the player selects "Boots" in the second menu, the "Which weapons would you like to repair?" menu will be displayed.
Following the steps of the script, you can see why. The player will be shown the "What would you like to repair?" menu. They select "Armor". For a few frames GetButtonPressed sets Choice to -1. About 15 frames after the player makes their choice, GetButtonPressed will return 0. This will bring up the second menu "Which armor...?". Choice2 will be set to -1, as the player hasn't read it yet. The player selects "Boots". Again, there will be several frames between the menu, and when GetButtonPressed returns the player's choice. This means the script will be running from the beginning of the GameMode block again. This time, Choice is set to 9 (because "Boots" was the tenth button), and the "Which weapon...?" menu is opened.
To prevent this from happening, use the Choosing variable to keep menus separate:
<pre>begin onActivate
set Choosing to -1
end
begin GameMode
if (Choosing == 0)
return
elseif (Choosing == -1)
messagebox "What would you like to repair?" "Armor" ... "Weapons"
set Choosing to 1
elseif (Choosing == 1)
set Choice to GetButtonPressed
if (Choice == -1)
...
elseif (Choice == 0) ;Armor
set Choosing to -10
...
elseif (Choice == 9) ;Weapons
set Choosing to -11
endif
elseif (Choosing == -10) ;Armor
messagebox "Which armor would you like to repair?" "Helmet" ... "Boots"
set Choosing to 10
elseif (Choosing == 10)
set Choice to GetButtonPressed
if (Choice == -1)
...
elseif (Choice == 0) ;Helmet
set Choosing to 0 ;To exit
...
elseif (Choice == 9) ;Boots
set Choosing to 0 ;To exit
endif
elseif (Choosing == -11) ;Weapon
messagebox "Which weapon would you like to repair?" "Blade" ... "Blunt"
set Choosing to 11
elseif (Choosing == 11)
set Choice to GetButtonPressed
if (Choice == -1)
...
elseif (Choice == 0) ;Blade
set Choosing to 0 ;To exit
...
elseif (Choice == 9) ;Blunt
set Choosing to 0 ;To exit
endif
endif
end</pre>
Note that each menu has a pair of corresponding numbers: Main menu, -1/1; Armor menu, -10/10; Weapon menu, -11/11. When you set Choosing to the corresponding number, that menu will be shown. See a better example of this in the [[Messagebox Tutorial# Moving Between Multiple Menus]].
===Running the same choice for multiple frames===
So far, we've set up the button catching section like this:
<pre>...
if
return
elseif (Choice == 0)
...</pre>
For 99% of what you'll do, this will work perfectly. However, let's say you need to scan through the player's inventory one item at a time:
<pre>...
elseif (Choosing == -1)
messagebox "What would you like to do?" "Duplicate everything" "Nothing"
set Choosing to 1
set Choice to GetButtonPressed
elseif (Choosing == 1)
set Choice to GetButtonPressed
if (Choice == -1)
return
elseif (Choice == 0) ;Duplicate items one by one from the player, into a container
set InvPos to (InvPos + 1)
set pInvObj to (player.GetInventoryObject
pContainer.AddItem pInvObj 1
...
elseif (Choice == 1) ;Nothing
set Choosing to 0 ;To exit
endif
...</pre>
"Duplicate Everything" requires several frames to complete. Once GetButtonPressed returns the player's choice, it will start off and add the first item to the container. However, on the following frames GetButtonPressed will return -1, causing an infinite loop of 'if (Choice == -1) -> return'. To prevent this, only run GetButtonPressed when it had previously returned -1:
<pre>...
elseif (Choosing == -1)
messagebox "What would you like to do?" "Duplicate everything" "Nothing"
set Choosing to 1
set Choice to -1
elseif (Choosing == 1)
if (Choice == -1)
set Choice to GetButtonPressed
elseif (Choice == 0) ;Duplicate items one by one from the player, into a container
set InvPos to (InvPos + 1)
set pInvObj to (player.GetInventoryObject
pContainer.AddItem pInvObj 1
...
elseif (Choice == 1) ;Nothing
set Choosing to 0 ;To exit
endif
...</pre>
Note that Choice is reset to -1 after displaying a menu. Otherwise, Choice would still be the same as for the last menu (let's say the player choose 0). This would not be -1, so GetButtonPressed would never be run, and that Choice (0) would run instead of the player's choice.
==Creating Your New Menu==
| |||