User:Quetzilla/How to Use QZ Menus

< User:Quetzilla
Revision as of 02:06, 17 January 2009 by imported>Quetzilla (New page: =Work In Progress= == About QZ Menus == QZ Menus is a modder's resource which is designed to enable you to make simple or complex Menu Systems without worrying about any of the annoying s...)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Work In Progress

About QZ Menus

QZ Menus is a modder's resource which is designed to enable you to make simple or complex Menu Systems without worrying about any of the annoying scripting usually involved with that. It is bafflingly simple to use, and I guarantee you will never go back to writing your own menu scripts again.

Using QZ Menus

The following may look like a lot of steps, but it's really not. Trust me.

Setting Up

Setting up is simple, but you have to do it right or things won't work.

  1. QZ Menus requires FOSE so make sure to install that first.
  2. Next, download QZ Menus, which you can find here, then install the files to your /Data/ folder.
  3. In order to use QZ Menus with the GECK, you need to enable multiple master editing in the GECKCustom.ini file. Directions for that can be found here.
  4. The next step is to load QZ Menus.esm when working on your mod. In the Data Files window of the GECK, set your mod as the Active File, but make sure to put a checkmark next to QZ Menus.esm (which will be at the top of the list). You only need to do this the first time you use QZ Menus with a mod, the next time it will be loaded automatically.

Creating Your Menu

QZ Menus uses Form Lists called MenuNodes to represent entire menu systems. Exactly how these MenuNodes work will be explained shortly, but it's easier to explain how one works after you've already set one up, so let's do that first.

Let's say we want to make a menu that does the following: The first message that pops up will ask the user to pick from 3 doors. The message will have 3 buttons: Door 1, Door 2, Door 3. Picking the right door will let the user pick a prize. Here's how to create the whole system:

  1. Create a Form List named 'PickADoorNode', and another Form List named 'PickYourPrizeNode'
  2. Create a Message named 'PickADoorMessage', type in some text telling the user to pick a door, then label 3 buttons: Door 1, Door 2, Door 3.
  3. Create a Message named 'PickYourPrizeMessage', type in some text telling the user to pick a prize, then label 3 buttons: Sniper Rifle, Stimpak, and 2 SPECIAL Points.
  4. Create a Message named 'WrongDoorMessage', type in some text telling the user they picked the wrong door.
  5. Create a Key item named 'StatPointsAction' and also create a new script and attach it to the Key. Paste the following code into the text area for the script:
scn StatPointsActionScript

begin onadd player
    AddSPECIALPoints 2
end

Now we've got the pieces we need we can assemble our MenuNodes. Open the PickADoorNode form list and add objects to it so that they show up in this order:

  • PickADoorMessage
  • WrongDoorMessage
  • PickYourPrizeNode
  • WrongDoorMessage

Next, Open the PickYourPrizeNode form list, and add object so that they show up in this order:

  • PickYourPrizeMessage
  • WeapSniperRifle
  • Stimpak
  • SkillPointsAction

Congratulations, we're almost done! Now if only we knew what we were doing...

How It Works

You may be able to piece together how the system works now. To start a menu system, we tell QZ Menus to start with one MenuNode. The first item in the MenuNode is the Message to display, and the rest of the items in the MenuNode list tell QZ Menus what to do when the user presses the associated button. Depending on what type of object is associated with a button, QZ Menus will do different things:

  • If the object is a MenuNode, it will set that node as the new node, display the message for that node, then wait for the user to press a button. It will assume that any Form List is a MenuNode, with a few exceptions for special menu actions (covered further down).
  • If the object is a Message, it displays that message, and when the user presses a button it displays the message for the MenuNode again. Technically the message can have any number of buttons, but since they'll all do the same thing it's best just to have one or none.
  • If the object is a Key, it interprets it as a scripted action, because if the script attached to the key has an 'onadd player' block, such as the one in our example does, then that script will run when the user presses that button. Sometimes we'll want the scripted action to display another menu (see the Notes section below), and this can be indicated by giving the Key object a weight greater than zero. If the system sees that the Key has a weight value, it will wait 4 seconds for the key's script to initiate the new menu. After 4 seconds it will automatically timeout to prevent buggy scripts from locking up the system. If the Key has a weight of zero, it will assume that that action doesn't lead to a new menu and will stop processing the current MenuNode.
  • If the object is any other inventory item, it will add one of those items to the player's inventory. It doesn't do anything special like for Keys.
  • If the object is a Perk, Ability, or Addiction it will be added to the player.
  • If the object is a regular Actor Effect, it will be cast on the player using CastImmediateOnSelf.
  • If the object is a Quest, it will start that quest, or if the quest is already started, it will stop the quest.
  • If the object is an ImageSpace Modifier, it will apply it, or if it is already active it will remove it.

Future versions may add handling for other object types as well.

Now, we've got our menu system set up, and hopefully we understand how it's supposed to work. We're almost done!

Queueing the Menu

Because there may be multiple mods that want to display a menu system at a particular time, QZ Menus uses a Queue system. To display our Mystery Door menu system requires only about two-and-a-half lines of script:

ref node
...
set node to PickADoorNode
ListAddForm MenuQueue node

(The reason we ahve to use the 'node' variable is that the compiler apparently doesn't like to see Form Lists as function arguments)

Assuming there are no other menus in the queue, QZ Menus will get your MenuNode from the queue and start up the menu system we made earlier. If another mod already has a menu system active, then your Node will wait in the queue until the previous menu system finishes.

That's it, there's really nothing else to do! No need to check for buttons to be pressed, manage menu sub levels, or any other annoying and complicated thing. QZ Menus handles all of that. You tell it to go and off it goes. Without QZ Menus, the above menu system would have taken 50-100 lines of code and who knows how many hours of debugging. With QZ Menus, you only wrote about 6 lines of code, and stuck some items in some form lists. Easy huh?

The Node system also allows you to set up relatively complex menu systems that would drive even the most experienced scripters absolutely crazy trying to set up normally (believe me, I know -- how do you think I ended up making this thing?!). If you really wanted to, you could probably remake Zork entirely with QZ Menus!

Things to Know

There are a few special (and empty) form lists included in the QZ Menus.esm file that perform special actions. You can use these in MenuNodes just like you would any other object:

  • MenuExit - this exits the current menu system entirely. If there is a MenuNode waiting in the queue, that MenuNode will take over.
  • MenuBack - this returns to the previous menu node. This is useful if you have one particular node that you might want to access from lots of other nodes, but you need to be able to get back to the node that linked to it in the first place.
  • MenuMore - this allows you to combine get around the 10 button limit by providing a 'More' button, and requires a specially structured MenuNode. Basically you set it up so that you have your Message at the top of the list as usual, followed by 10 objects to correspond to 10 buttons, but one of these buttons will be the MenuMore object. After these 10 buttons you then add another Message with button labels, followed by up to 10 associated objects. When the user presses the More button, it will simply display the second message and match the button presses to the second set of objects. You can continue using the MenuMore object to have as many buttons as you want in one node. The benefit of using this method is that you get to keep all of the objects in one list for better management, and the node is considered a single node for purposes of using MenuBack.

One drawback of the QZ Menus system is that it doesn't support using variables in the message windows such as %f and %g. When FOSE adds string support, it will be possible to work around this by using scripted actions to directly set the message text as desired.

Another thing you might run into is the need for multiple scripted actions for the same menu node -- do you really have to create a new Key item AND script for each button? Fortunately, the answer is no. You can use one key object for all the buttons in a MenuNode -- you could even use one Key object for an entire menu system. The QZ Menus script keeps track of the last button chosen in the variable LastChoice of the QZMenus quest, and you can access this number in a script:

set choice to QZMenus.LastChoice

So you can use the one Key item to check the variable for which button was pressed and have it do different things accordingly. There's one catch -- you still need to put the Key Object in the MenuNode list for each button it should handle, but the GECK won't let you add the same item to a list twice. Luckily FO3Edit does let you add more than one of an item to a form list, so you can just use that to get it set up properly. Additionally, you can check the ID of the current MenuNode by accessing QZMenus.CurrentMenuNode.