Skip to content

Tutorial

citrusCS edited this page Mar 10, 2019 · 4 revisions

Intro

So, you've just installed this program and you want to make some cool-looking menus in CS:GO. Before you get into actually making these, you need to know a little bit of background knowledge.

This section assumes that you know how to open and use a command prompt. If you do not know how to do that, I suggest reading this brief article, and becoming familiar with the cd command. If you do not know how to read, there is a bigger problem at hand.

This section will teach you how to invoke csgo-menu-maker and install the .cfg files that it generates.

In order to move through this tutorial, you need to have a local copy of the example repository.

If you know how to run a module's main program in python (python -m), and know how to install a configuration file in CS:GO (or any Source-based game) feel free to skip this section. If not, this section will teach you how to use the program for a very typical use case.

  1. To start, open a command prompt and navigate to the directory of the first example in the example repository.

  2. Next, run the command python -m csgomenumaker main.yml. Note that if you have multiple versions of python installed, you may need to use the commands python2 or python3 instead of just python. REMEMBER that the csgomenumaker does not have dashes in this case! No dashes!

  3. If you ran the command correctly, some instructions will be output to the screen looking like this:

Generation finished! Move the new 'menumaker' folder to your csgo cfg directory, and add this line to your autoexec:
exec menumaker/main.cfg
You may also test it by running the command in the console.

If you do not see this text, ensure that you followed all of the previous steps correctly.

  1. Next, use a file browser to navigate to your CS:GO configuration directory. On Windows, this is C:\Program Files (x86)\Steam\steamapps\common\Counter-Strike Global Offensive\csgo\cfg.

  2. Drag the menumaker folder that the command created to the directory you just opened.

  3. In CSGO, open the developer console (~) and type what the command outputted in step (3), e.g. exec menumaker/main.cfg

  4. Press ALT and an arrow key. A menu should pop up in the top left corner of the screen with some text.

  5. You're done. Onward!

File Structure

By this point, you should have a menu installed, and it should be the menu from the first lesson. Now, we will get into writing configuration files, but before that, a quick overview of the format.

Configuration files are in either YAML or JSON format. Each one has its own benefits, but for the purposes of this tutorial I will be using YAML. YAML follows a key-value format, e.g.:

key: value
string: "test"
number: 1
float: 1.0
list:
    - value1
    - value2
    - value3
object:
    nested1: 0
    nested2: "test"
    nested3: 69

You might be able to tell that the "keys" are the text to the left of each colon, and the "values" are the text to the right. I will be using these terms from now on. Values can assume different "types": a value can be a number, text (also known as a "string"), list of more values, or an "object", which allows sub-keys and sub-values.

The basic layout for a csgo-menu-maker configuration file is as follows:

settings:
    <All global settings, like keybinds, sounds, etc. go here>
tree:
    <All menu components, like choosers, sliders, and folders go here>

In many cases, you won't need to change certain key-value pairs. Most of the time, you can just omit them, for example, if you don't need to change any settings:

tree:
    ...

Because YAML allows the nesting (recursion) of key-value pairs, we are able to create some pretty elaborate data structures and thus have a very robust configuration format with lots of options.

Do note that YAML will not allow TAB ("\t") characters. Only use spaces for indentation.

If you have experience configuring a Minecraft server with plugins, you should have no problem with the YAML format.

Simple Example

Here is a very barebones example of the configuration format.

tree:
    Ammo: "cheats.givecurrentammo"
    Graph: "debug.netgraph"

Generating this config and running it through the steps listed in the first lesson should yield a result that looks like this:

λ | ┌──┤ root/Ammo/............................................................ ├──┐
λ | │                                │                                             │ [UPARROW] / [DOWNARROW] - Previous/Next
λ | │             > Ammo <           │            > givecurrentammo <              │ [LEFTARROW] / [RIGHTARROW] - Change Setting
λ | │              Graph             │                                             │ [ENTER] - Enter Folder / Run Command
λ | │                                │                                             │ [\] - Exit Folder
λ | └──┤ Give yourself ammo for the weapon in your main hand.                   ├──┘

Let's walk through the structure of this file. To start, there is the "tree" key. As previously stated, this key holds the menu components and objects that comprise the UI of the menu. It is called a "tree" because it is a tree-like structure; that is, components can be nested recursively. We will get in to how to do that in a later tutorial.

Next, note the two sub-keys under the tree key. You probably figured out that the name of the key determines the name of the text in the UI. These keys are called "components", in that they are the building blocks which make up the UI. Each component can be configured verbosely or concisely. So, the components's name is determined by the key name used in the configuration.

Likewise, the component's type is determined by the value. By "type", I mean the function that the component composes. For example, the Ammo component's type is "cheats.givecurrentammo". The "cheats.givecurrentammo" functions as a button, in that pressing the action button (by default, Enter), runs a command, in this case, the command "givecurrentammo." The Graph component is of the type "debug.netgraph". The "debug.netgraph" functions as a switch, because by pressing the setting selection buttons (by default, and ) the net_graph console variable is turned on and off, much like an everyday switch.

