News: Welcome back to Bullworth! If you haven't already, you will need to reset your password..


Author Topic: Menu's  (Read 1513 times)

0 Members and 1 Guest are viewing this topic.

Offline boyser

  • Wazzzuuupppp
  • Full Member
  • ***
  • Posts: 176
  • Gender: Male
  • THE REAL G IS ME
    • View Profile
Menu's
« on: February 27, 2016, 09:57:55 AM »
Can someone help me do a menu with multiple menu's like the super mod or the selector mod?

Offline DaBOSS54320

  • Hero Member
  • ****
  • Posts: 3,398
  • Gender: Female
    • View Profile
Re: Menu's
« Reply #1 on: February 27, 2016, 07:06:05 PM »
Once you understand how tables work and you feel confident using them effectively, this should be an easy task. I'll go from simple menus to what you're asking to make sure you understand all the concepts needed.

The basic idea of a menu in LUA is simple. Have a table with all your options, and a variable with your current selection to use as a key/index to the table. For example...

local menu = {"Option 1","Option 2"}
local selection = 1

This code does a few things. First, it creates a table in memory with 2 strings in it, then assigns that "menu" variable to be a reference to it (so using menu will access the table in memory). Secondly, it creates a selection variable and gives it the value 1. We can use that selection to get a part of the table.

menu[selection] -- this evaluates to "Option 1", because the value of selection is 1 and the first entry of the table is "Option 1". here, selection is referred to as the key.
menu[1] -- this also evaluates to "Option 1", because the first entry of the table is "Option 1". here, 1 is referred to as the key.
menu[2] -- this evaluates to "Option 2", because the second entry of the table is "Option 2". here, 2 is referred to as the key.

Pretty simply stuff. Now, for it to work like a menu that you can browse through, you just simply have to allow the value of selection to change according to some button presses. Below is a full example.

Code: [Select]
function MissionSetup()
  -- Transition to coordinates (270, -110, 6) in area #0 (outside).
  AreaTransitionXYZ(0,270,-110,6)
end

