Standard Menu UI/Number Setting Example

From the Oblivion ConstructionSet Wiki
Jump to navigation Jump to search

Below is the code for the Wrye Leveling options command token. This is fairly compact code for presenting several menus and handling the selected options. The point of this page is to demonstrate some techniques and standards for arranging hierachical menu code, and handling menu selections.

Background (Cobl Option Token handling):

  • This short section is a bit OT. Just FYI, explains the part of the code that's concerned with physical movement of the option tokens.
  • Option tokens are stored in a special options container. The player can then select options from the container, which then triggers the corresponding menu.
  • To prevent the player from using the container as free storage, all container contents are removed to the player when the container is closed.
  • Hence, each token, when added to the player will: 1) add a new copy of itself back into the options container, 2) (if not in cleanup mode), show the the options menu, and 3) self-destruct (removeMe).
  • Because of the way this is structured, it's guaranteed that everything that is menu display/handling related will all occure while in menu mode.

Menu Display/Handling:

  • Note that the menu display code is actually the last thing that happens. Even the onAdd block doesn't show a menu.
  • The current menu is indicated by menu variable. If this variable is negative, it means "Skip the menu handling section." So to trigger the top menu the first time, I set menu to -1; that gets inverted at the top of the handling section, and then falls through to the menu display section.
  • Menu handling is together, separate and above menu display. This means that menu handling can carry out operations and then change the current menu number as necessary. I'm starting to use the standard "menu == 100" means exit.

Button Handling Check out the menu handling section beginning with "elseif menu == 4 ;--Final Limits". There are a couple of things I need to do here:

  • Recognize the Back button.
  • Allow numbers to be incremented up or down.
  • Set restrictions on how much numbers can be incremented up or down.
  • Set different increment amounts for different buttons. Level goes up/down by 5 units at a time, while attrs and skill limit goes up/down by 10 units at a time.

So, what I do is:

  • First determine whether increment is up or down. Delta is thus set to 1 or -1 depending on whether shift key is pressed.
  • Set temp local variables to what value for each button will be if change is applied to it.
  • Finally, do the if block which:
    • Handles buttons and upper/lower limits for each item.
    • Handles back button.
    • Displays "Can't go up." or "Can't go down." message if the above blocks fail.

Note that there's a lot of similarity in the lines of the code. Coding was speeded by writing first example of a set of lines, then duplicating that several times, then doing search and replace.

scn wrLevOptOS
;--Wrye Levling: Options
short button
short menu

;--Temp values
long key
long delta
long costBase   ;--Levelup cost = costBase + nextLevel*costPerLevel
long costPerLevel 
long attrPoints  ;--Attribute points available per levelup
long skillPoints ;--Skill points available per levelup
long maxLevel   ;--Maximum level player is allowed to reach
long maxAttr     ;--Maximum value an attribute can have
long maxSkill   ;--Maximum value a skill can have
long maxAttrGain ;--Maximum attribute increase per levelup
long maxLuckGain ;--Maximum luck increase per levelup
long maxSkillGain;--Maximum skill increase per levelup
long daysBetween ;--Minimum days between levelups

begin onAdd player;-----------------------------------------------------------
;--Restock the options box
    cobOptChestRef.addItem wrLevOpt 1 

;--Ignore if added by optionsbox purge.
    if cobOptChestRef.state != 20 
        removeMe
    endif

    set menu to -1
end;onAdd