Hopefully now you understand the basic structure of the configuration files. In the next part, you will learn about paramaters and ways to organize the components in a configuration file.

Parameters

In many cases simply specifying the type of component is not enough. For example, what if you wanted to change the description of the component? (The description, by the way, is the bottom-most line of text in the UI.) To do this, one must take advantage of YAML's (or JSON's) object nesting capabilities.

Where, in the last tutorial, we used a string -- remember, a string is a "string" of characters, a.k.a. text -- we will need to use an object, which is a collection of sub-keys and sub-values.

Doing this is an easy process, thanks to the versatile configuration format. We will simply need to change this:

tree:
    Ammo: "cheats.givecurrentammo"
    Graph: "debug.netgraph"

into this:

tree:
    Ammo: 
        type: "cheats.givecurrentammo"
        desc: "Test Description."
    Graph: "debug.netgraph"

Let me explain what is going on here. You'll notice that the Ammo key now has two sub-keys, type and desc. The type sub-key does just what it is named: sets the type, and by association, function, of a component. It is analogous to the first example, but just more verbose. The desc sub-key sets the description of the component. Sub-keys organized in this matter are caled parameters, because they provide the component with information about its function. Therefore, the desc sub-key is a parameter.

So, by generating and running this config, we see a result like this:

λ | ┌──┤ root/Ammo/............................................................ ├──┐
λ | │                                │                                             │ [UPARROW] / [DOWNARROW] - Previous/Next
λ | │             > Ammo <           │            > givecurrentammo <              │ [LEFTARROW] / [RIGHTARROW] - Change Setting
λ | │              Graph             │                                             │ [ENTER] - Enter Folder / Run Command
λ | │                                │                                             │ [\] - Exit Folder
λ | └──┤ Test Description.                                                      ├──┘

Different component types have different parameters. However, all components share a few common parameters. For a list of all component types and their parameters, look here. Of course, you will not always need to use parameters. If that is the case, you can just use the format listed in the simple example and call it a day.

Folders

With the basic premise of parameters fresh in your mind, you are ready to tackle more challenging aspects of the format.

There are a multitude of different component types available in the "standard library" that comes with this program. However, there is a special one, called a folder. Much like how one uses folders to organize files on their computer, one also uses folders to organize components in the configuration file. Remember how many times I talked about the "object nesting" capabilities of the configuration format. This is perhaps the most versatile use for them.

How do you use a folder in this format, then? The folder structure, put simply, is an extension of the base configuration format. Take this example:

tree:
    Comp1: "cheats.noclip"
    Fold1:
        type: "folder"
        desc: "Bot Stuff"
        tree:
            NestComp1: "bots.addct"
            NestComp2: "bots.addt"

There is a lot to unpack here. Let's start at the top. The base tree key has two components: Comp1 and Fold1. The Comp1 component is of the type "cheats.noclip". Pretty standard. What about the Fold1 component, though? It is of the type "folder", and its description is "Bot Stuff". That is easy to tell. But it also has another parameter, tree.

The tree parameter functions exactly like the tree key at the start of the document (line 1), in that you can "nest" components under it. Notice how this tree key has two components under it, NestComp1 and NestComp2. Let's take a look at how this looks in-game, while "selecting" Fold1:

λ | ┌──┤ root/................................................................. ├──┐
λ | │              Comp1             │                                             │ [UPARROW] / [DOWNARROW] - Previous/Next
λ | │            > Fold1 <           │      Contents: NestComp1                    │ [LEFTARROW] / [RIGHTARROW] - Change Setting
λ | │                                │                NestComp2                    │ [ENTER] - Enter Folder / Run Command
λ | │                                │                                             │ [\] - Exit Folder
λ | └──┤ Bot Stuff                                                              ├──┘

Notice how the folder gives a "preview" of its contents. If we enter the folder by using the action button (by default, Enter), we then are able to interact with the two components nested in Fold1, NestComp1 and NestComp2:

λ | ┌──┤ root/Fold1/........................................................... ├──┐
λ | │                                │                                             │ [UPARROW] / [DOWNARROW] - Previous/Next
λ | │          > NestComp1 <         │              > bot_add_ct <                 │ [LEFTARROW] / [RIGHTARROW] - Change Setting
λ | │            NestComp2           │                                             │ [ENTER] - Enter Folder / Run Command
λ | │                                │                                             │ [\] - Exit Folder
λ | └──┤ Add a bot to the Counter-Terrorist team.                               ├──┘

To sum this up, folders are a powerful tool for controlling the organization and hierarchy of your configuration. You should aim to use them to group sets of tasks that have similar categories and functions, like they are in this example with NestComp1 and NestComp2.