function main()
  -- First, create our table, and create the 2 variables we need.
  local menu = {"Model Selector","Style Selector","Menu #3","P_Striker_A evade FULL look down strafe menu"}
  local selection = 1
 
  -- Start the main loop. the code between [i]do[/i] and [i]end[/i] will keep running over and over until the value between [i]while[/i] and [i]do[/i] evalutes to false (which it never will, because we used a constant value of [i]true[/i]).
  while true do
    -- Print the menu (text)
    TextPrintString(menu[selection],0,1) -- the 0ms means 1 frame.
   
    -- Wait 0 ms (this suspends the script for 1 frame so the text can show and so the game has a chance to process button presses before we call any button related functions.
    Wait(0)
   
    -- See if any buttons were pressed.
    if IsButtonBeingPressed(0,0) then
      -- 0 was pressed on controller 0 (player 1's controller, which can also be a keyboard. whatever the player is using to control jimmy is controller 0). decrement [i]selection[/i].
      selection = selection - 1
     
      -- Make sure [i]selection[/i] is still at least 1. (since the first entry in our table is accessed using [i]1[/i].
      if selection < 1 then
        selection = 1
      end
    elseif IsButtonBeingPressed(1,0) then
      selection = selection + 1
     
      -- Make sure [i]selection[/i] is no higher than the amount of elements in our table (we can get this by using [i]table.getn[/i])
      if selection > table.getn(menu) then
        selection = table.getn(menu)
      end
    end
   
    -- This is the end of the [i]while[/i] loop. now the script will go back to the start of the loop (where [i]do[/i] is) and continue from there again
  end
end

Once you fully understand how that works, we can move onto having multiple values in one option instead of just one string. This is really quite simple. All you need to do is instead of having strings, have tables. Those tables should contain things like the name of the option and the function that the option is related to. So like...

local menu = {{"Option 1",F_PlayerSetHealth},{"Option 2",F_PlayerSetInvincible}}

Or you can even just put the function right in there, it's really the same effect since similarly to tables, functions are just stored in memory and the variables are just references to them instead of each variable having storing the entire function. So...

local menu = {{"Option 1",function() PlayerSetHealth(PedGetMaxHealth(gPlayer)) end},{"Option 2",function() --[[ whatever ]] end}}

You could even add some linebreaks so it looks neater. Notice how we set that up the name (a string) is the first part of each option's table, and the function is the second part. So...

menu[selection] -- this is the option table (using selection the same way as before)
menu[selection][1] -- this is the string in the option table (the 1st part of the option table)
menu[selection][2] -- this is the function in the option table (the 2nd part of the option table)
menu[selection][2]() -- this calls the function in the option table

So now it'd basically be like the example up above, but when printing the text just remember to specify the first part of the table (by appending that [1]) and add an if statement for a button to call the function.

So now we have a table (the menu) of tables (the options). How would we add more menus? Well simply add a 3rd thing of tables! So it'd become a table (the menu) of tables (of sub-menus) of tables (the options). Well... there is one more thing to consider. Each of the sub-menus should have their own selection variable. So how should we set this up? A good way is for each sub-menu to be a table that is composed of 3 values. A selection variable, another table (for the options), and the name of the menu. I'll use linebreaks this time to make it clearer, but this is totally optional.

local menu = {
  {"Menu 1",menu1options,1}, -- first value is the name (a string), next is the options (a table, referenced by that menu1options variable), and 3rd is the selection (a number).
  {"Menu 2",{--[[ options here ]]},1} -- same as above, but here we create the table right in the menu table instead of using a variable.
}

We'll also have to change the code up a bit. I'll make a bunch of comments to help you understand.

Code: [Select]
function MissionSetup()
  AreaTransitionXYZ(0,270,-110,6)
end

function main()
  local menu = {
    {"Menu 1",{
      {"Full health",function()
        PlayerSetHealth(PedGetMaxHealth(gPlayer))
      end},
      {"Give apple",function()
        PlayerSetWeapon(310,1)
      end}
    },1},
    {"Menu 2",{
      {"Set P_Striker_A",function()
        if not HasAnimGroupLoaded("F_Preps") then
          LoadAnimationGroup("F_Preps")
        end
        if not HasAnimGroupLoaded("P_Striker") then
          LoadAnimationGroup("P_Striker")
        end
        if not HasAnimGroupLoaded("Straf_Prep") then
          LoadAnimationGroup("Straf_Prep")
        end
        PedSetActionTree(gPlayer,"/Global/P_Striker_A","Act/Anim/P_Striker_A.act")
      end}
    },1}
  }
  local selection = 1
  local currentMenu = nil -- this is where we will store the current sub-menu. when this is nil (nil means no value) then that means there is no sub-menu being used
 
  while true do
    if currentMenu == nil then -- it is nil, so browse the main menu
      TextPrintString(menu[selection][1],0,1)
      Wait(0)
      if IsButtonBeingPressed(0,0) then
        selection = selection - 1
        if selection < 1 then
          selection = 1
        end
      elseif IsButtonBeingPressed(1,0) then
        selection = selection + 1
        if selection > table.getn(menu) then
          selection = table.getn(menu)
        end
      elseif IsButtonBeingPressed(3,0) then -- we'll use 3 (zoom-out) for selecting a menu
        currentMenu = menu[selection] -- currentMenu now refers to the currently selected sub-menu table. currentMenu is no longer nil so next time the while loop runs, the 'else' part will run instead of this part.
      end
    else -- it is not nil, so browse that menu
      -- currentMenu refers to a sub-menu table
      -- currentMenu[1] is the name of the sub-menu
      -- currentMenu[2] is the table of options
      -- currentMenu[3] is the selection in that sub-menu
      -- currentMenu[2][currentMenu[3]] is the currently selected part of the table of options
      -- currentMenu[2][currentMenu[3]][1] is the name of the option
      -- currentMenu[2][currentMenu[3]][2] is the function
      TextPrintString(currentMenu[2][currentMenu[3]][1],0,1)
      Wait(0)
      if IsButtonBeingPressed(0,0) then
        currentMenu[3] = currentMenu[3] - 1
        if currentMenu[3] < 1 then
          currentMenu[3] = 1
        end
      elseif IsButtonBeingPressed(1,0) then
        currentMenu[3] = currentMenu[3] + 1
        if currentMenu[3] > table.getn(currentMenu[2]) then
          currentMenu[3] = table.getn(currentMenu[2])
        end
      elseif IsButtonBeingPressed(3,0) then
        currentMenu[2][currentMenu[3]][2]()
      elseif IsButtonBeingPressed(2,0) then -- we'll use 2 as a back button (zoom-in).
        -- make currentMenu nil again so it doesn't refer to any table, making it so you'll be browsing through the main menu again
        currentMenu = nil
      end
    end
  end
end

And there ya go! You have my full permission to use the code given in this post any way you'd like, however I do strongly encourage you to rewrite your own version of it using what you've learned so that you can both understand how it works and make your own version better suited to your needs.

Good luck and have fun!