begin menuMode;---------------------------------------------------------------
    ;--Quick return if not in menu displaying mode.
    if menu == 0 
        return
    endif

    set button to getButtonPressed
    if menu < 0
        set menu to -menu
    
    elseif button == -1
        return

    elseif menu == 1;--Main Menu
        if button < 3
            set menu to button + 2
        else
            set menu to 100
        endif

    elseif menu == 2;--Cost
        set key to getKeyPress 0
        set delta to 1 - 2 * (key == 42 || key == 54)
        set costBase to wrLevZ.costBase + 25*delta
        set costPerLevel to wrLevZ.costPerLevel + 25*delta
        if button == 0 && costBase >= 0 && costBase <= 10000
            set wrLevZ.costBase to costBase
        elseif button == 1 && costPerLevel >= 50 && costPerLevel <= 10000
            set wrLevZ.costPerLevel to costPerLevel
        elseif button > 1
            set menu to 1
        elseif delta > 0
            message "That cannot be raised further."
        else
            message "That cannot be lowered further."
        endif
    
    elseif menu == 3;--Round Limits
        set key to getKeyPress 0
        set delta to 1 - 2 * (key == 42 || key == 54)
        set attrPoints   to wrLevZ.attrPoints   + delta
        set skillPoints  to wrLevZ.skillPoints  + delta
        set maxAttrGain  to wrLevZ.maxAttrGain  + delta
        set maxLuckGain  to wrLevZ.maxLuckGain  + delta
        set maxSkillGain to wrLevZ.maxSkillGain + delta
        set daysBetween  to wrLevZ.daysBetween  + delta
        if button == 0 && attrPoints >= 3 && attrPoints <= 15
            set wrLevZ.attrPoints to attrPoints
        elseif button == 1 && skillPoints >= 10 && skillPoints <= 20
            set wrLevZ.skillPoints to skillPoints
        elseif button == 2 && maxAttrGain >= 3 && maxAttrGain <= 15
            set wrLevZ.maxAttrGain to maxAttrGain
        elseif button == 3 && maxLuckGain >= 1 && maxLuckGain <= 5
            set wrLevZ.maxLuckGain to maxLuckGain
        elseif button == 4 && maxSkillGain >= 5 && maxSkillGain <= 20
            set wrLevZ.maxSkillGain to maxSkillGain
        elseif button == 5 && daysBetween >= 0 && daysBetween <= 90
            set wrLevZ.daysBetween to daysBetween
        elseif button > 5
            set menu to 1
        elseif delta > 0
            message "That cannot be raised further."
        else
            message "That cannot be lowered further."
        endif

    elseif menu == 4;--Final Limits
        set key to getKeyPress 0
        set delta to 1 - 2 * (key == 42 || key == 54)
        set maxLevel to wrLevZ.maxLevel + 5*delta
        set maxAttr  to wrLevZ.maxAttr  + 10*delta
        set maxSkill to wrLevZ.maxSkill + 10*delta
        if button == 0 && maxLevel >= 30 && maxLevel <= 100
            set wrLevZ.maxLevel to maxLevel
        elseif button == 1 && maxAttr >= 50 && maxAttr <= 250
            set wrLevZ.maxAttr to maxAttr
        elseif button == 2 && maxSkill >= 50 && maxSkill <= 250
            set wrLevZ.maxSkill to maxSkill
        elseif button > 2
            set menu to 1
        elseif delta > 0
            message "That cannot be raised further."
        else
            message "That cannot be lowered further."
        endif

    endif

;--Menus ------------------------------------------------------------------
    if menu == 1;--Main Menu
        messageBoxEx "Wrye Leveling configuration.|Cost >|Round Limits >|Final Limits >|Done"

    elseif menu == 2
        messageBoxEx "Cost = CostBase + level*CostPerLevel. Click or shift-click to modify.|CostBase %g|CostPerLevel %g|< Back" wrLevZ.costBase wrLevZ.costPerLevel
    
    elseif menu == 3
        messageBoxEx "Configure levelup round limits. Click or shift-click to modify.|Attr Points %g|Skill Points %g|Max Attr Gain %g|Max Luck Gain %g|Max Skill Gain %g|Days Between %g|< Back" wrLevZ.attrPoints wrLevZ.skillPoints wrLevZ.maxAttrGain wrLevZ.maxLuckGain wrLevZ.maxSkillGain wrLevZ.daysBetween

    elseif menu == 4
        messageBoxEx "Configure level, attribute and skills limits. Click or shift-click to modify.|Level Max %g|Attr Max %g|Skill Max %g|< Back" wrLevZ.maxLevel wrLevZ.maxAttr wrLevz.maxSkill

    elseif menu == 100;--Done
        removeMe

    endif

end;--menuMode