/*SIMPLE MENU v1.0 follow the comments to use this Lua in your mod, if you find any issue let me know! -Felix44*/ local function sayHi() print("hi!") --this function is only for showing how a function settings works, you are free to remove it end addHook("PlayerSpawn", function(player) player.menu = {} player.menu.pointer = 1 player.menu.show = false player.menu.timer = 0 player.menu.contents = { {value = 0, name = "Slider 1", description = "This slider has 10 different values", maxvalue = 10, slider = true}, {value = 1, name = "Boolean 1", description = "A boolean (ON/OFF) setting"}, {value = 0, name = "Slider 2", description = "This slider has 4 different options", maxvalue = 4, slider = true}, {value = 1, name = "Value 9", description = "This setting can have different values,\nand it can be toggled by Slider 2", maxvalue = 5, options = {"OPTION 1", "OPTION 2", "ANOTHER OPTION", "4TH OPTION", "5TH"}, toggledby = 3}, {value = 1, name = "Say hi", description = "This option calls a function!", func = sayHi}, {value = 1, name = "Boolean 2", description = "A boolean (TRUE/FALSE) setting", options = {"FALSE", "TRUE"}}, {value = 0, name = "Slider 3", description = "This slider has 100 different values", maxvalue = 100, slider = true} } io.openlocal("client/Name.dat", "a+"):close() --you can change "Name" to something else, change it for the line below too if you do local file = io.openlocal("client/Name.dat", "r+") for i = 1,#player.menu.contents if player.menu.contents[i].func then continue end if not player.menu.contents[i].maxvalue player.menu.contents[i].maxvalue = 2 elseif player.menu.contents[i].maxvalue == 1 CONS_Printf(player, "\133Setting "..i.."'s maxvalue is 1! Are you sure it's intentional?") player.menu.contents[i].maxvalue = 2 CONS_Printf(player, "\133Maxvalue was set to 2.") elseif player.menu.contents[i].maxvalue < 1 CONS_Printf(player, "\133Setting "..i.."'s maxvalue("..player.menu.contents[i].maxvalue..") is too small! Are you sure it's intentional?") player.menu.contents[i].maxvalue = 2 CONS_Printf(player, "\133Maxvalue was set to 2.") end if not player.menu.contents[i].options player.menu.contents[i].options = {"OFF", "ON"} elseif #player.menu.contents[i].options < player.menu.contents[i].maxvalue and not player.menu.contents[i].slider CONS_Printf(player, "\133Setting "..i.."'s options can't be fewer than maxvalue("..player.menu.contents[i].maxvalue..")!") for e =1,player.menu.contents[i].maxvalue if player.menu.contents[i].options[e] then continue end player.menu.contents[i].options[e] = "Missing!" end end --player.menu.contents[i].value = tonumber(valt:sub(i-funcopts, i-funcopts)) local text = file:read("*l") if text player.menu.contents[i].value = tonumber(text) end end end) /*player.menu.contents is the main part of the menu, you can have as many elements as you want, but it might be best not to have more than 10, "value" sets their value, starting from 0, set this value to the setting's default value use this for your checks in your Lua, an example is at the end of this Lua "name" is the name of the setting that will appear on the menu "description" is the small text that will appear on the bottom of the screen "toggledby" is an extra parameter for subsections, set it to the number of the setting which your subsection setting should be depending on do note that if the setting that controls the subsecton is off, it will make the subsection not modifiable, but it will NOT set it to false automatically, remember that when making the checks in your other Luas "func" is an extra parameter for function setting, this settings can't be toggled on/off, selecting them will call the given function "maxvalue" is for a setting with more than 2 options, set this parameter to the amount of options your setting can be (max is 10!) do note that "value" starts from 0, so if for example you want a 3 option setting "value" will start from 0 and reach it's max at 2 (maxvalue would still have to be set to 3 though) if this parameter is omitted it will be set to 2 (equivalent to an ON/OFF setting) "options" must be a table containing the names of all the possible setting's options, this table should be as long as maxvalue (example: if maxvalue is 3 the table should contain 3 strings) if this parameter is omitted it will be set to {"OFF", "ON"} "slider" is a boolean parameter that when set to true it displays a slider instead of a string, thus "options" can be omitted */ addHook("PlayerCmd", function(player, cmd) local menu = player.menu menu.timer = max($-1, 0) if menu.show == false or menu.timer then return end if cmd.forwardmove > 0 menu.pointer = max($-1, 1) menu.timer = 5 S_StartSound(player.mo, sfx_menu1, player) elseif cmd.forwardmove < 0 menu.pointer = min($+1, #menu.contents) menu.timer = 5 S_StartSound(player.mo, sfx_menu1, player) end if cmd.buttons & BT_JUMP if menu.contents[menu.pointer].toggledby and menu.contents[menu.contents[menu.pointer].toggledby].value == 0 then return end if menu.contents[menu.pointer].func menu.contents[menu.pointer].func() else menu.contents[menu.pointer].value = ($+1)%menu.contents[menu.pointer].maxvalue end menu.timer = 5 S_StartSound(player.mo, sfx_menu1, player) end end) addHook("PlayerThink", function(player) if player.menu.show player.powers[pw_nocontrol] = 1 player.powers[pw_flashing] = 1 end end) COM_AddCommand("showmenu", function(player) --you can change the command's name to anything you want if not (player.mo and player.mo.valid) CONS_Printf(player, "You must be in a level to use this.") return end player.menu.show = not $ if player.menu.show == false local file = io.openlocal("client/Name.dat", "w") --if you changed "Name" in the other lines, change it here too! for i = 1,#player.menu.contents if player.menu.contents[i].func then continue end file:write(player.menu.contents[i].value.."\n") end file:close() end end, COM_LOCAL) local mapColors = { --this changes the menu's color based on the player's, I guess you can change it if you want [0] = 0, [V_MAGENTAMAP] = 182, [V_YELLOWMAP] = 74, [V_GREENMAP] = 115, [V_BLUEMAP] = 159, [V_REDMAP] = 41, [V_GRAYMAP] = 20, [V_ORANGEMAP] = 58, [V_SKYMAP] = 141, [V_PURPLEMAP] = 187, [V_AQUAMAP] = 173, [V_PERIDOTMAP] = 94, [V_AZUREMAP] = 170, [V_BROWNMAP] = 249, [V_ROSYMAP] = 203, [V_INVERTMAP] = 31 } hud.add(function(v,player) --this draws the menu on the screen, you can change the values to what you prefer if you know what you are doing if not player.menu.show then return end local color = mapColors[skincolors[player.skincolor].chatcolor] v.drawFill(60, 25, 200, 25+(10*#player.menu.contents), color) v.drawString(160, 30, "SIMPLE MENU", 0, "center") --you should probably change this to something that fits for your menu though for i = 1,#player.menu.contents local thecolor = 0 local thex = 0 if player.menu.pointer == i then thecolor = V_YELLOWMAP end if player.menu.contents[i].toggledby thex = 10 if player.menu.contents[player.menu.contents[i].toggledby].value == 0 thecolor = $|V_TRANSLUCENT end end local thename = "Missing name!" if player.menu.contents[i].name and player.menu.contents[i].name ~= "" thename = player.menu.contents[i].name end v.drawString(65+thex, 35+(10*i), thename, thecolor|V_ALLOWLOWERCASE) if not player.menu.contents[i].slider local thevalue = player.menu.contents[i].func and "" or player.menu.contents[i].options[player.menu.contents[i].value+1] v.drawString(255, 35+(10*i), thevalue, thecolor, "right") elseif not player.menu.contents[i].func local patchs = v.cachePatch("M_SLIDEL") local patchm = v.cachePatch("M_SLIDEM") local patche = v.cachePatch("M_SLIDER") local patchc = v.cachePatch("M_SLIDEC") v.draw(213, 35+(10*i), patchs) for e = 1,8 v.draw(215+(4*e), 35+(10*i), patchm) end v.draw(249, 35+(10*i), patche) local value = player.menu.contents[i].value local maxvalue = player.menu.contents[i].maxvalue-1 v.drawScaled(FRACUNIT*215 + 36*FixedDiv(value, maxvalue), FRACUNIT*35 + (10*i)*FRACUNIT, FRACUNIT, patchc) end end local patch = v.cachePatch("M_CURSOR") v.draw(45, 35+(10*player.menu.pointer), patch) local desctext = "No description found!" if player.menu.contents[player.menu.pointer].description and player.menu.contents[player.menu.pointer].description ~= "" desctext = player.menu.contents[player.menu.pointer].description end v.drawString(60, 160, desctext, V_ALLOWLOWERCASE, "thin") end) /*EXAMPLE FOR CHECKING A SETTING'S VALUE you have to check player.menu.contents[n].value, where n is the setting's number, this will return 1 when on and 0 when off, here's an example: local function myCoolFunction() if player.menu.contents[1].value --some cool code end return end to check for multi-options setting's value, you do the same, do note that the value start from 0 while maxnumber "starts" from 1, so to check for the first value you check for 0, for the 2nd you check for 1 and so on local function myOtherFunction() if player.menu.contents[2].value < 5 print("smol number") else print("beeg number") end end */