# F2 Menu (for derpy's script server)

## Thanks for downloading!

Thanks for using F2 menu! As a server owner, this mod should simply work out of the box for you. Just make sure that you keep the folder name as "f2menu" when you install it, as that's what other mods will expect when listing it as a dependency.

Also be sure to check out config.ini to change the menu text, key bind, or menu order.

## Scripting for F2 menu.

Do you want to make your mod work with f2menu? Well, integrating with it is as simple as handling the f2menu:Open event. This event passes a single function for you to call to add to the menu, and it runs each time the menu is opened so you won't have to worry about your menu option being missed. The function takes a single table with information about the menu option and what to do when it is selected.

`-- simple f2menu example RegisterLocalEventHandler("f2menu:Open", function(f_add) f_add({name = "Give Money", func = function() PlayerAddMoney(10000) end}) end)`

In the above example, you can see the most basic way to add an option by specifying a callback for "func". However, most the time you'll want more than a single option. The preferable way to use f2menu is to actually add your own sub-menus that your script controls. We can do this by instead specifying a "thread" that will be run when the option is selected. You can do this by assigning a function to the "thread" field, and that function will be used to create a thread. The thread will be passed the parent menu and the option table. You should usually use the parent to make a submenu so that the menu's visual settings are preserved.

When creating a thread like that, you'll have the freedom to make your menu however you like. Usually this will involve you using the utility/menu package, but you can script your menu however you like. Since f2menu has already loaded the package and will be passing your thread a parent menu to work off of, it's not necessary to require the package again.

`-- advanced f2menu example RegisterLocalEventHandler("f2menu:Open", function(f_add) f_add({ name = "Sub Menu Example", description = "Open the example menu.", thread = M_ExampleMenu, }) end) function M_ExampleMenu(parent, selected) local menu = parent:submenu(selected.name, "This is an example sub-menu for f2menu.") while menu:active() do if menu:option("Give Money") then PlayerAddMoney(10000) elseif menu:option("Give Up") then PedSetActionNode(gPlayer, "/G/HITTREE/STANDING/POSTHIT/STANDING/DEAD/COLLAPSE/COLLAPSE_B", "") PlayerSetHealth(0) end menu:draw() Wait(0) end end`

One last example I'd like to cover is in the case of giving your options some sort of state. Of course, you can use global variables for all your options if you want. But sometimes it's a lot neater to keep things packed in option tables, which is what you can do as long as you make sure your option table isn't re-created every time we handle the f2menu:Open event. If your option doesn't require persistent state though, remember it is perfectly okay to re-create the table every time like I've been showing in the examples up to this point.

`-- persistent option f2menu example require("utility/menu") gOptions = { -- important we make the option tables *once* so their state is preserved { name = "Disable Punishment System", description = "Turn the punishment system on or off.", right = "[OFF]", disable_punishment = false, -- this option isn't used by f2menu, it's entirely custom func = function(option) option.disable_punishment = not option.disable_punishment option.right = option.disable_punishment and "[ON]" or "[OFF]" DisablePunishmentSystem(option.disable_punishment) end, }, } RegisterLocalEventHandler("f2menu:Open", function(f_add) for _, option in ipairs(gOptions) do f_add(option) -- add each option table end end)`

## Event Specification

Here's a list of every event that can be triggered by f2menu.

### "f2menu:Open"

Triggered on the client when the player opens their f2menu, so that other scripts can add menu options.

It passes 1 argument, a function to add an option to f2menu. The function should be called for each option you want to add to / keep in the menu, and only be called during the event. If any callback returns true, the menu will not open. You can do this to prevent the menu from opening during times you want the menu disabled.

### "f2menu:Close"

Triggered on the client when the player closes their f2menu. It passes nothing and discards the results of every callback.

### "f2menu:Shutdown"

Triggered when the f2menu shuts down. This is a good time to perform any emergency cleanup. It passes nothing and discards the results of every callback. The "f2menu:Close" event is also triggered right before this if the menu was open.

## Shared Function Specification

Here's a list of every shared function that you can use with the global dsl table.

### dsl.f2menu.IsOpen()

Returns true if the menu is currently open.

### dsl.f2menu.Close()

Instantly closes the menu if it is open.

## Option Table Specification

Here's a list of every field you can put in your option tables when you add options during f2menu:Open. All fields are optional.

All fields designated as "menu text" are passed directly to the menu system (provided by utility/menu). These fields are only used if not nil, except for "name" which is always used. The menu system then passes them directly to the MeasureText and DrawText functions when needed, which means they'll be converted to strings using tostring if necessary as those functions are designed to do. This means you can give any type of value you want and rely on it being converted.

### "name"

The menu text that's used as the option's name.

### "right"

The menu text that shows up to the right of the option's name.

### "description"

The menu text that shows up in the description box when a menu alert isn't active.

### "priority"

Options with a higher priority are placed higher in the menu than options with a low priority. The default priority is 0. It is also worth noting that any options with the same priority are sorted by name (case-insensitive).

For more control over the order of menu items, see config.ini. If the name of a menu item is set using "menu_order", it will *always* show up in front of options that weren't.

### "func"

A function to be called synchronously when the option is selected. It cannot yield (wait), as it's not a thread.

It is passed 1 argument, the option table that was just selected. It is worth noting that this table is the exact same value that was added during the f2menu:Open event, not any form of copy. No return value is expected, and any results will be discarded.

### "thread"

A function to be run in a thread when the option is selected. This thread is attached to the script that added the option, which means it will run as if it were just created by that script in the first place rather than by the f2menu's script.

It is passed 2 arguments, the parent menu object and the option table that was just selected. You should use the parent menu object to create a sub-menu (by using `parent:submenu(...)`) instead of creating a new menu, unless you feel it's necessary to create a new menu or discard the visual style of f2menu. No return value is expected, and any results will be discarded.

Although the thread belongs to your script, it is only run when the menu isn't hidden. Since players can hide the menu at any point, this means your thread could be suspended for longer than you intended if you call Wait.

The thread is created as a "PRE_GAME" thread, which means it runs before all normal "GAME" threads. This is important because it gurantees that it will run before the f2menu's controlling thread.