CS2D Lua: Hats

Hats. Hat scripts are one of the most popular categories of scripts in Counter-Strike 2D and on Unreal Software – together with administration solutions and Tibia remakes. The majority of hat scripts, however, contain the same pitfalls and mistakes that lead to errors and malfunctions. This post is a tutorial on how to make good hat scripts. This tutorial is made for those with basic knowledge of Lua and its CS2D API.

Basic architecture

Most hat scripts follow the same basic model – a player says something into the chat or presses a server key and a menu is displayed to them. They can then select a hat to wear from that menu. Let’s express that in code.

Now, when a player presses F2, they will see a menu open with three options we specified above. At the moment, nothing happens if the player clicks an option – the menu simply disappears. The next step will be to implement actual menu functionality. Working with menus is fairly simple:

The foundation of the code has been laid. Now, the key functionality needs to be added – actual selection and drawing of hats.

Tables, not prayers

Most hat scripts contain one principal mistake – they either store the created image ID in the id variable of the menu processing function, or not at all. The same id variable is used when hats are removed. And while this approach may work with one player on a server running nothing but the script, which is usually how these creations are tested, it may (and eventually will, as Murphy’s Law dictates) fail on a server with more players or running more scripts that work with images. That is why another approach has to be taken – one based on tables.

Tables seem like a mystery to many beginners, but their functionality is actually very straight-forward. In essence, a table is a collection of values assigned to certain keys – as one might order information by page number, variables in a table are ordered by keys. In our case, we need to order IDs of hat images by player – an image ID has to correspond to the player wearing that image. With this in mind, let’s define the table that will store hat image IDs in no more than one line at the very beginning of the script:

Piece of cake. Now that the table exists, let’s start working on hat drawing and return to the process_menu function. We need to add a hat to the player, but only the hat that the player selected:

Since we know which button corresponds to which hat, we can control the flow of the script and perform different actions depending on which hat was selected. For adding hats we will need to use the image function to create the image and the imageblend function to remove the black background behind the sprites we will use for the hats (default sprites shipped with all CS2D versions).

This is where our hats table comes into play. To add a value into a table, the following syntax is used:

Since process_menu provides us with the player ID by means of the id argument, we can use that for our key, and a call to the image function for our value.

But hold on – there’s something I didn’t mention, namely lines 5, 8 and 12. Those lines are responsible for removing existing hats, if any; the expression if (hats[id]) then specifies that freeimage will be called only if the player is actually wearing a hat, in order to prevent any errors.

From a technical viewpoint, if (hats[id]) then is equivalent to if (hats[id] ~= nil and hats[id] ~= false) then . In our case, we’re checking hats[id] against nil only, but because it’s shorter to simply write if (hats[id]) then , it’s a perfectly acceptable substitute. Be careful – the short evaluation will return true only if the value is true or any other data type except nil – which means that if your value can be false but not nil , you have to use the longer if (hats[id] ~= nil) then .

Line 13 also contains a nil assignment. As you may know, assigning nil to a variable or, in this case, a table index essentially deletes that variable. Since our third option is No hat, we remove the existing hat image and remove the image’s ID as well; we didn’t need to do that in the other two cases, because by assigning a new image ID to hats[id] we overwrote the existing ID with a new one.

Okay, hat adding is complete, and so is menu opening. You may think that this concludes the script – but think again. Tables are abstract and are not tied in with CS2D in any way, so even though we store IDs in our hats table under player IDs, the values remain even if those players are no longer there. This may lead to players who just joined wearing the same hats as the players who left – and that leads to chaos. Thankfully, the uncomfortable hat inheritance is easily fixed with a few lines of code. We want to remove the hat from a player when they leave, so we’ll use the leave hook:

The surrounding clause if (hats[id]) then states that the code after it should only be executed if the player had a hat – there’s no need to remove what isn’t there. Now the script is complete, and your players can enjoy either wearing a human-sized block or a bright glow on their heads.

The complete code is as follows:

Published by



Developer, human and programming language enthusiast, teacher at heart. Please remember: all my opinions are independent and subjective.

4 thoughts on “CS2D Lua: Hats”

    1. — For the purposes of this demonstration, we will let the players open the hat menu by pressing F2.
      addhook(“serveraction”, “open_hats”)
      function open_hats(id, action)
      if (action == 1) then
      menu(id, “Select a hat,Block hat,Flare hat, No hat”)
      change action == 1
      action == 1 => F2
      action == 2 => F3
      action == 3 => F4

Leave a Reply

Your email address will not be published.